aboutsummaryrefslogtreecommitdiff
path: root/node_modules/svgo
diff options
context:
space:
mode:
authorruki <waruqi@gmail.com>2018-11-08 00:38:48 +0800
committerruki <waruqi@gmail.com>2018-11-07 21:53:09 +0800
commit26105034da4fcce7ac883c899d781f016559310d (patch)
treec459a5dc4e3aa0972d9919033ece511ce76dd129 /node_modules/svgo
parent2c77f00f1a7ecb6c8192f9c16d3b2001b254a107 (diff)
downloadxmake-docs-26105034da4fcce7ac883c899d781f016559310d.tar.gz
xmake-docs-26105034da4fcce7ac883c899d781f016559310d.zip
switch to vuepress
Diffstat (limited to 'node_modules/svgo')
l---------node_modules/svgo/.bin/svgo1
-rw-r--r--node_modules/svgo/.npmignore11
-rw-r--r--node_modules/svgo/.svgo.yml68
-rw-r--r--node_modules/svgo/CHANGELOG.md421
-rw-r--r--node_modules/svgo/LICENSE55
-rw-r--r--node_modules/svgo/Makefile21
-rw-r--r--node_modules/svgo/README.md155
-rw-r--r--node_modules/svgo/README.ru.md155
-rwxr-xr-xnode_modules/svgo/bin/svgo3
-rw-r--r--node_modules/svgo/lib/svgo.js80
-rw-r--r--node_modules/svgo/lib/svgo/coa.js581
-rw-r--r--node_modules/svgo/lib/svgo/config.js212
-rw-r--r--node_modules/svgo/lib/svgo/js2svg.js352
-rw-r--r--node_modules/svgo/lib/svgo/jsAPI.js298
-rw-r--r--node_modules/svgo/lib/svgo/plugins.js98
-rw-r--r--node_modules/svgo/lib/svgo/svg2js.js187
-rw-r--r--node_modules/svgo/lib/svgo/tools.js147
l---------node_modules/svgo/node_modules/.bin/csso1
l---------node_modules/svgo/node_modules/.bin/js-yaml1
l---------node_modules/svgo/node_modules/.bin/mkdirp1
l---------node_modules/svgo/node_modules/esprima/.bin/esparse1
l---------node_modules/svgo/node_modules/esprima/.bin/esvalidate1
-rw-r--r--node_modules/svgo/node_modules/esprima/ChangeLog174
-rw-r--r--node_modules/svgo/node_modules/esprima/LICENSE.BSD21
-rw-r--r--node_modules/svgo/node_modules/esprima/README.md27
-rwxr-xr-xnode_modules/svgo/node_modules/esprima/bin/esparse.js126
-rwxr-xr-xnode_modules/svgo/node_modules/esprima/bin/esvalidate.js199
-rw-r--r--node_modules/svgo/node_modules/esprima/esprima.js5740
-rw-r--r--node_modules/svgo/node_modules/esprima/package.json99
l---------node_modules/svgo/node_modules/js-yaml/.bin/js-yaml1
-rw-r--r--node_modules/svgo/node_modules/js-yaml/CHANGELOG.md409
-rw-r--r--node_modules/svgo/node_modules/js-yaml/LICENSE21
-rw-r--r--node_modules/svgo/node_modules/js-yaml/README.md295
-rwxr-xr-xnode_modules/svgo/node_modules/js-yaml/bin/js-yaml.js132
-rw-r--r--node_modules/svgo/node_modules/js-yaml/dist/js-yaml.js3855
-rw-r--r--node_modules/svgo/node_modules/js-yaml/dist/js-yaml.min.js3
-rw-r--r--node_modules/svgo/node_modules/js-yaml/index.js7
-rw-r--r--node_modules/svgo/node_modules/js-yaml/lib/js-yaml.js39
-rw-r--r--node_modules/svgo/node_modules/js-yaml/lib/js-yaml/common.js59
-rw-r--r--node_modules/svgo/node_modules/js-yaml/lib/js-yaml/dumper.js801
-rw-r--r--node_modules/svgo/node_modules/js-yaml/lib/js-yaml/exception.js43
-rw-r--r--node_modules/svgo/node_modules/js-yaml/lib/js-yaml/loader.js1587
-rw-r--r--node_modules/svgo/node_modules/js-yaml/lib/js-yaml/mark.js76
-rw-r--r--node_modules/svgo/node_modules/js-yaml/lib/js-yaml/schema.js108
-rw-r--r--node_modules/svgo/node_modules/js-yaml/lib/js-yaml/schema/core.js18
-rw-r--r--node_modules/svgo/node_modules/js-yaml/lib/js-yaml/schema/default_full.js25
-rw-r--r--node_modules/svgo/node_modules/js-yaml/lib/js-yaml/schema/default_safe.js28
-rw-r--r--node_modules/svgo/node_modules/js-yaml/lib/js-yaml/schema/failsafe.js17
-rw-r--r--node_modules/svgo/node_modules/js-yaml/lib/js-yaml/schema/json.js25
-rw-r--r--node_modules/svgo/node_modules/js-yaml/lib/js-yaml/type.js61
-rw-r--r--node_modules/svgo/node_modules/js-yaml/lib/js-yaml/type/binary.js135
-rw-r--r--node_modules/svgo/node_modules/js-yaml/lib/js-yaml/type/bool.js35
-rw-r--r--node_modules/svgo/node_modules/js-yaml/lib/js-yaml/type/float.js105
-rw-r--r--node_modules/svgo/node_modules/js-yaml/lib/js-yaml/type/int.js168
-rw-r--r--node_modules/svgo/node_modules/js-yaml/lib/js-yaml/type/js/function.js84
-rw-r--r--node_modules/svgo/node_modules/js-yaml/lib/js-yaml/type/js/regexp.js60
-rw-r--r--node_modules/svgo/node_modules/js-yaml/lib/js-yaml/type/js/undefined.js28
-rw-r--r--node_modules/svgo/node_modules/js-yaml/lib/js-yaml/type/map.js8
-rw-r--r--node_modules/svgo/node_modules/js-yaml/lib/js-yaml/type/merge.js12
-rw-r--r--node_modules/svgo/node_modules/js-yaml/lib/js-yaml/type/null.js34
-rw-r--r--node_modules/svgo/node_modules/js-yaml/lib/js-yaml/type/omap.js44
-rw-r--r--node_modules/svgo/node_modules/js-yaml/lib/js-yaml/type/pairs.js53
-rw-r--r--node_modules/svgo/node_modules/js-yaml/lib/js-yaml/type/seq.js8
-rw-r--r--node_modules/svgo/node_modules/js-yaml/lib/js-yaml/type/set.js29
-rw-r--r--node_modules/svgo/node_modules/js-yaml/lib/js-yaml/type/str.js8
-rw-r--r--node_modules/svgo/node_modules/js-yaml/lib/js-yaml/type/timestamp.js88
l---------node_modules/svgo/node_modules/js-yaml/node_modules/.bin/esparse1
l---------node_modules/svgo/node_modules/js-yaml/node_modules/.bin/esvalidate1
-rw-r--r--node_modules/svgo/node_modules/js-yaml/package.json46
-rw-r--r--node_modules/svgo/package.json70
-rw-r--r--node_modules/svgo/plugins/_collections.js2529
-rw-r--r--node_modules/svgo/plugins/_path.js962
-rw-r--r--node_modules/svgo/plugins/_transforms.js308
-rw-r--r--node_modules/svgo/plugins/addAttributesToSVGElement.js57
-rw-r--r--node_modules/svgo/plugins/addClassesToSVGElement.js64
-rw-r--r--node_modules/svgo/plugins/cleanupAttrs.js56
-rw-r--r--node_modules/svgo/plugins/cleanupEnableBackground.js84
-rw-r--r--node_modules/svgo/plugins/cleanupIDs.js208
-rw-r--r--node_modules/svgo/plugins/cleanupListOfValues.js141
-rw-r--r--node_modules/svgo/plugins/cleanupNumericValues.js76
-rw-r--r--node_modules/svgo/plugins/collapseGroups.js91
-rw-r--r--node_modules/svgo/plugins/convertColors.js127
-rw-r--r--node_modules/svgo/plugins/convertPathData.js957
-rw-r--r--node_modules/svgo/plugins/convertShapeToPath.js103
-rw-r--r--node_modules/svgo/plugins/convertStyleToAttrs.js117
-rw-r--r--node_modules/svgo/plugins/convertTransform.js364
-rw-r--r--node_modules/svgo/plugins/mergePaths.js71
-rw-r--r--node_modules/svgo/plugins/minifyStyles.js45
-rw-r--r--node_modules/svgo/plugins/moveElemsAttrsToGroup.js126
-rw-r--r--node_modules/svgo/plugins/moveGroupAttrsToElems.js63
-rw-r--r--node_modules/svgo/plugins/removeAttrs.js119
-rw-r--r--node_modules/svgo/plugins/removeComments.js27
-rw-r--r--node_modules/svgo/plugins/removeDesc.js32
-rw-r--r--node_modules/svgo/plugins/removeDimensions.js32
-rw-r--r--node_modules/svgo/plugins/removeDoctype.js40
-rw-r--r--node_modules/svgo/plugins/removeEditorsNSData.js65
-rw-r--r--node_modules/svgo/plugins/removeElementsByAttr.js80
-rw-r--r--node_modules/svgo/plugins/removeEmptyAttrs.js29
-rw-r--r--node_modules/svgo/plugins/removeEmptyContainers.js32
-rw-r--r--node_modules/svgo/plugins/removeEmptyText.js59
-rw-r--r--node_modules/svgo/plugins/removeHiddenElems.js218
-rw-r--r--node_modules/svgo/plugins/removeMetadata.js23
-rw-r--r--node_modules/svgo/plugins/removeNonInheritableGroupAttrs.js40
-rw-r--r--node_modules/svgo/plugins/removeRasterImages.js28
-rw-r--r--node_modules/svgo/plugins/removeStyleElement.js23
-rw-r--r--node_modules/svgo/plugins/removeTitle.js24
-rw-r--r--node_modules/svgo/plugins/removeUnknownsAndDefaults.js143
-rw-r--r--node_modules/svgo/plugins/removeUnusedNS.js107
-rw-r--r--node_modules/svgo/plugins/removeUselessDefs.js51
-rw-r--r--node_modules/svgo/plugins/removeUselessStrokeAndFill.js92
-rw-r--r--node_modules/svgo/plugins/removeViewBox.js49
-rw-r--r--node_modules/svgo/plugins/removeXMLNS.js28
-rw-r--r--node_modules/svgo/plugins/removeXMLProcInst.js24
-rw-r--r--node_modules/svgo/plugins/sortAttrs.js81
-rw-r--r--node_modules/svgo/plugins/transformsWithOnePath.js327
115 files changed, 26185 insertions, 0 deletions
diff --git a/node_modules/svgo/.bin/svgo b/node_modules/svgo/.bin/svgo
new file mode 120000
index 00000000..746740a5
--- /dev/null
+++ b/node_modules/svgo/.bin/svgo
@@ -0,0 +1 @@
+../bin/svgo \ No newline at end of file
diff --git a/node_modules/svgo/.npmignore b/node_modules/svgo/.npmignore
new file mode 100644
index 00000000..aab1a69a
--- /dev/null
+++ b/node_modules/svgo/.npmignore
@@ -0,0 +1,11 @@
+docs
+examples
+test
+lib-cov
+.editorconfig
+.jshintignore
+.jshintrc
+.travis.yml
+lcov.info
+logo.svg
+CHANGELOG.MD
diff --git a/node_modules/svgo/.svgo.yml b/node_modules/svgo/.svgo.yml
new file mode 100644
index 00000000..a2b6e520
--- /dev/null
+++ b/node_modules/svgo/.svgo.yml
@@ -0,0 +1,68 @@
+# replace default config
+
+# multipass: true
+# full: true
+
+plugins:
+
+ # - name
+ #
+ # or:
+ # - name: false
+ # - name: true
+ #
+ # or:
+ # - name:
+ # param1: 1
+ # param2: 2
+
+ - removeDoctype
+ - removeXMLProcInst
+ - removeComments
+ - removeMetadata
+ - removeXMLNS
+ - removeEditorsNSData
+ - cleanupAttrs
+ - minifyStyles
+ - convertStyleToAttrs
+ - cleanupIDs
+ - removeRasterImages
+ - removeUselessDefs
+ - cleanupNumericValues
+ - cleanupListOfValues
+ - convertColors
+ - removeUnknownsAndDefaults
+ - removeNonInheritableGroupAttrs
+ - removeUselessStrokeAndFill
+ - removeViewBox
+ - cleanupEnableBackground
+ - removeHiddenElems
+ - removeEmptyText
+ - convertShapeToPath
+ - moveElemsAttrsToGroup
+ - moveGroupAttrsToElems
+ - collapseGroups
+ - convertPathData
+ - convertTransform
+ - removeEmptyAttrs
+ - removeEmptyContainers
+ - mergePaths
+ - removeUnusedNS
+ - transformsWithOnePath
+ - sortAttrs
+ - removeTitle
+ - removeDesc
+ - removeDimensions
+ - removeAttrs
+ - removeElementsByAttr
+ - addClassesToSVGElement
+ - removeStyleElement
+ - addAttributesToSVGElement
+
+# configure the indent (default 4 spaces) used by `--pretty` here:
+#
+# @see https://github.com/svg/svgo/blob/master/lib/svgo/js2svg.js#L6 for more config options
+#
+# js2svg:
+# pretty: true
+# indent: ' '
diff --git a/node_modules/svgo/CHANGELOG.md b/node_modules/svgo/CHANGELOG.md
new file mode 100644
index 00000000..7a2084d7
--- /dev/null
+++ b/node_modules/svgo/CHANGELOG.md
@@ -0,0 +1,421 @@
+### [ [>](https://github.com/svg/svgo/tree/v0.7.2) ] 0.7.2 / 29.01.2017
+* Extended `currentColor` match conditions (string, rx, bool) (by @AlimovSV)
+* Fixed removing `<animate>` in `<stop>`.
+* Fixed removing same transform in inner element in `removeUnknownsAndDefaults`.
+* Fixed collapsing groups with same non-inheritable attribue.
+* Corrected removing of leading zero in case of exponential notation.
+
+### [ [>](https://github.com/svg/svgo/tree/v0.7.1) ] 0.7.1 / 27.09.2016
+* Reverted the requirement of Node.js to version 0.10.
+* Added `addAttributesToSVGElement` to the default config to allow using it with `--enable` option.
+* Added korean translation of “How it works” doc (by @primeiros).
+
+### [ [>](https://github.com/svg/svgo/tree/v0.7.0) ] 0.7.0 / 25.08.2016
+* Required Node.js version has increased to 0.12.
+* New plugins: `removeElementsByAttr` (by IDs or classes) by @elidupuis,
+ `addAttributesToSVGElement` by @gjjones,
+ `removeXMLNS` (for SVG inlining) by @ricardobeat.
+* Tests now correctly pass in Windows with CRLF line endings. Pretty print now accounts system line endings.
+* Fixed bugs with collapsing groups with masks and transforms in `collapseGroups`.
+* Fixed bugs with erroneous removing IDs in `cleanupIDs`.
+* Improved attributes sorting in `sortAttrs` by @darktrojan.
+* `addClassesToSVGElement` no more repeats classes (by @ricardobeat).
+
+### [ [>](https://github.com/svg/svgo/tree/v0.6.6) ] 0.6.6 / 25.04.2016
+* Corrected CSSO API usage
+
+### [ [>](https://github.com/svg/svgo/tree/v0.6.5) ] 0.6.5 / 25.04.2016
+* Extra content inserted by editors are now being removed within `<foreignObject>` as well thus fixing bug “Namespace prefix … is not defined“ after applying SVGO.
+* Doctype with entities declartion is now also being removed since svgo correctly parses them starting from the version [0.6.2](https://github.com/svg/svgo/tree/v0.6.2).
+* Corrected `moveGroupAttrsToElems` not to move attributes to `g` content if it's referenced (has an `id`).
+* `collapseGroups` now don't collapse a group if it has an animated attribute (SMIL).
+
+### [ [>](https://github.com/svg/svgo/tree/v0.6.4) ] 0.6.4 / 05.04.2016
+* Fixed bug in “[convertStyleToAttrs](https://github.com/svg/svgo/blob/master/plugins/convertStyleToAttrs.js)” plugin with converting styling properties to non-existent attributes (which are normally removed later by `removeUnknownsAndDefaults`).
+* Added `--indent` option to style pretty-printed SVG. (e.g. `--indent 2`) (by @scurker).
+* Added `currentColor` param to `convertColors` plugin for converting values like `fill` and `stroke` to `currentColor` (by @scurker).
+* Bumped CSSO to the current version and used [its new shiny API](https://github.com/css/csso#api) (thanks to @lahmatiy).
+
+### [ [>](https://github.com/svg/svgo/tree/v0.6.3) ] 0.6.3 / 20.03.2016
+* Smart rounding (introduced in 0.4.5) now applies only when rounding is needed, thus making subsequent passes more stable.
+* Fixed regression in converting curves to arcs.
+* `xlink:href` references are now being checked by local name `href`, thus correctly working with another namespace prefix.
+* Fixed `id` removing with disabled `plugins/convertStyleToAttrs.js`.
+
+### [ [>](https://github.com/svg/svgo/tree/v0.6.2) ] 0.6.2 / 08.03.2016
+* Better error handling and messaging improvements.
+* SVG files with XML entities (e.g. from Adobe Illustrator) are now correctly being parsed.
+* Fixed error on converting curves to arcs.
+* Corrected rounding in subsequent passes with `--multipass` option.
+* Data URI option now handles charset (by @holymonson)
+* Tranformations are no longer moved to group if there is a mask (`plugins/moveElemsAttrsToGroup.js`).
+* Fixed matrix decomposition losing sign in case like `[1, 0, 0, -1, 0, 0]` (`scale(1 -1)`).
+* Fixed crash on uppercased color name.
+* Paths with `id` and without `stroke-width` aren't being trasformed now since `stroke-width` may be applied later.
+
+### [ [>](https://github.com/svg/svgo/tree/v0.6.1) ] 0.6.1 / 21.11.2015
+* Added option `--quiet` to suppress output (by @phihag).
+* Removed `lib-cov` folder from the package, which was erroneously included before.
+* Fixed errors in “[minifyStyles](https://github.com/svg/svgo/blob/master/plugins/minifyStyles.js)” when there are `<style>` elements with `CDATA` content or without content at all.
+* Amended transform functions parsing to prevent errors when there are no separators between numbers (which isn't allowed by syntax, but understood by browsers).
+
+### [ [>](https://github.com/svg/svgo/tree/v0.6.0) ] 0.6.0 / 08.11.2015
+* New optimization: circular curves now being converted to arcs. A notable improvement for circles within paths.
+* New plugin “[minifyStyles](https://github.com/svg/svgo/blob/master/plugins/minifyStyles.js)” which minifies `<style>` elments content with CSSO by @strarsis (svgo still doesn't understand its content)
+* New plugin “[removeStyleElement](https://github.com/svg/svgo/blob/master/plugins/removeStyleElement.js)” (disabled by default) by @betsydupuis.
+* Fixed issues wuth parsing numbers with exponent fraction (could happen with high precision >= 7).
+* Fixed rounding error due to incorrect preserving of precision in transformations.
+* Fixed shortand curve distortion due to converted previous curve to not a curve.
+* Fixed interoperability issue with `precision` cli-option and `full` config.
+* Fixed an error produced by “[removeUnknownsAndDefaults](https://github.com/svg/svgo/blob/master/plugins/removeUnknownsAndDefaults.js)” by @thiakil
+* Another Inkscape prefix namespace is being removed.
+* Fixed an issue in [moveElemsAttrsToGroup“](https://github.com/svg/svgo/blob/master/plugins/moveElemsAttrsToGroup“.js)” with transforms moved around `clip-path`.
+
+### [ [>](https://github.com/svg/svgo/tree/v0.5.6) ] 0.5.6 / 13.08.2015
+* Fixed paths removing.
+
+### [ [>](https://github.com/svg/svgo/tree/v0.5.5) ] 0.5.5 / 05.08.2015
+* Reverted debugging changes.
+
+### [ [>](https://github.com/svg/svgo/tree/v0.5.4) ] 0.5.4 / 05.08.2015
+* New parameter `useShortTags` by @bradbarrow. Now svgo can produce correct non-selfclosing tags (useful in HTML in old browsers).
+* Fixed failing on empty transformation (which could be produced by two opposite).
+* Fixed removing paths which have numbers with exponent notation.
+* Fixed a bug with arc transformation.
+* Some typo fixes.
+
+### [ [>](https://github.com/svg/svgo/tree/v0.5.3) ] 0.5.3 / 21.06.2015
+* Fixed breaking related to rounding functions in “[convertTransform](https://github.com/svg/svgo/blob/master/plugins/convertTransform.js)”.
+* Fixed a bug with ID in animations not being worked on by “[cleanupIDs](https://github.com/svg/svgo/blob/master/plugins/cleanupIDs.js)”.
+* Fixed a bug with quoted reference in `url()`.
+* Now, if there are several same IDs in the document, then the first one is used and others are being removed.
+* New command-line option `--show-plugins` displaying list of plugins.
+* Two new optional plugins: “[removeDimensions](https://github.com/svg/svgo/blob/master/plugins/removeDimensions.js)” (removes `width` and `height` if there is `viewBox`) and “[removeAttrsPlugin](https://github.com/svg/svgo/blob/master/plugins/removeAttrs.js)” (by @bennyschudel).
+
+### [ [>](https://github.com/svg/svgo/tree/v0.5.2) ] 0.5.2 / 24.05.2015
+* Introduced new `transformPrecision` option for better image quality (defaults to 5) in “[convertTransform](https://github.com/svg/svgo/blob/master/plugins/convertTransform.js)” and “[convertPathData](https://github.com/svg/svgo/blob/master/plugins/convertPathData.js)” (for the purpose of applying transformations) plugins.
+* Matrix transformations now can be decomposed into a combination of few simple transforms like `translate`, `rotate`, `scale`.
+* Arcs (paths `arcto` command) are now correctly being transformed into another arcs without being converting to Bezier curves.
+* Fixed an issue with “[mergePaths](https://github.com/svg/svgo/blob/master/plugins/mergePaths.js)” failing to detect paths intersection in some cases.
+* Fixed a bug with “[removeUnknownsAndDefaults](https://github.com/svg/svgo/blob/master/plugins/removeUnknownsAndDefaults.js)” removing some paths, which was introduced in [v0.5.1](https://github.com/svg/svgo/tree/v0.5.1).
+* Fixed a bug with transformation having `rotate()` with optional parameters.
+* Patterns with inherited attributes are no longer being removed.
+* Styles are no longer being removed from `<desc>` (by @dennari).
+* SVGO no longer breaks during parsing.
+* Added `clone()` method to JSAPI (by @jakearchibald)
+
+### [ [>](https://github.com/svg/svgo/tree/v0.5.1) ] 0.5.1 / 30.03.2015
+* added new command-line option to set precision in floating point numbers.
+* fixed all known image-disruptive bugs
+* Notably [mergePaths](https://github.com/svg/svgo/blob/master/plugins/mergePaths.js) plugin now checks for possible intersections to avoid side-effects
+* new plugin [removeUselessDefs](https://github.com/svg/svgo/blob/master/plugins/removeUselessDefs.js) to remove elements in ``<defs>`` and similar non-rendering elements without an ``id`` and thus cannot be used
+* fix for ``--multipass`` command line option (by @dfilatov)
+* improved [cleanupEnableBackground](https://github.com/svg/svgo/blob/master/plugins/cleanupEnableBackground.js) and [convertColors](https://github.com/svg/svgo/blob/master/plugins/convertColors.js) plugins (by @YetiOr)
+* new plugin for image manipulation [cleanupListOfValues](https://github.com/svg/svgo/blob/master/plugins/cleanupListOfValues.js) (by @kiyopikko)
+* fixed fail on comments after closing root ``</svg>`` tag
+* updated parsing to account meaningful spaces in ``<text>``
+* ``data-*`` attributes are now preserved in [removeUnknownsAndDefaults](https://github.com/svg/svgo/blob/master/plugins/removeUnknownsAndDefaults.js)
+* prevented plugins from failing in ``<foreignObject>``
+* [cleanupNumericValues](https://github.com/svg/svgo/blob/master/plugins/cleanupNumericValues.js) plugin now converts other units to pixels (if it's better)
+* [removeUselessStrokeAndFill](https://github.com/svg/svgo/blob/master/plugins/removeUselessStrokeAndFill.js) plugin is enabled again with correct work in case of inherited attributes
+* fixed fail on images with incorrect paths like ``<path d="z"/>``
+* svgo now understands if an input is a folder (remember, you can set output to folder as well)
+* added support for some properties from SVG 2 like ``vector-effect="non-scaling-stroke"``
+* removed option to remove an ``id`` on root ``<svg>`` tag in [removeUnknownsAndDefaults](https://github.com/svg/svgo/blob/master/plugins/removeUnknownsAndDefaults.js) since it's already being done in [cleanupIDs](https://github.com/svg/svgo/blob/master/plugins/cleanupIDs.js)
+
+### [ [>](https://github.com/svg/svgo/tree/v0.5.0) ] 0.5.0 / 05.11.2014
+* added ``--multipass`` command line option which repeatedly applies optimizations like collapsing groups (by @dfilatov)
+* exposed JSAPI as a factory method (by @mistakster)
+* added removeDesc plugin (by @dwabyick), disabled by default
+* [removeUselessStrokeAndFill](https://github.com/svg/svgo/blob/master/plugins/removeUselessStrokeAndFill.js) plugin is disabled by default since it's unable to check inherited properties
+* transformations now apply to paths with arcs in [plugins/convertPathData](https://github.com/svg/svgo/blob/master/plugins/convertPathData.js)
+* a lot of bug fixes mostly related to transformations
+
+### [ [>](https://github.com/svg/svgo/tree/v0.4.5) ] 0.4.5 / 02.08.2014
+* significally improved plugin [plugins/convertPathData](https://github.com/svg/svgo/blob/master/plugins/convertPathData.js):
+ - Now data is being written relative or absolute whichever is shorter. You can turn it off by setting ``utilizeAbsolute`` to ``false``.
+ - Smarter rounding: values like 2.499 now rounds to 2.5. Rounding now takes in account accumulutive error meaning that points will not be misplaced due to rounding more than it neccessary.
+ - Fixed couple bugs.
+* ``--output`` option now can be a folder along with ``--folder``, thanks to @mako-taco.
+* [plugins/cleanupIDs](https://github.com/svg/svgo/blob/master/plugins/cleanupIDs.js) now have ``prefix`` option in case you want to combine multiple svg later (by @DanielMazurkiewicz).
+* Quotes now being escaped in attributes (by @ditesh).
+* Minor bugfixes.
+
+### [ [>](https://github.com/svg/svgo/tree/v0.4.4) ] 0.4.4 / 14.01.2014
+* new plugin [plugins/removeTitle](https://github.com/svg/svgo/blob/master/plugins/removeTitle.js) (disabled by default, close [#159](https://github.com/svg/svgo/issues/159))
+* plugins/convertPathData: skip data concatenation for z instruction in collapseRepeated
+* plugins/removeUnknownsAndDefaults: do not remove overriden attributes with default values (fix [#161](https://github.com/svg/svgo/issues/161) and [#168](https://github.com/svg/svgo/issues/168))
+* plugins/removeViewBox: disable by default (fix [#139](https://github.com/svg/svgo/issues/139))
+* update README with [gulp task](https://github.com/ben-eb/gulp-svgmin)
+
+### [ [>](https://github.com/svg/svgo/tree/v0.4.3) ] 0.4.3 / 02.01.2014
+* new plugin [plugins/convertShapeToPath](https://github.com/svg/svgo/blob/master/plugins/convertShapeToPath.js) (close [#96](https://github.com/svg/svgo/issues/96))
+* update sax version to fix [#140](https://github.com/svg/svgo/issues/140)
+* update deps
+
+### [ [>](https://github.com/svg/svgo/tree/v0.4.2) ] 0.4.2 / 19.12.2013
+* add `lcov.info` to npmignore
+* fix `js-yaml` version to suppress deprecation warning in stdout
+
+### [ [>](https://github.com/svg/svgo/tree/v0.4.1) ] 0.4.1 / 18.11.2013
+* node >=0.8.0
+
+### [ [>](https://github.com/svg/svgo/tree/v0.4.0) ] 0.4.0 / 18.11.2013
+* merge almost all pull-requests
+* update dependencies
+
+### [ [>](https://github.com/svg/svgo/tree/v0.3.7) ] 0.3.7 / 24.06.2013
+* do not remove `result` attribute from filter primitives (fix [#122](https://github.com/svg/svgo/issues/122))
+* plugins/cleanupAttrs: replace newline with space when needed (fix [#119](https://github.com/svg/svgo/issues/119))
+* lib/coa: look for config file in current folder
+* lib/coa: always traverse all files in the given folder
+* deprecate svgo-grunt in favor of [grunt-svgmin](https://github.com/sindresorhus/grunt-svgmin)
+* re-enable node-coveralls
+
+### [ [>](https://github.com/svg/svgo/tree/v0.3.6) ] 0.3.6 / 06.06.2013
+* plugins/removeNonInheritableGroupAttrs: more attrs groups to exclude (fix [#116](https://github.com/svg/svgo/issues/116) & [#118](https://github.com/svg/svgo/issues/118))
+* lib/coa: optimize folder file by file (temp fix [#114](https://github.com/svg/svgo/issues/114))
+* `.jshintrc`: JSHint 2.0
+* temporarily disable node-coveralls
+
+### [ [>](https://github.com/svg/svgo/tree/v0.3.5) ] 0.3.5 / 07.05.2013
+* plugins/transformsWithOnePath: fix curves bounding box calculation
+* plugins/transformsWithOnePath: fix possible c+t or q+s bug
+
+
+### [ [>](https://github.com/svg/svgo/tree/v0.3.4) ] 0.3.4 / 06.05.2013
+* plugins/convertPathData: fix m->M bug in some cases
+* plugins/transformsWithOnePath: fix last point calculation for C/S/Q/T
+* plugins/mergePaths: add space delimiter between z and m
+
+### [ [>](https://github.com/svg/svgo/tree/v0.3.3) ] 0.3.3 / 05.05.2013
+* plugins/convertPathData: convert very first m to M, fix applyTransforms with translate() (fix [#112](https://github.com/svg/svgo/issues/112))
+* plugins/transformsWithOnePath: fix real width/height rounding; fix scale transform origin; reorder transforms
+* plugins/transformsWithOnePath: ability to set new width or height independently with auto rescaling
+
+### [ [>](https://github.com/svg/svgo/tree/v0.3.2) ] 0.3.2 / 03.05.2013
+* new plugin [plugins/sortAttrs](https://github.com/svg/svgo/blob/master/plugins/sortAttrs.js)
+* plugins/transformsWithOnePath: buggy hcrop (fix [#111](https://github.com/svg/svgo/issues/111))
+* Impossible to set output presision to 0 (no fractional part) (fix [#110](https://github.com/svg/svgo/issues/110))
+* Istanbul + coveralls.io
+* update README with NPM version from badge.fury.io
+* update README with dependency status from gemnasium.com
+* npmignore unneeded files
+* reoptimized project logo
+
+### [ [>](https://github.com/svg/svgo/tree/v0.3.1) ] 0.3.1 / 15.04.2013
+* plugins/transformsWithOnePath: resize SVG and automatically rescale inner Path
+* better errors handling
+
+### [ [>](https://github.com/svg/svgo/tree/v0.3.0) ] 0.3.0 / 12.04.2013
+* global refactoring: getting rid of the many dependencies
+* new plugin [plugins/mergePaths](https://github.com/svg/svgo/blob/master/plugins/mergePaths.js)
+* new plugin [plugins/transformsWithOnePath](https://github.com/svg/svgo/blob/master/plugins/transformsWithOnePath.js) (renamed and featured `cropAndCenterAlongPath`)
+* config: replace default config with `full: true`
+* coa: JSON string as value of `--config`
+* coa: different types of Data URI strings (close [#105](https://github.com/svg/svgo/issues/105))
+* plugins/_transforms: allow spaces at the beginning of transform
+* Travis CI: Nodejs 0.10 & 0.11
+* `node.extend` → `whet.extend`
+* update `.gitignore`
+* update docs
+
+### [ [>](https://github.com/svg/svgo/tree/v0.2.4) ] 0.2.4 / 05.04.2013
+* new plugin [plugins/cropAndCenterAlongPath](https://github.com/svg/svgo/blob/master/plugins/cropAndCenterAlongPath.js) for the [Fontello](https://github.com/fontello) project
+
+### [ [>](https://github.com/svg/svgo/tree/v0.2.3) ] 0.2.3 / 22.02.2013
+* new plugin [plugins/removeNonInheritableGroupAttrs](https://github.com/svg/svgo/blob/master/plugins/removeNonInheritableGroupAttrs.js) (fix [#101](https://github.com/svg/svgo/issues/101))
+* new plugin [plugins/removeRasterImages](https://github.com/svg/svgo/blob/master/plugins/removeRasterImages.js) (close [#98](https://github.com/svg/svgo/issues/98))
+* plugins/convertTransform: bug with trailing spaces in transform value string (fix [#103](https://github.com/svg/svgo/issues/103))
+
+### [ [>](https://github.com/svg/svgo/tree/v0.2.2) ] 0.2.2 / 09.02.2013
+* plugins/convertTransforms: wrong translate() shorthand (fix [#94](https://github.com/svg/svgo/issues/94))
+* [yaml.js](https://github.com/jeremyfa/yaml.js) → [js-yaml](https://github.com/nodeca/js-yaml)
+* update outdated deps
+
+### [ [>](https://github.com/svg/svgo/tree/v0.2.1) ] 0.2.1 / 18.01.2013
+* plugins/moveElemsAttrsToGroup + plugins/moveGroupAttrsToElems: move or just leave transform attr from Group to the inner Path Elems (close [#86](https://github.com/svg/svgo/issues/86))
+* plugins/removeViewBox: doesn't catch floating-point numbers (fix [#88](https://github.com/svg/svgo/issues/88))
+* plugins/cleanupEnableBackground: doesn't catch floating-point numbers (fix [#89](https://github.com/svg/svgo/issues/89))
+* plugins/cleanupNumericValues: wrong floating-point numbers regexp (fix [#92](https://github.com/svg/svgo/issues/92))
+* SVG file generated by fontcustom.com not properly compressed (fix [#90](https://github.com/svg/svgo/issues/90))
+* `README.ru.md`: стилизация русского языка, улучшение языковых конструкций, правка ошибок (close [#91](https://github.com/svg/svgo/issues/91))
+* minor JSHint warning fix
+
+### [ [>](https://github.com/svg/svgo/tree/v0.2.0) ] 0.2.0 / 23.12.2012
+* plugins/convertPathData: apply transforms to Path pata (close [#33](https://github.com/svg/svgo/issues/33))
+* plugins/convertPathData: `-1.816-9.278.682-13.604` parsing error (fix [#85](https://github.com/svg/svgo/issues/85))
+* plugins/convertTransform: `translate(10, 0)` eq `translate(10)`, but not `translate(10, 10)` eq `translate(10)` (fix [#83](https://github.com/svg/svgo/issues/83))
+* run plugins/cleanupIDs before plugins/collapseGroups (fix [#84](https://github.com/svg/svgo/issues/84))
+* update `.gitignore`
+
+### [ [>](https://github.com/svg/svgo/tree/v0.1.9) ] 0.1.9 / 17.12.2012
+* plugins/cleanupIDs: renamed from removeUnusedIDs; minify used IDs (fix [#7](https://github.com/svg/svgo/issues/7))
+* lib/svgo/js2svg: restore HTML entities back (fix [#80](https://github.com/svg/svgo/issues/80) + [#81](https://github.com/svg/svgo/issues/81))
+* plugins/removeDoctype: do not remove if custom XML entities presents (fix [#77](https://github.com/svg/svgo/issues/77))
+* lib/svgo/coa: refactoring, colors and fix [#70](https://github.com/svg/svgo/issues/70)
+* lib/svgo: store elapsed time in result object
+* usage examples with SVGZ (close [#18](https://github.com/svg/svgo/issues/18))
+* more optimized logo
+* update `.gitignore`
+
+### [ [>](https://github.com/svg/svgo/tree/v0.1.8) ] 0.1.8 / 11.12.2012
+* new plugin [plugins/removeUselessStrokeAndFill](https://github.com/svg/svgo/blob/master/plugins/removeUselessStrokeAndFill.js) (close [#75](https://github.com/svg/svgo/issues/75))
+* new plugin [plugins/removeUnusedIDs](https://github.com/svg/svgo/blob/master/plugins/removeUnusedIDs.js) (close [#76](https://github.com/svg/svgo/issues/76))
+* plugins/convertPathData: wrong M interpretation in some cases (fix [#73](https://github.com/svg/svgo/issues/73))
+* plugins/cleanupAttrs: use `isElem()` API
+* `.travis.yml`: check all branches
+
+
+### [ [>](https://github.com/svg/svgo/tree/v0.1.7) ] 0.1.7 / 08.12.2012
+* plugins/convertPathData: incorrect interpretation of `z + m` (fix [#69](https://github.com/svg/svgo/issues/69))
+* plugins/convertTransform: do a more accurate floating numbers rounding in `matrixToTransform()` (fix [#68](https://github.com/svg/svgo/issues/68))
+
+### [ [>](https://github.com/svg/svgo/tree/v0.1.6) ] 0.1.6 / 07.12.2012
+* plugins/convertPathData: collapse repeated instructions only after curveSmoothShorthands (fix [#64](https://github.com/svg/svgo/issues/64))
+* lib/svgo/coa: handle 'there is nothing to optimize' case and display a message about it (fix [#61](https://github.com/svg/svgo/issues/61))
+* plugins/cleanupSVGElem: delete as useless artefact
+
+
+### [ [>](https://github.com/svg/svgo/tree/v0.1.5) ] 0.1.5 / 06.12.2012
+* E-notated numbers in paths not recognised (fix [#63](https://github.com/svg/svgo/issues/63))
+* update README with `svgo-grunt` and `svgo-osx-folder-action`
+* fix `mocha-as-promised` plug in node 0.6
+
+### [ [>](https://github.com/svg/svgo/tree/v0.1.4) ] 0.1.4 / 05.12.2012
+* plugins/_collections: more defaults
+* `README.ru.md`
+* `docs/how-it-works/ru.md`
+* mocha + mocha-as-promised + chai + chai-as-promised + should + istanbul = <3
+* update dependencies semvers in `package.json`
+* `v0.1.x` and `v0.2.x` milestones
+
+### [ [>](https://github.com/svg/svgo/tree/v0.1.3) ] 0.1.3 / 30.11.2012
+* new plugin [plugins/cleanupNumericValues](https://github.com/svg/svgo/blob/master/plugins/cleanupNumericValues.js) (close [#8](https://github.com/svg/svgo/issues/8))
+* plugins/removeDefaultPx functionality now included in plugins/removeUnknownsAndDefaults
+* plugins/removeUnknownsAndDefaults: refactoring and picking up the complete elems+attrs collection (close [#59](https://github.com/svg/svgo/issues/59))
+* plugins/convertTransform: error in matrices multiplication (fix [#58](https://github.com/svg/svgo/issues/58))
+* plugins/convertTransform: mark translate() and scale() as useless only with one param (fix [#57](https://github.com/svg/svgo/issues/57))
+* plugins/convertPathData: drastic speed improvement with huge Path data
+* plugins/convertPathData: fix the very first Mm with multiple points (fix [#56](https://github.com/svg/svgo/issues/56))
+* plugins/moveElemsAttrsToGroup: additional check for transform attr
+* brand-new project `logo.svg`
+* `.travis.yml`: build only master branch
+* global `'use strict'`
+* `.jshintignore`
+* README and CHANGELOG: minor corrections
+
+### [ [>](https://github.com/svg/svgo/tree/v0.1.2) ] 0.1.2 / 24.11.2012
+* lib/svgo/svg2js: correct 'onerror' failure (fix [#51](https://github.com/svg/svgo/issues/51))
+* config: disable sax-js position tracking by default (fix [#52](https://github.com/svg/svgo/issues/52))
+* lib/svgo: rename 'startBytes' to 'inBytes' and 'endBytes' to 'outBytes' (close [#53](https://github.com/svg/svgo/issues/53))
+* plugins/removeUnknownsAndDefaults: remove SVG id attr (close [#54](https://github.com/svg/svgo/issues/54))
+
+### [ [>](https://github.com/svg/svgo/tree/v0.1.1) ] 0.1.1 / 23.11.2012
+* plugins/moveElemsAttrsToGroup: fix inheitable only attrs array (fix [#47](https://github.com/svg/svgo/issues/47))
+* plugins/removeEmptyContainers: do not remove an empty 'svg' element (fix [#48](https://github.com/svg/svgo/issues/48))
+* plugins/removeDefaultPx: should also understand a floating-numbers too (fix [#49](https://github.com/svg/svgo/issues/49))
+* plugins/removeUnknownsAndDefaults: merge multiple groupDefaults attrs (close [#50](https://github.com/svg/svgo/issues/50))
+
+### [ [>](https://github.com/svg/svgo/tree/v0.1.0) ] 0.1.0 / 22.11.2012
+* new plugin [plugins/removeUnknownsAndDefaults](https://github.com/svg/svgo/blob/master/plugins/removeUnknownsAndDefaults.js) (close [#6](https://github.com/svg/svgo/issues/6))
+* plugins/convertPathData: convert straight curves into lines segments (close [#17](https://github.com/svg/svgo/issues/17)); remove an absolute coords conversions
+* plugins/convertPathData: convert quadratic Bézier curveto into smooth shorthand (close [#31](https://github.com/svg/svgo/issues/31))
+* plugins/convertPathData: convert curveto into smooth shorthand (close [#30](https://github.com/svg/svgo/issues/30))
+* lib/svgo: global API refactoring (close [#37](https://github.com/svg/svgo/issues/37))
+* lib/svgo: fatal and stupid error in stream chunks concatenation (fix [#40](https://github.com/svg/svgo/issues/40))
+* lib/coa: batch folder optimization (close [#29](https://github.com/svg/svgo/issues/29))
+* lib/coa: support arguments as aliases to `--input` and `--output` (close [#28](https://github.com/svg/svgo/issues/28))
+* project logo by [Egor Bolhshakov](http://xizzzy.ru/)
+* move modules to `./lib/svgo/`
+* rename and convert `config.json` to `.svgo.yml`
+* add [./docs/](https://github.com/svg/svgo/tree/master/docs)
+* plugins/convertPathData: don't remove first `M` even if it's `0,0`
+* plugins/convertPathData: stronger defense from infinite loop
+* plugins/moveElemsAttrsToGroup: should affect only inheritable attributes (fix [#46](https://github.com/svg/svgo/issues/46))*
+* plugins/removeComments: ignore comments which starts with '!' (close [#43](https://github.com/svg/svgo/issues/43))
+* config: `cleanupAttrs` should be before `convertStyleToAttrs` (fix [#44](https://github.com/svg/svgo/issues/44))*
+* lib/svgo/jsAPI: add `eachAttr()` optional context param
+* temporarily remove PhantomJS and `--test` (close [#38](https://github.com/svg/svgo/issues/38))
+* q@0.8.10 compatibility: 'end is deprecated, use done instead' fix
+* add [Istanbul](https://github.com/gotwarlost/istanbul) code coverage
+* update dependencies versions and gitignore
+* README: add TODO section with versions milestones
+* update README with License section
+* update LICENSE with russian translation
+* `.editorconfig`: 2 spaces for YAML
+
+### [ [>](https://github.com/svg/svgo/tree/v0.0.9) ] 0.0.9 / 29.10.2012
+* [plugins how-to](https://github.com/svg/svgo/tree/master/plugins#readme) (close [#27](https://github.com/svg/svgo/issues/27))
+* allow any plugin of any type to go in any order (close [#14](https://github.com/svg/svgo/issues/14))
+* allow to do a multiple optimizations with one init (close [#25](https://github.com/svg/svgo/issues/25))
+* plugins/convertPathData: global refactoring
+* plugins/convertPathData: do all the tricks with absolute coords too (fix [#22](https://github.com/svg/svgo/issues/22))
+* plugins/convertPathData: accumulation of rounding errors (fix [#23](https://github.com/svg/svgo/issues/23))
+* plugins/convertPathData: prevent an infinity loop on invalid path data (fix [#26](https://github.com/svg/svgo/issues/26))
+* plugins/convertPathData: do not remove very first M from the path data (fix [#24](https://github.com/svg/svgo/issues/24))
+* plugins/convertPathData: optimize path data in &lt;glyph&gt; and &lt;missing-glyph&gt; (close [#20](https://github.com/svg/svgo/issues/20))
+* plugins/convertTransform: add patternTransform attribute to the process (close [#15](https://github.com/svg/svgo/issues/15))
+* plugins/convertTransform: Firefox: removing extra space in front of negative number is alowed only in path data, but not in transform (fix [#12](https://github.com/svg/svgo/issues/12))
+* plugins/removeXMLProcInst: remove only 'xml' but not 'xml-stylesheet' (fix [#21](https://github.com/svg/svgo/issues/15))
+* plugins/collapseGroups: merge split-level transforms (fix [#13](https://github.com/svg/svgo/issues/13))
+* jsdoc corrections
+
+### [ [>](https://github.com/svg/svgo/tree/v0.0.8) ] 0.0.8 / 20.10.2012
+* new plugin [convertTransform](plugins/convertTransform.js) (close [#5](https://github.com/svg/svgo/issues/5))
+* new plugin [removeUnusedNS](plugins/removeUnusedNS.js)
+* plugins/convertPathData: remove useless segments
+* plugins/convertPathData: a lot of refactoring
+* plugins/convertPathData: round numbers before conditions because of exponential notation (fix [#3](https://github.com/svg/svgo/issues/3))
+* plugins/moveElemsAttrsToGroup: merge split-level transforms instead of replacing (fix [#10](https://github.com/svg/svgo/issues/10))
+* lib/svg2js: catch and output xml parser errors (fix [#4](https://github.com/svg/svgo/issues/4))
+* lib/coa: open file for writing only when we are ready (fix [#2](https://github.com/svg/svgo/issues/2))
+* lib/tools: node.extend module
+* lib/plugins: refactoring
+* lib/js2svg: refactoring
+* lib/jsAPI: simplification and refactoring
+* absolute urls in README
+* update .editorconfig
+* update .travis.yml with nodejs 0.9
+
+### [ [>](https://github.com/svg/svgo/tree/v0.0.7) ] 0.0.7 / 14.10.2012
+* new plugin [convertPathData](plugins/convertPathData.js)
+* --input data now can be a Data URI base64 string
+* --output data now can be a Data URI base64 string with --datauri flag
+* Travis CI
+* JSHint corrections + .jshintrc
+* [.editorconfig](http://editorconfig.org/)
+* display time spent on optimization
+* .svgo → config.json
+* lib/phantom_wrapper.js → lib/phantom.js
+
+### [ [>](https://github.com/svg/svgo/tree/v0.0.6) ] 0.0.6 / 04.10.2012
+* add --test option to make a visual comparison of two files (PhantomJS pre-required)
+* update README and CHANGELOG with the correct relative urls
+
+### [ [>](https://github.com/svg/svgo/tree/v0.0.5) ] 0.0.5 / 03.10.2012
+* every plugin now has [at least one test](plugins)
+* removeViewBox, cleanupEnableBackground, removeEditorsNSData, convertStyleToAttrs and collapseGroups plugins fixes
+* new --pretty option for the pretty printed SVG
+* lib/config refactoring
+
+### [ [>](https://github.com/svg/svgo/tree/v0.0.4) ] 0.0.4 / 30.09.2012
+* new plugin [removeViewBox](plugins/removeViewBox.js)
+* new plugin [cleanupEnableBackground](plugins/cleanupEnableBackground.js)
+* display useful info after successful optimization
+* 'npm test' with 'spec' mocha output by default
+
+### [ [>](https://github.com/svg/svgo/tree/v0.0.3) ] 0.0.3 / 29.09.2012
+* plugins/collapseGroups bugfix
+* plugins/moveElemsAttrsToGroup bugfix
+* svgo now display --help if running w/o arguments
+* massive jsdoc updates
+* plugins engine main filter function optimization
+
+### [ [>](https://github.com/svg/svgo/tree/v0.0.2) ] 0.0.2 / 28.09.2012
+* add --disable and --enable command line options
+* add an empty values rejecting to coa.js
+* update README
+
+### [ [>](https://github.com/svg/svgo/tree/v0.0.1) ] 0.0.1 / 27.09.2012
+* initial public version
diff --git a/node_modules/svgo/LICENSE b/node_modules/svgo/LICENSE
new file mode 100644
index 00000000..cd8d5003
--- /dev/null
+++ b/node_modules/svgo/LICENSE
@@ -0,0 +1,55 @@
+The MIT License
+
+Copyright © 2012–2016 Kir Belevich
+
+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.
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+Лицензия MIT
+
+Copyright © 2012–2016 Кир Белевич
+
+Данная лицензия разрешает лицам, получившим копию данного
+программного обеспечения и сопутствующей документации
+(в дальнейшем именуемыми «Программное Обеспечение»), безвозмездно
+использовать Программное Обеспечение без ограничений, включая
+неограниченное право на использование, копирование, изменение,
+добавление, публикацию, распространение, сублицензирование
+и/или продажу копий Программного Обеспечения, также как и лицам,
+которым предоставляется данное Программное Обеспечение,
+при соблюдении следующих условий:
+
+Указанное выше уведомление об авторском праве и данные условия
+должны быть включены во все копии или значимые части данного
+Программного Обеспечения.
+
+ДАННОЕ ПРОГРАММНОЕ ОБЕСПЕЧЕНИЕ ПРЕДОСТАВЛЯЕТСЯ «КАК ЕСТЬ»,
+БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ, ЯВНО ВЫРАЖЕННЫХ ИЛИ ПОДРАЗУМЕВАЕМЫХ,
+ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИВАЯСЬ ГАРАНТИЯМИ ТОВАРНОЙ ПРИГОДНОСТИ,
+СООТВЕТСТВИЯ ПО ЕГО КОНКРЕТНОМУ НАЗНАЧЕНИЮ И ОТСУТСТВИЯ НАРУШЕНИЙ
+ПРАВ. НИ В КАКОМ СЛУЧАЕ АВТОРЫ ИЛИ ПРАВООБЛАДАТЕЛИ НЕ НЕСУТ
+ОТВЕТСТВЕННОСТИ ПО ИСКАМ О ВОЗМЕЩЕНИИ УЩЕРБА, УБЫТКОВ ИЛИ ДРУГИХ
+ТРЕБОВАНИЙ ПО ДЕЙСТВУЮЩИМ КОНТРАКТАМ, ДЕЛИКТАМ ИЛИ ИНОМУ,
+ВОЗНИКШИМ ИЗ, ИМЕЮЩИМ ПРИЧИНОЙ ИЛИ СВЯЗАННЫМ С ПРОГРАММНЫМ
+ОБЕСПЕЧЕНИЕМ ИЛИ ИСПОЛЬЗОВАНИЕМ ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ
+ИЛИ ИНЫМИ ДЕЙСТВИЯМИ С ПРОГРАММНЫМ ОБЕСПЕЧЕНИЕМ.
diff --git a/node_modules/svgo/Makefile b/node_modules/svgo/Makefile
new file mode 100644
index 00000000..c11daab9
--- /dev/null
+++ b/node_modules/svgo/Makefile
@@ -0,0 +1,21 @@
+test:
+ @npm run test
+
+lib-cov:
+ @./node_modules/.bin/istanbul instrument --output lib-cov --no-compact --variable global.__coverage__ lib
+
+coverage: lib-cov
+ @COVERAGE=1 ISTANBUL_REPORTERS=text-summary ./node_modules/.bin/mocha --reporter mocha-istanbul
+ @rm -rf lib-cov
+
+coveralls: lib-cov
+ @COVERAGE=1 ISTANBUL_REPORTERS=lcovonly ./node_modules/.bin/mocha --reporter mocha-istanbul
+ @cat lcov.info | ./node_modules/.bin/coveralls
+ @rm -rf lib-cov lcov.info
+
+travis: jshint test coveralls
+
+jshint:
+ @npm run jshint
+
+.PHONY: test
diff --git a/node_modules/svgo/README.md b/node_modules/svgo/README.md
new file mode 100644
index 00000000..c77c6812
--- /dev/null
+++ b/node_modules/svgo/README.md
@@ -0,0 +1,155 @@
+**english** | [русский](https://github.com/svg/svgo/blob/master/README.ru.md)
+- - -
+
+<img src="https://svg.github.io/svgo-logo.svg" width="200" height="200" alt="logo"/>
+
+## SVGO [![NPM version](https://badge.fury.io/js/svgo.svg)](https://npmjs.org/package/svgo) [![Dependency Status](https://gemnasium.com/svg/svgo.svg)](https://gemnasium.com/svg/svgo) [![Build Status](https://secure.travis-ci.org/svg/svgo.svg)](https://travis-ci.org/svg/svgo) [![Coverage Status](https://img.shields.io/coveralls/svg/svgo.svg)](https://coveralls.io/r/svg/svgo?branch=master)
+
+**SVG O**ptimizer is a Nodejs-based tool for optimizing SVG vector graphics files.
+![](https://mc.yandex.ru/watch/18431326)
+
+## Why?
+
+SVG files, especially exported from various editors, usually contain a lot of redundant and useless information such as editor metadata, comments, hidden elements, default or non-optimal values and other stuff that can be safely removed or converted without affecting SVG rendering result.
+
+## What it can do
+
+SVGO has a plugin-based architecture, so almost every optimization is a separate plugin.
+
+Today we have:
+
+| Plugin | Description |
+| ------ | ----------- |
+| [cleanupAttrs](https://github.com/svg/svgo/blob/master/plugins/cleanupAttrs.js) | cleanup attributes from newlines, trailing, and repeating spaces |
+| [removeDoctype](https://github.com/svg/svgo/blob/master/plugins/removeDoctype.js) | remove doctype declaration |
+| [removeXMLProcInst](https://github.com/svg/svgo/blob/master/plugins/removeXMLProcInst.js) | remove XML processing instructions |
+| [removeComments](https://github.com/svg/svgo/blob/master/plugins/removeComments.js) | remove comments |
+| [removeMetadata](https://github.com/svg/svgo/blob/master/plugins/removeMetadata.js) | remove `<metadata>` |
+| [removeTitle](https://github.com/svg/svgo/blob/master/plugins/removeTitle.js) | remove `<title>` (disabled by default) |
+| [removeDesc](https://github.com/svg/svgo/blob/master/plugins/removeDesc.js) | remove `<desc>` (only non-meaningful by default) |
+| [removeUselessDefs](https://github.com/svg/svgo/blob/master/plugins/removeUselessDefs.js) | remove elements of `<defs>` without `id` |
+| [removeXMLNS](https://github.com/svg/svgo/blob/master/plugins/removeXMLNS.js) | removes `xmlns` attribute (for inline svg, disabled by default) |
+| [removeEditorsNSData](https://github.com/svg/svgo/blob/master/plugins/removeEditorsNSData.js) | remove editors namespaces, elements, and attributes |
+| [removeEmptyAttrs](https://github.com/svg/svgo/blob/master/plugins/removeEmptyAttrs.js) | remove empty attributes |
+| [removeHiddenElems](https://github.com/svg/svgo/blob/master/plugins/removeHiddenElems.js) | remove hidden elements |
+| [removeEmptyText](https://github.com/svg/svgo/blob/master/plugins/removeEmptyText.js) | remove empty Text elements |
+| [removeEmptyContainers](https://github.com/svg/svgo/blob/master/plugins/removeEmptyContainers.js) | remove empty Container elements |
+| [removeViewBox](https://github.com/svg/svgo/blob/master/plugins/removeViewBox.js) | remove `viewBox` attribute when possible (disabled by default) |
+| [cleanupEnableBackground](https://github.com/svg/svgo/blob/master/plugins/cleanupEnableBackground.js) | remove or cleanup `enable-background` attribute when possible |
+| [minifyStyles](https://github.com/svg/svgo/blob/master/plugins/minifyStyles.js) | minify `<style>` elements content with [CSSO](https://github.com/css/csso) |
+| [convertStyleToAttrs](https://github.com/svg/svgo/blob/master/plugins/convertStyleToAttrs.js) | convert styles into attributes |
+| [convertColors](https://github.com/svg/svgo/blob/master/plugins/convertColors.js) | convert colors (from `rgb()` to `#rrggbb`, from `#rrggbb` to `#rgb`) |
+| [convertPathData](https://github.com/svg/svgo/blob/master/plugins/convertPathData.js) | convert Path data to relative or absolute (whichever is shorter), convert one segment to another, trim useless delimiters, smart rounding, and much more |
+| [convertTransform](https://github.com/svg/svgo/blob/master/plugins/convertTransform.js) | collapse multiple transforms into one, convert matrices to the short aliases, and much more |
+| [removeUnknownsAndDefaults](https://github.com/svg/svgo/blob/master/plugins/removeUnknownsAndDefaults.js) | remove unknown elements content and attributes, remove attrs with default values |
+| [removeNonInheritableGroupAttrs](https://github.com/svg/svgo/blob/master/plugins/removeNonInheritableGroupAttrs.js) | remove non-inheritable group's "presentation" attributes |
+| [removeUselessStrokeAndFill](https://github.com/svg/svgo/blob/master/plugins/removeUselessStrokeAndFill.js) | remove useless `stroke` and `fill` attrs |
+| [removeUnusedNS](https://github.com/svg/svgo/blob/master/plugins/removeUnusedNS.js) | remove unused namespaces declaration |
+| [cleanupIDs](https://github.com/svg/svgo/blob/master/plugins/cleanupIDs.js) | remove unused and minify used IDs |
+| [cleanupNumericValues](https://github.com/svg/svgo/blob/master/plugins/cleanupNumericValues.js) | round numeric values to the fixed precision, remove default `px` units |
+| [cleanupListOfValues](https://github.com/svg/svgo/blob/master/plugins/cleanupListOfValues.js) | round numeric values in attributes that take a list of numbers (like `viewBox` or `enableBackground`) |
+| [moveElemsAttrsToGroup](https://github.com/svg/svgo/blob/master/plugins/moveElemsAttrsToGroup.js) | move elements' attributes to their enclosing group |
+| [moveGroupAttrsToElems](https://github.com/svg/svgo/blob/master/plugins/moveGroupAttrsToElems.js) | move some group attributes to the contained elements |
+| [collapseGroups](https://github.com/svg/svgo/blob/master/plugins/collapseGroups.js) | collapse useless groups |
+| [removeRasterImages](https://github.com/svg/svgo/blob/master/plugins/removeRasterImages.js) | remove raster images (disabled by default) |
+| [mergePaths](https://github.com/svg/svgo/blob/master/plugins/mergePaths.js) | merge multiple Paths into one |
+| [convertShapeToPath](https://github.com/svg/svgo/blob/master/plugins/convertShapeToPath.js) | convert some basic shapes to `<path>` |
+| [sortAttrs](https://github.com/svg/svgo/blob/master/plugins/sortAttrs.js) | sort element attributes for epic readability (disabled by default) |
+| [transformsWithOnePath](https://github.com/svg/svgo/blob/master/plugins/transformsWithOnePath.js) | apply transforms, crop by real width, center vertical alignment, and resize SVG with one Path inside (disabled by default) |
+| [removeDimensions](https://github.com/svg/svgo/blob/master/plugins/removeDimensions.js) | remove `width`/`height` attributes if `viewBox` is present (disabled by default) |
+| [removeAttrs](https://github.com/svg/svgo/blob/master/plugins/removeAttrs.js) | remove attributes by pattern (disabled by default) |
+| [removeElementsByAttr](https://github.com/svg/svgo/blob/master/plugins/removeElementsByAttr.js) | remove arbitrary elements by ID or className (disabled by default) |
+| [addClassesToSVGElement](https://github.com/svg/svgo/blob/master/plugins/addClassesToSVGElement.js) | add classnames to an outer `<svg>` element (disabled by default) |
+| [addAttributesToSVGElement](https://github.com/svg/svgo/blob/master/plugins/addAttributesToSVGElement.js) | adds attributes to an outer `<svg>` element (disabled by default) |
+| [removeStyleElement](https://github.com/svg/svgo/blob/master/plugins/removeStyleElement.js) | remove `<style>` elements (disabled by default) |
+
+Want to know how it works and how to write your own plugin? [Of course you want to](https://github.com/svg/svgo/blob/master/docs/how-it-works/en.md). ([동작방법](https://github.com/svg/svgo/blob/master/docs/how-it-works/ko.md))
+
+
+## How to use
+
+```sh
+$ [sudo] npm install -g svgo
+```
+
+```
+Usage:
+ svgo [OPTIONS] [ARGS]
+
+Options:
+ -h, --help : Help
+ -v, --version : Version
+ -i INPUT, --input=INPUT : Input file, "-" for STDIN
+ -s STRING, --string=STRING : Input SVG data string
+ -f FOLDER, --folder=FOLDER : Input folder, optimize and rewrite all *.svg files
+ -o OUTPUT, --output=OUTPUT : Output file or folder (by default the same as the input), "-" for STDOUT
+ -p PRECISION, --precision=PRECISION : Set number of digits in the fractional part, overrides plugins params
+ --config=CONFIG : Config file or JSON string to extend or replace default
+ --disable=DISABLE : Disable plugin by name
+ --enable=ENABLE : Enable plugin by name
+ --datauri=DATAURI : Output as Data URI string (base64, URI encoded or unencoded)
+ --multipass : Enable multipass
+ --pretty : Make SVG pretty printed
+ --indent=INDENT : Indent number when pretty printing SVGs
+ -q, --quiet : Only output error messages, not regular status messages
+ --show-plugins : Show available plugins and exit
+
+Arguments:
+ INPUT : Alias to --input
+ OUTPUT : Alias to --output
+```
+
+* with files:
+
+ $ svgo test.svg
+
+ or:
+
+ $ svgo test.svg test.min.svg
+
+* with STDIN / STDOUT:
+
+ $ cat test.svg | svgo -i - -o - > test.min.svg
+
+* with folder
+
+ $ svgo -f ../path/to/folder/with/svg/files
+
+ or:
+
+ $ svgo -f ../path/to/folder/with/svg/files -o ../path/to/folder/with/svg/output
+
+* with strings:
+
+ $ svgo -s '<svg version="1.1">test</svg>' -o test.min.svg
+
+ or even with Data URI base64:
+
+ $ svgo -s 'data:image/svg+xml;base64,…' -o test.min.svg
+
+* with SVGZ:
+
+ from `.svgz` to `.svg`:
+
+ $ gunzip -c test.svgz | svgo -i - -o test.min.svg
+
+ from `.svg` to `.svgz`:
+
+ $ svgo test.svg -o - | gzip -cfq9 > test.svgz
+
+* with GUI – [svgo-gui](https://github.com/svg/svgo-gui)
+* as a web app - [SVGOMG](https://jakearchibald.github.io/svgomg/)
+* as a Nodejs module – [examples](https://github.com/svg/svgo/tree/master/examples)
+* as a Grunt task – [grunt-svgmin](https://github.com/sindresorhus/grunt-svgmin)
+* as a Gulp task – [gulp-svgmin](https://github.com/ben-eb/gulp-svgmin)
+* as a Mimosa module – [mimosa-minify-svg](https://github.com/dbashford/mimosa-minify-svg)
+* as an OSX Folder Action – [svgo-osx-folder-action](https://github.com/svg/svgo-osx-folder-action)
+* as a webpack loader – [image-webpack-loader](https://github.com/tcoopman/image-webpack-loader)
+* as a Telegram Bot – [svgo_bot](https://github.com/maksugr/svgo_bot)
+* as a PostCSS plugin - [postcss-svgo](https://github.com/ben-eb/postcss-svgo)
+
+## License and copyrights
+
+This software is released under the terms of the [MIT license](https://github.com/svg/svgo/blob/master/LICENSE).
+
+Logo by [Yegor Bolshakov](http://xizzzy.ru/).
diff --git a/node_modules/svgo/README.ru.md b/node_modules/svgo/README.ru.md
new file mode 100644
index 00000000..ef236f38
--- /dev/null
+++ b/node_modules/svgo/README.ru.md
@@ -0,0 +1,155 @@
+[english](https://github.com/svg/svgo/blob/master/README.md) | **русский**
+- - -
+
+<img src="https://svg.github.io/svgo-logo.svg" width="200" height="200" alt="logo"/>
+
+## SVGO [![NPM version](https://badge.fury.io/js/svgo.svg)](https://npmjs.org/package/svgo) [![Dependency Status](https://gemnasium.com/svg/svgo.svg)](https://gemnasium.com/svg/svgo) [![Build Status](https://secure.travis-ci.org/svg/svgo.svg)](https://travis-ci.org/svg/svgo) [![Coverage Status](https://img.shields.io/coveralls/svg/svgo.svg)](https://coveralls.io/r/svg/svgo?branch=master)
+
+**SVG** **O**ptimizer – это инструмент для оптимизации векторной графики в формате SVG, написанный на Node.js.
+![](https://mc.yandex.ru/watch/18431326)
+
+## Зачем?
+
+SVG-файлы, особенно – экспортированные из различных редакторов, содержат много избыточной и бесполезной информации, комментариев, скрытых элементов, неоптимальные или стандартные значения и другой мусор, удаление которого безопасно и не влияет на конечный результат отрисовки.
+
+## Возможности
+
+SVGO имеет расширяемую архитектуру, в которой почти каждая оптимизация является отдельным расширением.
+
+Сегодня у нас есть:
+
+| Plugin | Description |
+| ------ | ----------- |
+| [cleanupAttrs](https://github.com/svg/svgo/blob/master/plugins/cleanupAttrs.js) | удаление переносов строк и лишних пробелов |
+| [removeDoctype](https://github.com/svg/svgo/blob/master/plugins/removeDoctype.js) | удаление doctype |
+| [removeXMLProcInst](https://github.com/svg/svgo/blob/master/plugins/removeXMLProcInst.js) | удаление XML-инструкций |
+| [removeComments](https://github.com/svg/svgo/blob/master/plugins/removeComments.js) | удаление комментариев |
+| [removeMetadata](https://github.com/svg/svgo/blob/master/plugins/removeMetadata.js) | удаление `<metadata>` |
+| [removeTitle](https://github.com/svg/svgo/blob/master/plugins/removeTitle.js) | удаление `<title>` (выключено по умолчанию) |
+| [removeDesc](https://github.com/svg/svgo/blob/master/plugins/removeDesc.js) | удаление `<desc>` (по умолчанию только незначимых) |
+| [removeUselessDefs](https://github.com/svg/svgo/blob/master/plugins/removeUselessDefs.js) | удаление элементов в `<defs>` без `id` |
+| [removeXMLNS](https://github.com/svg/svgo/blob/master/plugins/removeXMLNS.js) | удаление атрибута xmlns (для заинлайненных svg, выключено по умолчанию) |
+| [removeEditorsNSData](https://github.com/svg/svgo/blob/master/plugins/removeEditorsNSData.js) | удаление пространств имён различных редакторов, их элементов и атрибутов |
+| [removeEmptyAttrs](https://github.com/svg/svgo/blob/master/plugins/removeEmptyAttrs.js) | удаление пустых атрибутов |
+| [removeHiddenElems](https://github.com/svg/svgo/blob/master/plugins/removeHiddenElems.js) | удаление скрытых элементов |
+| [removeEmptyText](https://github.com/svg/svgo/blob/master/plugins/removeEmptyText.js) | удаление пустых текстовых элементов |
+| [removeEmptyContainers](https://github.com/svg/svgo/blob/master/plugins/removeEmptyContainers.js) | удаление пустых элементов-контейнеров |
+| [removeViewBox](https://github.com/svg/svgo/blob/master/plugins/removeViewBox.js) | удаление атрибута `viewBox`, когда это возможно |
+| [cleanupEnableBackground](https://github.com/svg/svgo/blob/master/plugins/cleanupEnableBackground.js) | удаление или оптимизация атрибута `enable-background`, когда это возможно |
+| [minifyStyles](https://github.com/svg/svgo/blob/master/plugins/minifyStyles.js) | уменьшает содержимое элементов `<style>` с помощью [CSSO](https://github.com/css/csso). |
+| [convertStyleToAttrs](https://github.com/svg/svgo/blob/master/plugins/convertStyleToAttrs.js) | конвертирование стилей в атрибуте `style` в отдельные svg-атрибуты |
+| [convertColors](https://github.com/svg/svgo/blob/master/plugins/convertColors.js) | конвертирование цветовых значений: из `rgb()` в `#rrggbb`, из `#rrggbb` в `#rgb` |
+| [convertPathData](https://github.com/svg/svgo/blob/master/plugins/convertPathData.js) | конвертирование данных Path в относительные или абсолютные координаты, смотря что |короче; конвертирование одних типов сегментов в другие; удаление ненужных разделителей; умное округление и тому подобное
+| [convertTransform](https://github.com/svg/svgo/blob/master/plugins/convertTransform.js) | схлопывание нескольких трансформаций в одну, конвертирование матриц в короткие алиасы |и многое другое
+| [removeUnknownsAndDefaults](https://github.com/svg/svgo/blob/master/plugins/removeUnknownsAndDefaults.js) | удаление неизвестных элементов, контента и атрибутов |
+| [removeNonInheritableGroupAttrs](https://github.com/svg/svgo/blob/master/plugins/removeNonInheritableGroupAttrs.js) | удаление ненаследуемых "презентационных" атрибутов групп |
+| [removeUselessStrokeAndFill](https://github.com/svg/svgo/blob/master/plugins/removeUselessStrokeAndFill.js) | удаление неиспользуемых атрибутов stroke-* и fill-* |
+| [removeUnusedNS](https://github.com/svg/svgo/blob/master/plugins/removeUnusedNS.js) | удаление деклараций неиспользуемых пространств имён |
+| [cleanupIDs](https://github.com/svg/svgo/blob/master/plugins/cleanupIDs.js) | удаление неиспользуемых и сокращение используемых ID |
+| [cleanupNumericValues](https://github.com/svg/svgo/blob/master/plugins/cleanupNumericValues.js) | округление дробных чисел до заданной точности, удаление `px` как единицы |измерения по-умолчанию
+| [cleanupListOfValues](https://github.com/svg/svgo/blob/master/plugins/cleanupListOfValues.js) | округление числовых значений в атрибутах со списком чисел, таких как `viewBox` |или `enableBackground`
+| [moveElemsAttrsToGroup](https://github.com/svg/svgo/blob/master/plugins/moveElemsAttrsToGroup.js) | перемещение совпадающих атрибутов у всех элементов внутри группы `<g>` |
+| [moveGroupAttrsToElems](https://github.com/svg/svgo/blob/master/plugins/moveGroupAttrsToElems.js) | перемещение некоторых атрибутов группы на элементы внутри |
+| [collapseGroups](https://github.com/svg/svgo/blob/master/plugins/collapseGroups.js) | схлопывание бесполезных групп `<g>` |
+| [removeRasterImage](https://github.com/svg/svgo/blob/master/plugins/removeRasterImages.js) | удаление растровых изображений (выключено по умолчанию) |
+| [mergePaths](https://github.com/svg/svgo/blob/master/plugins/mergePaths.js) | склеивание нескольких Path в одну кривую |
+| [convertShapeToPath](https://github.com/svg/svgo/blob/master/plugins/convertShapeToPath.js) | конвертирование простых форм в Path |
+| [sortAttrs](https://github.com/svg/svgo/blob/master/plugins/sortAttrs.js) | сортировка атрибутов элементов для удобочитаемости (выключено по умолчанию) |
+| [transformsWithOnePath](https://github.com/svg/svgo/blob/master/plugins/transformsWithOnePath.js) | применение трансформаций, обрезка по реальной ширине, вертикальное |выравнивание по центру и изменение размеров SVG с одним Path внутри
+| [removeDimensions](https://github.com/svg/svgo/blob/master/plugins/removeDimensions.js) | удаляет атрибуты width/height при наличии viewBox (выключено по умолчанию) |
+| [removeAttrs](https://github.com/svg/svgo/blob/master/plugins/removeAttrs.js) | удаляет атрибуты по указанному паттерну (выключено по умолчанию) |
+| [removeElementsByAttr](https://github.com/svg/svgo/blob/master/plugins/removeElementsByAttr.js) | удаляет элементы по указанным ID или классам (выключено по умолчанию) |
+| [addClassesToSVGElement](https://github.com/svg/svgo/blob/master/plugins/addClassesToSVGElement.js) | добавляет имена классов корневому элементу `<svg>` (выключено по умолчанию) |
+| [addAttributesToSVGElement](https://github.com/svg/svgo/blob/master/plugins/addAttributesToSVGElement.js) | добавляет атрибуты корневому элементу `<svg>` (выключено |по умолчанию)
+| [removeStyleElement](https://github.com/svg/svgo/blob/master/plugins/removeStyleElement.js) | удаляет элементы `<style>` (выключено по умолчанию) |
+
+Хотите узнать, как это работает и как написать свой плагин? [Конечно же, да!](https://github.com/svg/svgo/blob/master/docs/how-it-works/ru.md).
+
+
+## Как использовать
+
+```sh
+$ [sudo] npm install -g svgo
+```
+
+```
+Выполнение:
+ svgo [OPTIONS] [ARGS]
+
+Параметры:
+ -h, --help : Помощь
+ -v, --version : Версия программы
+ -i INPUT, --input=INPUT : Входной файл, "-" для STDIN
+ -s STRING, --string=STRING : Входная строка SVG
+ -f FOLDER, --folder=FOLDER : Входная папка, оптимизирует и перезаписывает все файлы *.svg
+ -o OUTPUT, --output=OUTPUT : Выходной файл или папка (совпадает с входным по умолчанию), "-" для STDOUT
+ -p PRECISION, --precision=PRECISION : Число цифр после запятой, переопределяет параметры плагинов
+ --config=CONFIG : Файл конфигурации (или строка JSON) для расширения и замены настроек
+ --disable=DISABLE : Выключение плагина по имени
+ --enable=ENABLE : Включение плагина по имени
+ --datauri=DATAURI : Результат в виде строки Data URI (base64, URI encoded или unencoded)
+ --multipass : Оптимизация в несколько проходов
+ --pretty : Удобочитаемое форматирование SVG
+ --indent=INDENT : Размер отступа для удобочитаемого форматирования
+ -q, --quiet : Подавляет вывод информации, выводятся только сообщения об ошибках
+ --show-plugins : Доступные плагины
+
+Аргументы:
+ INPUT : Аналогично --input
+ OUTPUT : Аналогично --output
+```
+
+* с файлами:
+
+ $ svgo test.svg
+
+ или:
+
+ $ svgo test.svg test.min.svg
+
+* со STDIN / STDOUT:
+
+ $ cat test.svg | svgo -i - -o - > test.min.svg
+
+* с папками
+
+ $ svgo -f ../path/to/folder/with/svg/files
+
+ или:
+
+ $ svgo -f ../path/to/folder/with/svg/files -o ../path/to/folder/with/svg/output
+
+* со строками:
+
+ $ svgo -s '<svg version="1.1">test</svg>' -o test.min.svg
+
+ или даже с Data URI base64:
+
+ $ svgo -s 'data:image/svg+xml;base64,…' -o test.min.svg
+
+* с SVGZ:
+
+ из `.svgz` в `.svg`:
+
+ $ gunzip -c test.svgz | svgo -i - -o test.min.svg
+
+ из `.svg` в `.svgz`:
+
+ $ svgo test.svg -o - | gzip -cfq9 > test.svgz
+
+* с помощью GUI – [svgo-gui](https://github.com/svg/svgo-gui)
+* в виде веб-приложения - [SVGOMG](https://jakearchibald.github.io/svgomg/)
+* как модуль Node.js – [examples](https://github.com/svg/svgo/tree/master/examples)
+* как таск для Grunt – [grunt-svgmin](https://github.com/sindresorhus/grunt-svgmin)
+* как таск для Gulp – [gulp-svgmin](https://github.com/ben-eb/gulp-svgmin)
+* как таск для Mimosa – [mimosa-minify-svg](https://github.com/dbashford/mimosa-minify-svg)
+* как действие папки в OSX – [svgo-osx-folder-action](https://github.com/svg/svgo-osx-folder-action)
+* через загрузчик в webpack – [image-webpack-loader](https://github.com/tcoopman/image-webpack-loader)
+* с помощью бота в Telegram – [svgo_bot](https://github.com/maksugr/svgo_bot)
+* как плагин PostCSS - [postcss-svgo](https://github.com/ben-eb/postcss-svgo)
+
+## Лицензия и копирайты
+
+Данное программное обеспечение выпускается под [лицензией MIT](https://github.com/svg/svgo/blob/master/LICENSE).
+
+Логотип – [Егор Большаков](http://xizzzy.ru/).
diff --git a/node_modules/svgo/bin/svgo b/node_modules/svgo/bin/svgo
new file mode 100755
index 00000000..2fd77c02
--- /dev/null
+++ b/node_modules/svgo/bin/svgo
@@ -0,0 +1,3 @@
+#!/usr/bin/env node
+
+require('../lib/svgo/coa').run();
diff --git a/node_modules/svgo/lib/svgo.js b/node_modules/svgo/lib/svgo.js
new file mode 100644
index 00000000..c593023f
--- /dev/null
+++ b/node_modules/svgo/lib/svgo.js
@@ -0,0 +1,80 @@
+'use strict';
+
+/**
+ * SVGO is a Nodejs-based tool for optimizing SVG vector graphics files.
+ *
+ * @see https://github.com/svg/svgo
+ *
+ * @author Kir Belevich <kir@soulshine.in> (https://github.com/deepsweet)
+ * @copyright © 2012 Kir Belevich
+ * @license MIT https://raw.githubusercontent.com/svg/svgo/master/LICENSE
+ */
+
+var CONFIG = require('./svgo/config.js'),
+ SVG2JS = require('./svgo/svg2js.js'),
+ PLUGINS = require('./svgo/plugins.js'),
+ JSAPI = require('./svgo/jsAPI.js'),
+ JS2SVG = require('./svgo/js2svg.js');
+
+var SVGO = module.exports = function(config) {
+
+ this.config = CONFIG(config);
+
+};
+
+SVGO.prototype.optimize = function(svgstr, callback) {
+ if (this.config.error) return callback(this.config);
+
+ var _this = this,
+ config = this.config,
+ maxPassCount = config.multipass ? 10 : 1,
+ counter = 0,
+ prevResultSize = Number.POSITIVE_INFINITY,
+ optimizeOnceCallback = function(svgjs) {
+
+ if (svgjs.error) {
+ callback(svgjs);
+ return;
+ }
+
+ if (++counter < maxPassCount && svgjs.data.length < prevResultSize) {
+ prevResultSize = svgjs.data.length;
+ _this._optimizeOnce(svgjs.data, optimizeOnceCallback);
+ } else {
+ callback(svgjs);
+ }
+
+ };
+
+ _this._optimizeOnce(svgstr, optimizeOnceCallback);
+
+};
+
+SVGO.prototype._optimizeOnce = function(svgstr, callback) {
+ var config = this.config;
+
+ SVG2JS(svgstr, function(svgjs) {
+
+ if (svgjs.error) {
+ callback(svgjs);
+ return;
+ }
+
+ svgjs = PLUGINS(svgjs, config.plugins);
+
+ callback(JS2SVG(svgjs, config.js2svg));
+
+ });
+};
+
+/**
+ * The factory that creates a content item with the helper methods.
+ *
+ * @param {Object} data which passed to jsAPI constructor
+ * @returns {JSAPI} content item
+ */
+SVGO.prototype.createContentItem = function(data) {
+
+ return new JSAPI(data);
+
+};
diff --git a/node_modules/svgo/lib/svgo/coa.js b/node_modules/svgo/lib/svgo/coa.js
new file mode 100644
index 00000000..6b482231
--- /dev/null
+++ b/node_modules/svgo/lib/svgo/coa.js
@@ -0,0 +1,581 @@
+/* jshint quotmark: false */
+'use strict';
+
+require('colors');
+
+var FS = require('fs'),
+ PATH = require('path'),
+ SVGO = require('../svgo.js'),
+ YAML = require('js-yaml'),
+ PKG = require('../../package.json'),
+ mkdirp = require('mkdirp'),
+ encodeSVGDatauri = require('./tools.js').encodeSVGDatauri,
+ decodeSVGDatauri = require('./tools.js').decodeSVGDatauri,
+ regSVGFile = /\.svg$/;
+
+/**
+ * Command-Option-Argument.
+ *
+ * @see https://github.com/veged/coa
+ */
+module.exports = require('coa').Cmd()
+ .helpful()
+ .name(PKG.name)
+ .title(PKG.description)
+ .opt()
+ .name('version').title('Version')
+ .short('v').long('version')
+ .only()
+ .flag()
+ .act(function() {
+ // output the version to stdout instead of stderr if returned
+ process.stdout.write(PKG.version + '\n');
+ // coa will run `.toString` on the returned value and send it to stderr
+ return '';
+ })
+ .end()
+ .opt()
+ .name('input').title('Input file, "-" for STDIN')
+ .short('i').long('input')
+ .val(function(val) {
+ return val || this.reject("Option '--input' must have a value.");
+ })
+ .end()
+ .opt()
+ .name('string').title('Input SVG data string')
+ .short('s').long('string')
+ .end()
+ .opt()
+ .name('folder').title('Input folder, optimize and rewrite all *.svg files')
+ .short('f').long('folder')
+ .val(function(val) {
+ return val || this.reject("Option '--folder' must have a value.");
+ })
+ .end()
+ .opt()
+ .name('output').title('Output file or folder (by default the same as the input), "-" for STDOUT')
+ .short('o').long('output')
+ .val(function(val) {
+ return val || this.reject("Option '--output' must have a value.");
+ })
+ .end()
+ .opt()
+ .name('precision').title('Set number of digits in the fractional part, overrides plugins params')
+ .short('p').long('precision')
+ .val(function(val) {
+ return !isNaN(val) ? val : this.reject("Option '--precision' must be an integer number");
+ })
+ .end()
+ .opt()
+ .name('config').title('Config file or JSON string to extend or replace default')
+ .long('config')
+ .val(function(val) {
+ return val || this.reject("Option '--config' must have a value.");
+ })
+ .end()
+ .opt()
+ .name('disable').title('Disable plugin by name')
+ .long('disable')
+ .arr()
+ .val(function(val) {
+ return val || this.reject("Option '--disable' must have a value.");
+ })
+ .end()
+ .opt()
+ .name('enable').title('Enable plugin by name')
+ .long('enable')
+ .arr()
+ .val(function(val) {
+ return val || this.reject("Option '--enable' must have a value.");
+ })
+ .end()
+ .opt()
+ .name('datauri').title('Output as Data URI string (base64, URI encoded or unencoded)')
+ .long('datauri')
+ .val(function(val) {
+ return val || this.reject("Option '--datauri' must have one of the following values: 'base64', 'enc' or 'unenc'");
+ })
+ .end()
+ .opt()
+ .name('multipass').title('Enable multipass')
+ .long('multipass')
+ .flag()
+ .end()
+ .opt()
+ .name('pretty').title('Make SVG pretty printed')
+ .long('pretty')
+ .flag()
+ .end()
+ .opt()
+ .name('indent').title('Indent number when pretty printing SVGs')
+ .long('indent')
+ .val(function(val) {
+ return !isNaN(val) ? val : this.reject("Option '--indent' must be an integer number");
+ })
+ .end()
+ .opt()
+ .name('quiet').title('Only output error messages, not regular status messages')
+ .short('q').long('quiet')
+ .flag()
+ .end()
+ .opt()
+ .name('show-plugins').title('Show available plugins and exit')
+ .long('show-plugins')
+ .flag()
+ .end()
+ .arg()
+ .name('input').title('Alias to --input')
+ .end()
+ .arg()
+ .name('output').title('Alias to --output')
+ .end()
+ .act(function(opts, args) {
+
+ var input = args && args.input ? args.input : opts.input,
+ output = args && args.output ? args.output : opts.output,
+ config = {};
+
+ // --show-plugins
+ if (opts['show-plugins']) {
+
+ showAvailablePlugins();
+ process.exit(0);
+
+ }
+
+ // w/o anything
+ if (
+ (!input || input === '-') &&
+ !opts.string &&
+ !opts.stdin &&
+ !opts.folder &&
+ process.stdin.isTTY
+ ) return this.usage();
+
+
+ // --config
+ if (opts.config) {
+
+ // string
+ if (opts.config.charAt(0) === '{') {
+ try {
+ config = JSON.parse(opts.config);
+ } catch (e) {
+ console.error("Error: Couldn't parse config JSON.");
+ console.error(String(e));
+ return;
+ }
+
+ // external file
+ } else {
+ var configPath = PATH.resolve(opts.config);
+ try {
+ // require() adds some weird output on YML files
+ config = JSON.parse(FS.readFileSync(configPath, 'utf8'));
+ } catch (err) {
+ if (err.code === 'ENOENT') {
+ console.error('Error: couldn\'t find config file \'' + opts.config + '\'.');
+ return;
+ } else if (err.code === 'EISDIR') {
+ console.error('Error: directory \'' + opts.config + '\' is not a config file.');
+ return;
+ }
+ config = YAML.safeLoad(FS.readFileSync(configPath, 'utf8'));
+
+ if (!config || Array.isArray(config)) {
+ console.error('Error: invalid config file \'' + opts.config + '\'.');
+ return;
+ }
+ }
+ }
+
+ }
+
+ // --quiet
+ if (opts.quiet) {
+ config.quiet = opts.quiet;
+ }
+
+ // --precision
+ if (opts.precision) {
+ config.floatPrecision = Math.max(0, parseInt(opts.precision));
+ }
+
+ // --disable
+ if (opts.disable) {
+ changePluginsState(opts.disable, false, config);
+ }
+
+ // --enable
+ if (opts.enable) {
+ changePluginsState(opts.enable, true, config);
+ }
+
+ // --multipass
+ if (opts.multipass) {
+
+ config.multipass = true;
+
+ }
+
+ // --pretty
+ if (opts.pretty) {
+
+ config.js2svg = config.js2svg || {};
+ config.js2svg.pretty = true;
+ if (opts.indent) {
+ config.js2svg.indent = parseInt(opts.indent, 10);
+ }
+
+ }
+
+ // --output
+ if (opts.output) {
+ config.output = opts.output;
+ }
+
+ // --folder
+ if (opts.folder) {
+ optimizeFolder(opts.folder, config, output);
+
+ return;
+ }
+
+ // --input
+ if (input) {
+
+ // STDIN
+ if (input === '-') {
+
+ var data = '';
+
+ process.stdin.pause();
+
+ process.stdin
+ .on('data', function(chunk) {
+ data += chunk;
+ })
+ .once('end', function() {
+ optimizeFromString(data, config, opts.datauri, input, output);
+ })
+ .resume();
+
+ // file
+ } else {
+
+ FS.readFile(input, 'utf8', function(err, data) {
+ if (err) {
+ if (err.code === 'EISDIR')
+ optimizeFolder(input, config, output);
+ else if (err.code === 'ENOENT')
+ console.error('Error: no such file or directory \'' + input + '\'.');
+ else
+ console.error(err);
+ return;
+ }
+ optimizeFromString(data, config, opts.datauri, input, output);
+ });
+
+ }
+
+ // --string
+ } else if (opts.string) {
+
+ opts.string = decodeSVGDatauri(opts.string);
+
+ optimizeFromString(opts.string, config, opts.datauri, input, output);
+
+ }
+ });
+
+function optimizeFromString(svgstr, config, datauri, input, output) {
+
+ var startTime = Date.now(config),
+ time,
+ inBytes = Buffer.byteLength(svgstr, 'utf8'),
+ outBytes,
+ svgo = new SVGO(config);
+
+ svgo.optimize(svgstr, function(result) {
+
+ if (result.error) {
+ console.error(result.error);
+ return;
+ }
+
+ if (datauri) {
+ result.data = encodeSVGDatauri(result.data, datauri);
+ }
+
+ outBytes = Buffer.byteLength(result.data, 'utf8');
+ time = Date.now() - startTime;
+
+ // stdout
+ if (output === '-' || (!input || input === '-') && !output) {
+
+ process.stdout.write(result.data + '\n');
+
+ // file
+ } else {
+
+ // overwrite input file if there is no output
+ if (!output && input) {
+ output = input;
+ }
+
+ if (!config.quiet) {
+ console.log('\r');
+ }
+
+ saveFileAndPrintInfo(config, result.data, output, inBytes, outBytes, time);
+
+ }
+
+ });
+
+}
+
+function saveFileAndPrintInfo(config, data, path, inBytes, outBytes, time) {
+
+ FS.writeFile(path, data, 'utf8', function() {
+ if (config.quiet) {
+ return;
+ }
+
+ // print time info
+ printTimeInfo(time);
+
+ // print optimization profit info
+ printProfitInfo(inBytes, outBytes);
+
+ });
+
+}
+
+function printTimeInfo(time) {
+ console.log('Done in ' + time + ' ms!');
+
+}
+
+function printProfitInfo(inBytes, outBytes) {
+
+ var profitPercents = 100 - outBytes * 100 / inBytes;
+
+ console.log(
+ (Math.round((inBytes / 1024) * 1000) / 1000) + ' KiB' +
+ (profitPercents < 0 ? ' + ' : ' - ') +
+ String(Math.abs((Math.round(profitPercents * 10) / 10)) + '%').green + ' = ' +
+ (Math.round((outBytes / 1024) * 1000) / 1000) + ' KiB\n'
+ );
+
+}
+
+/**
+ * Change plugins state by names array.
+ *
+ * @param {Array} names plugins names
+ * @param {Boolean} state active state
+ * @param {Object} config original config
+ * @return {Object} changed config
+ */
+function changePluginsState(names, state, config) {
+
+ // extend config
+ if (config.plugins) {
+
+ names.forEach(function(name) {
+
+ var matched,
+ key;
+
+ config.plugins.forEach(function(plugin) {
+
+ // get plugin name
+ if (typeof plugin === 'object') {
+ key = Object.keys(plugin)[0];
+ } else {
+ key = plugin;
+ }
+
+ // if there is such a plugin name
+ if (key === name) {
+ // don't replace plugin's params with true
+ if (typeof plugin[key] !== 'object' || !state) {
+ plugin[key] = state;
+ }
+
+ // mark it as matched
+ matched = true;
+ }
+
+ });
+
+ // if not matched and current config is not full
+ if (!matched && !config.full) {
+
+ var obj = {};
+
+ obj[name] = state;
+
+ // push new plugin Object
+ config.plugins.push(obj);
+
+ matched = true;
+
+ }
+
+ });
+
+ // just push
+ } else {
+
+ config.plugins = [];
+
+ names.forEach(function(name) {
+ var obj = {};
+
+ obj[name] = state;
+
+ config.plugins.push(obj);
+ });
+
+ }
+
+ return config;
+
+}
+
+function optimizeFolder(dir, config, output) {
+
+ var svgo = new SVGO(config);
+
+ if (!config.quiet) {
+ console.log('Processing directory \'' + dir + '\':\n');
+ }
+
+ // absoluted folder path
+ var path = PATH.resolve(dir);
+
+ // list folder content
+ FS.readdir(path, function(err, files) {
+
+ if (err) {
+ console.error(err);
+ return;
+ }
+
+ if (!files.length) {
+ console.log('Directory \'' + dir + '\' is empty.');
+ return;
+ }
+
+ var i = 0,
+ found = false;
+
+ function optimizeFile(file) {
+
+ // absoluted file path
+ var filepath = PATH.resolve(path, file);
+ var outfilepath = output ? PATH.resolve(output, file) : filepath;
+
+ // check if file name matches *.svg
+ if (regSVGFile.test(filepath)) {
+
+ found = true;
+ FS.readFile(filepath, 'utf8', function(err, data) {
+
+ if (err) {
+ console.error(err);
+ return;
+ }
+
+ var startTime = Date.now(),
+ time,
+ inBytes = Buffer.byteLength(data, 'utf8'),
+ outBytes;
+
+ svgo.optimize(data, function(result) {
+
+ if (result.error) {
+ console.error(result.error);
+ return;
+ }
+
+ outBytes = Buffer.byteLength(result.data, 'utf8');
+ time = Date.now() - startTime;
+
+ writeOutput();
+
+ function writeOutput() {
+ FS.writeFile(outfilepath, result.data, 'utf8', report);
+ }
+
+ function report(err) {
+
+ if (err) {
+ if (err.code === 'ENOENT') {
+ mkdirp(output, writeOutput);
+ return;
+ } else if (err.code === 'ENOTDIR') {
+ console.error('Error: output \'' + output + '\' is not a directory.');
+ return;
+ }
+ console.error(err);
+ return;
+ }
+
+ if (!config.quiet) {
+ console.log(file + ':');
+
+ // print time info
+ printTimeInfo(time);
+
+ // print optimization profit info
+ printProfitInfo(inBytes, outBytes);
+ }
+
+ //move on to the next file
+ if (++i < files.length) {
+ optimizeFile(files[i]);
+ }
+
+ }
+
+ });
+
+ });
+
+ }
+ //move on to the next file
+ else if (++i < files.length) {
+ optimizeFile(files[i]);
+ } else if (!found) {
+ console.log('No SVG files have been found.');
+ }
+
+
+ }
+
+ optimizeFile(files[i]);
+
+ });
+
+}
+
+
+var showAvailablePlugins = function () {
+
+ var svgo = new SVGO(),
+ // Flatten an array of plugins grouped per type and sort alphabetically
+ list = Array.prototype.concat.apply([], svgo.config.plugins).sort(function(a, b) {
+ return a.name > b.name ? 1 : -1;
+ });
+
+ console.log('Currently available plugins:');
+
+ list.forEach(function (plugin) {
+ console.log(' [ ' + plugin.name.green + ' ] ' + plugin.description);
+ });
+
+ //console.log(JSON.stringify(svgo, null, 4));
+};
diff --git a/node_modules/svgo/lib/svgo/config.js b/node_modules/svgo/lib/svgo/config.js
new file mode 100644
index 00000000..093067d4
--- /dev/null
+++ b/node_modules/svgo/lib/svgo/config.js
@@ -0,0 +1,212 @@
+'use strict';
+
+var FS = require('fs');
+var yaml = require('js-yaml');
+
+var EXTEND = require('whet.extend');
+
+/**
+ * Read and/or extend/replace default config file,
+ * prepare and optimize plugins array.
+ *
+ * @param {Object} [config] input config
+ * @return {Object} output config
+ */
+module.exports = function(config) {
+
+ var defaults;
+ config = typeof config == 'object' && config || {};
+
+ if (config.plugins && !Array.isArray(config.plugins)) {
+ return { error: 'Error: Invalid plugins list. Provided \'plugins\' in config should be an array.' };
+ }
+
+ if (config.full) {
+ defaults = config;
+
+ if (Array.isArray(defaults.plugins)) {
+ defaults.plugins = preparePluginsArray(defaults.plugins);
+ }
+ } else {
+ defaults = EXTEND({}, yaml.safeLoad(FS.readFileSync(__dirname + '/../../.svgo.yml', 'utf8')));
+ defaults.plugins = preparePluginsArray(defaults.plugins);
+ defaults = extendConfig(defaults, config);
+ }
+
+ if ('floatPrecision' in config && Array.isArray(defaults.plugins)) {
+ defaults.plugins.forEach(function(plugin) {
+ if (plugin.params && ('floatPrecision' in plugin.params)) {
+ // Don't touch default plugin params
+ plugin.params = EXTEND({}, plugin.params, { floatPrecision: config.floatPrecision });
+ }
+ });
+ }
+
+ if (Array.isArray(defaults.plugins)) {
+ defaults.plugins = optimizePluginsArray(defaults.plugins);
+ }
+
+ return defaults;
+
+};
+
+/**
+ * Require() all plugins in array.
+ *
+ * @param {Array} plugins input plugins array
+ * @return {Array} input plugins array of arrays
+ */
+function preparePluginsArray(plugins) {
+
+ var plugin,
+ key;
+
+ return plugins.map(function(item) {
+
+ // {}
+ if (typeof item === 'object') {
+
+ key = Object.keys(item)[0];
+
+ // custom
+ if (typeof item[key] === 'object' && item[key].fn && typeof item[key].fn === 'function') {
+ plugin = setupCustomPlugin(key, item[key]);
+
+ } else {
+
+ plugin = EXTEND({}, require('../../plugins/' + key));
+
+ // name: {}
+ if (typeof item[key] === 'object') {
+ plugin.params = EXTEND({}, plugin.params || {}, item[key]);
+ plugin.active = true;
+
+ // name: false
+ } else if (item[key] === false) {
+ plugin.active = false;
+
+ // name: true
+ } else if (item[key] === true) {
+ plugin.active = true;
+ }
+
+ plugin.name = key;
+ }
+
+ // name
+ } else {
+
+ plugin = EXTEND({}, require('../../plugins/' + item));
+ plugin.name = item;
+
+ }
+
+ return plugin;
+
+ });
+
+}
+
+/**
+ * Extend plugins with the custom config object.
+ *
+ * @param {Array} plugins input plugins
+ * @param {Object} config config
+ * @return {Array} output plugins
+ */
+function extendConfig(defaults, config) {
+
+ var key;
+
+ // plugins
+ if (config.plugins) {
+
+ config.plugins.forEach(function(item) {
+
+ // {}
+ if (typeof item === 'object') {
+
+ key = Object.keys(item)[0];
+
+ // custom
+ if (typeof item[key] === 'object' && item[key].fn && typeof item[key].fn === 'function') {
+ defaults.plugins.push(setupCustomPlugin(key, item[key]));
+
+ } else {
+ defaults.plugins.forEach(function(plugin) {
+
+ if (plugin.name === key) {
+ // name: {}
+ if (typeof item[key] === 'object') {
+ plugin.params = EXTEND({}, plugin.params || {}, item[key]);
+ plugin.active = true;
+
+ // name: false
+ } else if (item[key] === false) {
+ plugin.active = false;
+
+ // name: true
+ } else if (item[key] === true) {
+ plugin.active = true;
+ }
+ }
+ });
+ }
+
+ }
+
+ });
+
+ }
+
+ defaults.multipass = config.multipass;
+
+ // svg2js
+ if (config.svg2js) {
+ defaults.svg2js = config.svg2js;
+ }
+
+ // js2svg
+ if (config.js2svg) {
+ defaults.js2svg = config.js2svg;
+ }
+
+ return defaults;
+
+}
+
+/**
+ * Setup and enable a custom plugin
+ *
+ * @param {String} plugin name
+ * @param {Object} custom plugin
+ * @return {Array} enabled plugin
+ */
+function setupCustomPlugin(name, plugin) {
+ plugin.active = true;
+ plugin.params = EXTEND({}, plugin.params || {});
+ plugin.name = name;
+
+ return plugin;
+}
+
+/**
+ * Try to group sequential elements of plugins array.
+ *
+ * @param {Object} plugins input plugins
+ * @return {Array} output plugins
+ */
+function optimizePluginsArray(plugins) {
+
+ var prev;
+
+ return plugins.reduce(function(plugins, item) {
+ if (prev && item.type == prev[0].type) {
+ prev.push(item);
+ } else {
+ plugins.push(prev = [item]);
+ }
+ return plugins;
+ }, []);
+
+}
diff --git a/node_modules/svgo/lib/svgo/js2svg.js b/node_modules/svgo/lib/svgo/js2svg.js
new file mode 100644
index 00000000..5d19cc8d
--- /dev/null
+++ b/node_modules/svgo/lib/svgo/js2svg.js
@@ -0,0 +1,352 @@
+'use strict';
+
+var EOL = require('os').EOL,
+ EXTEND = require('whet.extend'),
+ textElem = require('../../plugins/_collections.js').elemsGroups.textContent.concat('title');
+
+var defaults = {
+ doctypeStart: '<!DOCTYPE',
+ doctypeEnd: '>',
+ procInstStart: '<?',
+ procInstEnd: '?>',
+ tagOpenStart: '<',
+ tagOpenEnd: '>',
+ tagCloseStart: '</',
+ tagCloseEnd: '>',
+ tagShortStart: '<',
+ tagShortEnd: '/>',
+ attrStart: '="',
+ attrEnd: '"',
+ commentStart: '<!--',
+ commentEnd: '-->',
+ cdataStart: '<![CDATA[',
+ cdataEnd: ']]>',
+ textStart: '',
+ textEnd: '',
+ indent: 4,
+ regEntities: /[&'"<>]/g,
+ regValEntities: /[&"<>]/g,
+ encodeEntity: encodeEntity,
+ pretty: false,
+ useShortTags: true
+};
+
+var entities = {
+ '&': '&amp;',
+ '\'': '&apos;',
+ '"': '&quot;',
+ '>': '&gt;',
+ '<': '&lt;',
+ };
+
+/**
+ * Convert SVG-as-JS object to SVG (XML) string.
+ *
+ * @param {Object} data input data
+ * @param {Object} config config
+ *
+ * @return {Object} output data
+ */
+module.exports = function(data, config) {
+
+ return new JS2SVG(config).convert(data);
+
+};
+
+function JS2SVG(config) {
+
+ if (config) {
+ this.config = EXTEND(true, {}, defaults, config);
+ } else {
+ this.config = defaults;
+ }
+
+ var indent = this.config.indent;
+ if (typeof indent == 'number' && !isNaN(indent)) {
+ this.config.indent = '';
+ for (var i = indent; i-- > 0;) this.config.indent += ' ';
+ } else if (typeof indent != 'string') {
+ this.config.indent = ' ';
+ }
+
+ if (this.config.pretty) {
+ this.config.doctypeEnd += EOL;
+ this.config.procInstEnd += EOL;
+ this.config.commentEnd += EOL;
+ this.config.cdataEnd += EOL;
+ this.config.tagShortEnd += EOL;
+ this.config.tagOpenEnd += EOL;
+ this.config.tagCloseEnd += EOL;
+ this.config.textEnd += EOL;
+ }
+
+ this.indentLevel = 0;
+ this.textContext = null;
+
+}
+
+function encodeEntity(char) {
+ return entities[char];
+}
+
+/**
+ * Start conversion.
+ *
+ * @param {Object} data input data
+ *
+ * @return {String}
+ */
+JS2SVG.prototype.convert = function(data) {
+
+ var svg = '';
+
+ if (data.content) {
+
+ this.indentLevel++;
+
+ data.content.forEach(function(item) {
+
+ if (item.elem) {
+ svg += this.createElem(item);
+ } else if (item.text) {
+ svg += this.createText(item.text);
+ } else if (item.doctype) {
+ svg += this.createDoctype(item.doctype);
+ } else if (item.processinginstruction) {
+ svg += this.createProcInst(item.processinginstruction);
+ } else if (item.comment) {
+ svg += this.createComment(item.comment);
+ } else if (item.cdata) {
+ svg += this.createCDATA(item.cdata);
+ }
+
+ }, this);
+
+ }
+
+ this.indentLevel--;
+
+ return {
+ data: svg,
+ info: {
+ width: this.width,
+ height: this.height
+ }
+ };
+
+};
+
+/**
+ * Create indent string in accordance with the current node level.
+ *
+ * @return {String}
+ */
+JS2SVG.prototype.createIndent = function() {
+
+ var indent = '';
+
+ if (this.config.pretty && !this.textContext) {
+ for (var i = 1; i < this.indentLevel; i++) {
+ indent += this.config.indent;
+ }
+ }
+
+ return indent;
+
+};
+
+/**
+ * Create doctype tag.
+ *
+ * @param {String} doctype doctype body string
+ *
+ * @return {String}
+ */
+JS2SVG.prototype.createDoctype = function(doctype) {
+
+ return this.config.doctypeStart +
+ doctype +
+ this.config.doctypeEnd;
+
+};
+
+/**
+ * Create XML Processing Instruction tag.
+ *
+ * @param {Object} instruction instruction object
+ *
+ * @return {String}
+ */
+JS2SVG.prototype.createProcInst = function(instruction) {
+
+ return this.config.procInstStart +
+ instruction.name +
+ ' ' +
+ instruction.body +
+ this.config.procInstEnd;
+
+};
+
+/**
+ * Create comment tag.
+ *
+ * @param {String} comment comment body
+ *
+ * @return {String}
+ */
+JS2SVG.prototype.createComment = function(comment) {
+
+ return this.config.commentStart +
+ comment +
+ this.config.commentEnd;
+
+};
+
+/**
+ * Create CDATA section.
+ *
+ * @param {String} cdata CDATA body
+ *
+ * @return {String}
+ */
+JS2SVG.prototype.createCDATA = function(cdata) {
+
+ return this.createIndent() +
+ this.config.cdataStart +
+ cdata +
+ this.config.cdataEnd;
+
+};
+
+/**
+ * Create element tag.
+ *
+ * @param {Object} data element object
+ *
+ * @return {String}
+ */
+JS2SVG.prototype.createElem = function(data) {
+
+ // beautiful injection for obtaining SVG information :)
+ if (
+ data.isElem('svg') &&
+ data.hasAttr('width') &&
+ data.hasAttr('height')
+ ) {
+ this.width = data.attr('width').value;
+ this.height = data.attr('height').value;
+ }
+
+ // empty element and short tag
+ if (data.isEmpty()) {
+ if (this.config.useShortTags) {
+ return this.createIndent() +
+ this.config.tagShortStart +
+ data.elem +
+ this.createAttrs(data) +
+ this.config.tagShortEnd;
+ } else {
+ return this.createIndent() +
+ this.config.tagShortStart +
+ data.elem +
+ this.createAttrs(data) +
+ this.config.tagOpenEnd +
+ this.config.tagCloseStart +
+ data.elem +
+ this.config.tagCloseEnd;
+ }
+ // non-empty element
+ } else {
+ var tagOpenStart = this.config.tagOpenStart,
+ tagOpenEnd = this.config.tagOpenEnd,
+ tagCloseStart = this.config.tagCloseStart,
+ tagCloseEnd = this.config.tagCloseEnd,
+ openIndent = this.createIndent(),
+ textIndent = '',
+ processedData = '',
+ dataEnd = '';
+
+ if (this.textContext) {
+ tagOpenStart = defaults.tagOpenStart;
+ tagOpenEnd = defaults.tagOpenEnd;
+ tagCloseStart = defaults.tagCloseStart;
+ tagCloseEnd = defaults.tagCloseEnd;
+ openIndent = '';
+ } else if (data.isElem(textElem)) {
+ if (this.config.pretty) {
+ textIndent += openIndent + this.config.indent;
+ }
+ this.textContext = data;
+ }
+
+ processedData += this.convert(data).data;
+
+ if (this.textContext == data) {
+ this.textContext = null;
+ if (this.config.pretty) dataEnd = EOL;
+ }
+
+ return openIndent +
+ tagOpenStart +
+ data.elem +
+ this.createAttrs(data) +
+ tagOpenEnd +
+ textIndent +
+ processedData +
+ dataEnd +
+ this.createIndent() +
+ tagCloseStart +
+ data.elem +
+ tagCloseEnd;
+
+ }
+
+};
+
+/**
+ * Create element attributes.
+ *
+ * @param {Object} elem attributes object
+ *
+ * @return {String}
+ */
+JS2SVG.prototype.createAttrs = function(elem) {
+
+ var attrs = '';
+
+ elem.eachAttr(function(attr) {
+
+ if (attr.value !== undefined) {
+ attrs += ' ' +
+ attr.name +
+ this.config.attrStart +
+ String(attr.value).replace(this.config.regValEntities, this.config.encodeEntity) +
+ this.config.attrEnd;
+ }
+ else {
+ attrs += ' ' +
+ attr.name;
+ }
+
+
+ }, this);
+
+ return attrs;
+
+};
+
+/**
+ * Create text node.
+ *
+ * @param {String} text text
+ *
+ * @return {String}
+ */
+JS2SVG.prototype.createText = function(text) {
+
+ return this.createIndent() +
+ this.config.textStart +
+ text.replace(this.config.regEntities, this.config.encodeEntity) +
+ (this.textContext ? '' : this.config.textEnd);
+
+};
diff --git a/node_modules/svgo/lib/svgo/jsAPI.js b/node_modules/svgo/lib/svgo/jsAPI.js
new file mode 100644
index 00000000..1e2f55fb
--- /dev/null
+++ b/node_modules/svgo/lib/svgo/jsAPI.js
@@ -0,0 +1,298 @@
+'use strict';
+
+var EXTEND = require('whet.extend');
+
+var JSAPI = module.exports = function(data, parentNode) {
+ EXTEND(this, data);
+ if (parentNode) {
+ Object.defineProperty(this, 'parentNode', {
+ writable: true,
+ value: parentNode
+ });
+ }
+};
+
+/**
+ * Perform a deep clone of this node.
+ *
+ * @return {Object} element
+ */
+JSAPI.prototype.clone = function() {
+ var node = this;
+ var nodeData = {};
+
+ Object.keys(node).forEach(function(key) {
+ if (key !== 'content') {
+ nodeData[key] = node[key];
+ }
+ });
+
+ // Deep-clone node data
+ // This is still faster than using EXTEND(true…)
+ nodeData = JSON.parse(JSON.stringify(nodeData));
+
+ // parentNode gets set to a proper object by the parent clone,
+ // but it needs to be true/false now to do the right thing
+ // in the constructor.
+ var clonedNode = new JSAPI(nodeData, !!node.parentNode);
+
+ if (node.content) {
+ clonedNode.content = node.content.map(function(childNode) {
+ var clonedChild = childNode.clone();
+ clonedChild.parentNode = clonedNode;
+ return clonedChild;
+ });
+ }
+
+ return clonedNode;
+};
+
+/**
+ * Determine if item is an element
+ * (any, with a specific name or in a names array).
+ *
+ * @param {String|Array} [param] element name or names arrays
+ * @return {Boolean}
+ */
+JSAPI.prototype.isElem = function(param) {
+
+ if (!param) return !!this.elem;
+
+ if (Array.isArray(param)) return !!this.elem && (param.indexOf(this.elem) > -1);
+
+ return !!this.elem && this.elem === param;
+
+};
+
+/**
+ * Renames an element
+ *
+ * @param {String} name new element name
+ * @return {Object} element
+ */
+JSAPI.prototype.renameElem = function(name) {
+
+ if (name && typeof name === 'string')
+ this.elem = this.local = name;
+
+ return this;
+
+};
+
+/**
+ * Determine if element is empty.
+ *
+ * @return {Boolean}
+ */
+ JSAPI.prototype.isEmpty = function() {
+
+ return !this.content || !this.content.length;
+
+};
+
+/**
+ * Changes content by removing elements and/or adding new elements.
+ *
+ * @param {Number} start Index at which to start changing the content.
+ * @param {Number} n Number of elements to remove.
+ * @param {Array|Object} [insertion] Elements to add to the content.
+ * @return {Array} Removed elements.
+ */
+ JSAPI.prototype.spliceContent = function(start, n, insertion) {
+
+ if (arguments.length < 2) return [];
+
+ if (!Array.isArray(insertion))
+ insertion = Array.apply(null, arguments).slice(2);
+
+ insertion.forEach(function(inner) { inner.parentNode = this }, this);
+
+ return this.content.splice.apply(this.content, [start, n].concat(insertion));
+
+
+};
+
+/**
+ * Determine if element has an attribute
+ * (any, or by name or by name + value).
+ *
+ * @param {String} [name] attribute name
+ * @param {String} [val] attribute value (will be toString()'ed)
+ * @return {Boolean}
+ */
+ JSAPI.prototype.hasAttr = function(name, val) {
+
+ if (!this.attrs || !Object.keys(this.attrs).length) return false;
+
+ if (!arguments.length) return !!this.attrs;
+
+ if (val !== undefined) return !!this.attrs[name] && this.attrs[name].value === val.toString();
+
+ return !!this.attrs[name];
+
+};
+
+/**
+ * Determine if element has an attribute by local name
+ * (any, or by name or by name + value).
+ *
+ * @param {String} [localName] local attribute name
+ * @param {Number|String|RegExp|Function} [val] attribute value (will be toString()'ed or executed, otherwise ignored)
+ * @return {Boolean}
+ */
+ JSAPI.prototype.hasAttrLocal = function(localName, val) {
+
+ if (!this.attrs || !Object.keys(this.attrs).length) return false;
+
+ if (!arguments.length) return !!this.attrs;
+
+ var callback;
+
+ switch (val != null && val.constructor && val.constructor.name) {
+ case 'Number': // same as String
+ case 'String': callback = stringValueTest; break;
+ case 'RegExp': callback = regexpValueTest; break;
+ case 'Function': callback = funcValueTest; break;
+ default: callback = nameTest;
+ }
+ return this.someAttr(callback);
+
+ function nameTest(attr) {
+ return attr.local === localName;
+ }
+
+ function stringValueTest(attr) {
+ return attr.local === localName && val == attr.value;
+ }
+
+ function regexpValueTest(attr) {
+ return attr.local === localName && val.test(attr.value);
+ }
+
+ function funcValueTest(attr) {
+ return attr.local === localName && val(attr.value);
+ }
+
+};
+
+/**
+ * Get a specific attribute from an element
+ * (by name or name + value).
+ *
+ * @param {String} name attribute name
+ * @param {String} [val] attribute value (will be toString()'ed)
+ * @return {Object|Undefined}
+ */
+ JSAPI.prototype.attr = function(name, val) {
+
+ if (!this.hasAttr() || !arguments.length) return undefined;
+
+ if (val !== undefined) return this.hasAttr(name, val) ? this.attrs[name] : undefined;
+
+ return this.attrs[name];
+
+};
+
+/**
+ * Get computed attribute value from an element
+ *
+ * @param {String} name attribute name
+ * @return {Object|Undefined}
+ */
+ JSAPI.prototype.computedAttr = function(name, val) {
+ /* jshint eqnull: true */
+ if (!arguments.length) return;
+
+ for (var elem = this; elem && (!elem.hasAttr(name) || !elem.attr(name).value); elem = elem.parentNode);
+
+ if (val != null) {
+ return elem ? elem.hasAttr(name, val) : false;
+ } else if (elem && elem.hasAttr(name)) {
+ return elem.attrs[name].value;
+ }
+
+};
+
+/**
+ * Remove a specific attribute.
+ *
+ * @param {String|Array} name attribute name
+ * @param {String} [val] attribute value
+ * @return {Boolean}
+ */
+ JSAPI.prototype.removeAttr = function(name, val, recursive) {
+
+ if (!arguments.length) return false;
+
+ if (Array.isArray(name)) name.forEach(this.removeAttr, this);
+
+ if (!this.hasAttr(name)) return false;
+
+ if (!recursive && val && this.attrs[name].value !== val) return false;
+
+ delete this.attrs[name];
+
+ if (!Object.keys(this.attrs).length) delete this.attrs;
+
+ return true;
+
+};
+
+/**
+ * Add attribute.
+ *
+ * @param {Object} [attr={}] attribute object
+ * @return {Object|Boolean} created attribute or false if no attr was passed in
+ */
+ JSAPI.prototype.addAttr = function(attr) {
+ attr = attr || {};
+
+ if (attr.name === undefined ||
+ attr.prefix === undefined ||
+ attr.local === undefined
+ ) return false;
+
+ this.attrs = this.attrs || {};
+ this.attrs[attr.name] = attr;
+
+ return this.attrs[attr.name];
+
+};
+
+/**
+ * Iterates over all attributes.
+ *
+ * @param {Function} callback callback
+ * @param {Object} [context] callback context
+ * @return {Boolean} false if there are no any attributes
+ */
+ JSAPI.prototype.eachAttr = function(callback, context) {
+
+ if (!this.hasAttr()) return false;
+
+ for (var name in this.attrs) {
+ callback.call(context, this.attrs[name]);
+ }
+
+ return true;
+
+};
+
+/**
+ * Tests whether some attribute passes the test.
+ *
+ * @param {Function} callback callback
+ * @param {Object} [context] callback context
+ * @return {Boolean} false if there are no any attributes
+ */
+ JSAPI.prototype.someAttr = function(callback, context) {
+
+ if (!this.hasAttr()) return false;
+
+ for (var name in this.attrs) {
+ if (callback.call(context, this.attrs[name])) return true;
+ }
+
+ return false;
+
+};
diff --git a/node_modules/svgo/lib/svgo/plugins.js b/node_modules/svgo/lib/svgo/plugins.js
new file mode 100644
index 00000000..4e0308da
--- /dev/null
+++ b/node_modules/svgo/lib/svgo/plugins.js
@@ -0,0 +1,98 @@
+'use strict';
+
+/**
+ * Plugins engine.
+ *
+ * @module plugins
+ *
+ * @param {Object} data input data
+ * @param {Object} plugins plugins object from config
+ * @return {Object} output data
+ */
+module.exports = function(data, plugins) {
+
+ plugins.forEach(function(group) {
+
+ switch(group[0].type) {
+ case 'perItem':
+ data = perItem(data, group);
+ break;
+ case 'perItemReverse':
+ data = perItem(data, group, true);
+ break;
+ case 'full':
+ data = full(data, group);
+ break;
+ }
+
+ });
+
+ return data;
+
+};
+
+/**
+ * Direct or reverse per-item loop.
+ *
+ * @param {Object} data input data
+ * @param {Array} plugins plugins list to process
+ * @param {Boolean} [reverse] reverse pass?
+ * @return {Object} output data
+ */
+function perItem(data, plugins, reverse) {
+
+ function monkeys(items) {
+
+ items.content = items.content.filter(function(item) {
+
+ // reverse pass
+ if (reverse && item.content) {
+ monkeys(item);
+ }
+
+ // main filter
+ var filter = true;
+
+ for (var i = 0; filter && i < plugins.length; i++) {
+ var plugin = plugins[i];
+
+ if (plugin.active && plugin.fn(item, plugin.params) === false) {
+ filter = false;
+ }
+ }
+
+ // direct pass
+ if (!reverse && item.content) {
+ monkeys(item);
+ }
+
+ return filter;
+
+ });
+
+ return items;
+
+ }
+
+ return monkeys(data);
+
+}
+
+/**
+ * "Full" plugins.
+ *
+ * @param {Object} data input data
+ * @param {Array} plugins plugins list to process
+ * @return {Object} output data
+ */
+function full(data, plugins) {
+
+ plugins.forEach(function(plugin) {
+ if (plugin.active) {
+ data = plugin.fn(data, plugin.params);
+ }
+ });
+
+ return data;
+
+}
diff --git a/node_modules/svgo/lib/svgo/svg2js.js b/node_modules/svgo/lib/svgo/svg2js.js
new file mode 100644
index 00000000..2c36900c
--- /dev/null
+++ b/node_modules/svgo/lib/svgo/svg2js.js
@@ -0,0 +1,187 @@
+'use strict';
+
+var SAX = require('sax'),
+ JSAPI = require('./jsAPI.js'),
+ entityDeclaration = /<!ENTITY\s+(\S+)\s+(?:'([^\']+)'|"([^\"]+)")\s*>/g;
+
+var config = {
+ strict: true,
+ trim: false,
+ normalize: true,
+ lowercase: true,
+ xmlns: true,
+ position: true
+};
+
+/**
+ * Convert SVG (XML) string to SVG-as-JS object.
+ *
+ * @param {String} data input data
+ * @param {Function} callback
+ */
+module.exports = function(data, callback) {
+
+ var sax = SAX.parser(config.strict, config),
+ root = new JSAPI({ elem: '#document' }),
+ current = root,
+ stack = [root],
+ textContext = null,
+ parsingError = false;
+
+ function pushToContent(content) {
+
+ content = new JSAPI(content, current);
+
+ (current.content = current.content || []).push(content);
+
+ return content;
+
+ }
+
+ sax.ondoctype = function(doctype) {
+
+ pushToContent({
+ doctype: doctype
+ });
+
+ var subsetStart = doctype.indexOf('['),
+ entityMatch;
+
+ if (subsetStart >= 0) {
+ entityDeclaration.lastIndex = subsetStart;
+
+ while ((entityMatch = entityDeclaration.exec(data)) != null) {
+ sax.ENTITIES[entityMatch[1]] = entityMatch[2] || entityMatch[3];
+ }
+ }
+ };
+
+ sax.onprocessinginstruction = function(data) {
+
+ pushToContent({
+ processinginstruction: data
+ });
+
+ };
+
+ sax.oncomment = function(comment) {
+
+ pushToContent({
+ comment: comment.trim()
+ });
+
+ };
+
+ sax.oncdata = function(cdata) {
+
+ pushToContent({
+ cdata: cdata
+ });
+
+ };
+
+ sax.onopentag = function(data) {
+
+ var elem = {
+ elem: data.name,
+ prefix: data.prefix,
+ local: data.local
+ };
+
+ if (Object.keys(data.attributes).length) {
+ elem.attrs = {};
+
+ for (var name in data.attributes) {
+ elem.attrs[name] = {
+ name: name,
+ value: data.attributes[name].value,
+ prefix: data.attributes[name].prefix,
+ local: data.attributes[name].local
+ };
+ }
+ }
+
+ elem = pushToContent(elem);
+ current = elem;
+
+ // Save info about <text> tag to prevent trimming of meaningful whitespace
+ if (data.name == 'text' && !data.prefix) {
+ textContext = current;
+ }
+
+ stack.push(elem);
+
+ };
+
+ sax.ontext = function(text) {
+
+ if (/\S/.test(text) || textContext) {
+
+ if (!textContext)
+ text = text.trim();
+
+ pushToContent({
+ text: text
+ });
+
+ }
+
+ };
+
+ sax.onclosetag = function() {
+
+ var last = stack.pop();
+
+ // Trim text inside <text> tag.
+ if (last == textContext) {
+ trim(textContext);
+ textContext = null;
+ }
+ current = stack[stack.length - 1];
+
+ };
+
+ sax.onerror = function(e) {
+
+ e.message = 'Error in parsing SVG: ' + e.message;
+ if (e.message.indexOf('Unexpected end') < 0) {
+ throw e;
+ }
+
+ };
+
+ sax.onend = function() {
+
+ if (!this.error) {
+ callback(root);
+ } else {
+ callback({ error: this.error.message });
+ }
+
+ };
+
+ try {
+ sax.write(data);
+ } catch (e) {
+ callback({ error: e.message });
+ parsingError = true;
+ }
+ if (!parsingError) sax.close();
+
+ function trim(elem) {
+ if (!elem.content) return elem;
+
+ var start = elem.content[0],
+ end = elem.content[elem.content.length - 1];
+
+ while (start && start.content && !start.text) start = start.content[0];
+ if (start && start.text) start.text = start.text.replace(/^\s+/, '');
+
+ while (end && end.content && !end.text) end = end.content[end.content.length - 1];
+ if (end && end.text) end.text = end.text.replace(/\s+$/, '');
+
+ return elem;
+
+ }
+
+};
diff --git a/node_modules/svgo/lib/svgo/tools.js b/node_modules/svgo/lib/svgo/tools.js
new file mode 100644
index 00000000..7dd33c07
--- /dev/null
+++ b/node_modules/svgo/lib/svgo/tools.js
@@ -0,0 +1,147 @@
+'use strict';
+
+/**
+ * Encode plain SVG data string into Data URI string.
+ *
+ * @param {String} str input string
+ * @param {String} type Data URI type
+ * @return {String} output string
+ */
+exports.encodeSVGDatauri = function(str, type) {
+
+ var prefix = 'data:image/svg+xml';
+
+ // base64
+ if (!type || type === 'base64') {
+
+ prefix += ';base64,';
+
+ str = prefix + new Buffer(str).toString('base64');
+
+ // URI encoded
+ } else if (type === 'enc') {
+
+ str = prefix + ',' + encodeURIComponent(str);
+
+ // unencoded
+ } else if (type === 'unenc') {
+
+ str = prefix + ',' + str;
+
+ }
+
+ return str;
+
+};
+
+/**
+ * Decode SVG Data URI string into plain SVG string.
+ *
+ * @param {string} str input string
+ * @return {String} output string
+ */
+exports.decodeSVGDatauri = function(str) {
+ var regexp = /data:image\/svg\+xml(;charset=[^;,]*)?(;base64)?,(.*)/;
+ var match = regexp.exec(str);
+
+ // plain string
+ if (!match) return str;
+
+ var data = match[3];
+
+ // base64
+ if (match[2]) {
+
+ str = new Buffer(data, 'base64').toString('utf8');
+
+ // URI encoded
+ } else if (data.charAt(0) === '%') {
+
+ str = decodeURIComponent(data);
+
+ // unencoded
+ } else if (data.charAt(0) === '<') {
+
+ str = data;
+
+ }
+
+ return str;
+};
+
+exports.intersectArrays = function(a, b) {
+ return a.filter(function(n) {
+ return b.indexOf(n) > -1;
+ });
+};
+
+exports.cleanupOutData = function(data, params) {
+
+ var str = '',
+ delimiter,
+ prev;
+
+ data.forEach(function(item, i) {
+
+ // space delimiter by default
+ delimiter = ' ';
+
+ // no extra space in front of first number
+ if (i === 0) {
+ delimiter = '';
+ }
+
+ // remove floating-point numbers leading zeros
+ // 0.5 → .5
+ // -0.5 → -.5
+ if (params.leadingZero) {
+ item = removeLeadingZero(item);
+ }
+
+ // no extra space in front of negative number or
+ // in front of a floating number if a previous number is floating too
+ if (
+ params.negativeExtraSpace &&
+ (item < 0 ||
+ (String(item).charCodeAt(0) == 46 && prev % 1 !== 0)
+ )
+ ) {
+ delimiter = '';
+ }
+
+ // save prev item value
+ prev = item;
+
+ str += delimiter + item;
+
+ });
+
+ return str;
+
+};
+
+/**
+ * Remove floating-point numbers leading zero.
+ *
+ * @example
+ * 0.5 → .5
+ *
+ * @example
+ * -0.5 → -.5
+ *
+ * @param {Float} num input number
+ *
+ * @return {String} output number as string
+ */
+var removeLeadingZero = exports.removeLeadingZero = function(num) {
+ var strNum = num.toString();
+
+ if (0 < num && num < 1 && strNum.charCodeAt(0) == 48) {
+ strNum = strNum.slice(1);
+ } else if (-1 < num && num < 0 && strNum.charCodeAt(1) == 48) {
+ strNum = strNum.charAt(0) + strNum.slice(2);
+ }
+
+ return strNum;
+
+};
diff --git a/node_modules/svgo/node_modules/.bin/csso b/node_modules/svgo/node_modules/.bin/csso
new file mode 120000
index 00000000..b14445ba
--- /dev/null
+++ b/node_modules/svgo/node_modules/.bin/csso
@@ -0,0 +1 @@
+../../../csso/bin/csso \ No newline at end of file
diff --git a/node_modules/svgo/node_modules/.bin/js-yaml b/node_modules/svgo/node_modules/.bin/js-yaml
new file mode 120000
index 00000000..9dbd010d
--- /dev/null
+++ b/node_modules/svgo/node_modules/.bin/js-yaml
@@ -0,0 +1 @@
+../js-yaml/bin/js-yaml.js \ No newline at end of file
diff --git a/node_modules/svgo/node_modules/.bin/mkdirp b/node_modules/svgo/node_modules/.bin/mkdirp
new file mode 120000
index 00000000..91a5f623
--- /dev/null
+++ b/node_modules/svgo/node_modules/.bin/mkdirp
@@ -0,0 +1 @@
+../../../mkdirp/bin/cmd.js \ No newline at end of file
diff --git a/node_modules/svgo/node_modules/esprima/.bin/esparse b/node_modules/svgo/node_modules/esprima/.bin/esparse
new file mode 120000
index 00000000..88083f29
--- /dev/null
+++ b/node_modules/svgo/node_modules/esprima/.bin/esparse
@@ -0,0 +1 @@
+../bin/esparse.js \ No newline at end of file
diff --git a/node_modules/svgo/node_modules/esprima/.bin/esvalidate b/node_modules/svgo/node_modules/esprima/.bin/esvalidate
new file mode 120000
index 00000000..5f4621b4
--- /dev/null
+++ b/node_modules/svgo/node_modules/esprima/.bin/esvalidate
@@ -0,0 +1 @@
+../bin/esvalidate.js \ No newline at end of file
diff --git a/node_modules/svgo/node_modules/esprima/ChangeLog b/node_modules/svgo/node_modules/esprima/ChangeLog
new file mode 100644
index 00000000..fd687ae3
--- /dev/null
+++ b/node_modules/svgo/node_modules/esprima/ChangeLog
@@ -0,0 +1,174 @@
+2016-08-23: Version 2.7.3
+
+ * Fix tokenizer confusion with a comment (issue 1493, 1516)
+
+2016-02-02: Version 2.7.2
+
+ * Fix out-of-bound error location in an invalid string literal (issue 1457)
+ * Fix shorthand object destructuring defaults in variable declarations (issue 1459)
+
+2015-12-10: Version 2.7.1
+
+ * Do not allow trailing comma in a variable declaration (issue 1360)
+ * Fix assignment to `let` in non-strict mode (issue 1376)
+ * Fix missing delegate property in YieldExpression (issue 1407)
+
+2015-10-22: Version 2.7.0
+
+ * Fix the handling of semicolon in a break statement (issue 1044)
+ * Run the test suite with major web browsers (issue 1259, 1317)
+ * Allow `let` as an identifier in non-strict mode (issue 1289)
+ * Attach orphaned comments as `innerComments` (issue 1328)
+ * Add the support for token delegator (issue 1332)
+
+2015-09-01: Version 2.6.0
+
+ * Properly allow or prohibit `let` in a binding identifier/pattern (issue 1048, 1098)
+ * Add sourceType field for Program node (issue 1159)
+ * Ensure that strict mode reserved word binding throw an error (issue 1171)
+ * Run the test suite with Node.js and IE 11 on Windows (issue 1294)
+ * Allow binding pattern with no initializer in a for statement (issue 1301)
+
+2015-07-31: Version 2.5.0
+
+ * Run the test suite in a browser environment (issue 1004)
+ * Ensure a comma between imported default binding and named imports (issue 1046)
+ * Distinguish `yield` as a keyword vs an identifier (issue 1186)
+ * Support ES6 meta property `new.target` (issue 1203)
+ * Fix the syntax node for yield with expression (issue 1223)
+ * Fix the check of duplicated proto in property names (issue 1225)
+ * Fix ES6 Unicode escape in identifier name (issue 1229)
+ * Support ES6 IdentifierStart and IdentifierPart (issue 1232)
+ * Treat await as a reserved word when parsing as a module (issue 1234)
+ * Recognize identifier characters from Unicode SMP (issue 1244)
+ * Ensure that export and import can be followed by a comma (issue 1250)
+ * Fix yield operator precedence (issue 1262)
+
+2015-07-01: Version 2.4.1
+
+ * Fix some cases of comment attachment (issue 1071, 1175)
+ * Fix the handling of destructuring in function arguments (issue 1193)
+ * Fix invalid ranges in assignment expression (issue 1201)
+
+2015-06-26: Version 2.4.0
+
+ * Support ES6 for-of iteration (issue 1047)
+ * Support ES6 spread arguments (issue 1169)
+ * Minimize npm payload (issue 1191)
+
+2015-06-16: Version 2.3.0
+
+ * Support ES6 generator (issue 1033)
+ * Improve parsing of regular expressions with `u` flag (issue 1179)
+
+2015-04-17: Version 2.2.0
+
+ * Support ES6 import and export declarations (issue 1000)
+ * Fix line terminator before arrow not recognized as error (issue 1009)
+ * Support ES6 destructuring (issue 1045)
+ * Support ES6 template literal (issue 1074)
+ * Fix the handling of invalid/incomplete string escape sequences (issue 1106)
+ * Fix ES3 static member access restriction (issue 1120)
+ * Support for `super` in ES6 class (issue 1147)
+
+2015-03-09: Version 2.1.0
+
+ * Support ES6 class (issue 1001)
+ * Support ES6 rest parameter (issue 1011)
+ * Expand the location of property getter, setter, and methods (issue 1029)
+ * Enable TryStatement transition to a single handler (issue 1031)
+ * Support ES6 computed property name (issue 1037)
+ * Tolerate unclosed block comment (issue 1041)
+ * Support ES6 lexical declaration (issue 1065)
+
+2015-02-06: Version 2.0.0
+
+ * Support ES6 arrow function (issue 517)
+ * Support ES6 Unicode code point escape (issue 521)
+ * Improve the speed and accuracy of comment attachment (issue 522)
+ * Support ES6 default parameter (issue 519)
+ * Support ES6 regular expression flags (issue 557)
+ * Fix scanning of implicit octal literals (issue 565)
+ * Fix the handling of automatic semicolon insertion (issue 574)
+ * Support ES6 method definition (issue 620)
+ * Support ES6 octal integer literal (issue 621)
+ * Support ES6 binary integer literal (issue 622)
+ * Support ES6 object literal property value shorthand (issue 624)
+
+2015-03-03: Version 1.2.5
+
+ * Fix scanning of implicit octal literals (issue 565)
+
+2015-02-05: Version 1.2.4
+
+ * Fix parsing of LeftHandSideExpression in ForInStatement (issue 560)
+ * Fix the handling of automatic semicolon insertion (issue 574)
+
+2015-01-18: Version 1.2.3
+
+ * Fix division by this (issue 616)
+
+2014-05-18: Version 1.2.2
+
+ * Fix duplicated tokens when collecting comments (issue 537)
+
+2014-05-04: Version 1.2.1
+
+ * Ensure that Program node may still have leading comments (issue 536)
+
+2014-04-29: Version 1.2.0
+
+ * Fix semicolon handling for expression statement (issue 462, 533)
+ * Disallow escaped characters in regular expression flags (issue 503)
+ * Performance improvement for location tracking (issue 520)
+ * Improve the speed of comment attachment (issue 522)
+
+2014-03-26: Version 1.1.1
+
+ * Fix token handling of forward slash after an array literal (issue 512)
+
+2014-03-23: Version 1.1.0
+
+ * Optionally attach comments to the owning syntax nodes (issue 197)
+ * Simplify binary parsing with stack-based shift reduce (issue 352)
+ * Always include the raw source of literals (issue 376)
+ * Add optional input source information (issue 386)
+ * Tokenizer API for pure lexical scanning (issue 398)
+ * Improve the web site and its online demos (issue 337, 400, 404)
+ * Performance improvement for location tracking (issue 417, 424)
+ * Support HTML comment syntax (issue 451)
+ * Drop support for legacy browsers (issue 474)
+
+2013-08-27: Version 1.0.4
+
+ * Minimize the payload for packages (issue 362)
+ * Fix missing cases on an empty switch statement (issue 436)
+ * Support escaped ] in regexp literal character classes (issue 442)
+ * Tolerate invalid left-hand side expression (issue 130)
+
+2013-05-17: Version 1.0.3
+
+ * Variable declaration needs at least one declarator (issue 391)
+ * Fix benchmark's variance unit conversion (issue 397)
+ * IE < 9: \v should be treated as vertical tab (issue 405)
+ * Unary expressions should always have prefix: true (issue 418)
+ * Catch clause should only accept an identifier (issue 423)
+ * Tolerate setters without parameter (issue 426)
+
+2012-11-02: Version 1.0.2
+
+ Improvement:
+
+ * Fix esvalidate JUnit output upon a syntax error (issue 374)
+
+2012-10-28: Version 1.0.1
+
+ Improvements:
+
+ * esvalidate understands shebang in a Unix shell script (issue 361)
+ * esvalidate treats fatal parsing failure as an error (issue 361)
+ * Reduce Node.js package via .npmignore (issue 362)
+
+2012-10-22: Version 1.0.0
+
+ Initial release.
diff --git a/node_modules/svgo/node_modules/esprima/LICENSE.BSD b/node_modules/svgo/node_modules/esprima/LICENSE.BSD
new file mode 100644
index 00000000..17557ece
--- /dev/null
+++ b/node_modules/svgo/node_modules/esprima/LICENSE.BSD
@@ -0,0 +1,21 @@
+Copyright (c) jQuery Foundation, Inc. and Contributors, All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/node_modules/svgo/node_modules/esprima/README.md b/node_modules/svgo/node_modules/esprima/README.md
new file mode 100644
index 00000000..749454f4
--- /dev/null
+++ b/node_modules/svgo/node_modules/esprima/README.md
@@ -0,0 +1,27 @@
+[![NPM version](https://img.shields.io/npm/v/esprima.svg)](https://www.npmjs.com/package/esprima)
+[![npm download](https://img.shields.io/npm/dm/esprima.svg)](https://www.npmjs.com/package/esprima)
+[![Build Status](https://img.shields.io/travis/jquery/esprima/master.svg)](https://travis-ci.org/jquery/esprima)
+[![Coverage Status](https://img.shields.io/codecov/c/github/jquery/esprima/master.svg)](https://codecov.io/github/jquery/esprima)
+
+**Esprima** ([esprima.org](http://esprima.org), BSD license) is a high performance,
+standard-compliant [ECMAScript](http://www.ecma-international.org/publications/standards/Ecma-262.htm)
+parser written in ECMAScript (also popularly known as
+[JavaScript](https://en.wikipedia.org/wiki/JavaScript)).
+Esprima is created and maintained by [Ariya Hidayat](https://twitter.com/ariyahidayat),
+with the help of [many contributors](https://github.com/jquery/esprima/contributors).
+
+### Features
+
+- Full support for ECMAScript 6 ([ECMA-262](http://www.ecma-international.org/publications/standards/Ecma-262.htm))
+- Sensible [syntax tree format](https://github.com/estree/estree/blob/master/spec.md) as standardized by [ESTree project](https://github.com/estree/estree)
+- Optional tracking of syntax node location (index-based and line-column)
+- [Heavily tested](http://esprima.org/test/ci.html) (~1250 [unit tests](https://github.com/jquery/esprima/tree/master/test/fixtures) with [full code coverage](https://codecov.io/github/jquery/esprima))
+
+Esprima serves as a **building block** for some JavaScript
+language tools, from [code instrumentation](http://esprima.org/demo/functiontrace.html)
+to [editor autocompletion](http://esprima.org/demo/autocomplete.html).
+
+Esprima runs on many popular web browsers, as well as other ECMAScript platforms such as
+[Rhino](http://www.mozilla.org/rhino), [Nashorn](http://openjdk.java.net/projects/nashorn/), and [Node.js](https://npmjs.org/package/esprima).
+
+For more information, check the web site [esprima.org](http://esprima.org).
diff --git a/node_modules/svgo/node_modules/esprima/bin/esparse.js b/node_modules/svgo/node_modules/esprima/bin/esparse.js
new file mode 100755
index 00000000..98bdbf48
--- /dev/null
+++ b/node_modules/svgo/node_modules/esprima/bin/esparse.js
@@ -0,0 +1,126 @@
+#!/usr/bin/env node
+/*
+ Copyright (c) jQuery Foundation, Inc. and Contributors, All Rights Reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*jslint sloppy:true node:true rhino:true */
+
+var fs, esprima, fname, content, options, syntax;
+
+if (typeof require === 'function') {
+ fs = require('fs');
+ esprima = require('esprima');
+} else if (typeof load === 'function') {
+ try {
+ load('esprima.js');
+ } catch (e) {
+ load('../esprima.js');
+ }
+}
+
+// Shims to Node.js objects when running under Rhino.
+if (typeof console === 'undefined' && typeof process === 'undefined') {
+ console = { log: print };
+ fs = { readFileSync: readFile };
+ process = { argv: arguments, exit: quit };
+ process.argv.unshift('esparse.js');
+ process.argv.unshift('rhino');
+}
+
+function showUsage() {
+ console.log('Usage:');
+ console.log(' esparse [options] file.js');
+ console.log();
+ console.log('Available options:');
+ console.log();
+ console.log(' --comment Gather all line and block comments in an array');
+ console.log(' --loc Include line-column location info for each syntax node');
+ console.log(' --range Include index-based range for each syntax node');
+ console.log(' --raw Display the raw value of literals');
+ console.log(' --tokens List all tokens in an array');
+ console.log(' --tolerant Tolerate errors on a best-effort basis (experimental)');
+ console.log(' -v, --version Shows program version');
+ console.log();
+ process.exit(1);
+}
+
+if (process.argv.length <= 2) {
+ showUsage();
+}
+
+options = {};
+
+process.argv.splice(2).forEach(function (entry) {
+
+ if (entry === '-h' || entry === '--help') {
+ showUsage();
+ } else if (entry === '-v' || entry === '--version') {
+ console.log('ECMAScript Parser (using Esprima version', esprima.version, ')');
+ console.log();
+ process.exit(0);
+ } else if (entry === '--comment') {
+ options.comment = true;
+ } else if (entry === '--loc') {
+ options.loc = true;
+ } else if (entry === '--range') {
+ options.range = true;
+ } else if (entry === '--raw') {
+ options.raw = true;
+ } else if (entry === '--tokens') {
+ options.tokens = true;
+ } else if (entry === '--tolerant') {
+ options.tolerant = true;
+ } else if (entry.slice(0, 2) === '--') {
+ console.log('Error: unknown option ' + entry + '.');
+ process.exit(1);
+ } else if (typeof fname === 'string') {
+ console.log('Error: more than one input file.');
+ process.exit(1);
+ } else {
+ fname = entry;
+ }
+});
+
+if (typeof fname !== 'string') {
+ console.log('Error: no input file.');
+ process.exit(1);
+}
+
+// Special handling for regular expression literal since we need to
+// convert it to a string literal, otherwise it will be decoded
+// as object "{}" and the regular expression would be lost.
+function adjustRegexLiteral(key, value) {
+ if (key === 'value' && value instanceof RegExp) {
+ value = value.toString();
+ }
+ return value;
+}
+
+try {
+ content = fs.readFileSync(fname, 'utf-8');
+ syntax = esprima.parse(content, options);
+ console.log(JSON.stringify(syntax, adjustRegexLiteral, 4));
+} catch (e) {
+ console.log('Error: ' + e.message);
+ process.exit(1);
+}
diff --git a/node_modules/svgo/node_modules/esprima/bin/esvalidate.js b/node_modules/svgo/node_modules/esprima/bin/esvalidate.js
new file mode 100755
index 00000000..f522dec2
--- /dev/null
+++ b/node_modules/svgo/node_modules/esprima/bin/esvalidate.js
@@ -0,0 +1,199 @@
+#!/usr/bin/env node
+/*
+ Copyright (c) jQuery Foundation, Inc. and Contributors, All Rights Reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*jslint sloppy:true plusplus:true node:true rhino:true */
+/*global phantom:true */
+
+var fs, system, esprima, options, fnames, count;
+
+if (typeof esprima === 'undefined') {
+ // PhantomJS can only require() relative files
+ if (typeof phantom === 'object') {
+ fs = require('fs');
+ system = require('system');
+ esprima = require('./esprima');
+ } else if (typeof require === 'function') {
+ fs = require('fs');
+ esprima = require('esprima');
+ } else if (typeof load === 'function') {
+ try {
+ load('esprima.js');
+ } catch (e) {
+ load('../esprima.js');
+ }
+ }
+}
+
+// Shims to Node.js objects when running under PhantomJS 1.7+.
+if (typeof phantom === 'object') {
+ fs.readFileSync = fs.read;
+ process = {
+ argv: [].slice.call(system.args),
+ exit: phantom.exit
+ };
+ process.argv.unshift('phantomjs');
+}
+
+// Shims to Node.js objects when running under Rhino.
+if (typeof console === 'undefined' && typeof process === 'undefined') {
+ console = { log: print };
+ fs = { readFileSync: readFile };
+ process = { argv: arguments, exit: quit };
+ process.argv.unshift('esvalidate.js');
+ process.argv.unshift('rhino');
+}
+
+function showUsage() {
+ console.log('Usage:');
+ console.log(' esvalidate [options] file.js');
+ console.log();
+ console.log('Available options:');
+ console.log();
+ console.log(' --format=type Set the report format, plain (default) or junit');
+ console.log(' -v, --version Print program version');
+ console.log();
+ process.exit(1);
+}
+
+if (process.argv.length <= 2) {
+ showUsage();
+}
+
+options = {
+ format: 'plain'
+};
+
+fnames = [];
+
+process.argv.splice(2).forEach(function (entry) {
+
+ if (entry === '-h' || entry === '--help') {
+ showUsage();
+ } else if (entry === '-v' || entry === '--version') {
+ console.log('ECMAScript Validator (using Esprima version', esprima.version, ')');
+ console.log();
+ process.exit(0);
+ } else if (entry.slice(0, 9) === '--format=') {
+ options.format = entry.slice(9);
+ if (options.format !== 'plain' && options.format !== 'junit') {
+ console.log('Error: unknown report format ' + options.format + '.');
+ process.exit(1);
+ }
+ } else if (entry.slice(0, 2) === '--') {
+ console.log('Error: unknown option ' + entry + '.');
+ process.exit(1);
+ } else {
+ fnames.push(entry);
+ }
+});
+
+if (fnames.length === 0) {
+ console.log('Error: no input file.');
+ process.exit(1);
+}
+
+if (options.format === 'junit') {
+ console.log('<?xml version="1.0" encoding="UTF-8"?>');
+ console.log('<testsuites>');
+}
+
+count = 0;
+fnames.forEach(function (fname) {
+ var content, timestamp, syntax, name;
+ try {
+ content = fs.readFileSync(fname, 'utf-8');
+
+ if (content[0] === '#' && content[1] === '!') {
+ content = '//' + content.substr(2, content.length);
+ }
+
+ timestamp = Date.now();
+ syntax = esprima.parse(content, { tolerant: true });
+
+ if (options.format === 'junit') {
+
+ name = fname;
+ if (name.lastIndexOf('/') >= 0) {
+ name = name.slice(name.lastIndexOf('/') + 1);
+ }
+
+ console.log('<testsuite name="' + fname + '" errors="0" ' +
+ ' failures="' + syntax.errors.length + '" ' +
+ ' tests="' + syntax.errors.length + '" ' +
+ ' time="' + Math.round((Date.now() - timestamp) / 1000) +
+ '">');
+
+ syntax.errors.forEach(function (error) {
+ var msg = error.message;
+ msg = msg.replace(/^Line\ [0-9]*\:\ /, '');
+ console.log(' <testcase name="Line ' + error.lineNumber + ': ' + msg + '" ' +
+ ' time="0">');
+ console.log(' <error type="SyntaxError" message="' + error.message + '">' +
+ error.message + '(' + name + ':' + error.lineNumber + ')' +
+ '</error>');
+ console.log(' </testcase>');
+ });
+
+ console.log('</testsuite>');
+
+ } else if (options.format === 'plain') {
+
+ syntax.errors.forEach(function (error) {
+ var msg = error.message;
+ msg = msg.replace(/^Line\ [0-9]*\:\ /, '');
+ msg = fname + ':' + error.lineNumber + ': ' + msg;
+ console.log(msg);
+ ++count;
+ });
+
+ }
+ } catch (e) {
+ ++count;
+ if (options.format === 'junit') {
+ console.log('<testsuite name="' + fname + '" errors="1" failures="0" tests="1" ' +
+ ' time="' + Math.round((Date.now() - timestamp) / 1000) + '">');
+ console.log(' <testcase name="' + e.message + '" ' + ' time="0">');
+ console.log(' <error type="ParseError" message="' + e.message + '">' +
+ e.message + '(' + fname + ((e.lineNumber) ? ':' + e.lineNumber : '') +
+ ')</error>');
+ console.log(' </testcase>');
+ console.log('</testsuite>');
+ } else {
+ console.log('Error: ' + e.message);
+ }
+ }
+});
+
+if (options.format === 'junit') {
+ console.log('</testsuites>');
+}
+
+if (count > 0) {
+ process.exit(1);
+}
+
+if (count === 0 && typeof phantom === 'object') {
+ process.exit(0);
+}
diff --git a/node_modules/svgo/node_modules/esprima/esprima.js b/node_modules/svgo/node_modules/esprima/esprima.js
new file mode 100644
index 00000000..0cb0a936
--- /dev/null
+++ b/node_modules/svgo/node_modules/esprima/esprima.js
@@ -0,0 +1,5740 @@
+/*
+ Copyright (c) jQuery Foundation, Inc. and Contributors, All Rights Reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+(function (root, factory) {
+ 'use strict';
+
+ // Universal Module Definition (UMD) to support AMD, CommonJS/Node.js,
+ // Rhino, and plain browser loading.
+
+ /* istanbul ignore next */
+ if (typeof define === 'function' && define.amd) {
+ define(['exports'], factory);
+ } else if (typeof exports !== 'undefined') {
+ factory(exports);
+ } else {
+ factory((root.esprima = {}));
+ }
+}(this, function (exports) {
+ 'use strict';
+
+ var Token,
+ TokenName,
+ FnExprTokens,
+ Syntax,
+ PlaceHolders,
+ Messages,
+ Regex,
+ source,
+ strict,
+ index,
+ lineNumber,
+ lineStart,
+ hasLineTerminator,
+ lastIndex,
+ lastLineNumber,
+ lastLineStart,
+ startIndex,
+ startLineNumber,
+ startLineStart,
+ scanning,
+ length,
+ lookahead,
+ state,
+ extra,
+ isBindingElement,
+ isAssignmentTarget,
+ firstCoverInitializedNameError;
+
+ Token = {
+ BooleanLiteral: 1,
+ EOF: 2,
+ Identifier: 3,
+ Keyword: 4,
+ NullLiteral: 5,
+ NumericLiteral: 6,
+ Punctuator: 7,
+ StringLiteral: 8,
+ RegularExpression: 9,
+ Template: 10
+ };
+
+ TokenName = {};
+ TokenName[Token.BooleanLiteral] = 'Boolean';
+ TokenName[Token.EOF] = '<end>';
+ TokenName[Token.Identifier] = 'Identifier';
+ TokenName[Token.Keyword] = 'Keyword';
+ TokenName[Token.NullLiteral] = 'Null';
+ TokenName[Token.NumericLiteral] = 'Numeric';
+ TokenName[Token.Punctuator] = 'Punctuator';
+ TokenName[Token.StringLiteral] = 'String';
+ TokenName[Token.RegularExpression] = 'RegularExpression';
+ TokenName[Token.Template] = 'Template';
+
+ // A function following one of those tokens is an expression.
+ FnExprTokens = ['(', '{', '[', 'in', 'typeof', 'instanceof', 'new',
+ 'return', 'case', 'delete', 'throw', 'void',
+ // assignment operators
+ '=', '+=', '-=', '*=', '/=', '%=', '<<=', '>>=', '>>>=',
+ '&=', '|=', '^=', ',',
+ // binary/unary operators
+ '+', '-', '*', '/', '%', '++', '--', '<<', '>>', '>>>', '&',
+ '|', '^', '!', '~', '&&', '||', '?', ':', '===', '==', '>=',
+ '<=', '<', '>', '!=', '!=='];
+
+ Syntax = {
+ AssignmentExpression: 'AssignmentExpression',
+ AssignmentPattern: 'AssignmentPattern',
+ ArrayExpression: 'ArrayExpression',
+ ArrayPattern: 'ArrayPattern',
+ ArrowFunctionExpression: 'ArrowFunctionExpression',
+ BlockStatement: 'BlockStatement',
+ BinaryExpression: 'BinaryExpression',
+ BreakStatement: 'BreakStatement',
+ CallExpression: 'CallExpression',
+ CatchClause: 'CatchClause',
+ ClassBody: 'ClassBody',
+ ClassDeclaration: 'ClassDeclaration',
+ ClassExpression: 'ClassExpression',
+ ConditionalExpression: 'ConditionalExpression',
+ ContinueStatement: 'ContinueStatement',
+ DoWhileStatement: 'DoWhileStatement',
+ DebuggerStatement: 'DebuggerStatement',
+ EmptyStatement: 'EmptyStatement',
+ ExportAllDeclaration: 'ExportAllDeclaration',
+ ExportDefaultDeclaration: 'ExportDefaultDeclaration',
+ ExportNamedDeclaration: 'ExportNamedDeclaration',
+ ExportSpecifier: 'ExportSpecifier',
+ ExpressionStatement: 'ExpressionStatement',
+ ForStatement: 'ForStatement',
+ ForOfStatement: 'ForOfStatement',
+ ForInStatement: 'ForInStatement',
+ FunctionDeclaration: 'FunctionDeclaration',
+ FunctionExpression: 'FunctionExpression',
+ Identifier: 'Identifier',
+ IfStatement: 'IfStatement',
+ ImportDeclaration: 'ImportDeclaration',
+ ImportDefaultSpecifier: 'ImportDefaultSpecifier',
+ ImportNamespaceSpecifier: 'ImportNamespaceSpecifier',
+ ImportSpecifier: 'ImportSpecifier',
+ Literal: 'Literal',
+ LabeledStatement: 'LabeledStatement',
+ LogicalExpression: 'LogicalExpression',
+ MemberExpression: 'MemberExpression',
+ MetaProperty: 'MetaProperty',
+ MethodDefinition: 'MethodDefinition',
+ NewExpression: 'NewExpression',
+ ObjectExpression: 'ObjectExpression',
+ ObjectPattern: 'ObjectPattern',
+ Program: 'Program',
+ Property: 'Property',
+ RestElement: 'RestElement',
+ ReturnStatement: 'ReturnStatement',
+ SequenceExpression: 'SequenceExpression',
+ SpreadElement: 'SpreadElement',
+ Super: 'Super',
+ SwitchCase: 'SwitchCase',
+ SwitchStatement: 'SwitchStatement',
+ TaggedTemplateExpression: 'TaggedTemplateExpression',
+ TemplateElement: 'TemplateElement',
+ TemplateLiteral: 'TemplateLiteral',
+ ThisExpression: 'ThisExpression',
+ ThrowStatement: 'ThrowStatement',
+ TryStatement: 'TryStatement',
+ UnaryExpression: 'UnaryExpression',
+ UpdateExpression: 'UpdateExpression',
+ VariableDeclaration: 'VariableDeclaration',
+ VariableDeclarator: 'VariableDeclarator',
+ WhileStatement: 'WhileStatement',
+ WithStatement: 'WithStatement',
+ YieldExpression: 'YieldExpression'
+ };
+
+ PlaceHolders = {
+ ArrowParameterPlaceHolder: 'ArrowParameterPlaceHolder'
+ };
+
+ // Error messages should be identical to V8.
+ Messages = {
+ UnexpectedToken: 'Unexpected token %0',
+ UnexpectedNumber: 'Unexpected number',
+ UnexpectedString: 'Unexpected string',
+ UnexpectedIdentifier: 'Unexpected identifier',
+ UnexpectedReserved: 'Unexpected reserved word',
+ UnexpectedTemplate: 'Unexpected quasi %0',
+ UnexpectedEOS: 'Unexpected end of input',
+ NewlineAfterThrow: 'Illegal newline after throw',
+ InvalidRegExp: 'Invalid regular expression',
+ UnterminatedRegExp: 'Invalid regular expression: missing /',
+ InvalidLHSInAssignment: 'Invalid left-hand side in assignment',
+ InvalidLHSInForIn: 'Invalid left-hand side in for-in',
+ InvalidLHSInForLoop: 'Invalid left-hand side in for-loop',
+ MultipleDefaultsInSwitch: 'More than one default clause in switch statement',
+ NoCatchOrFinally: 'Missing catch or finally after try',
+ UnknownLabel: 'Undefined label \'%0\'',
+ Redeclaration: '%0 \'%1\' has already been declared',
+ IllegalContinue: 'Illegal continue statement',
+ IllegalBreak: 'Illegal break statement',
+ IllegalReturn: 'Illegal return statement',
+ StrictModeWith: 'Strict mode code may not include a with statement',
+ StrictCatchVariable: 'Catch variable may not be eval or arguments in strict mode',
+ StrictVarName: 'Variable name may not be eval or arguments in strict mode',
+ StrictParamName: 'Parameter name eval or arguments is not allowed in strict mode',
+ StrictParamDupe: 'Strict mode function may not have duplicate parameter names',
+ StrictFunctionName: 'Function name may not be eval or arguments in strict mode',
+ StrictOctalLiteral: 'Octal literals are not allowed in strict mode.',
+ StrictDelete: 'Delete of an unqualified identifier in strict mode.',
+ StrictLHSAssignment: 'Assignment to eval or arguments is not allowed in strict mode',
+ StrictLHSPostfix: 'Postfix increment/decrement may not have eval or arguments operand in strict mode',
+ StrictLHSPrefix: 'Prefix increment/decrement may not have eval or arguments operand in strict mode',
+ StrictReservedWord: 'Use of future reserved word in strict mode',
+ TemplateOctalLiteral: 'Octal literals are not allowed in template strings.',
+ ParameterAfterRestParameter: 'Rest parameter must be last formal parameter',
+ DefaultRestParameter: 'Unexpected token =',
+ ObjectPatternAsRestParameter: 'Unexpected token {',
+ DuplicateProtoProperty: 'Duplicate __proto__ fields are not allowed in object literals',
+ ConstructorSpecialMethod: 'Class constructor may not be an accessor',
+ DuplicateConstructor: 'A class may only have one constructor',
+ StaticPrototype: 'Classes may not have static property named prototype',
+ MissingFromClause: 'Unexpected token',
+ NoAsAfterImportNamespace: 'Unexpected token',
+ InvalidModuleSpecifier: 'Unexpected token',
+ IllegalImportDeclaration: 'Unexpected token',
+ IllegalExportDeclaration: 'Unexpected token',
+ DuplicateBinding: 'Duplicate binding %0'
+ };
+
+ // See also tools/generate-unicode-regex.js.
+ Regex = {
+ // ECMAScript 6/Unicode v7.0.0 NonAsciiIdentifierStart:
+ NonAsciiIdentifierStart: /[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0-\u08B2\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58\u0C59\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D60\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19C1-\u19C7\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2118-\u211D\u2124\u2126\u2128\u212A-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309B-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA7AD\uA7B0\uA7B1\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB5F\uAB64\uAB65\uABC0-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDE80-\uDE9C\uDEA0-\uDED0\uDF00-\uDF1F\uDF30-\uDF4A\uDF50-\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE4\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48]|\uD804[\uDC03-\uDC37\uDC83-\uDCAF\uDCD0-\uDCE8\uDD03-\uDD26\uDD50-\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDDA\uDE00-\uDE11\uDE13-\uDE2B\uDEB0-\uDEDE\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF5D-\uDF61]|\uD805[\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDD80-\uDDAE\uDE00-\uDE2F\uDE44\uDE80-\uDEAA]|\uD806[\uDCA0-\uDCDF\uDCFF\uDEC0-\uDEF8]|\uD808[\uDC00-\uDF98]|\uD809[\uDC00-\uDC6E]|[\uD80C\uD840-\uD868\uD86A-\uD86C][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50\uDF93-\uDF9F]|\uD82C[\uDC00\uDC01]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB]|\uD83A[\uDC00-\uDCC4]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D]|\uD87E[\uDC00-\uDE1D]/,
+
+ // ECMAScript 6/Unicode v7.0.0 NonAsciiIdentifierPart:
+ NonAsciiIdentifierPart: /[\xAA\xB5\xB7\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0300-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u0483-\u0487\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u05D0-\u05EA\u05F0-\u05F2\u0610-\u061A\u0620-\u0669\u066E-\u06D3\u06D5-\u06DC\u06DF-\u06E8\u06EA-\u06FC\u06FF\u0710-\u074A\u074D-\u07B1\u07C0-\u07F5\u07FA\u0800-\u082D\u0840-\u085B\u08A0-\u08B2\u08E4-\u0963\u0966-\u096F\u0971-\u0983\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BC-\u09C4\u09C7\u09C8\u09CB-\u09CE\u09D7\u09DC\u09DD\u09DF-\u09E3\u09E6-\u09F1\u0A01-\u0A03\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A59-\u0A5C\u0A5E\u0A66-\u0A75\u0A81-\u0A83\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABC-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AD0\u0AE0-\u0AE3\u0AE6-\u0AEF\u0B01-\u0B03\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3C-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B5C\u0B5D\u0B5F-\u0B63\u0B66-\u0B6F\u0B71\u0B82\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD0\u0BD7\u0BE6-\u0BEF\u0C00-\u0C03\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C58\u0C59\u0C60-\u0C63\u0C66-\u0C6F\u0C81-\u0C83\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBC-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CDE\u0CE0-\u0CE3\u0CE6-\u0CEF\u0CF1\u0CF2\u0D01-\u0D03\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D-\u0D44\u0D46-\u0D48\u0D4A-\u0D4E\u0D57\u0D60-\u0D63\u0D66-\u0D6F\u0D7A-\u0D7F\u0D82\u0D83\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DE6-\u0DEF\u0DF2\u0DF3\u0E01-\u0E3A\u0E40-\u0E4E\u0E50-\u0E59\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB9\u0EBB-\u0EBD\u0EC0-\u0EC4\u0EC6\u0EC8-\u0ECD\u0ED0-\u0ED9\u0EDC-\u0EDF\u0F00\u0F18\u0F19\u0F20-\u0F29\u0F35\u0F37\u0F39\u0F3E-\u0F47\u0F49-\u0F6C\u0F71-\u0F84\u0F86-\u0F97\u0F99-\u0FBC\u0FC6\u1000-\u1049\u1050-\u109D\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u135D-\u135F\u1369-\u1371\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176C\u176E-\u1770\u1772\u1773\u1780-\u17D3\u17D7\u17DC\u17DD\u17E0-\u17E9\u180B-\u180D\u1810-\u1819\u1820-\u1877\u1880-\u18AA\u18B0-\u18F5\u1900-\u191E\u1920-\u192B\u1930-\u193B\u1946-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u19D0-\u19DA\u1A00-\u1A1B\u1A20-\u1A5E\u1A60-\u1A7C\u1A7F-\u1A89\u1A90-\u1A99\u1AA7\u1AB0-\u1ABD\u1B00-\u1B4B\u1B50-\u1B59\u1B6B-\u1B73\u1B80-\u1BF3\u1C00-\u1C37\u1C40-\u1C49\u1C4D-\u1C7D\u1CD0-\u1CD2\u1CD4-\u1CF6\u1CF8\u1CF9\u1D00-\u1DF5\u1DFC-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u200C\u200D\u203F\u2040\u2054\u2071\u207F\u2090-\u209C\u20D0-\u20DC\u20E1\u20E5-\u20F0\u2102\u2107\u210A-\u2113\u2115\u2118-\u211D\u2124\u2126\u2128\u212A-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D7F-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2DE0-\u2DFF\u3005-\u3007\u3021-\u302F\u3031-\u3035\u3038-\u303C\u3041-\u3096\u3099-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA62B\uA640-\uA66F\uA674-\uA67D\uA67F-\uA69D\uA69F-\uA6F1\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA7AD\uA7B0\uA7B1\uA7F7-\uA827\uA840-\uA873\uA880-\uA8C4\uA8D0-\uA8D9\uA8E0-\uA8F7\uA8FB\uA900-\uA92D\uA930-\uA953\uA960-\uA97C\uA980-\uA9C0\uA9CF-\uA9D9\uA9E0-\uA9FE\uAA00-\uAA36\uAA40-\uAA4D\uAA50-\uAA59\uAA60-\uAA76\uAA7A-\uAAC2\uAADB-\uAADD\uAAE0-\uAAEF\uAAF2-\uAAF6\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB5F\uAB64\uAB65\uABC0-\uABEA\uABEC\uABED\uABF0-\uABF9\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE00-\uFE0F\uFE20-\uFE2D\uFE33\uFE34\uFE4D-\uFE4F\uFE70-\uFE74\uFE76-\uFEFC\uFF10-\uFF19\uFF21-\uFF3A\uFF3F\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDDFD\uDE80-\uDE9C\uDEA0-\uDED0\uDEE0\uDF00-\uDF1F\uDF30-\uDF4A\uDF50-\uDF7A\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDCA0-\uDCA9\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00-\uDE03\uDE05\uDE06\uDE0C-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE38-\uDE3A\uDE3F\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE6\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48]|\uD804[\uDC00-\uDC46\uDC66-\uDC6F\uDC7F-\uDCBA\uDCD0-\uDCE8\uDCF0-\uDCF9\uDD00-\uDD34\uDD36-\uDD3F\uDD50-\uDD73\uDD76\uDD80-\uDDC4\uDDD0-\uDDDA\uDE00-\uDE11\uDE13-\uDE37\uDEB0-\uDEEA\uDEF0-\uDEF9\uDF01-\uDF03\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3C-\uDF44\uDF47\uDF48\uDF4B-\uDF4D\uDF57\uDF5D-\uDF63\uDF66-\uDF6C\uDF70-\uDF74]|\uD805[\uDC80-\uDCC5\uDCC7\uDCD0-\uDCD9\uDD80-\uDDB5\uDDB8-\uDDC0\uDE00-\uDE40\uDE44\uDE50-\uDE59\uDE80-\uDEB7\uDEC0-\uDEC9]|\uD806[\uDCA0-\uDCE9\uDCFF\uDEC0-\uDEF8]|\uD808[\uDC00-\uDF98]|\uD809[\uDC00-\uDC6E]|[\uD80C\uD840-\uD868\uD86A-\uD86C][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDE60-\uDE69\uDED0-\uDEED\uDEF0-\uDEF4\uDF00-\uDF36\uDF40-\uDF43\uDF50-\uDF59\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50-\uDF7E\uDF8F-\uDF9F]|\uD82C[\uDC00\uDC01]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99\uDC9D\uDC9E]|\uD834[\uDD65-\uDD69\uDD6D-\uDD72\uDD7B-\uDD82\uDD85-\uDD8B\uDDAA-\uDDAD\uDE42-\uDE44]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB\uDFCE-\uDFFF]|\uD83A[\uDC00-\uDCC4\uDCD0-\uDCD6]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D]|\uD87E[\uDC00-\uDE1D]|\uDB40[\uDD00-\uDDEF]/
+ };
+
+ // Ensure the condition is true, otherwise throw an error.
+ // This is only to have a better contract semantic, i.e. another safety net
+ // to catch a logic error. The condition shall be fulfilled in normal case.
+ // Do NOT use this to enforce a certain condition on any user input.
+
+ function assert(condition, message) {
+ /* istanbul ignore if */
+ if (!condition) {
+ throw new Error('ASSERT: ' + message);
+ }
+ }
+
+ function isDecimalDigit(ch) {
+ return (ch >= 0x30 && ch <= 0x39); // 0..9
+ }
+
+ function isHexDigit(ch) {
+ return '0123456789abcdefABCDEF'.indexOf(ch) >= 0;
+ }
+
+ function isOctalDigit(ch) {
+ return '01234567'.indexOf(ch) >= 0;
+ }
+
+ function octalToDecimal(ch) {
+ // \0 is not octal escape sequence
+ var octal = (ch !== '0'), code = '01234567'.indexOf(ch);
+
+ if (index < length && isOctalDigit(source[index])) {
+ octal = true;
+ code = code * 8 + '01234567'.indexOf(source[index++]);
+
+ // 3 digits are only allowed when string starts
+ // with 0, 1, 2, 3
+ if ('0123'.indexOf(ch) >= 0 &&
+ index < length &&
+ isOctalDigit(source[index])) {
+ code = code * 8 + '01234567'.indexOf(source[index++]);
+ }
+ }
+
+ return {
+ code: code,
+ octal: octal
+ };
+ }
+
+ // ECMA-262 11.2 White Space
+
+ function isWhiteSpace(ch) {
+ return (ch === 0x20) || (ch === 0x09) || (ch === 0x0B) || (ch === 0x0C) || (ch === 0xA0) ||
+ (ch >= 0x1680 && [0x1680, 0x180E, 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007, 0x2008, 0x2009, 0x200A, 0x202F, 0x205F, 0x3000, 0xFEFF].indexOf(ch) >= 0);
+ }
+
+ // ECMA-262 11.3 Line Terminators
+
+ function isLineTerminator(ch) {
+ return (ch === 0x0A) || (ch === 0x0D) || (ch === 0x2028) || (ch === 0x2029);
+ }
+
+ // ECMA-262 11.6 Identifier Names and Identifiers
+
+ function fromCodePoint(cp) {
+ return (cp < 0x10000) ? String.fromCharCode(cp) :
+ String.fromCharCode(0xD800 + ((cp - 0x10000) >> 10)) +
+ String.fromCharCode(0xDC00 + ((cp - 0x10000) & 1023));
+ }
+
+ function isIdentifierStart(ch) {
+ return (ch === 0x24) || (ch === 0x5F) || // $ (dollar) and _ (underscore)
+ (ch >= 0x41 && ch <= 0x5A) || // A..Z
+ (ch >= 0x61 && ch <= 0x7A) || // a..z
+ (ch === 0x5C) || // \ (backslash)
+ ((ch >= 0x80) && Regex.NonAsciiIdentifierStart.test(fromCodePoint(ch)));
+ }
+
+ function isIdentifierPart(ch) {
+ return (ch === 0x24) || (ch === 0x5F) || // $ (dollar) and _ (underscore)
+ (ch >= 0x41 && ch <= 0x5A) || // A..Z
+ (ch >= 0x61 && ch <= 0x7A) || // a..z
+ (ch >= 0x30 && ch <= 0x39) || // 0..9
+ (ch === 0x5C) || // \ (backslash)
+ ((ch >= 0x80) && Regex.NonAsciiIdentifierPart.test(fromCodePoint(ch)));
+ }
+
+ // ECMA-262 11.6.2.2 Future Reserved Words
+
+ function isFutureReservedWord(id) {
+ switch (id) {
+ case 'enum':
+ case 'export':
+ case 'import':
+ case 'super':
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ function isStrictModeReservedWord(id) {
+ switch (id) {
+ case 'implements':
+ case 'interface':
+ case 'package':
+ case 'private':
+ case 'protected':
+ case 'public':
+ case 'static':
+ case 'yield':
+ case 'let':
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ function isRestrictedWord(id) {
+ return id === 'eval' || id === 'arguments';
+ }
+
+ // ECMA-262 11.6.2.1 Keywords
+
+ function isKeyword(id) {
+ switch (id.length) {
+ case 2:
+ return (id === 'if') || (id === 'in') || (id === 'do');
+ case 3:
+ return (id === 'var') || (id === 'for') || (id === 'new') ||
+ (id === 'try') || (id === 'let');
+ case 4:
+ return (id === 'this') || (id === 'else') || (id === 'case') ||
+ (id === 'void') || (id === 'with') || (id === 'enum');
+ case 5:
+ return (id === 'while') || (id === 'break') || (id === 'catch') ||
+ (id === 'throw') || (id === 'const') || (id === 'yield') ||
+ (id === 'class') || (id === 'super');
+ case 6:
+ return (id === 'return') || (id === 'typeof') || (id === 'delete') ||
+ (id === 'switch') || (id === 'export') || (id === 'import');
+ case 7:
+ return (id === 'default') || (id === 'finally') || (id === 'extends');
+ case 8:
+ return (id === 'function') || (id === 'continue') || (id === 'debugger');
+ case 10:
+ return (id === 'instanceof');
+ default:
+ return false;
+ }
+ }
+
+ // ECMA-262 11.4 Comments
+
+ function addComment(type, value, start, end, loc) {
+ var comment;
+
+ assert(typeof start === 'number', 'Comment must have valid position');
+
+ state.lastCommentStart = start;
+
+ comment = {
+ type: type,
+ value: value
+ };
+ if (extra.range) {
+ comment.range = [start, end];
+ }
+ if (extra.loc) {
+ comment.loc = loc;
+ }
+ extra.comments.push(comment);
+ if (extra.attachComment) {
+ extra.leadingComments.push(comment);
+ extra.trailingComments.push(comment);
+ }
+ if (extra.tokenize) {
+ comment.type = comment.type + 'Comment';
+ if (extra.delegate) {
+ comment = extra.delegate(comment);
+ }
+ extra.tokens.push(comment);
+ }
+ }
+
+ function skipSingleLineComment(offset) {
+ var start, loc, ch, comment;
+
+ start = index - offset;
+ loc = {
+ start: {
+ line: lineNumber,
+ column: index - lineStart - offset
+ }
+ };
+
+ while (index < length) {
+ ch = source.charCodeAt(index);
+ ++index;
+ if (isLineTerminator(ch)) {
+ hasLineTerminator = true;
+ if (extra.comments) {
+ comment = source.slice(start + offset, index - 1);
+ loc.end = {
+ line: lineNumber,
+ column: index - lineStart - 1
+ };
+ addComment('Line', comment, start, index - 1, loc);
+ }
+ if (ch === 13 && source.charCodeAt(index) === 10) {
+ ++index;
+ }
+ ++lineNumber;
+ lineStart = index;
+ return;
+ }
+ }
+
+ if (extra.comments) {
+ comment = source.slice(start + offset, index);
+ loc.end = {
+ line: lineNumber,
+ column: index - lineStart
+ };
+ addComment('Line', comment, start, index, loc);
+ }
+ }
+
+ function skipMultiLineComment() {
+ var start, loc, ch, comment;
+
+ if (extra.comments) {
+ start = index - 2;
+ loc = {
+ start: {
+ line: lineNumber,
+ column: index - lineStart - 2
+ }
+ };
+ }
+
+ while (index < length) {
+ ch = source.charCodeAt(index);
+ if (isLineTerminator(ch)) {
+ if (ch === 0x0D && source.charCodeAt(index + 1) === 0x0A) {
+ ++index;
+ }
+ hasLineTerminator = true;
+ ++lineNumber;
+ ++index;
+ lineStart = index;
+ } else if (ch === 0x2A) {
+ // Block comment ends with '*/'.
+ if (source.charCodeAt(index + 1) === 0x2F) {
+ ++index;
+ ++index;
+ if (extra.comments) {
+ comment = source.slice(start + 2, index - 2);
+ loc.end = {
+ line: lineNumber,
+ column: index - lineStart
+ };
+ addComment('Block', comment, start, index, loc);
+ }
+ return;
+ }
+ ++index;
+ } else {
+ ++index;
+ }
+ }
+
+ // Ran off the end of the file - the whole thing is a comment
+ if (extra.comments) {
+ loc.end = {
+ line: lineNumber,
+ column: index - lineStart
+ };
+ comment = source.slice(start + 2, index);
+ addComment('Block', comment, start, index, loc);
+ }
+ tolerateUnexpectedToken();
+ }
+
+ function skipComment() {
+ var ch, start;
+ hasLineTerminator = false;
+
+ start = (index === 0);
+ while (index < length) {
+ ch = source.charCodeAt(index);
+
+ if (isWhiteSpace(ch)) {
+ ++index;
+ } else if (isLineTerminator(ch)) {
+ hasLineTerminator = true;
+ ++index;
+ if (ch === 0x0D && source.charCodeAt(index) === 0x0A) {
+ ++index;
+ }
+ ++lineNumber;
+ lineStart = index;
+ start = true;
+ } else if (ch === 0x2F) { // U+002F is '/'
+ ch = source.charCodeAt(index + 1);
+ if (ch === 0x2F) {
+ ++index;
+ ++index;
+ skipSingleLineComment(2);
+ start = true;
+ } else if (ch === 0x2A) { // U+002A is '*'
+ ++index;
+ ++index;
+ skipMultiLineComment();
+ } else {
+ break;
+ }
+ } else if (start && ch === 0x2D) { // U+002D is '-'
+ // U+003E is '>'
+ if ((source.charCodeAt(index + 1) === 0x2D) && (source.charCodeAt(index + 2) === 0x3E)) {
+ // '-->' is a single-line comment
+ index += 3;
+ skipSingleLineComment(3);
+ } else {
+ break;
+ }
+ } else if (ch === 0x3C) { // U+003C is '<'
+ if (source.slice(index + 1, index + 4) === '!--') {
+ ++index; // `<`
+ ++index; // `!`
+ ++index; // `-`
+ ++index; // `-`
+ skipSingleLineComment(4);
+ } else {
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+ }
+
+ function scanHexEscape(prefix) {
+ var i, len, ch, code = 0;
+
+ len = (prefix === 'u') ? 4 : 2;
+ for (i = 0; i < len; ++i) {
+ if (index < length && isHexDigit(source[index])) {
+ ch = source[index++];
+ code = code * 16 + '0123456789abcdef'.indexOf(ch.toLowerCase());
+ } else {
+ return '';
+ }
+ }
+ return String.fromCharCode(code);
+ }
+
+ function scanUnicodeCodePointEscape() {
+ var ch, code;
+
+ ch = source[index];
+ code = 0;
+
+ // At least, one hex digit is required.
+ if (ch === '}') {
+ throwUnexpectedToken();
+ }
+
+ while (index < length) {
+ ch = source[index++];
+ if (!isHexDigit(ch)) {
+ break;
+ }
+ code = code * 16 + '0123456789abcdef'.indexOf(ch.toLowerCase());
+ }
+
+ if (code > 0x10FFFF || ch !== '}') {
+ throwUnexpectedToken();
+ }
+
+ return fromCodePoint(code);
+ }
+
+ function codePointAt(i) {
+ var cp, first, second;
+
+ cp = source.charCodeAt(i);
+ if (cp >= 0xD800 && cp <= 0xDBFF) {
+ second = source.charCodeAt(i + 1);
+ if (second >= 0xDC00 && second <= 0xDFFF) {
+ first = cp;
+ cp = (first - 0xD800) * 0x400 + second - 0xDC00 + 0x10000;
+ }
+ }
+
+ return cp;
+ }
+
+ function getComplexIdentifier() {
+ var cp, ch, id;
+
+ cp = codePointAt(index);
+ id = fromCodePoint(cp);
+ index += id.length;
+
+ // '\u' (U+005C, U+0075) denotes an escaped character.
+ if (cp === 0x5C) {
+ if (source.charCodeAt(index) !== 0x75) {
+ throwUnexpectedToken();
+ }
+ ++index;
+ if (source[index] === '{') {
+ ++index;
+ ch = scanUnicodeCodePointEscape();
+ } else {
+ ch = scanHexEscape('u');
+ cp = ch.charCodeAt(0);
+ if (!ch || ch === '\\' || !isIdentifierStart(cp)) {
+ throwUnexpectedToken();
+ }
+ }
+ id = ch;
+ }
+
+ while (index < length) {
+ cp = codePointAt(index);
+ if (!isIdentifierPart(cp)) {
+ break;
+ }
+ ch = fromCodePoint(cp);
+ id += ch;
+ index += ch.length;
+
+ // '\u' (U+005C, U+0075) denotes an escaped character.
+ if (cp === 0x5C) {
+ id = id.substr(0, id.length - 1);
+ if (source.charCodeAt(index) !== 0x75) {
+ throwUnexpectedToken();
+ }
+ ++index;
+ if (source[index] === '{') {
+ ++index;
+ ch = scanUnicodeCodePointEscape();
+ } else {
+ ch = scanHexEscape('u');
+ cp = ch.charCodeAt(0);
+ if (!ch || ch === '\\' || !isIdentifierPart(cp)) {
+ throwUnexpectedToken();
+ }
+ }
+ id += ch;
+ }
+ }
+
+ return id;
+ }
+
+ function getIdentifier() {
+ var start, ch;
+
+ start = index++;
+ while (index < length) {
+ ch = source.charCodeAt(index);
+ if (ch === 0x5C) {
+ // Blackslash (U+005C) marks Unicode escape sequence.
+ index = start;
+ return getComplexIdentifier();
+ } else if (ch >= 0xD800 && ch < 0xDFFF) {
+ // Need to handle surrogate pairs.
+ index = start;
+ return getComplexIdentifier();
+ }
+ if (isIdentifierPart(ch)) {
+ ++index;
+ } else {
+ break;
+ }
+ }
+
+ return source.slice(start, index);
+ }
+
+ function scanIdentifier() {
+ var start, id, type;
+
+ start = index;
+
+ // Backslash (U+005C) starts an escaped character.
+ id = (source.charCodeAt(index) === 0x5C) ? getComplexIdentifier() : getIdentifier();
+
+ // There is no keyword or literal with only one character.
+ // Thus, it must be an identifier.
+ if (id.length === 1) {
+ type = Token.Identifier;
+ } else if (isKeyword(id)) {
+ type = Token.Keyword;
+ } else if (id === 'null') {
+ type = Token.NullLiteral;
+ } else if (id === 'true' || id === 'false') {
+ type = Token.BooleanLiteral;
+ } else {
+ type = Token.Identifier;
+ }
+
+ return {
+ type: type,
+ value: id,
+ lineNumber: lineNumber,
+ lineStart: lineStart,
+ start: start,
+ end: index
+ };
+ }
+
+
+ // ECMA-262 11.7 Punctuators
+
+ function scanPunctuator() {
+ var token, str;
+
+ token = {
+ type: Token.Punctuator,
+ value: '',
+ lineNumber: lineNumber,
+ lineStart: lineStart,
+ start: index,
+ end: index
+ };
+
+ // Check for most common single-character punctuators.
+ str = source[index];
+ switch (str) {
+
+ case '(':
+ if (extra.tokenize) {
+ extra.openParenToken = extra.tokenValues.length;
+ }
+ ++index;
+ break;
+
+ case '{':
+ if (extra.tokenize) {
+ extra.openCurlyToken = extra.tokenValues.length;
+ }
+ state.curlyStack.push('{');
+ ++index;
+ break;
+
+ case '.':
+ ++index;
+ if (source[index] === '.' && source[index + 1] === '.') {
+ // Spread operator: ...
+ index += 2;
+ str = '...';
+ }
+ break;
+
+ case '}':
+ ++index;
+ state.curlyStack.pop();
+ break;
+ case ')':
+ case ';':
+ case ',':
+ case '[':
+ case ']':
+ case ':':
+ case '?':
+ case '~':
+ ++index;
+ break;
+
+ default:
+ // 4-character punctuator.
+ str = source.substr(index, 4);
+ if (str === '>>>=') {
+ index += 4;
+ } else {
+
+ // 3-character punctuators.
+ str = str.substr(0, 3);
+ if (str === '===' || str === '!==' || str === '>>>' ||
+ str === '<<=' || str === '>>=') {
+ index += 3;
+ } else {
+
+ // 2-character punctuators.
+ str = str.substr(0, 2);
+ if (str === '&&' || str === '||' || str === '==' || str === '!=' ||
+ str === '+=' || str === '-=' || str === '*=' || str === '/=' ||
+ str === '++' || str === '--' || str === '<<' || str === '>>' ||
+ str === '&=' || str === '|=' || str === '^=' || str === '%=' ||
+ str === '<=' || str === '>=' || str === '=>') {
+ index += 2;
+ } else {
+
+ // 1-character punctuators.
+ str = source[index];
+ if ('<>=!+-*%&|^/'.indexOf(str) >= 0) {
+ ++index;
+ }
+ }
+ }
+ }
+ }
+
+ if (index === token.start) {
+ throwUnexpectedToken();
+ }
+
+ token.end = index;
+ token.value = str;
+ return token;
+ }
+
+ // ECMA-262 11.8.3 Numeric Literals
+
+ function scanHexLiteral(start) {
+ var number = '';
+
+ while (index < length) {
+ if (!isHexDigit(source[index])) {
+ break;
+ }
+ number += source[index++];
+ }
+
+ if (number.length === 0) {
+ throwUnexpectedToken();
+ }
+
+ if (isIdentifierStart(source.charCodeAt(index))) {
+ throwUnexpectedToken();
+ }
+
+ return {
+ type: Token.NumericLiteral,
+ value: parseInt('0x' + number, 16),
+ lineNumber: lineNumber,
+ lineStart: lineStart,
+ start: start,
+ end: index
+ };
+ }
+
+ function scanBinaryLiteral(start) {
+ var ch, number;
+
+ number = '';
+
+ while (index < length) {
+ ch = source[index];
+ if (ch !== '0' && ch !== '1') {
+ break;
+ }
+ number += source[index++];
+ }
+
+ if (number.length === 0) {
+ // only 0b or 0B
+ throwUnexpectedToken();
+ }
+
+ if (index < length) {
+ ch = source.charCodeAt(index);
+ /* istanbul ignore else */
+ if (isIdentifierStart(ch) || isDecimalDigit(ch)) {
+ throwUnexpectedToken();
+ }
+ }
+
+ return {
+ type: Token.NumericLiteral,
+ value: parseInt(number, 2),
+ lineNumber: lineNumber,
+ lineStart: lineStart,
+ start: start,
+ end: index
+ };
+ }
+
+ function scanOctalLiteral(prefix, start) {
+ var number, octal;
+
+ if (isOctalDigit(prefix)) {
+ octal = true;
+ number = '0' + source[index++];
+ } else {
+ octal = false;
+ ++index;
+ number = '';
+ }
+
+ while (index < length) {
+ if (!isOctalDigit(source[index])) {
+ break;
+ }
+ number += source[index++];
+ }
+
+ if (!octal && number.length === 0) {
+ // only 0o or 0O
+ throwUnexpectedToken();
+ }
+
+ if (isIdentifierStart(source.charCodeAt(index)) || isDecimalDigit(source.charCodeAt(index))) {
+ throwUnexpectedToken();
+ }
+
+ return {
+ type: Token.NumericLiteral,
+ value: parseInt(number, 8),
+ octal: octal,
+ lineNumber: lineNumber,
+ lineStart: lineStart,
+ start: start,
+ end: index
+ };
+ }
+
+ function isImplicitOctalLiteral() {
+ var i, ch;
+
+ // Implicit octal, unless there is a non-octal digit.
+ // (Annex B.1.1 on Numeric Literals)
+ for (i = index + 1; i < length; ++i) {
+ ch = source[i];
+ if (ch === '8' || ch === '9') {
+ return false;
+ }
+ if (!isOctalDigit(ch)) {
+ return true;
+ }
+ }
+
+ return true;
+ }
+
+ function scanNumericLiteral() {
+ var number, start, ch;
+
+ ch = source[index];
+ assert(isDecimalDigit(ch.charCodeAt(0)) || (ch === '.'),
+ 'Numeric literal must start with a decimal digit or a decimal point');
+
+ start = index;
+ number = '';
+ if (ch !== '.') {
+ number = source[index++];
+ ch = source[index];
+
+ // Hex number starts with '0x'.
+ // Octal number starts with '0'.
+ // Octal number in ES6 starts with '0o'.
+ // Binary number in ES6 starts with '0b'.
+ if (number === '0') {
+ if (ch === 'x' || ch === 'X') {
+ ++index;
+ return scanHexLiteral(start);
+ }
+ if (ch === 'b' || ch === 'B') {
+ ++index;
+ return scanBinaryLiteral(start);
+ }
+ if (ch === 'o' || ch === 'O') {
+ return scanOctalLiteral(ch, start);
+ }
+
+ if (isOctalDigit(ch)) {
+ if (isImplicitOctalLiteral()) {
+ return scanOctalLiteral(ch, start);
+ }
+ }
+ }
+
+ while (isDecimalDigit(source.charCodeAt(index))) {
+ number += source[index++];
+ }
+ ch = source[index];
+ }
+
+ if (ch === '.') {
+ number += source[index++];
+ while (isDecimalDigit(source.charCodeAt(index))) {
+ number += source[index++];
+ }
+ ch = source[index];
+ }
+
+ if (ch === 'e' || ch === 'E') {
+ number += source[index++];
+
+ ch = source[index];
+ if (ch === '+' || ch === '-') {
+ number += source[index++];
+ }
+ if (isDecimalDigit(source.charCodeAt(index))) {
+ while (isDecimalDigit(source.charCodeAt(index))) {
+ number += source[index++];
+ }
+ } else {
+ throwUnexpectedToken();
+ }
+ }
+
+ if (isIdentifierStart(source.charCodeAt(index))) {
+ throwUnexpectedToken();
+ }
+
+ return {
+ type: Token.NumericLiteral,
+ value: parseFloat(number),
+ lineNumber: lineNumber,
+ lineStart: lineStart,
+ start: start,
+ end: index
+ };
+ }
+
+ // ECMA-262 11.8.4 String Literals
+
+ function scanStringLiteral() {
+ var str = '', quote, start, ch, unescaped, octToDec, octal = false;
+
+ quote = source[index];
+ assert((quote === '\'' || quote === '"'),
+ 'String literal must starts with a quote');
+
+ start = index;
+ ++index;
+
+ while (index < length) {
+ ch = source[index++];
+
+ if (ch === quote) {
+ quote = '';
+ break;
+ } else if (ch === '\\') {
+ ch = source[index++];
+ if (!ch || !isLineTerminator(ch.charCodeAt(0))) {
+ switch (ch) {
+ case 'u':
+ case 'x':
+ if (source[index] === '{') {
+ ++index;
+ str += scanUnicodeCodePointEscape();
+ } else {
+ unescaped = scanHexEscape(ch);
+ if (!unescaped) {
+ throw throwUnexpectedToken();
+ }
+ str += unescaped;
+ }
+ break;
+ case 'n':
+ str += '\n';
+ break;
+ case 'r':
+ str += '\r';
+ break;
+ case 't':
+ str += '\t';
+ break;
+ case 'b':
+ str += '\b';
+ break;
+ case 'f':
+ str += '\f';
+ break;
+ case 'v':
+ str += '\x0B';
+ break;
+ case '8':
+ case '9':
+ str += ch;
+ tolerateUnexpectedToken();
+ break;
+
+ default:
+ if (isOctalDigit(ch)) {
+ octToDec = octalToDecimal(ch);
+
+ octal = octToDec.octal || octal;
+ str += String.fromCharCode(octToDec.code);
+ } else {
+ str += ch;
+ }
+ break;
+ }
+ } else {
+ ++lineNumber;
+ if (ch === '\r' && source[index] === '\n') {
+ ++index;
+ }
+ lineStart = index;
+ }
+ } else if (isLineTerminator(ch.charCodeAt(0))) {
+ break;
+ } else {
+ str += ch;
+ }
+ }
+
+ if (quote !== '') {
+ index = start;
+ throwUnexpectedToken();
+ }
+
+ return {
+ type: Token.StringLiteral,
+ value: str,
+ octal: octal,
+ lineNumber: startLineNumber,
+ lineStart: startLineStart,
+ start: start,
+ end: index
+ };
+ }
+
+ // ECMA-262 11.8.6 Template Literal Lexical Components
+
+ function scanTemplate() {
+ var cooked = '', ch, start, rawOffset, terminated, head, tail, restore, unescaped;
+
+ terminated = false;
+ tail = false;
+ start = index;
+ head = (source[index] === '`');
+ rawOffset = 2;
+
+ ++index;
+
+ while (index < length) {
+ ch = source[index++];
+ if (ch === '`') {
+ rawOffset = 1;
+ tail = true;
+ terminated = true;
+ break;
+ } else if (ch === '$') {
+ if (source[index] === '{') {
+ state.curlyStack.push('${');
+ ++index;
+ terminated = true;
+ break;
+ }
+ cooked += ch;
+ } else if (ch === '\\') {
+ ch = source[index++];
+ if (!isLineTerminator(ch.charCodeAt(0))) {
+ switch (ch) {
+ case 'n':
+ cooked += '\n';
+ break;
+ case 'r':
+ cooked += '\r';
+ break;
+ case 't':
+ cooked += '\t';
+ break;
+ case 'u':
+ case 'x':
+ if (source[index] === '{') {
+ ++index;
+ cooked += scanUnicodeCodePointEscape();
+ } else {
+ restore = index;
+ unescaped = scanHexEscape(ch);
+ if (unescaped) {
+ cooked += unescaped;
+ } else {
+ index = restore;
+ cooked += ch;
+ }
+ }
+ break;
+ case 'b':
+ cooked += '\b';
+ break;
+ case 'f':
+ cooked += '\f';
+ break;
+ case 'v':
+ cooked += '\v';
+ break;
+
+ default:
+ if (ch === '0') {
+ if (isDecimalDigit(source.charCodeAt(index))) {
+ // Illegal: \01 \02 and so on
+ throwError(Messages.TemplateOctalLiteral);
+ }
+ cooked += '\0';
+ } else if (isOctalDigit(ch)) {
+ // Illegal: \1 \2
+ throwError(Messages.TemplateOctalLiteral);
+ } else {
+ cooked += ch;
+ }
+ break;
+ }
+ } else {
+ ++lineNumber;
+ if (ch === '\r' && source[index] === '\n') {
+ ++index;
+ }
+ lineStart = index;
+ }
+ } else if (isLineTerminator(ch.charCodeAt(0))) {
+ ++lineNumber;
+ if (ch === '\r' && source[index] === '\n') {
+ ++index;
+ }
+ lineStart = index;
+ cooked += '\n';
+ } else {
+ cooked += ch;
+ }
+ }
+
+ if (!terminated) {
+ throwUnexpectedToken();
+ }
+
+ if (!head) {
+ state.curlyStack.pop();
+ }
+
+ return {
+ type: Token.Template,
+ value: {
+ cooked: cooked,
+ raw: source.slice(start + 1, index - rawOffset)
+ },
+ head: head,
+ tail: tail,
+ lineNumber: lineNumber,
+ lineStart: lineStart,
+ start: start,
+ end: index
+ };
+ }
+
+ // ECMA-262 11.8.5 Regular Expression Literals
+
+ function testRegExp(pattern, flags) {
+ // The BMP character to use as a replacement for astral symbols when
+ // translating an ES6 "u"-flagged pattern to an ES5-compatible
+ // approximation.
+ // Note: replacing with '\uFFFF' enables false positives in unlikely
+ // scenarios. For example, `[\u{1044f}-\u{10440}]` is an invalid
+ // pattern that would not be detected by this substitution.
+ var astralSubstitute = '\uFFFF',
+ tmp = pattern;
+
+ if (flags.indexOf('u') >= 0) {
+ tmp = tmp
+ // Replace every Unicode escape sequence with the equivalent
+ // BMP character or a constant ASCII code point in the case of
+ // astral symbols. (See the above note on `astralSubstitute`
+ // for more information.)
+ .replace(/\\u\{([0-9a-fA-F]+)\}|\\u([a-fA-F0-9]{4})/g, function ($0, $1, $2) {
+ var codePoint = parseInt($1 || $2, 16);
+ if (codePoint > 0x10FFFF) {
+ throwUnexpectedToken(null, Messages.InvalidRegExp);
+ }
+ if (codePoint <= 0xFFFF) {
+ return String.fromCharCode(codePoint);
+ }
+ return astralSubstitute;
+ })
+ // Replace each paired surrogate with a single ASCII symbol to
+ // avoid throwing on regular expressions that are only valid in
+ // combination with the "u" flag.
+ .replace(
+ /[\uD800-\uDBFF][\uDC00-\uDFFF]/g,
+ astralSubstitute
+ );
+ }
+
+ // First, detect invalid regular expressions.
+ try {
+ RegExp(tmp);
+ } catch (e) {
+ throwUnexpectedToken(null, Messages.InvalidRegExp);
+ }
+
+ // Return a regular expression object for this pattern-flag pair, or
+ // `null` in case the current environment doesn't support the flags it
+ // uses.
+ try {
+ return new RegExp(pattern, flags);
+ } catch (exception) {
+ /* istanbul ignore next */
+ return null;
+ }
+ }
+
+ function scanRegExpBody() {
+ var ch, str, classMarker, terminated, body;
+
+ ch = source[index];
+ assert(ch === '/', 'Regular expression literal must start with a slash');
+ str = source[index++];
+
+ classMarker = false;
+ terminated = false;
+ while (index < length) {
+ ch = source[index++];
+ str += ch;
+ if (ch === '\\') {
+ ch = source[index++];
+ // ECMA-262 7.8.5
+ if (isLineTerminator(ch.charCodeAt(0))) {
+ throwUnexpectedToken(null, Messages.UnterminatedRegExp);
+ }
+ str += ch;
+ } else if (isLineTerminator(ch.charCodeAt(0))) {
+ throwUnexpectedToken(null, Messages.UnterminatedRegExp);
+ } else if (classMarker) {
+ if (ch === ']') {
+ classMarker = false;
+ }
+ } else {
+ if (ch === '/') {
+ terminated = true;
+ break;
+ } else if (ch === '[') {
+ classMarker = true;
+ }
+ }
+ }
+
+ if (!terminated) {
+ throwUnexpectedToken(null, Messages.UnterminatedRegExp);
+ }
+
+ // Exclude leading and trailing slash.
+ body = str.substr(1, str.length - 2);
+ return {
+ value: body,
+ literal: str
+ };
+ }
+
+ function scanRegExpFlags() {
+ var ch, str, flags, restore;
+
+ str = '';
+ flags = '';
+ while (index < length) {
+ ch = source[index];
+ if (!isIdentifierPart(ch.charCodeAt(0))) {
+ break;
+ }
+
+ ++index;
+ if (ch === '\\' && index < length) {
+ ch = source[index];
+ if (ch === 'u') {
+ ++index;
+ restore = index;
+ ch = scanHexEscape('u');
+ if (ch) {
+ flags += ch;
+ for (str += '\\u'; restore < index; ++restore) {
+ str += source[restore];
+ }
+ } else {
+ index = restore;
+ flags += 'u';
+ str += '\\u';
+ }
+ tolerateUnexpectedToken();
+ } else {
+ str += '\\';
+ tolerateUnexpectedToken();
+ }
+ } else {
+ flags += ch;
+ str += ch;
+ }
+ }
+
+ return {
+ value: flags,
+ literal: str
+ };
+ }
+
+ function scanRegExp() {
+ var start, body, flags, value;
+ scanning = true;
+
+ lookahead = null;
+ skipComment();
+ start = index;
+
+ body = scanRegExpBody();
+ flags = scanRegExpFlags();
+ value = testRegExp(body.value, flags.value);
+ scanning = false;
+ if (extra.tokenize) {
+ return {
+ type: Token.RegularExpression,
+ value: value,
+ regex: {
+ pattern: body.value,
+ flags: flags.value
+ },
+ lineNumber: lineNumber,
+ lineStart: lineStart,
+ start: start,
+ end: index
+ };
+ }
+
+ return {
+ literal: body.literal + flags.literal,
+ value: value,
+ regex: {
+ pattern: body.value,
+ flags: flags.value
+ },
+ start: start,
+ end: index
+ };
+ }
+
+ function collectRegex() {
+ var pos, loc, regex, token;
+
+ skipComment();
+
+ pos = index;
+ loc = {
+ start: {
+ line: lineNumber,
+ column: index - lineStart
+ }
+ };
+
+ regex = scanRegExp();
+
+ loc.end = {
+ line: lineNumber,
+ column: index - lineStart
+ };
+
+ /* istanbul ignore next */
+ if (!extra.tokenize) {
+ // Pop the previous token, which is likely '/' or '/='
+ if (extra.tokens.length > 0) {
+ token = extra.tokens[extra.tokens.length - 1];
+ if (token.range[0] === pos && token.type === 'Punctuator') {
+ if (token.value === '/' || token.value === '/=') {
+ extra.tokens.pop();
+ }
+ }
+ }
+
+ extra.tokens.push({
+ type: 'RegularExpression',
+ value: regex.literal,
+ regex: regex.regex,
+ range: [pos, index],
+ loc: loc
+ });
+ }
+
+ return regex;
+ }
+
+ function isIdentifierName(token) {
+ return token.type === Token.Identifier ||
+ token.type === Token.Keyword ||
+ token.type === Token.BooleanLiteral ||
+ token.type === Token.NullLiteral;
+ }
+
+ // Using the following algorithm:
+ // https://github.com/mozilla/sweet.js/wiki/design
+
+ function advanceSlash() {
+ var regex, previous, check;
+
+ function testKeyword(value) {
+ return value && (value.length > 1) && (value[0] >= 'a') && (value[0] <= 'z');
+ }
+
+ previous = extra.tokenValues[extra.tokenValues.length - 1];
+ regex = (previous !== null);
+
+ switch (previous) {
+ case 'this':
+ case ']':
+ regex = false;
+ break;
+
+ case ')':
+ check = extra.tokenValues[extra.openParenToken - 1];
+ regex = (check === 'if' || check === 'while' || check === 'for' || check === 'with');
+ break;
+
+ case '}':
+ // Dividing a function by anything makes little sense,
+ // but we have to check for that.
+ regex = false;
+ if (testKeyword(extra.tokenValues[extra.openCurlyToken - 3])) {
+ // Anonymous function, e.g. function(){} /42
+ check = extra.tokenValues[extra.openCurlyToken - 4];
+ regex = check ? (FnExprTokens.indexOf(check) < 0) : false;
+ } else if (testKeyword(extra.tokenValues[extra.openCurlyToken - 4])) {
+ // Named function, e.g. function f(){} /42/
+ check = extra.tokenValues[extra.openCurlyToken - 5];
+ regex = check ? (FnExprTokens.indexOf(check) < 0) : true;
+ }
+ }
+
+ return regex ? collectRegex() : scanPunctuator();
+ }
+
+ function advance() {
+ var cp, token;
+
+ if (index >= length) {
+ return {
+ type: Token.EOF,
+ lineNumber: lineNumber,
+ lineStart: lineStart,
+ start: index,
+ end: index
+ };
+ }
+
+ cp = source.charCodeAt(index);
+
+ if (isIdentifierStart(cp)) {
+ token = scanIdentifier();
+ if (strict && isStrictModeReservedWord(token.value)) {
+ token.type = Token.Keyword;
+ }
+ return token;
+ }
+
+ // Very common: ( and ) and ;
+ if (cp === 0x28 || cp === 0x29 || cp === 0x3B) {
+ return scanPunctuator();
+ }
+
+ // String literal starts with single quote (U+0027) or double quote (U+0022).
+ if (cp === 0x27 || cp === 0x22) {
+ return scanStringLiteral();
+ }
+
+ // Dot (.) U+002E can also start a floating-point number, hence the need
+ // to check the next character.
+ if (cp === 0x2E) {
+ if (isDecimalDigit(source.charCodeAt(index + 1))) {
+ return scanNumericLiteral();
+ }
+ return scanPunctuator();
+ }
+
+ if (isDecimalDigit(cp)) {
+ return scanNumericLiteral();
+ }
+
+ // Slash (/) U+002F can also start a regex.
+ if (extra.tokenize && cp === 0x2F) {
+ return advanceSlash();
+ }
+
+ // Template literals start with ` (U+0060) for template head
+ // or } (U+007D) for template middle or template tail.
+ if (cp === 0x60 || (cp === 0x7D && state.curlyStack[state.curlyStack.length - 1] === '${')) {
+ return scanTemplate();
+ }
+
+ // Possible identifier start in a surrogate pair.
+ if (cp >= 0xD800 && cp < 0xDFFF) {
+ cp = codePointAt(index);
+ if (isIdentifierStart(cp)) {
+ return scanIdentifier();
+ }
+ }
+
+ return scanPunctuator();
+ }
+
+ function collectToken() {
+ var loc, token, value, entry;
+
+ loc = {
+ start: {
+ line: lineNumber,
+ column: index - lineStart
+ }
+ };
+
+ token = advance();
+ loc.end = {
+ line: lineNumber,
+ column: index - lineStart
+ };
+
+ if (token.type !== Token.EOF) {
+ value = source.slice(token.start, token.end);
+ entry = {
+ type: TokenName[token.type],
+ value: value,
+ range: [token.start, token.end],
+ loc: loc
+ };
+ if (token.regex) {
+ entry.regex = {
+ pattern: token.regex.pattern,
+ flags: token.regex.flags
+ };
+ }
+ if (extra.tokenValues) {
+ extra.tokenValues.push((entry.type === 'Punctuator' || entry.type === 'Keyword') ? entry.value : null);
+ }
+ if (extra.tokenize) {
+ if (!extra.range) {
+ delete entry.range;
+ }
+ if (!extra.loc) {
+ delete entry.loc;
+ }
+ if (extra.delegate) {
+ entry = extra.delegate(entry);
+ }
+ }
+ extra.tokens.push(entry);
+ }
+
+ return token;
+ }
+
+ function lex() {
+ var token;
+ scanning = true;
+
+ lastIndex = index;
+ lastLineNumber = lineNumber;
+ lastLineStart = lineStart;
+
+ skipComment();
+
+ token = lookahead;
+
+ startIndex = index;
+ startLineNumber = lineNumber;
+ startLineStart = lineStart;
+
+ lookahead = (typeof extra.tokens !== 'undefined') ? collectToken() : advance();
+ scanning = false;
+ return token;
+ }
+
+ function peek() {
+ scanning = true;
+
+ skipComment();
+
+ lastIndex = index;
+ lastLineNumber = lineNumber;
+ lastLineStart = lineStart;
+
+ startIndex = index;
+ startLineNumber = lineNumber;
+ startLineStart = lineStart;
+
+ lookahead = (typeof extra.tokens !== 'undefined') ? collectToken() : advance();
+ scanning = false;
+ }
+
+ function Position() {
+ this.line = startLineNumber;
+ this.column = startIndex - startLineStart;
+ }
+
+ function SourceLocation() {
+ this.start = new Position();
+ this.end = null;
+ }
+
+ function WrappingSourceLocation(startToken) {
+ this.start = {
+ line: startToken.lineNumber,
+ column: startToken.start - startToken.lineStart
+ };
+ this.end = null;
+ }
+
+ function Node() {
+ if (extra.range) {
+ this.range = [startIndex, 0];
+ }
+ if (extra.loc) {
+ this.loc = new SourceLocation();
+ }
+ }
+
+ function WrappingNode(startToken) {
+ if (extra.range) {
+ this.range = [startToken.start, 0];
+ }
+ if (extra.loc) {
+ this.loc = new WrappingSourceLocation(startToken);
+ }
+ }
+
+ WrappingNode.prototype = Node.prototype = {
+
+ processComment: function () {
+ var lastChild,
+ innerComments,
+ leadingComments,
+ trailingComments,
+ bottomRight = extra.bottomRightStack,
+ i,
+ comment,
+ last = bottomRight[bottomRight.length - 1];
+
+ if (this.type === Syntax.Program) {
+ if (this.body.length > 0) {
+ return;
+ }
+ }
+ /**
+ * patch innnerComments for properties empty block
+ * `function a() {/** comments **\/}`
+ */
+
+ if (this.type === Syntax.BlockStatement && this.body.length === 0) {
+ innerComments = [];
+ for (i = extra.leadingComments.length - 1; i >= 0; --i) {
+ comment = extra.leadingComments[i];
+ if (this.range[1] >= comment.range[1]) {
+ innerComments.unshift(comment);
+ extra.leadingComments.splice(i, 1);
+ extra.trailingComments.splice(i, 1);
+ }
+ }
+ if (innerComments.length) {
+ this.innerComments = innerComments;
+ //bottomRight.push(this);
+ return;
+ }
+ }
+
+ if (extra.trailingComments.length > 0) {
+ trailingComments = [];
+ for (i = extra.trailingComments.length - 1; i >= 0; --i) {
+ comment = extra.trailingComments[i];
+ if (comment.range[0] >= this.range[1]) {
+ trailingComments.unshift(comment);
+ extra.trailingComments.splice(i, 1);
+ }
+ }
+ extra.trailingComments = [];
+ } else {
+ if (last && last.trailingComments && last.trailingComments[0].range[0] >= this.range[1]) {
+ trailingComments = last.trailingComments;
+ delete last.trailingComments;
+ }
+ }
+
+ // Eating the stack.
+ while (last && last.range[0] >= this.range[0]) {
+ lastChild = bottomRight.pop();
+ last = bottomRight[bottomRight.length - 1];
+ }
+
+ if (lastChild) {
+ if (lastChild.leadingComments) {
+ leadingComments = [];
+ for (i = lastChild.leadingComments.length - 1; i >= 0; --i) {
+ comment = lastChild.leadingComments[i];
+ if (comment.range[1] <= this.range[0]) {
+ leadingComments.unshift(comment);
+ lastChild.leadingComments.splice(i, 1);
+ }
+ }
+
+ if (!lastChild.leadingComments.length) {
+ lastChild.leadingComments = undefined;
+ }
+ }
+ } else if (extra.leadingComments.length > 0) {
+ leadingComments = [];
+ for (i = extra.leadingComments.length - 1; i >= 0; --i) {
+ comment = extra.leadingComments[i];
+ if (comment.range[1] <= this.range[0]) {
+ leadingComments.unshift(comment);
+ extra.leadingComments.splice(i, 1);
+ }
+ }
+ }
+
+
+ if (leadingComments && leadingComments.length > 0) {
+ this.leadingComments = leadingComments;
+ }
+ if (trailingComments && trailingComments.length > 0) {
+ this.trailingComments = trailingComments;
+ }
+
+ bottomRight.push(this);
+ },
+
+ finish: function () {
+ if (extra.range) {
+ this.range[1] = lastIndex;
+ }
+ if (extra.loc) {
+ this.loc.end = {
+ line: lastLineNumber,
+ column: lastIndex - lastLineStart
+ };
+ if (extra.source) {
+ this.loc.source = extra.source;
+ }
+ }
+
+ if (extra.attachComment) {
+ this.processComment();
+ }
+ },
+
+ finishArrayExpression: function (elements) {
+ this.type = Syntax.ArrayExpression;
+ this.elements = elements;
+ this.finish();
+ return this;
+ },
+
+ finishArrayPattern: function (elements) {
+ this.type = Syntax.ArrayPattern;
+ this.elements = elements;
+ this.finish();
+ return this;
+ },
+
+ finishArrowFunctionExpression: function (params, defaults, body, expression) {
+ this.type = Syntax.ArrowFunctionExpression;
+ this.id = null;
+ this.params = params;
+ this.defaults = defaults;
+ this.body = body;
+ this.generator = false;
+ this.expression = expression;
+ this.finish();
+ return this;
+ },
+
+ finishAssignmentExpression: function (operator, left, right) {
+ this.type = Syntax.AssignmentExpression;
+ this.operator = operator;
+ this.left = left;
+ this.right = right;
+ this.finish();
+ return this;
+ },
+
+ finishAssignmentPattern: function (left, right) {
+ this.type = Syntax.AssignmentPattern;
+ this.left = left;
+ this.right = right;
+ this.finish();
+ return this;
+ },
+
+ finishBinaryExpression: function (operator, left, right) {
+ this.type = (operator === '||' || operator === '&&') ? Syntax.LogicalExpression : Syntax.BinaryExpression;
+ this.operator = operator;
+ this.left = left;
+ this.right = right;
+ this.finish();
+ return this;
+ },
+
+ finishBlockStatement: function (body) {
+ this.type = Syntax.BlockStatement;
+ this.body = body;
+ this.finish();
+ return this;
+ },
+
+ finishBreakStatement: function (label) {
+ this.type = Syntax.BreakStatement;
+ this.label = label;
+ this.finish();
+ return this;
+ },
+
+ finishCallExpression: function (callee, args) {
+ this.type = Syntax.CallExpression;
+ this.callee = callee;
+ this.arguments = args;
+ this.finish();
+ return this;
+ },
+
+ finishCatchClause: function (param, body) {
+ this.type = Syntax.CatchClause;
+ this.param = param;
+ this.body = body;
+ this.finish();
+ return this;
+ },
+
+ finishClassBody: function (body) {
+ this.type = Syntax.ClassBody;
+ this.body = body;
+ this.finish();
+ return this;
+ },
+
+ finishClassDeclaration: function (id, superClass, body) {
+ this.type = Syntax.ClassDeclaration;
+ this.id = id;
+ this.superClass = superClass;
+ this.body = body;
+ this.finish();
+ return this;
+ },
+
+ finishClassExpression: function (id, superClass, body) {
+ this.type = Syntax.ClassExpression;
+ this.id = id;
+ this.superClass = superClass;
+ this.body = body;
+ this.finish();
+ return this;
+ },
+
+ finishConditionalExpression: function (test, consequent, alternate) {
+ this.type = Syntax.ConditionalExpression;
+ this.test = test;
+ this.consequent = consequent;
+ this.alternate = alternate;
+ this.finish();
+ return this;
+ },
+
+ finishContinueStatement: function (label) {
+ this.type = Syntax.ContinueStatement;
+ this.label = label;
+ this.finish();
+ return this;
+ },
+
+ finishDebuggerStatement: function () {
+ this.type = Syntax.DebuggerStatement;
+ this.finish();
+ return this;
+ },
+
+ finishDoWhileStatement: function (body, test) {
+ this.type = Syntax.DoWhileStatement;
+ this.body = body;
+ this.test = test;
+ this.finish();
+ return this;
+ },
+
+ finishEmptyStatement: function () {
+ this.type = Syntax.EmptyStatement;
+ this.finish();
+ return this;
+ },
+
+ finishExpressionStatement: function (expression) {
+ this.type = Syntax.ExpressionStatement;
+ this.expression = expression;
+ this.finish();
+ return this;
+ },
+
+ finishForStatement: function (init, test, update, body) {
+ this.type = Syntax.ForStatement;
+ this.init = init;
+ this.test = test;
+ this.update = update;
+ this.body = body;
+ this.finish();
+ return this;
+ },
+
+ finishForOfStatement: function (left, right, body) {
+ this.type = Syntax.ForOfStatement;
+ this.left = left;
+ this.right = right;
+ this.body = body;
+ this.finish();
+ return this;
+ },
+
+ finishForInStatement: function (left, right, body) {
+ this.type = Syntax.ForInStatement;
+ this.left = left;
+ this.right = right;
+ this.body = body;
+ this.each = false;
+ this.finish();
+ return this;
+ },
+
+ finishFunctionDeclaration: function (id, params, defaults, body, generator) {
+ this.type = Syntax.FunctionDeclaration;
+ this.id = id;
+ this.params = params;
+ this.defaults = defaults;
+ this.body = body;
+ this.generator = generator;
+ this.expression = false;
+ this.finish();
+ return this;
+ },
+
+ finishFunctionExpression: function (id, params, defaults, body, generator) {
+ this.type = Syntax.FunctionExpression;
+ this.id = id;
+ this.params = params;
+ this.defaults = defaults;
+ this.body = body;
+ this.generator = generator;
+ this.expression = false;
+ this.finish();
+ return this;
+ },
+
+ finishIdentifier: function (name) {
+ this.type = Syntax.Identifier;
+ this.name = name;
+ this.finish();
+ return this;
+ },
+
+ finishIfStatement: function (test, consequent, alternate) {
+ this.type = Syntax.IfStatement;
+ this.test = test;
+ this.consequent = consequent;
+ this.alternate = alternate;
+ this.finish();
+ return this;
+ },
+
+ finishLabeledStatement: function (label, body) {
+ this.type = Syntax.LabeledStatement;
+ this.label = label;
+ this.body = body;
+ this.finish();
+ return this;
+ },
+
+ finishLiteral: function (token) {
+ this.type = Syntax.Literal;
+ this.value = token.value;
+ this.raw = source.slice(token.start, token.end);
+ if (token.regex) {
+ this.regex = token.regex;
+ }
+ this.finish();
+ return this;
+ },
+
+ finishMemberExpression: function (accessor, object, property) {
+ this.type = Syntax.MemberExpression;
+ this.computed = accessor === '[';
+ this.object = object;
+ this.property = property;
+ this.finish();
+ return this;
+ },
+
+ finishMetaProperty: function (meta, property) {
+ this.type = Syntax.MetaProperty;
+ this.meta = meta;
+ this.property = property;
+ this.finish();
+ return this;
+ },
+
+ finishNewExpression: function (callee, args) {
+ this.type = Syntax.NewExpression;
+ this.callee = callee;
+ this.arguments = args;
+ this.finish();
+ return this;
+ },
+
+ finishObjectExpression: function (properties) {
+ this.type = Syntax.ObjectExpression;
+ this.properties = properties;
+ this.finish();
+ return this;
+ },
+
+ finishObjectPattern: function (properties) {
+ this.type = Syntax.ObjectPattern;
+ this.properties = properties;
+ this.finish();
+ return this;
+ },
+
+ finishPostfixExpression: function (operator, argument) {
+ this.type = Syntax.UpdateExpression;
+ this.operator = operator;
+ this.argument = argument;
+ this.prefix = false;
+ this.finish();
+ return this;
+ },
+
+ finishProgram: function (body, sourceType) {
+ this.type = Syntax.Program;
+ this.body = body;
+ this.sourceType = sourceType;
+ this.finish();
+ return this;
+ },
+
+ finishProperty: function (kind, key, computed, value, method, shorthand) {
+ this.type = Syntax.Property;
+ this.key = key;
+ this.computed = computed;
+ this.value = value;
+ this.kind = kind;
+ this.method = method;
+ this.shorthand = shorthand;
+ this.finish();
+ return this;
+ },
+
+ finishRestElement: function (argument) {
+ this.type = Syntax.RestElement;
+ this.argument = argument;
+ this.finish();
+ return this;
+ },
+
+ finishReturnStatement: function (argument) {
+ this.type = Syntax.ReturnStatement;
+ this.argument = argument;
+ this.finish();
+ return this;
+ },
+
+ finishSequenceExpression: function (expressions) {
+ this.type = Syntax.SequenceExpression;
+ this.expressions = expressions;
+ this.finish();
+ return this;
+ },
+
+ finishSpreadElement: function (argument) {
+ this.type = Syntax.SpreadElement;
+ this.argument = argument;
+ this.finish();
+ return this;
+ },
+
+ finishSwitchCase: function (test, consequent) {
+ this.type = Syntax.SwitchCase;
+ this.test = test;
+ this.consequent = consequent;
+ this.finish();
+ return this;
+ },
+
+ finishSuper: function () {
+ this.type = Syntax.Super;
+ this.finish();
+ return this;
+ },
+
+ finishSwitchStatement: function (discriminant, cases) {
+ this.type = Syntax.SwitchStatement;
+ this.discriminant = discriminant;
+ this.cases = cases;
+ this.finish();
+ return this;
+ },
+
+ finishTaggedTemplateExpression: function (tag, quasi) {
+ this.type = Syntax.TaggedTemplateExpression;
+ this.tag = tag;
+ this.quasi = quasi;
+ this.finish();
+ return this;
+ },
+
+ finishTemplateElement: function (value, tail) {
+ this.type = Syntax.TemplateElement;
+ this.value = value;
+ this.tail = tail;
+ this.finish();
+ return this;
+ },
+
+ finishTemplateLiteral: function (quasis, expressions) {
+ this.type = Syntax.TemplateLiteral;
+ this.quasis = quasis;
+ this.expressions = expressions;
+ this.finish();
+ return this;
+ },
+
+ finishThisExpression: function () {
+ this.type = Syntax.ThisExpression;
+ this.finish();
+ return this;
+ },
+
+ finishThrowStatement: function (argument) {
+ this.type = Syntax.ThrowStatement;
+ this.argument = argument;
+ this.finish();
+ return this;
+ },
+
+ finishTryStatement: function (block, handler, finalizer) {
+ this.type = Syntax.TryStatement;
+ this.block = block;
+ this.guardedHandlers = [];
+ this.handlers = handler ? [handler] : [];
+ this.handler = handler;
+ this.finalizer = finalizer;
+ this.finish();
+ return this;
+ },
+
+ finishUnaryExpression: function (operator, argument) {
+ this.type = (operator === '++' || operator === '--') ? Syntax.UpdateExpression : Syntax.UnaryExpression;
+ this.operator = operator;
+ this.argument = argument;
+ this.prefix = true;
+ this.finish();
+ return this;
+ },
+
+ finishVariableDeclaration: function (declarations) {
+ this.type = Syntax.VariableDeclaration;
+ this.declarations = declarations;
+ this.kind = 'var';
+ this.finish();
+ return this;
+ },
+
+ finishLexicalDeclaration: function (declarations, kind) {
+ this.type = Syntax.VariableDeclaration;
+ this.declarations = declarations;
+ this.kind = kind;
+ this.finish();
+ return this;
+ },
+
+ finishVariableDeclarator: function (id, init) {
+ this.type = Syntax.VariableDeclarator;
+ this.id = id;
+ this.init = init;
+ this.finish();
+ return this;
+ },
+
+ finishWhileStatement: function (test, body) {
+ this.type = Syntax.WhileStatement;
+ this.test = test;
+ this.body = body;
+ this.finish();
+ return this;
+ },
+
+ finishWithStatement: function (object, body) {
+ this.type = Syntax.WithStatement;
+ this.object = object;
+ this.body = body;
+ this.finish();
+ return this;
+ },
+
+ finishExportSpecifier: function (local, exported) {
+ this.type = Syntax.ExportSpecifier;
+ this.exported = exported || local;
+ this.local = local;
+ this.finish();
+ return this;
+ },
+
+ finishImportDefaultSpecifier: function (local) {
+ this.type = Syntax.ImportDefaultSpecifier;
+ this.local = local;
+ this.finish();
+ return this;
+ },
+
+ finishImportNamespaceSpecifier: function (local) {
+ this.type = Syntax.ImportNamespaceSpecifier;
+ this.local = local;
+ this.finish();
+ return this;
+ },
+
+ finishExportNamedDeclaration: function (declaration, specifiers, src) {
+ this.type = Syntax.ExportNamedDeclaration;
+ this.declaration = declaration;
+ this.specifiers = specifiers;
+ this.source = src;
+ this.finish();
+ return this;
+ },
+
+ finishExportDefaultDeclaration: function (declaration) {
+ this.type = Syntax.ExportDefaultDeclaration;
+ this.declaration = declaration;
+ this.finish();
+ return this;
+ },
+
+ finishExportAllDeclaration: function (src) {
+ this.type = Syntax.ExportAllDeclaration;
+ this.source = src;
+ this.finish();
+ return this;
+ },
+
+ finishImportSpecifier: function (local, imported) {
+ this.type = Syntax.ImportSpecifier;
+ this.local = local || imported;
+ this.imported = imported;
+ this.finish();
+ return this;
+ },
+
+ finishImportDeclaration: function (specifiers, src) {
+ this.type = Syntax.ImportDeclaration;
+ this.specifiers = specifiers;
+ this.source = src;
+ this.finish();
+ return this;
+ },
+
+ finishYieldExpression: function (argument, delegate) {
+ this.type = Syntax.YieldExpression;
+ this.argument = argument;
+ this.delegate = delegate;
+ this.finish();
+ return this;
+ }
+ };
+
+
+ function recordError(error) {
+ var e, existing;
+
+ for (e = 0; e < extra.errors.length; e++) {
+ existing = extra.errors[e];
+ // Prevent duplicated error.
+ /* istanbul ignore next */
+ if (existing.index === error.index && existing.message === error.message) {
+ return;
+ }
+ }
+
+ extra.errors.push(error);
+ }
+
+ function constructError(msg, column) {
+ var error = new Error(msg);
+ try {
+ throw error;
+ } catch (base) {
+ /* istanbul ignore else */
+ if (Object.create && Object.defineProperty) {
+ error = Object.create(base);
+ Object.defineProperty(error, 'column', { value: column });
+ }
+ } finally {
+ return error;
+ }
+ }
+
+ function createError(line, pos, description) {
+ var msg, column, error;
+
+ msg = 'Line ' + line + ': ' + description;
+ column = pos - (scanning ? lineStart : lastLineStart) + 1;
+ error = constructError(msg, column);
+ error.lineNumber = line;
+ error.description = description;
+ error.index = pos;
+ return error;
+ }
+
+ // Throw an exception
+
+ function throwError(messageFormat) {
+ var args, msg;
+
+ args = Array.prototype.slice.call(arguments, 1);
+ msg = messageFormat.replace(/%(\d)/g,
+ function (whole, idx) {
+ assert(idx < args.length, 'Message reference must be in range');
+ return args[idx];
+ }
+ );
+
+ throw createError(lastLineNumber, lastIndex, msg);
+ }
+
+ function tolerateError(messageFormat) {
+ var args, msg, error;
+
+ args = Array.prototype.slice.call(arguments, 1);
+ /* istanbul ignore next */
+ msg = messageFormat.replace(/%(\d)/g,
+ function (whole, idx) {
+ assert(idx < args.length, 'Message reference must be in range');
+ return args[idx];
+ }
+ );
+
+ error = createError(lineNumber, lastIndex, msg);
+ if (extra.errors) {
+ recordError(error);
+ } else {
+ throw error;
+ }
+ }
+
+ // Throw an exception because of the token.
+
+ function unexpectedTokenError(token, message) {
+ var value, msg = message || Messages.UnexpectedToken;
+
+ if (token) {
+ if (!message) {
+ msg = (token.type === Token.EOF) ? Messages.UnexpectedEOS :
+ (token.type === Token.Identifier) ? Messages.UnexpectedIdentifier :
+ (token.type === Token.NumericLiteral) ? Messages.UnexpectedNumber :
+ (token.type === Token.StringLiteral) ? Messages.UnexpectedString :
+ (token.type === Token.Template) ? Messages.UnexpectedTemplate :
+ Messages.UnexpectedToken;
+
+ if (token.type === Token.Keyword) {
+ if (isFutureReservedWord(token.value)) {
+ msg = Messages.UnexpectedReserved;
+ } else if (strict && isStrictModeReservedWord(token.value)) {
+ msg = Messages.StrictReservedWord;
+ }
+ }
+ }
+
+ value = (token.type === Token.Template) ? token.value.raw : token.value;
+ } else {
+ value = 'ILLEGAL';
+ }
+
+ msg = msg.replace('%0', value);
+
+ return (token && typeof token.lineNumber === 'number') ?
+ createError(token.lineNumber, token.start, msg) :
+ createError(scanning ? lineNumber : lastLineNumber, scanning ? index : lastIndex, msg);
+ }
+
+ function throwUnexpectedToken(token, message) {
+ throw unexpectedTokenError(token, message);
+ }
+
+ function tolerateUnexpectedToken(token, message) {
+ var error = unexpectedTokenError(token, message);
+ if (extra.errors) {
+ recordError(error);
+ } else {
+ throw error;
+ }
+ }
+
+ // Expect the next token to match the specified punctuator.
+ // If not, an exception will be thrown.
+
+ function expect(value) {
+ var token = lex();
+ if (token.type !== Token.Punctuator || token.value !== value) {
+ throwUnexpectedToken(token);
+ }
+ }
+
+ /**
+ * @name expectCommaSeparator
+ * @description Quietly expect a comma when in tolerant mode, otherwise delegates
+ * to <code>expect(value)</code>
+ * @since 2.0
+ */
+ function expectCommaSeparator() {
+ var token;
+
+ if (extra.errors) {
+ token = lookahead;
+ if (token.type === Token.Punctuator && token.value === ',') {
+ lex();
+ } else if (token.type === Token.Punctuator && token.value === ';') {
+ lex();
+ tolerateUnexpectedToken(token);
+ } else {
+ tolerateUnexpectedToken(token, Messages.UnexpectedToken);
+ }
+ } else {
+ expect(',');
+ }
+ }
+
+ // Expect the next token to match the specified keyword.
+ // If not, an exception will be thrown.
+
+ function expectKeyword(keyword) {
+ var token = lex();
+ if (token.type !== Token.Keyword || token.value !== keyword) {
+ throwUnexpectedToken(token);
+ }
+ }
+
+ // Return true if the next token matches the specified punctuator.
+
+ function match(value) {
+ return lookahead.type === Token.Punctuator && lookahead.value === value;
+ }
+
+ // Return true if the next token matches the specified keyword
+
+ function matchKeyword(keyword) {
+ return lookahead.type === Token.Keyword && lookahead.value === keyword;
+ }
+
+ // Return true if the next token matches the specified contextual keyword
+ // (where an identifier is sometimes a keyword depending on the context)
+
+ function matchContextualKeyword(keyword) {
+ return lookahead.type === Token.Identifier && lookahead.value === keyword;
+ }
+
+ // Return true if the next token is an assignment operator
+
+ function matchAssign() {
+ var op;
+
+ if (lookahead.type !== Token.Punctuator) {
+ return false;
+ }
+ op = lookahead.value;
+ return op === '=' ||
+ op === '*=' ||
+ op === '/=' ||
+ op === '%=' ||
+ op === '+=' ||
+ op === '-=' ||
+ op === '<<=' ||
+ op === '>>=' ||
+ op === '>>>=' ||
+ op === '&=' ||
+ op === '^=' ||
+ op === '|=';
+ }
+
+ function consumeSemicolon() {
+ // Catch the very common case first: immediately a semicolon (U+003B).
+ if (source.charCodeAt(startIndex) === 0x3B || match(';')) {
+ lex();
+ return;
+ }
+
+ if (hasLineTerminator) {
+ return;
+ }
+
+ // FIXME(ikarienator): this is seemingly an issue in the previous location info convention.
+ lastIndex = startIndex;
+ lastLineNumber = startLineNumber;
+ lastLineStart = startLineStart;
+
+ if (lookahead.type !== Token.EOF && !match('}')) {
+ throwUnexpectedToken(lookahead);
+ }
+ }
+
+ // Cover grammar support.
+ //
+ // When an assignment expression position starts with an left parenthesis, the determination of the type
+ // of the syntax is to be deferred arbitrarily long until the end of the parentheses pair (plus a lookahead)
+ // or the first comma. This situation also defers the determination of all the expressions nested in the pair.
+ //
+ // There are three productions that can be parsed in a parentheses pair that needs to be determined
+ // after the outermost pair is closed. They are:
+ //
+ // 1. AssignmentExpression
+ // 2. BindingElements
+ // 3. AssignmentTargets
+ //
+ // In order to avoid exponential backtracking, we use two flags to denote if the production can be
+ // binding element or assignment target.
+ //
+ // The three productions have the relationship:
+ //
+ // BindingElements ⊆ AssignmentTargets ⊆ AssignmentExpression
+ //
+ // with a single exception that CoverInitializedName when used directly in an Expression, generates
+ // an early error. Therefore, we need the third state, firstCoverInitializedNameError, to track the
+ // first usage of CoverInitializedName and report it when we reached the end of the parentheses pair.
+ //
+ // isolateCoverGrammar function runs the given parser function with a new cover grammar context, and it does not
+ // effect the current flags. This means the production the parser parses is only used as an expression. Therefore
+ // the CoverInitializedName check is conducted.
+ //
+ // inheritCoverGrammar function runs the given parse function with a new cover grammar context, and it propagates
+ // the flags outside of the parser. This means the production the parser parses is used as a part of a potential
+ // pattern. The CoverInitializedName check is deferred.
+ function isolateCoverGrammar(parser) {
+ var oldIsBindingElement = isBindingElement,
+ oldIsAssignmentTarget = isAssignmentTarget,
+ oldFirstCoverInitializedNameError = firstCoverInitializedNameError,
+ result;
+ isBindingElement = true;
+ isAssignmentTarget = true;
+ firstCoverInitializedNameError = null;
+ result = parser();
+ if (firstCoverInitializedNameError !== null) {
+ throwUnexpectedToken(firstCoverInitializedNameError);
+ }
+ isBindingElement = oldIsBindingElement;
+ isAssignmentTarget = oldIsAssignmentTarget;
+ firstCoverInitializedNameError = oldFirstCoverInitializedNameError;
+ return result;
+ }
+
+ function inheritCoverGrammar(parser) {
+ var oldIsBindingElement = isBindingElement,
+ oldIsAssignmentTarget = isAssignmentTarget,
+ oldFirstCoverInitializedNameError = firstCoverInitializedNameError,
+ result;
+ isBindingElement = true;
+ isAssignmentTarget = true;
+ firstCoverInitializedNameError = null;
+ result = parser();
+ isBindingElement = isBindingElement && oldIsBindingElement;
+ isAssignmentTarget = isAssignmentTarget && oldIsAssignmentTarget;
+ firstCoverInitializedNameError = oldFirstCoverInitializedNameError || firstCoverInitializedNameError;
+ return result;
+ }
+
+ // ECMA-262 13.3.3 Destructuring Binding Patterns
+
+ function parseArrayPattern(params, kind) {
+ var node = new Node(), elements = [], rest, restNode;
+ expect('[');
+
+ while (!match(']')) {
+ if (match(',')) {
+ lex();
+ elements.push(null);
+ } else {
+ if (match('...')) {
+ restNode = new Node();
+ lex();
+ params.push(lookahead);
+ rest = parseVariableIdentifier(kind);
+ elements.push(restNode.finishRestElement(rest));
+ break;
+ } else {
+ elements.push(parsePatternWithDefault(params, kind));
+ }
+ if (!match(']')) {
+ expect(',');
+ }
+ }
+
+ }
+
+ expect(']');
+
+ return node.finishArrayPattern(elements);
+ }
+
+ function parsePropertyPattern(params, kind) {
+ var node = new Node(), key, keyToken, computed = match('['), init;
+ if (lookahead.type === Token.Identifier) {
+ keyToken = lookahead;
+ key = parseVariableIdentifier();
+ if (match('=')) {
+ params.push(keyToken);
+ lex();
+ init = parseAssignmentExpression();
+
+ return node.finishProperty(
+ 'init', key, false,
+ new WrappingNode(keyToken).finishAssignmentPattern(key, init), false, true);
+ } else if (!match(':')) {
+ params.push(keyToken);
+ return node.finishProperty('init', key, false, key, false, true);
+ }
+ } else {
+ key = parseObjectPropertyKey();
+ }
+ expect(':');
+ init = parsePatternWithDefault(params, kind);
+ return node.finishProperty('init', key, computed, init, false, false);
+ }
+
+ function parseObjectPattern(params, kind) {
+ var node = new Node(), properties = [];
+
+ expect('{');
+
+ while (!match('}')) {
+ properties.push(parsePropertyPattern(params, kind));
+ if (!match('}')) {
+ expect(',');
+ }
+ }
+
+ lex();
+
+ return node.finishObjectPattern(properties);
+ }
+
+ function parsePattern(params, kind) {
+ if (match('[')) {
+ return parseArrayPattern(params, kind);
+ } else if (match('{')) {
+ return parseObjectPattern(params, kind);
+ } else if (matchKeyword('let')) {
+ if (kind === 'const' || kind === 'let') {
+ tolerateUnexpectedToken(lookahead, Messages.UnexpectedToken);
+ }
+ }
+
+ params.push(lookahead);
+ return parseVariableIdentifier(kind);
+ }
+
+ function parsePatternWithDefault(params, kind) {
+ var startToken = lookahead, pattern, previousAllowYield, right;
+ pattern = parsePattern(params, kind);
+ if (match('=')) {
+ lex();
+ previousAllowYield = state.allowYield;
+ state.allowYield = true;
+ right = isolateCoverGrammar(parseAssignmentExpression);
+ state.allowYield = previousAllowYield;
+ pattern = new WrappingNode(startToken).finishAssignmentPattern(pattern, right);
+ }
+ return pattern;
+ }
+
+ // ECMA-262 12.2.5 Array Initializer
+
+ function parseArrayInitializer() {
+ var elements = [], node = new Node(), restSpread;
+
+ expect('[');
+
+ while (!match(']')) {
+ if (match(',')) {
+ lex();
+ elements.push(null);
+ } else if (match('...')) {
+ restSpread = new Node();
+ lex();
+ restSpread.finishSpreadElement(inheritCoverGrammar(parseAssignmentExpression));
+
+ if (!match(']')) {
+ isAssignmentTarget = isBindingElement = false;
+ expect(',');
+ }
+ elements.push(restSpread);
+ } else {
+ elements.push(inheritCoverGrammar(parseAssignmentExpression));
+
+ if (!match(']')) {
+ expect(',');
+ }
+ }
+ }
+
+ lex();
+
+ return node.finishArrayExpression(elements);
+ }
+
+ // ECMA-262 12.2.6 Object Initializer
+
+ function parsePropertyFunction(node, paramInfo, isGenerator) {
+ var previousStrict, body;
+
+ isAssignmentTarget = isBindingElement = false;
+
+ previousStrict = strict;
+ body = isolateCoverGrammar(parseFunctionSourceElements);
+
+ if (strict && paramInfo.firstRestricted) {
+ tolerateUnexpectedToken(paramInfo.firstRestricted, paramInfo.message);
+ }
+ if (strict && paramInfo.stricted) {
+ tolerateUnexpectedToken(paramInfo.stricted, paramInfo.message);
+ }
+
+ strict = previousStrict;
+ return node.finishFunctionExpression(null, paramInfo.params, paramInfo.defaults, body, isGenerator);
+ }
+
+ function parsePropertyMethodFunction() {
+ var params, method, node = new Node(),
+ previousAllowYield = state.allowYield;
+
+ state.allowYield = false;
+ params = parseParams();
+ state.allowYield = previousAllowYield;
+
+ state.allowYield = false;
+ method = parsePropertyFunction(node, params, false);
+ state.allowYield = previousAllowYield;
+
+ return method;
+ }
+
+ function parseObjectPropertyKey() {
+ var token, node = new Node(), expr;
+
+ token = lex();
+
+ // Note: This function is called only from parseObjectProperty(), where
+ // EOF and Punctuator tokens are already filtered out.
+
+ switch (token.type) {
+ case Token.StringLiteral:
+ case Token.NumericLiteral:
+ if (strict && token.octal) {
+ tolerateUnexpectedToken(token, Messages.StrictOctalLiteral);
+ }
+ return node.finishLiteral(token);
+ case Token.Identifier:
+ case Token.BooleanLiteral:
+ case Token.NullLiteral:
+ case Token.Keyword:
+ return node.finishIdentifier(token.value);
+ case Token.Punctuator:
+ if (token.value === '[') {
+ expr = isolateCoverGrammar(parseAssignmentExpression);
+ expect(']');
+ return expr;
+ }
+ break;
+ }
+ throwUnexpectedToken(token);
+ }
+
+ function lookaheadPropertyName() {
+ switch (lookahead.type) {
+ case Token.Identifier:
+ case Token.StringLiteral:
+ case Token.BooleanLiteral:
+ case Token.NullLiteral:
+ case Token.NumericLiteral:
+ case Token.Keyword:
+ return true;
+ case Token.Punctuator:
+ return lookahead.value === '[';
+ }
+ return false;
+ }
+
+ // This function is to try to parse a MethodDefinition as defined in 14.3. But in the case of object literals,
+ // it might be called at a position where there is in fact a short hand identifier pattern or a data property.
+ // This can only be determined after we consumed up to the left parentheses.
+ //
+ // In order to avoid back tracking, it returns `null` if the position is not a MethodDefinition and the caller
+ // is responsible to visit other options.
+ function tryParseMethodDefinition(token, key, computed, node) {
+ var value, options, methodNode, params,
+ previousAllowYield = state.allowYield;
+
+ if (token.type === Token.Identifier) {
+ // check for `get` and `set`;
+
+ if (token.value === 'get' && lookaheadPropertyName()) {
+ computed = match('[');
+ key = parseObjectPropertyKey();
+ methodNode = new Node();
+ expect('(');
+ expect(')');
+
+ state.allowYield = false;
+ value = parsePropertyFunction(methodNode, {
+ params: [],
+ defaults: [],
+ stricted: null,
+ firstRestricted: null,
+ message: null
+ }, false);
+ state.allowYield = previousAllowYield;
+
+ return node.finishProperty('get', key, computed, value, false, false);
+ } else if (token.value === 'set' && lookaheadPropertyName()) {
+ computed = match('[');
+ key = parseObjectPropertyKey();
+ methodNode = new Node();
+ expect('(');
+
+ options = {
+ params: [],
+ defaultCount: 0,
+ defaults: [],
+ firstRestricted: null,
+ paramSet: {}
+ };
+ if (match(')')) {
+ tolerateUnexpectedToken(lookahead);
+ } else {
+ state.allowYield = false;
+ parseParam(options);
+ state.allowYield = previousAllowYield;
+ if (options.defaultCount === 0) {
+ options.defaults = [];
+ }
+ }
+ expect(')');
+
+ state.allowYield = false;
+ value = parsePropertyFunction(methodNode, options, false);
+ state.allowYield = previousAllowYield;
+
+ return node.finishProperty('set', key, computed, value, false, false);
+ }
+ } else if (token.type === Token.Punctuator && token.value === '*' && lookaheadPropertyName()) {
+ computed = match('[');
+ key = parseObjectPropertyKey();
+ methodNode = new Node();
+
+ state.allowYield = true;
+ params = parseParams();
+ state.allowYield = previousAllowYield;
+
+ state.allowYield = false;
+ value = parsePropertyFunction(methodNode, params, true);
+ state.allowYield = previousAllowYield;
+
+ return node.finishProperty('init', key, computed, value, true, false);
+ }
+
+ if (key && match('(')) {
+ value = parsePropertyMethodFunction();
+ return node.finishProperty('init', key, computed, value, true, false);
+ }
+
+ // Not a MethodDefinition.
+ return null;
+ }
+
+ function parseObjectProperty(hasProto) {
+ var token = lookahead, node = new Node(), computed, key, maybeMethod, proto, value;
+
+ computed = match('[');
+ if (match('*')) {
+ lex();
+ } else {
+ key = parseObjectPropertyKey();
+ }
+ maybeMethod = tryParseMethodDefinition(token, key, computed, node);
+ if (maybeMethod) {
+ return maybeMethod;
+ }
+
+ if (!key) {
+ throwUnexpectedToken(lookahead);
+ }
+
+ // Check for duplicated __proto__
+ if (!computed) {
+ proto = (key.type === Syntax.Identifier && key.name === '__proto__') ||
+ (key.type === Syntax.Literal && key.value === '__proto__');
+ if (hasProto.value && proto) {
+ tolerateError(Messages.DuplicateProtoProperty);
+ }
+ hasProto.value |= proto;
+ }
+
+ if (match(':')) {
+ lex();
+ value = inheritCoverGrammar(parseAssignmentExpression);
+ return node.finishProperty('init', key, computed, value, false, false);
+ }
+
+ if (token.type === Token.Identifier) {
+ if (match('=')) {
+ firstCoverInitializedNameError = lookahead;
+ lex();
+ value = isolateCoverGrammar(parseAssignmentExpression);
+ return node.finishProperty('init', key, computed,
+ new WrappingNode(token).finishAssignmentPattern(key, value), false, true);
+ }
+ return node.finishProperty('init', key, computed, key, false, true);
+ }
+
+ throwUnexpectedToken(lookahead);
+ }
+
+ function parseObjectInitializer() {
+ var properties = [], hasProto = {value: false}, node = new Node();
+
+ expect('{');
+
+ while (!match('}')) {
+ properties.push(parseObjectProperty(hasProto));
+
+ if (!match('}')) {
+ expectCommaSeparator();
+ }
+ }
+
+ expect('}');
+
+ return node.finishObjectExpression(properties);
+ }
+
+ function reinterpretExpressionAsPattern(expr) {
+ var i;
+ switch (expr.type) {
+ case Syntax.Identifier:
+ case Syntax.MemberExpression:
+ case Syntax.RestElement:
+ case Syntax.AssignmentPattern:
+ break;
+ case Syntax.SpreadElement:
+ expr.type = Syntax.RestElement;
+ reinterpretExpressionAsPattern(expr.argument);
+ break;
+ case Syntax.ArrayExpression:
+ expr.type = Syntax.ArrayPattern;
+ for (i = 0; i < expr.elements.length; i++) {
+ if (expr.elements[i] !== null) {
+ reinterpretExpressionAsPattern(expr.elements[i]);
+ }
+ }
+ break;
+ case Syntax.ObjectExpression:
+ expr.type = Syntax.ObjectPattern;
+ for (i = 0; i < expr.properties.length; i++) {
+ reinterpretExpressionAsPattern(expr.properties[i].value);
+ }
+ break;
+ case Syntax.AssignmentExpression:
+ expr.type = Syntax.AssignmentPattern;
+ reinterpretExpressionAsPattern(expr.left);
+ break;
+ default:
+ // Allow other node type for tolerant parsing.
+ break;
+ }
+ }
+
+ // ECMA-262 12.2.9 Template Literals
+
+ function parseTemplateElement(option) {
+ var node, token;
+
+ if (lookahead.type !== Token.Template || (option.head && !lookahead.head)) {
+ throwUnexpectedToken();
+ }
+
+ node = new Node();
+ token = lex();
+
+ return node.finishTemplateElement({ raw: token.value.raw, cooked: token.value.cooked }, token.tail);
+ }
+
+ function parseTemplateLiteral() {
+ var quasi, quasis, expressions, node = new Node();
+
+ quasi = parseTemplateElement({ head: true });
+ quasis = [quasi];
+ expressions = [];
+
+ while (!quasi.tail) {
+ expressions.push(parseExpression());
+ quasi = parseTemplateElement({ head: false });
+ quasis.push(quasi);
+ }
+
+ return node.finishTemplateLiteral(quasis, expressions);
+ }
+
+ // ECMA-262 12.2.10 The Grouping Operator
+
+ function parseGroupExpression() {
+ var expr, expressions, startToken, i, params = [];
+
+ expect('(');
+
+ if (match(')')) {
+ lex();
+ if (!match('=>')) {
+ expect('=>');
+ }
+ return {
+ type: PlaceHolders.ArrowParameterPlaceHolder,
+ params: [],
+ rawParams: []
+ };
+ }
+
+ startToken = lookahead;
+ if (match('...')) {
+ expr = parseRestElement(params);
+ expect(')');
+ if (!match('=>')) {
+ expect('=>');
+ }
+ return {
+ type: PlaceHolders.ArrowParameterPlaceHolder,
+ params: [expr]
+ };
+ }
+
+ isBindingElement = true;
+ expr = inheritCoverGrammar(parseAssignmentExpression);
+
+ if (match(',')) {
+ isAssignmentTarget = false;
+ expressions = [expr];
+
+ while (startIndex < length) {
+ if (!match(',')) {
+ break;
+ }
+ lex();
+
+ if (match('...')) {
+ if (!isBindingElement) {
+ throwUnexpectedToken(lookahead);
+ }
+ expressions.push(parseRestElement(params));
+ expect(')');
+ if (!match('=>')) {
+ expect('=>');
+ }
+ isBindingElement = false;
+ for (i = 0; i < expressions.length; i++) {
+ reinterpretExpressionAsPattern(expressions[i]);
+ }
+ return {
+ type: PlaceHolders.ArrowParameterPlaceHolder,
+ params: expressions
+ };
+ }
+
+ expressions.push(inheritCoverGrammar(parseAssignmentExpression));
+ }
+
+ expr = new WrappingNode(startToken).finishSequenceExpression(expressions);
+ }
+
+
+ expect(')');
+
+ if (match('=>')) {
+ if (expr.type === Syntax.Identifier && expr.name === 'yield') {
+ return {
+ type: PlaceHolders.ArrowParameterPlaceHolder,
+ params: [expr]
+ };
+ }
+
+ if (!isBindingElement) {
+ throwUnexpectedToken(lookahead);
+ }
+
+ if (expr.type === Syntax.SequenceExpression) {
+ for (i = 0; i < expr.expressions.length; i++) {
+ reinterpretExpressionAsPattern(expr.expressions[i]);
+ }
+ } else {
+ reinterpretExpressionAsPattern(expr);
+ }
+
+ expr = {
+ type: PlaceHolders.ArrowParameterPlaceHolder,
+ params: expr.type === Syntax.SequenceExpression ? expr.expressions : [expr]
+ };
+ }
+ isBindingElement = false;
+ return expr;
+ }
+
+
+ // ECMA-262 12.2 Primary Expressions
+
+ function parsePrimaryExpression() {
+ var type, token, expr, node;
+
+ if (match('(')) {
+ isBindingElement = false;
+ return inheritCoverGrammar(parseGroupExpression);
+ }
+
+ if (match('[')) {
+ return inheritCoverGrammar(parseArrayInitializer);
+ }
+
+ if (match('{')) {
+ return inheritCoverGrammar(parseObjectInitializer);
+ }
+
+ type = lookahead.type;
+ node = new Node();
+
+ if (type === Token.Identifier) {
+ if (state.sourceType === 'module' && lookahead.value === 'await') {
+ tolerateUnexpectedToken(lookahead);
+ }
+ expr = node.finishIdentifier(lex().value);
+ } else if (type === Token.StringLiteral || type === Token.NumericLiteral) {
+ isAssignmentTarget = isBindingElement = false;
+ if (strict && lookahead.octal) {
+ tolerateUnexpectedToken(lookahead, Messages.StrictOctalLiteral);
+ }
+ expr = node.finishLiteral(lex());
+ } else if (type === Token.Keyword) {
+ if (!strict && state.allowYield && matchKeyword('yield')) {
+ return parseNonComputedProperty();
+ }
+ if (!strict && matchKeyword('let')) {
+ return node.finishIdentifier(lex().value);
+ }
+ isAssignmentTarget = isBindingElement = false;
+ if (matchKeyword('function')) {
+ return parseFunctionExpression();
+ }
+ if (matchKeyword('this')) {
+ lex();
+ return node.finishThisExpression();
+ }
+ if (matchKeyword('class')) {
+ return parseClassExpression();
+ }
+ throwUnexpectedToken(lex());
+ } else if (type === Token.BooleanLiteral) {
+ isAssignmentTarget = isBindingElement = false;
+ token = lex();
+ token.value = (token.value === 'true');
+ expr = node.finishLiteral(token);
+ } else if (type === Token.NullLiteral) {
+ isAssignmentTarget = isBindingElement = false;
+ token = lex();
+ token.value = null;
+ expr = node.finishLiteral(token);
+ } else if (match('/') || match('/=')) {
+ isAssignmentTarget = isBindingElement = false;
+ index = startIndex;
+
+ if (typeof extra.tokens !== 'undefined') {
+ token = collectRegex();
+ } else {
+ token = scanRegExp();
+ }
+ lex();
+ expr = node.finishLiteral(token);
+ } else if (type === Token.Template) {
+ expr = parseTemplateLiteral();
+ } else {
+ throwUnexpectedToken(lex());
+ }
+
+ return expr;
+ }
+
+ // ECMA-262 12.3 Left-Hand-Side Expressions
+
+ function parseArguments() {
+ var args = [], expr;
+
+ expect('(');
+
+ if (!match(')')) {
+ while (startIndex < length) {
+ if (match('...')) {
+ expr = new Node();
+ lex();
+ expr.finishSpreadElement(isolateCoverGrammar(parseAssignmentExpression));
+ } else {
+ expr = isolateCoverGrammar(parseAssignmentExpression);
+ }
+ args.push(expr);
+ if (match(')')) {
+ break;
+ }
+ expectCommaSeparator();
+ }
+ }
+
+ expect(')');
+
+ return args;
+ }
+
+ function parseNonComputedProperty() {
+ var token, node = new Node();
+
+ token = lex();
+
+ if (!isIdentifierName(token)) {
+ throwUnexpectedToken(token);
+ }
+
+ return node.finishIdentifier(token.value);
+ }
+
+ function parseNonComputedMember() {
+ expect('.');
+
+ return parseNonComputedProperty();
+ }
+
+ function parseComputedMember() {
+ var expr;
+
+ expect('[');
+
+ expr = isolateCoverGrammar(parseExpression);
+
+ expect(']');
+
+ return expr;
+ }
+
+ // ECMA-262 12.3.3 The new Operator
+
+ function parseNewExpression() {
+ var callee, args, node = new Node();
+
+ expectKeyword('new');
+
+ if (match('.')) {
+ lex();
+ if (lookahead.type === Token.Identifier && lookahead.value === 'target') {
+ if (state.inFunctionBody) {
+ lex();
+ return node.finishMetaProperty('new', 'target');
+ }
+ }
+ throwUnexpectedToken(lookahead);
+ }
+
+ callee = isolateCoverGrammar(parseLeftHandSideExpression);
+ args = match('(') ? parseArguments() : [];
+
+ isAssignmentTarget = isBindingElement = false;
+
+ return node.finishNewExpression(callee, args);
+ }
+
+ // ECMA-262 12.3.4 Function Calls
+
+ function parseLeftHandSideExpressionAllowCall() {
+ var quasi, expr, args, property, startToken, previousAllowIn = state.allowIn;
+
+ startToken = lookahead;
+ state.allowIn = true;
+
+ if (matchKeyword('super') && state.inFunctionBody) {
+ expr = new Node();
+ lex();
+ expr = expr.finishSuper();
+ if (!match('(') && !match('.') && !match('[')) {
+ throwUnexpectedToken(lookahead);
+ }
+ } else {
+ expr = inheritCoverGrammar(matchKeyword('new') ? parseNewExpression : parsePrimaryExpression);
+ }
+
+ for (;;) {
+ if (match('.')) {
+ isBindingElement = false;
+ isAssignmentTarget = true;
+ property = parseNonComputedMember();
+ expr = new WrappingNode(startToken).finishMemberExpression('.', expr, property);
+ } else if (match('(')) {
+ isBindingElement = false;
+ isAssignmentTarget = false;
+ args = parseArguments();
+ expr = new WrappingNode(startToken).finishCallExpression(expr, args);
+ } else if (match('[')) {
+ isBindingElement = false;
+ isAssignmentTarget = true;
+ property = parseComputedMember();
+ expr = new WrappingNode(startToken).finishMemberExpression('[', expr, property);
+ } else if (lookahead.type === Token.Template && lookahead.head) {
+ quasi = parseTemplateLiteral();
+ expr = new WrappingNode(startToken).finishTaggedTemplateExpression(expr, quasi);
+ } else {
+ break;
+ }
+ }
+ state.allowIn = previousAllowIn;
+
+ return expr;
+ }
+
+ // ECMA-262 12.3 Left-Hand-Side Expressions
+
+ function parseLeftHandSideExpression() {
+ var quasi, expr, property, startToken;
+ assert(state.allowIn, 'callee of new expression always allow in keyword.');
+
+ startToken = lookahead;
+
+ if (matchKeyword('super') && state.inFunctionBody) {
+ expr = new Node();
+ lex();
+ expr = expr.finishSuper();
+ if (!match('[') && !match('.')) {
+ throwUnexpectedToken(lookahead);
+ }
+ } else {
+ expr = inheritCoverGrammar(matchKeyword('new') ? parseNewExpression : parsePrimaryExpression);
+ }
+
+ for (;;) {
+ if (match('[')) {
+ isBindingElement = false;
+ isAssignmentTarget = true;
+ property = parseComputedMember();
+ expr = new WrappingNode(startToken).finishMemberExpression('[', expr, property);
+ } else if (match('.')) {
+ isBindingElement = false;
+ isAssignmentTarget = true;
+ property = parseNonComputedMember();
+ expr = new WrappingNode(startToken).finishMemberExpression('.', expr, property);
+ } else if (lookahead.type === Token.Template && lookahead.head) {
+ quasi = parseTemplateLiteral();
+ expr = new WrappingNode(startToken).finishTaggedTemplateExpression(expr, quasi);
+ } else {
+ break;
+ }
+ }
+ return expr;
+ }
+
+ // ECMA-262 12.4 Postfix Expressions
+
+ function parsePostfixExpression() {
+ var expr, token, startToken = lookahead;
+
+ expr = inheritCoverGrammar(parseLeftHandSideExpressionAllowCall);
+
+ if (!hasLineTerminator && lookahead.type === Token.Punctuator) {
+ if (match('++') || match('--')) {
+ // ECMA-262 11.3.1, 11.3.2
+ if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) {
+ tolerateError(Messages.StrictLHSPostfix);
+ }
+
+ if (!isAssignmentTarget) {
+ tolerateError(Messages.InvalidLHSInAssignment);
+ }
+
+ isAssignmentTarget = isBindingElement = false;
+
+ token = lex();
+ expr = new WrappingNode(startToken).finishPostfixExpression(token.value, expr);
+ }
+ }
+
+ return expr;
+ }
+
+ // ECMA-262 12.5 Unary Operators
+
+ function parseUnaryExpression() {
+ var token, expr, startToken;
+
+ if (lookahead.type !== Token.Punctuator && lookahead.type !== Token.Keyword) {
+ expr = parsePostfixExpression();
+ } else if (match('++') || match('--')) {
+ startToken = lookahead;
+ token = lex();
+ expr = inheritCoverGrammar(parseUnaryExpression);
+ // ECMA-262 11.4.4, 11.4.5
+ if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) {
+ tolerateError(Messages.StrictLHSPrefix);
+ }
+
+ if (!isAssignmentTarget) {
+ tolerateError(Messages.InvalidLHSInAssignment);
+ }
+ expr = new WrappingNode(startToken).finishUnaryExpression(token.value, expr);
+ isAssignmentTarget = isBindingElement = false;
+ } else if (match('+') || match('-') || match('~') || match('!')) {
+ startToken = lookahead;
+ token = lex();
+ expr = inheritCoverGrammar(parseUnaryExpression);
+ expr = new WrappingNode(startToken).finishUnaryExpression(token.value, expr);
+ isAssignmentTarget = isBindingElement = false;
+ } else if (matchKeyword('delete') || matchKeyword('void') || matchKeyword('typeof')) {
+ startToken = lookahead;
+ token = lex();
+ expr = inheritCoverGrammar(parseUnaryExpression);
+ expr = new WrappingNode(startToken).finishUnaryExpression(token.value, expr);
+ if (strict && expr.operator === 'delete' && expr.argument.type === Syntax.Identifier) {
+ tolerateError(Messages.StrictDelete);
+ }
+ isAssignmentTarget = isBindingElement = false;
+ } else {
+ expr = parsePostfixExpression();
+ }
+
+ return expr;
+ }
+
+ function binaryPrecedence(token, allowIn) {
+ var prec = 0;
+
+ if (token.type !== Token.Punctuator && token.type !== Token.Keyword) {
+ return 0;
+ }
+
+ switch (token.value) {
+ case '||':
+ prec = 1;
+ break;
+
+ case '&&':
+ prec = 2;
+ break;
+
+ case '|':
+ prec = 3;
+ break;
+
+ case '^':
+ prec = 4;
+ break;
+
+ case '&':
+ prec = 5;
+ break;
+
+ case '==':
+ case '!=':
+ case '===':
+ case '!==':
+ prec = 6;
+ break;
+
+ case '<':
+ case '>':
+ case '<=':
+ case '>=':
+ case 'instanceof':
+ prec = 7;
+ break;
+
+ case 'in':
+ prec = allowIn ? 7 : 0;
+ break;
+
+ case '<<':
+ case '>>':
+ case '>>>':
+ prec = 8;
+ break;
+
+ case '+':
+ case '-':
+ prec = 9;
+ break;
+
+ case '*':
+ case '/':
+ case '%':
+ prec = 11;
+ break;
+
+ default:
+ break;
+ }
+
+ return prec;
+ }
+
+ // ECMA-262 12.6 Multiplicative Operators
+ // ECMA-262 12.7 Additive Operators
+ // ECMA-262 12.8 Bitwise Shift Operators
+ // ECMA-262 12.9 Relational Operators
+ // ECMA-262 12.10 Equality Operators
+ // ECMA-262 12.11 Binary Bitwise Operators
+ // ECMA-262 12.12 Binary Logical Operators
+
+ function parseBinaryExpression() {
+ var marker, markers, expr, token, prec, stack, right, operator, left, i;
+
+ marker = lookahead;
+ left = inheritCoverGrammar(parseUnaryExpression);
+
+ token = lookahead;
+ prec = binaryPrecedence(token, state.allowIn);
+ if (prec === 0) {
+ return left;
+ }
+ isAssignmentTarget = isBindingElement = false;
+ token.prec = prec;
+ lex();
+
+ markers = [marker, lookahead];
+ right = isolateCoverGrammar(parseUnaryExpression);
+
+ stack = [left, token, right];
+
+ while ((prec = binaryPrecedence(lookahead, state.allowIn)) > 0) {
+
+ // Reduce: make a binary expression from the three topmost entries.
+ while ((stack.length > 2) && (prec <= stack[stack.length - 2].prec)) {
+ right = stack.pop();
+ operator = stack.pop().value;
+ left = stack.pop();
+ markers.pop();
+ expr = new WrappingNode(markers[markers.length - 1]).finishBinaryExpression(operator, left, right);
+ stack.push(expr);
+ }
+
+ // Shift.
+ token = lex();
+ token.prec = prec;
+ stack.push(token);
+ markers.push(lookahead);
+ expr = isolateCoverGrammar(parseUnaryExpression);
+ stack.push(expr);
+ }
+
+ // Final reduce to clean-up the stack.
+ i = stack.length - 1;
+ expr = stack[i];
+ markers.pop();
+ while (i > 1) {
+ expr = new WrappingNode(markers.pop()).finishBinaryExpression(stack[i - 1].value, stack[i - 2], expr);
+ i -= 2;
+ }
+
+ return expr;
+ }
+
+
+ // ECMA-262 12.13 Conditional Operator
+
+ function parseConditionalExpression() {
+ var expr, previousAllowIn, consequent, alternate, startToken;
+
+ startToken = lookahead;
+
+ expr = inheritCoverGrammar(parseBinaryExpression);
+ if (match('?')) {
+ lex();
+ previousAllowIn = state.allowIn;
+ state.allowIn = true;
+ consequent = isolateCoverGrammar(parseAssignmentExpression);
+ state.allowIn = previousAllowIn;
+ expect(':');
+ alternate = isolateCoverGrammar(parseAssignmentExpression);
+
+ expr = new WrappingNode(startToken).finishConditionalExpression(expr, consequent, alternate);
+ isAssignmentTarget = isBindingElement = false;
+ }
+
+ return expr;
+ }
+
+ // ECMA-262 14.2 Arrow Function Definitions
+
+ function parseConciseBody() {
+ if (match('{')) {
+ return parseFunctionSourceElements();
+ }
+ return isolateCoverGrammar(parseAssignmentExpression);
+ }
+
+ function checkPatternParam(options, param) {
+ var i;
+ switch (param.type) {
+ case Syntax.Identifier:
+ validateParam(options, param, param.name);
+ break;
+ case Syntax.RestElement:
+ checkPatternParam(options, param.argument);
+ break;
+ case Syntax.AssignmentPattern:
+ checkPatternParam(options, param.left);
+ break;
+ case Syntax.ArrayPattern:
+ for (i = 0; i < param.elements.length; i++) {
+ if (param.elements[i] !== null) {
+ checkPatternParam(options, param.elements[i]);
+ }
+ }
+ break;
+ case Syntax.YieldExpression:
+ break;
+ default:
+ assert(param.type === Syntax.ObjectPattern, 'Invalid type');
+ for (i = 0; i < param.properties.length; i++) {
+ checkPatternParam(options, param.properties[i].value);
+ }
+ break;
+ }
+ }
+ function reinterpretAsCoverFormalsList(expr) {
+ var i, len, param, params, defaults, defaultCount, options, token;
+
+ defaults = [];
+ defaultCount = 0;
+ params = [expr];
+
+ switch (expr.type) {
+ case Syntax.Identifier:
+ break;
+ case PlaceHolders.ArrowParameterPlaceHolder:
+ params = expr.params;
+ break;
+ default:
+ return null;
+ }
+
+ options = {
+ paramSet: {}
+ };
+
+ for (i = 0, len = params.length; i < len; i += 1) {
+ param = params[i];
+ switch (param.type) {
+ case Syntax.AssignmentPattern:
+ params[i] = param.left;
+ if (param.right.type === Syntax.YieldExpression) {
+ if (param.right.argument) {
+ throwUnexpectedToken(lookahead);
+ }
+ param.right.type = Syntax.Identifier;
+ param.right.name = 'yield';
+ delete param.right.argument;
+ delete param.right.delegate;
+ }
+ defaults.push(param.right);
+ ++defaultCount;
+ checkPatternParam(options, param.left);
+ break;
+ default:
+ checkPatternParam(options, param);
+ params[i] = param;
+ defaults.push(null);
+ break;
+ }
+ }
+
+ if (strict || !state.allowYield) {
+ for (i = 0, len = params.length; i < len; i += 1) {
+ param = params[i];
+ if (param.type === Syntax.YieldExpression) {
+ throwUnexpectedToken(lookahead);
+ }
+ }
+ }
+
+ if (options.message === Messages.StrictParamDupe) {
+ token = strict ? options.stricted : options.firstRestricted;
+ throwUnexpectedToken(token, options.message);
+ }
+
+ if (defaultCount === 0) {
+ defaults = [];
+ }
+
+ return {
+ params: params,
+ defaults: defaults,
+ stricted: options.stricted,
+ firstRestricted: options.firstRestricted,
+ message: options.message
+ };
+ }
+
+ function parseArrowFunctionExpression(options, node) {
+ var previousStrict, previousAllowYield, body;
+
+ if (hasLineTerminator) {
+ tolerateUnexpectedToken(lookahead);
+ }
+ expect('=>');
+
+ previousStrict = strict;
+ previousAllowYield = state.allowYield;
+ state.allowYield = true;
+
+ body = parseConciseBody();
+
+ if (strict && options.firstRestricted) {
+ throwUnexpectedToken(options.firstRestricted, options.message);
+ }
+ if (strict && options.stricted) {
+ tolerateUnexpectedToken(options.stricted, options.message);
+ }
+
+ strict = previousStrict;
+ state.allowYield = previousAllowYield;
+
+ return node.finishArrowFunctionExpression(options.params, options.defaults, body, body.type !== Syntax.BlockStatement);
+ }
+
+ // ECMA-262 14.4 Yield expression
+
+ function parseYieldExpression() {
+ var argument, expr, delegate, previousAllowYield;
+
+ argument = null;
+ expr = new Node();
+ delegate = false;
+
+ expectKeyword('yield');
+
+ if (!hasLineTerminator) {
+ previousAllowYield = state.allowYield;
+ state.allowYield = false;
+ delegate = match('*');
+ if (delegate) {
+ lex();
+ argument = parseAssignmentExpression();
+ } else {
+ if (!match(';') && !match('}') && !match(')') && lookahead.type !== Token.EOF) {
+ argument = parseAssignmentExpression();
+ }
+ }
+ state.allowYield = previousAllowYield;
+ }
+
+ return expr.finishYieldExpression(argument, delegate);
+ }
+
+ // ECMA-262 12.14 Assignment Operators
+
+ function parseAssignmentExpression() {
+ var token, expr, right, list, startToken;
+
+ startToken = lookahead;
+ token = lookahead;
+
+ if (!state.allowYield && matchKeyword('yield')) {
+ return parseYieldExpression();
+ }
+
+ expr = parseConditionalExpression();
+
+ if (expr.type === PlaceHolders.ArrowParameterPlaceHolder || match('=>')) {
+ isAssignmentTarget = isBindingElement = false;
+ list = reinterpretAsCoverFormalsList(expr);
+
+ if (list) {
+ firstCoverInitializedNameError = null;
+ return parseArrowFunctionExpression(list, new WrappingNode(startToken));
+ }
+
+ return expr;
+ }
+
+ if (matchAssign()) {
+ if (!isAssignmentTarget) {
+ tolerateError(Messages.InvalidLHSInAssignment);
+ }
+
+ // ECMA-262 12.1.1
+ if (strict && expr.type === Syntax.Identifier) {
+ if (isRestrictedWord(expr.name)) {
+ tolerateUnexpectedToken(token, Messages.StrictLHSAssignment);
+ }
+ if (isStrictModeReservedWord(expr.name)) {
+ tolerateUnexpectedToken(token, Messages.StrictReservedWord);
+ }
+ }
+
+ if (!match('=')) {
+ isAssignmentTarget = isBindingElement = false;
+ } else {
+ reinterpretExpressionAsPattern(expr);
+ }
+
+ token = lex();
+ right = isolateCoverGrammar(parseAssignmentExpression);
+ expr = new WrappingNode(startToken).finishAssignmentExpression(token.value, expr, right);
+ firstCoverInitializedNameError = null;
+ }
+
+ return expr;
+ }
+
+ // ECMA-262 12.15 Comma Operator
+
+ function parseExpression() {
+ var expr, startToken = lookahead, expressions;
+
+ expr = isolateCoverGrammar(parseAssignmentExpression);
+
+ if (match(',')) {
+ expressions = [expr];
+
+ while (startIndex < length) {
+ if (!match(',')) {
+ break;
+ }
+ lex();
+ expressions.push(isolateCoverGrammar(parseAssignmentExpression));
+ }
+
+ expr = new WrappingNode(startToken).finishSequenceExpression(expressions);
+ }
+
+ return expr;
+ }
+
+ // ECMA-262 13.2 Block
+
+ function parseStatementListItem() {
+ if (lookahead.type === Token.Keyword) {
+ switch (lookahead.value) {
+ case 'export':
+ if (state.sourceType !== 'module') {
+ tolerateUnexpectedToken(lookahead, Messages.IllegalExportDeclaration);
+ }
+ return parseExportDeclaration();
+ case 'import':
+ if (state.sourceType !== 'module') {
+ tolerateUnexpectedToken(lookahead, Messages.IllegalImportDeclaration);
+ }
+ return parseImportDeclaration();
+ case 'const':
+ return parseLexicalDeclaration({inFor: false});
+ case 'function':
+ return parseFunctionDeclaration(new Node());
+ case 'class':
+ return parseClassDeclaration();
+ }
+ }
+
+ if (matchKeyword('let') && isLexicalDeclaration()) {
+ return parseLexicalDeclaration({inFor: false});
+ }
+
+ return parseStatement();
+ }
+
+ function parseStatementList() {
+ var list = [];
+ while (startIndex < length) {
+ if (match('}')) {
+ break;
+ }
+ list.push(parseStatementListItem());
+ }
+
+ return list;
+ }
+
+ function parseBlock() {
+ var block, node = new Node();
+
+ expect('{');
+
+ block = parseStatementList();
+
+ expect('}');
+
+ return node.finishBlockStatement(block);
+ }
+
+ // ECMA-262 13.3.2 Variable Statement
+
+ function parseVariableIdentifier(kind) {
+ var token, node = new Node();
+
+ token = lex();
+
+ if (token.type === Token.Keyword && token.value === 'yield') {
+ if (strict) {
+ tolerateUnexpectedToken(token, Messages.StrictReservedWord);
+ } if (!state.allowYield) {
+ throwUnexpectedToken(token);
+ }
+ } else if (token.type !== Token.Identifier) {
+ if (strict && token.type === Token.Keyword && isStrictModeReservedWord(token.value)) {
+ tolerateUnexpectedToken(token, Messages.StrictReservedWord);
+ } else {
+ if (strict || token.value !== 'let' || kind !== 'var') {
+ throwUnexpectedToken(token);
+ }
+ }
+ } else if (state.sourceType === 'module' && token.type === Token.Identifier && token.value === 'await') {
+ tolerateUnexpectedToken(token);
+ }
+
+ return node.finishIdentifier(token.value);
+ }
+
+ function parseVariableDeclaration(options) {
+ var init = null, id, node = new Node(), params = [];
+
+ id = parsePattern(params, 'var');
+
+ // ECMA-262 12.2.1
+ if (strict && isRestrictedWord(id.name)) {
+ tolerateError(Messages.StrictVarName);
+ }
+
+ if (match('=')) {
+ lex();
+ init = isolateCoverGrammar(parseAssignmentExpression);
+ } else if (id.type !== Syntax.Identifier && !options.inFor) {
+ expect('=');
+ }
+
+ return node.finishVariableDeclarator(id, init);
+ }
+
+ function parseVariableDeclarationList(options) {
+ var opt, list;
+
+ opt = { inFor: options.inFor };
+ list = [parseVariableDeclaration(opt)];
+
+ while (match(',')) {
+ lex();
+ list.push(parseVariableDeclaration(opt));
+ }
+
+ return list;
+ }
+
+ function parseVariableStatement(node) {
+ var declarations;
+
+ expectKeyword('var');
+
+ declarations = parseVariableDeclarationList({ inFor: false });
+
+ consumeSemicolon();
+
+ return node.finishVariableDeclaration(declarations);
+ }
+
+ // ECMA-262 13.3.1 Let and Const Declarations
+
+ function parseLexicalBinding(kind, options) {
+ var init = null, id, node = new Node(), params = [];
+
+ id = parsePattern(params, kind);
+
+ // ECMA-262 12.2.1
+ if (strict && id.type === Syntax.Identifier && isRestrictedWord(id.name)) {
+ tolerateError(Messages.StrictVarName);
+ }
+
+ if (kind === 'const') {
+ if (!matchKeyword('in') && !matchContextualKeyword('of')) {
+ expect('=');
+ init = isolateCoverGrammar(parseAssignmentExpression);
+ }
+ } else if ((!options.inFor && id.type !== Syntax.Identifier) || match('=')) {
+ expect('=');
+ init = isolateCoverGrammar(parseAssignmentExpression);
+ }
+
+ return node.finishVariableDeclarator(id, init);
+ }
+
+ function parseBindingList(kind, options) {
+ var list = [parseLexicalBinding(kind, options)];
+
+ while (match(',')) {
+ lex();
+ list.push(parseLexicalBinding(kind, options));
+ }
+
+ return list;
+ }
+
+
+ function tokenizerState() {
+ return {
+ index: index,
+ lineNumber: lineNumber,
+ lineStart: lineStart,
+ hasLineTerminator: hasLineTerminator,
+ lastIndex: lastIndex,
+ lastLineNumber: lastLineNumber,
+ lastLineStart: lastLineStart,
+ startIndex: startIndex,
+ startLineNumber: startLineNumber,
+ startLineStart: startLineStart,
+ lookahead: lookahead,
+ tokenCount: extra.tokens ? extra.tokens.length : 0
+ };
+ }
+
+ function resetTokenizerState(ts) {
+ index = ts.index;
+ lineNumber = ts.lineNumber;
+ lineStart = ts.lineStart;
+ hasLineTerminator = ts.hasLineTerminator;
+ lastIndex = ts.lastIndex;
+ lastLineNumber = ts.lastLineNumber;
+ lastLineStart = ts.lastLineStart;
+ startIndex = ts.startIndex;
+ startLineNumber = ts.startLineNumber;
+ startLineStart = ts.startLineStart;
+ lookahead = ts.lookahead;
+ if (extra.tokens) {
+ extra.tokens.splice(ts.tokenCount, extra.tokens.length);
+ }
+ }
+
+ function isLexicalDeclaration() {
+ var lexical, ts;
+
+ ts = tokenizerState();
+
+ lex();
+ lexical = (lookahead.type === Token.Identifier) || match('[') || match('{') ||
+ matchKeyword('let') || matchKeyword('yield');
+
+ resetTokenizerState(ts);
+
+ return lexical;
+ }
+
+ function parseLexicalDeclaration(options) {
+ var kind, declarations, node = new Node();
+
+ kind = lex().value;
+ assert(kind === 'let' || kind === 'const', 'Lexical declaration must be either let or const');
+
+ declarations = parseBindingList(kind, options);
+
+ consumeSemicolon();
+
+ return node.finishLexicalDeclaration(declarations, kind);
+ }
+
+ function parseRestElement(params) {
+ var param, node = new Node();
+
+ lex();
+
+ if (match('{')) {
+ throwError(Messages.ObjectPatternAsRestParameter);
+ }
+
+ params.push(lookahead);
+
+ param = parseVariableIdentifier();
+
+ if (match('=')) {
+ throwError(Messages.DefaultRestParameter);
+ }
+
+ if (!match(')')) {
+ throwError(Messages.ParameterAfterRestParameter);
+ }
+
+ return node.finishRestElement(param);
+ }
+
+ // ECMA-262 13.4 Empty Statement
+
+ function parseEmptyStatement(node) {
+ expect(';');
+ return node.finishEmptyStatement();
+ }
+
+ // ECMA-262 12.4 Expression Statement
+
+ function parseExpressionStatement(node) {
+ var expr = parseExpression();
+ consumeSemicolon();
+ return node.finishExpressionStatement(expr);
+ }
+
+ // ECMA-262 13.6 If statement
+
+ function parseIfStatement(node) {
+ var test, consequent, alternate;
+
+ expectKeyword('if');
+
+ expect('(');
+
+ test = parseExpression();
+
+ expect(')');
+
+ consequent = parseStatement();
+
+ if (matchKeyword('else')) {
+ lex();
+ alternate = parseStatement();
+ } else {
+ alternate = null;
+ }
+
+ return node.finishIfStatement(test, consequent, alternate);
+ }
+
+ // ECMA-262 13.7 Iteration Statements
+
+ function parseDoWhileStatement(node) {
+ var body, test, oldInIteration;
+
+ expectKeyword('do');
+
+ oldInIteration = state.inIteration;
+ state.inIteration = true;
+
+ body = parseStatement();
+
+ state.inIteration = oldInIteration;
+
+ expectKeyword('while');
+
+ expect('(');
+
+ test = parseExpression();
+
+ expect(')');
+
+ if (match(';')) {
+ lex();
+ }
+
+ return node.finishDoWhileStatement(body, test);
+ }
+
+ function parseWhileStatement(node) {
+ var test, body, oldInIteration;
+
+ expectKeyword('while');
+
+ expect('(');
+
+ test = parseExpression();
+
+ expect(')');
+
+ oldInIteration = state.inIteration;
+ state.inIteration = true;
+
+ body = parseStatement();
+
+ state.inIteration = oldInIteration;
+
+ return node.finishWhileStatement(test, body);
+ }
+
+ function parseForStatement(node) {
+ var init, forIn, initSeq, initStartToken, test, update, left, right, kind, declarations,
+ body, oldInIteration, previousAllowIn = state.allowIn;
+
+ init = test = update = null;
+ forIn = true;
+
+ expectKeyword('for');
+
+ expect('(');
+
+ if (match(';')) {
+ lex();
+ } else {
+ if (matchKeyword('var')) {
+ init = new Node();
+ lex();
+
+ state.allowIn = false;
+ declarations = parseVariableDeclarationList({ inFor: true });
+ state.allowIn = previousAllowIn;
+
+ if (declarations.length === 1 && matchKeyword('in')) {
+ init = init.finishVariableDeclaration(declarations);
+ lex();
+ left = init;
+ right = parseExpression();
+ init = null;
+ } else if (declarations.length === 1 && declarations[0].init === null && matchContextualKeyword('of')) {
+ init = init.finishVariableDeclaration(declarations);
+ lex();
+ left = init;
+ right = parseAssignmentExpression();
+ init = null;
+ forIn = false;
+ } else {
+ init = init.finishVariableDeclaration(declarations);
+ expect(';');
+ }
+ } else if (matchKeyword('const') || matchKeyword('let')) {
+ init = new Node();
+ kind = lex().value;
+
+ if (!strict && lookahead.value === 'in') {
+ init = init.finishIdentifier(kind);
+ lex();
+ left = init;
+ right = parseExpression();
+ init = null;
+ } else {
+ state.allowIn = false;
+ declarations = parseBindingList(kind, {inFor: true});
+ state.allowIn = previousAllowIn;
+
+ if (declarations.length === 1 && declarations[0].init === null && matchKeyword('in')) {
+ init = init.finishLexicalDeclaration(declarations, kind);
+ lex();
+ left = init;
+ right = parseExpression();
+ init = null;
+ } else if (declarations.length === 1 && declarations[0].init === null && matchContextualKeyword('of')) {
+ init = init.finishLexicalDeclaration(declarations, kind);
+ lex();
+ left = init;
+ right = parseAssignmentExpression();
+ init = null;
+ forIn = false;
+ } else {
+ consumeSemicolon();
+ init = init.finishLexicalDeclaration(declarations, kind);
+ }
+ }
+ } else {
+ initStartToken = lookahead;
+ state.allowIn = false;
+ init = inheritCoverGrammar(parseAssignmentExpression);
+ state.allowIn = previousAllowIn;
+
+ if (matchKeyword('in')) {
+ if (!isAssignmentTarget) {
+ tolerateError(Messages.InvalidLHSInForIn);
+ }
+
+ lex();
+ reinterpretExpressionAsPattern(init);
+ left = init;
+ right = parseExpression();
+ init = null;
+ } else if (matchContextualKeyword('of')) {
+ if (!isAssignmentTarget) {
+ tolerateError(Messages.InvalidLHSInForLoop);
+ }
+
+ lex();
+ reinterpretExpressionAsPattern(init);
+ left = init;
+ right = parseAssignmentExpression();
+ init = null;
+ forIn = false;
+ } else {
+ if (match(',')) {
+ initSeq = [init];
+ while (match(',')) {
+ lex();
+ initSeq.push(isolateCoverGrammar(parseAssignmentExpression));
+ }
+ init = new WrappingNode(initStartToken).finishSequenceExpression(initSeq);
+ }
+ expect(';');
+ }
+ }
+ }
+
+ if (typeof left === 'undefined') {
+
+ if (!match(';')) {
+ test = parseExpression();
+ }
+ expect(';');
+
+ if (!match(')')) {
+ update = parseExpression();
+ }
+ }
+
+ expect(')');
+
+ oldInIteration = state.inIteration;
+ state.inIteration = true;
+
+ body = isolateCoverGrammar(parseStatement);
+
+ state.inIteration = oldInIteration;
+
+ return (typeof left === 'undefined') ?
+ node.finishForStatement(init, test, update, body) :
+ forIn ? node.finishForInStatement(left, right, body) :
+ node.finishForOfStatement(left, right, body);
+ }
+
+ // ECMA-262 13.8 The continue statement
+
+ function parseContinueStatement(node) {
+ var label = null, key;
+
+ expectKeyword('continue');
+
+ // Optimize the most common form: 'continue;'.
+ if (source.charCodeAt(startIndex) === 0x3B) {
+ lex();
+
+ if (!state.inIteration) {
+ throwError(Messages.IllegalContinue);
+ }
+
+ return node.finishContinueStatement(null);
+ }
+
+ if (hasLineTerminator) {
+ if (!state.inIteration) {
+ throwError(Messages.IllegalContinue);
+ }
+
+ return node.finishContinueStatement(null);
+ }
+
+ if (lookahead.type === Token.Identifier) {
+ label = parseVariableIdentifier();
+
+ key = '$' + label.name;
+ if (!Object.prototype.hasOwnProperty.call(state.labelSet, key)) {
+ throwError(Messages.UnknownLabel, label.name);
+ }
+ }
+
+ consumeSemicolon();
+
+ if (label === null && !state.inIteration) {
+ throwError(Messages.IllegalContinue);
+ }
+
+ return node.finishContinueStatement(label);
+ }
+
+ // ECMA-262 13.9 The break statement
+
+ function parseBreakStatement(node) {
+ var label = null, key;
+
+ expectKeyword('break');
+
+ // Catch the very common case first: immediately a semicolon (U+003B).
+ if (source.charCodeAt(lastIndex) === 0x3B) {
+ lex();
+
+ if (!(state.inIteration || state.inSwitch)) {
+ throwError(Messages.IllegalBreak);
+ }
+
+ return node.finishBreakStatement(null);
+ }
+
+ if (hasLineTerminator) {
+ if (!(state.inIteration || state.inSwitch)) {
+ throwError(Messages.IllegalBreak);
+ }
+ } else if (lookahead.type === Token.Identifier) {
+ label = parseVariableIdentifier();
+
+ key = '$' + label.name;
+ if (!Object.prototype.hasOwnProperty.call(state.labelSet, key)) {
+ throwError(Messages.UnknownLabel, label.name);
+ }
+ }
+
+ consumeSemicolon();
+
+ if (label === null && !(state.inIteration || state.inSwitch)) {
+ throwError(Messages.IllegalBreak);
+ }
+
+ return node.finishBreakStatement(label);
+ }
+
+ // ECMA-262 13.10 The return statement
+
+ function parseReturnStatement(node) {
+ var argument = null;
+
+ expectKeyword('return');
+
+ if (!state.inFunctionBody) {
+ tolerateError(Messages.IllegalReturn);
+ }
+
+ // 'return' followed by a space and an identifier is very common.
+ if (source.charCodeAt(lastIndex) === 0x20) {
+ if (isIdentifierStart(source.charCodeAt(lastIndex + 1))) {
+ argument = parseExpression();
+ consumeSemicolon();
+ return node.finishReturnStatement(argument);
+ }
+ }
+
+ if (hasLineTerminator) {
+ // HACK
+ return node.finishReturnStatement(null);
+ }
+
+ if (!match(';')) {
+ if (!match('}') && lookahead.type !== Token.EOF) {
+ argument = parseExpression();
+ }
+ }
+
+ consumeSemicolon();
+
+ return node.finishReturnStatement(argument);
+ }
+
+ // ECMA-262 13.11 The with statement
+
+ function parseWithStatement(node) {
+ var object, body;
+
+ if (strict) {
+ tolerateError(Messages.StrictModeWith);
+ }
+
+ expectKeyword('with');
+
+ expect('(');
+
+ object = parseExpression();
+
+ expect(')');
+
+ body = parseStatement();
+
+ return node.finishWithStatement(object, body);
+ }
+
+ // ECMA-262 13.12 The switch statement
+
+ function parseSwitchCase() {
+ var test, consequent = [], statement, node = new Node();
+
+ if (matchKeyword('default')) {
+ lex();
+ test = null;
+ } else {
+ expectKeyword('case');
+ test = parseExpression();
+ }
+ expect(':');
+
+ while (startIndex < length) {
+ if (match('}') || matchKeyword('default') || matchKeyword('case')) {
+ break;
+ }
+ statement = parseStatementListItem();
+ consequent.push(statement);
+ }
+
+ return node.finishSwitchCase(test, consequent);
+ }
+
+ function parseSwitchStatement(node) {
+ var discriminant, cases, clause, oldInSwitch, defaultFound;
+
+ expectKeyword('switch');
+
+ expect('(');
+
+ discriminant = parseExpression();
+
+ expect(')');
+
+ expect('{');
+
+ cases = [];
+
+ if (match('}')) {
+ lex();
+ return node.finishSwitchStatement(discriminant, cases);
+ }
+
+ oldInSwitch = state.inSwitch;
+ state.inSwitch = true;
+ defaultFound = false;
+
+ while (startIndex < length) {
+ if (match('}')) {
+ break;
+ }
+ clause = parseSwitchCase();
+ if (clause.test === null) {
+ if (defaultFound) {
+ throwError(Messages.MultipleDefaultsInSwitch);
+ }
+ defaultFound = true;
+ }
+ cases.push(clause);
+ }
+
+ state.inSwitch = oldInSwitch;
+
+ expect('}');
+
+ return node.finishSwitchStatement(discriminant, cases);
+ }
+
+ // ECMA-262 13.14 The throw statement
+
+ function parseThrowStatement(node) {
+ var argument;
+
+ expectKeyword('throw');
+
+ if (hasLineTerminator) {
+ throwError(Messages.NewlineAfterThrow);
+ }
+
+ argument = parseExpression();
+
+ consumeSemicolon();
+
+ return node.finishThrowStatement(argument);
+ }
+
+ // ECMA-262 13.15 The try statement
+
+ function parseCatchClause() {
+ var param, params = [], paramMap = {}, key, i, body, node = new Node();
+
+ expectKeyword('catch');
+
+ expect('(');
+ if (match(')')) {
+ throwUnexpectedToken(lookahead);
+ }
+
+ param = parsePattern(params);
+ for (i = 0; i < params.length; i++) {
+ key = '$' + params[i].value;
+ if (Object.prototype.hasOwnProperty.call(paramMap, key)) {
+ tolerateError(Messages.DuplicateBinding, params[i].value);
+ }
+ paramMap[key] = true;
+ }
+
+ // ECMA-262 12.14.1
+ if (strict && isRestrictedWord(param.name)) {
+ tolerateError(Messages.StrictCatchVariable);
+ }
+
+ expect(')');
+ body = parseBlock();
+ return node.finishCatchClause(param, body);
+ }
+
+ function parseTryStatement(node) {
+ var block, handler = null, finalizer = null;
+
+ expectKeyword('try');
+
+ block = parseBlock();
+
+ if (matchKeyword('catch')) {
+ handler = parseCatchClause();
+ }
+
+ if (matchKeyword('finally')) {
+ lex();
+ finalizer = parseBlock();
+ }
+
+ if (!handler && !finalizer) {
+ throwError(Messages.NoCatchOrFinally);
+ }
+
+ return node.finishTryStatement(block, handler, finalizer);
+ }
+
+ // ECMA-262 13.16 The debugger statement
+
+ function parseDebuggerStatement(node) {
+ expectKeyword('debugger');
+
+ consumeSemicolon();
+
+ return node.finishDebuggerStatement();
+ }
+
+ // 13 Statements
+
+ function parseStatement() {
+ var type = lookahead.type,
+ expr,
+ labeledBody,
+ key,
+ node;
+
+ if (type === Token.EOF) {
+ throwUnexpectedToken(lookahead);
+ }
+
+ if (type === Token.Punctuator && lookahead.value === '{') {
+ return parseBlock();
+ }
+ isAssignmentTarget = isBindingElement = true;
+ node = new Node();
+
+ if (type === Token.Punctuator) {
+ switch (lookahead.value) {
+ case ';':
+ return parseEmptyStatement(node);
+ case '(':
+ return parseExpressionStatement(node);
+ default:
+ break;
+ }
+ } else if (type === Token.Keyword) {
+ switch (lookahead.value) {
+ case 'break':
+ return parseBreakStatement(node);
+ case 'continue':
+ return parseContinueStatement(node);
+ case 'debugger':
+ return parseDebuggerStatement(node);
+ case 'do':
+ return parseDoWhileStatement(node);
+ case 'for':
+ return parseForStatement(node);
+ case 'function':
+ return parseFunctionDeclaration(node);
+ case 'if':
+ return parseIfStatement(node);
+ case 'return':
+ return parseReturnStatement(node);
+ case 'switch':
+ return parseSwitchStatement(node);
+ case 'throw':
+ return parseThrowStatement(node);
+ case 'try':
+ return parseTryStatement(node);
+ case 'var':
+ return parseVariableStatement(node);
+ case 'while':
+ return parseWhileStatement(node);
+ case 'with':
+ return parseWithStatement(node);
+ default:
+ break;
+ }
+ }
+
+ expr = parseExpression();
+
+ // ECMA-262 12.12 Labelled Statements
+ if ((expr.type === Syntax.Identifier) && match(':')) {
+ lex();
+
+ key = '$' + expr.name;
+ if (Object.prototype.hasOwnProperty.call(state.labelSet, key)) {
+ throwError(Messages.Redeclaration, 'Label', expr.name);
+ }
+
+ state.labelSet[key] = true;
+ labeledBody = parseStatement();
+ delete state.labelSet[key];
+ return node.finishLabeledStatement(expr, labeledBody);
+ }
+
+ consumeSemicolon();
+
+ return node.finishExpressionStatement(expr);
+ }
+
+ // ECMA-262 14.1 Function Definition
+
+ function parseFunctionSourceElements() {
+ var statement, body = [], token, directive, firstRestricted,
+ oldLabelSet, oldInIteration, oldInSwitch, oldInFunctionBody,
+ node = new Node();
+
+ expect('{');
+
+ while (startIndex < length) {
+ if (lookahead.type !== Token.StringLiteral) {
+ break;
+ }
+ token = lookahead;
+
+ statement = parseStatementListItem();
+ body.push(statement);
+ if (statement.expression.type !== Syntax.Literal) {
+ // this is not directive
+ break;
+ }
+ directive = source.slice(token.start + 1, token.end - 1);
+ if (directive === 'use strict') {
+ strict = true;
+ if (firstRestricted) {
+ tolerateUnexpectedToken(firstRestricted, Messages.StrictOctalLiteral);
+ }
+ } else {
+ if (!firstRestricted && token.octal) {
+ firstRestricted = token;
+ }
+ }
+ }
+
+ oldLabelSet = state.labelSet;
+ oldInIteration = state.inIteration;
+ oldInSwitch = state.inSwitch;
+ oldInFunctionBody = state.inFunctionBody;
+
+ state.labelSet = {};
+ state.inIteration = false;
+ state.inSwitch = false;
+ state.inFunctionBody = true;
+
+ while (startIndex < length) {
+ if (match('}')) {
+ break;
+ }
+ body.push(parseStatementListItem());
+ }
+
+ expect('}');
+
+ state.labelSet = oldLabelSet;
+ state.inIteration = oldInIteration;
+ state.inSwitch = oldInSwitch;
+ state.inFunctionBody = oldInFunctionBody;
+
+ return node.finishBlockStatement(body);
+ }
+
+ function validateParam(options, param, name) {
+ var key = '$' + name;
+ if (strict) {
+ if (isRestrictedWord(name)) {
+ options.stricted = param;
+ options.message = Messages.StrictParamName;
+ }
+ if (Object.prototype.hasOwnProperty.call(options.paramSet, key)) {
+ options.stricted = param;
+ options.message = Messages.StrictParamDupe;
+ }
+ } else if (!options.firstRestricted) {
+ if (isRestrictedWord(name)) {
+ options.firstRestricted = param;
+ options.message = Messages.StrictParamName;
+ } else if (isStrictModeReservedWord(name)) {
+ options.firstRestricted = param;
+ options.message = Messages.StrictReservedWord;
+ } else if (Object.prototype.hasOwnProperty.call(options.paramSet, key)) {
+ options.stricted = param;
+ options.message = Messages.StrictParamDupe;
+ }
+ }
+ options.paramSet[key] = true;
+ }
+
+ function parseParam(options) {
+ var token, param, params = [], i, def;
+
+ token = lookahead;
+ if (token.value === '...') {
+ param = parseRestElement(params);
+ validateParam(options, param.argument, param.argument.name);
+ options.params.push(param);
+ options.defaults.push(null);
+ return false;
+ }
+
+ param = parsePatternWithDefault(params);
+ for (i = 0; i < params.length; i++) {
+ validateParam(options, params[i], params[i].value);
+ }
+
+ if (param.type === Syntax.AssignmentPattern) {
+ def = param.right;
+ param = param.left;
+ ++options.defaultCount;
+ }
+
+ options.params.push(param);
+ options.defaults.push(def);
+
+ return !match(')');
+ }
+
+ function parseParams(firstRestricted) {
+ var options;
+
+ options = {
+ params: [],
+ defaultCount: 0,
+ defaults: [],
+ firstRestricted: firstRestricted
+ };
+
+ expect('(');
+
+ if (!match(')')) {
+ options.paramSet = {};
+ while (startIndex < length) {
+ if (!parseParam(options)) {
+ break;
+ }
+ expect(',');
+ }
+ }
+
+ expect(')');
+
+ if (options.defaultCount === 0) {
+ options.defaults = [];
+ }
+
+ return {
+ params: options.params,
+ defaults: options.defaults,
+ stricted: options.stricted,
+ firstRestricted: options.firstRestricted,
+ message: options.message
+ };
+ }
+
+ function parseFunctionDeclaration(node, identifierIsOptional) {
+ var id = null, params = [], defaults = [], body, token, stricted, tmp, firstRestricted, message, previousStrict,
+ isGenerator, previousAllowYield;
+
+ previousAllowYield = state.allowYield;
+
+ expectKeyword('function');
+
+ isGenerator = match('*');
+ if (isGenerator) {
+ lex();
+ }
+
+ if (!identifierIsOptional || !match('(')) {
+ token = lookahead;
+ id = parseVariableIdentifier();
+ if (strict) {
+ if (isRestrictedWord(token.value)) {
+ tolerateUnexpectedToken(token, Messages.StrictFunctionName);
+ }
+ } else {
+ if (isRestrictedWord(token.value)) {
+ firstRestricted = token;
+ message = Messages.StrictFunctionName;
+ } else if (isStrictModeReservedWord(token.value)) {
+ firstRestricted = token;
+ message = Messages.StrictReservedWord;
+ }
+ }
+ }
+
+ state.allowYield = !isGenerator;
+ tmp = parseParams(firstRestricted);
+ params = tmp.params;
+ defaults = tmp.defaults;
+ stricted = tmp.stricted;
+ firstRestricted = tmp.firstRestricted;
+ if (tmp.message) {
+ message = tmp.message;
+ }
+
+
+ previousStrict = strict;
+ body = parseFunctionSourceElements();
+ if (strict && firstRestricted) {
+ throwUnexpectedToken(firstRestricted, message);
+ }
+ if (strict && stricted) {
+ tolerateUnexpectedToken(stricted, message);
+ }
+
+ strict = previousStrict;
+ state.allowYield = previousAllowYield;
+
+ return node.finishFunctionDeclaration(id, params, defaults, body, isGenerator);
+ }
+
+ function parseFunctionExpression() {
+ var token, id = null, stricted, firstRestricted, message, tmp,
+ params = [], defaults = [], body, previousStrict, node = new Node(),
+ isGenerator, previousAllowYield;
+
+ previousAllowYield = state.allowYield;
+
+ expectKeyword('function');
+
+ isGenerator = match('*');
+ if (isGenerator) {
+ lex();
+ }
+
+ state.allowYield = !isGenerator;
+ if (!match('(')) {
+ token = lookahead;
+ id = (!strict && !isGenerator && matchKeyword('yield')) ? parseNonComputedProperty() : parseVariableIdentifier();
+ if (strict) {
+ if (isRestrictedWord(token.value)) {
+ tolerateUnexpectedToken(token, Messages.StrictFunctionName);
+ }
+ } else {
+ if (isRestrictedWord(token.value)) {
+ firstRestricted = token;
+ message = Messages.StrictFunctionName;
+ } else if (isStrictModeReservedWord(token.value)) {
+ firstRestricted = token;
+ message = Messages.StrictReservedWord;
+ }
+ }
+ }
+
+ tmp = parseParams(firstRestricted);
+ params = tmp.params;
+ defaults = tmp.defaults;
+ stricted = tmp.stricted;
+ firstRestricted = tmp.firstRestricted;
+ if (tmp.message) {
+ message = tmp.message;
+ }
+
+ previousStrict = strict;
+ body = parseFunctionSourceElements();
+ if (strict && firstRestricted) {
+ throwUnexpectedToken(firstRestricted, message);
+ }
+ if (strict && stricted) {
+ tolerateUnexpectedToken(stricted, message);
+ }
+ strict = previousStrict;
+ state.allowYield = previousAllowYield;
+
+ return node.finishFunctionExpression(id, params, defaults, body, isGenerator);
+ }
+
+ // ECMA-262 14.5 Class Definitions
+
+ function parseClassBody() {
+ var classBody, token, isStatic, hasConstructor = false, body, method, computed, key;
+
+ classBody = new Node();
+
+ expect('{');
+ body = [];
+ while (!match('}')) {
+ if (match(';')) {
+ lex();
+ } else {
+ method = new Node();
+ token = lookahead;
+ isStatic = false;
+ computed = match('[');
+ if (match('*')) {
+ lex();
+ } else {
+ key = parseObjectPropertyKey();
+ if (key.name === 'static' && (lookaheadPropertyName() || match('*'))) {
+ token = lookahead;
+ isStatic = true;
+ computed = match('[');
+ if (match('*')) {
+ lex();
+ } else {
+ key = parseObjectPropertyKey();
+ }
+ }
+ }
+ method = tryParseMethodDefinition(token, key, computed, method);
+ if (method) {
+ method['static'] = isStatic; // jscs:ignore requireDotNotation
+ if (method.kind === 'init') {
+ method.kind = 'method';
+ }
+ if (!isStatic) {
+ if (!method.computed && (method.key.name || method.key.value.toString()) === 'constructor') {
+ if (method.kind !== 'method' || !method.method || method.value.generator) {
+ throwUnexpectedToken(token, Messages.ConstructorSpecialMethod);
+ }
+ if (hasConstructor) {
+ throwUnexpectedToken(token, Messages.DuplicateConstructor);
+ } else {
+ hasConstructor = true;
+ }
+ method.kind = 'constructor';
+ }
+ } else {
+ if (!method.computed && (method.key.name || method.key.value.toString()) === 'prototype') {
+ throwUnexpectedToken(token, Messages.StaticPrototype);
+ }
+ }
+ method.type = Syntax.MethodDefinition;
+ delete method.method;
+ delete method.shorthand;
+ body.push(method);
+ } else {
+ throwUnexpectedToken(lookahead);
+ }
+ }
+ }
+ lex();
+ return classBody.finishClassBody(body);
+ }
+
+ function parseClassDeclaration(identifierIsOptional) {
+ var id = null, superClass = null, classNode = new Node(), classBody, previousStrict = strict;
+ strict = true;
+
+ expectKeyword('class');
+
+ if (!identifierIsOptional || lookahead.type === Token.Identifier) {
+ id = parseVariableIdentifier();
+ }
+
+ if (matchKeyword('extends')) {
+ lex();
+ superClass = isolateCoverGrammar(parseLeftHandSideExpressionAllowCall);
+ }
+ classBody = parseClassBody();
+ strict = previousStrict;
+
+ return classNode.finishClassDeclaration(id, superClass, classBody);
+ }
+
+ function parseClassExpression() {
+ var id = null, superClass = null, classNode = new Node(), classBody, previousStrict = strict;
+ strict = true;
+
+ expectKeyword('class');
+
+ if (lookahead.type === Token.Identifier) {
+ id = parseVariableIdentifier();
+ }
+
+ if (matchKeyword('extends')) {
+ lex();
+ superClass = isolateCoverGrammar(parseLeftHandSideExpressionAllowCall);
+ }
+ classBody = parseClassBody();
+ strict = previousStrict;
+
+ return classNode.finishClassExpression(id, superClass, classBody);
+ }
+
+ // ECMA-262 15.2 Modules
+
+ function parseModuleSpecifier() {
+ var node = new Node();
+
+ if (lookahead.type !== Token.StringLiteral) {
+ throwError(Messages.InvalidModuleSpecifier);
+ }
+ return node.finishLiteral(lex());
+ }
+
+ // ECMA-262 15.2.3 Exports
+
+ function parseExportSpecifier() {
+ var exported, local, node = new Node(), def;
+ if (matchKeyword('default')) {
+ // export {default} from 'something';
+ def = new Node();
+ lex();
+ local = def.finishIdentifier('default');
+ } else {
+ local = parseVariableIdentifier();
+ }
+ if (matchContextualKeyword('as')) {
+ lex();
+ exported = parseNonComputedProperty();
+ }
+ return node.finishExportSpecifier(local, exported);
+ }
+
+ function parseExportNamedDeclaration(node) {
+ var declaration = null,
+ isExportFromIdentifier,
+ src = null, specifiers = [];
+
+ // non-default export
+ if (lookahead.type === Token.Keyword) {
+ // covers:
+ // export var f = 1;
+ switch (lookahead.value) {
+ case 'let':
+ case 'const':
+ declaration = parseLexicalDeclaration({inFor: false});
+ return node.finishExportNamedDeclaration(declaration, specifiers, null);
+ case 'var':
+ case 'class':
+ case 'function':
+ declaration = parseStatementListItem();
+ return node.finishExportNamedDeclaration(declaration, specifiers, null);
+ }
+ }
+
+ expect('{');
+ while (!match('}')) {
+ isExportFromIdentifier = isExportFromIdentifier || matchKeyword('default');
+ specifiers.push(parseExportSpecifier());
+ if (!match('}')) {
+ expect(',');
+ if (match('}')) {
+ break;
+ }
+ }
+ }
+ expect('}');
+
+ if (matchContextualKeyword('from')) {
+ // covering:
+ // export {default} from 'foo';
+ // export {foo} from 'foo';
+ lex();
+ src = parseModuleSpecifier();
+ consumeSemicolon();
+ } else if (isExportFromIdentifier) {
+ // covering:
+ // export {default}; // missing fromClause
+ throwError(lookahead.value ?
+ Messages.UnexpectedToken : Messages.MissingFromClause, lookahead.value);
+ } else {
+ // cover
+ // export {foo};
+ consumeSemicolon();
+ }
+ return node.finishExportNamedDeclaration(declaration, specifiers, src);
+ }
+
+ function parseExportDefaultDeclaration(node) {
+ var declaration = null,
+ expression = null;
+
+ // covers:
+ // export default ...
+ expectKeyword('default');
+
+ if (matchKeyword('function')) {
+ // covers:
+ // export default function foo () {}
+ // export default function () {}
+ declaration = parseFunctionDeclaration(new Node(), true);
+ return node.finishExportDefaultDeclaration(declaration);
+ }
+ if (matchKeyword('class')) {
+ declaration = parseClassDeclaration(true);
+ return node.finishExportDefaultDeclaration(declaration);
+ }
+
+ if (matchContextualKeyword('from')) {
+ throwError(Messages.UnexpectedToken, lookahead.value);
+ }
+
+ // covers:
+ // export default {};
+ // export default [];
+ // export default (1 + 2);
+ if (match('{')) {
+ expression = parseObjectInitializer();
+ } else if (match('[')) {
+ expression = parseArrayInitializer();
+ } else {
+ expression = parseAssignmentExpression();
+ }
+ consumeSemicolon();
+ return node.finishExportDefaultDeclaration(expression);
+ }
+
+ function parseExportAllDeclaration(node) {
+ var src;
+
+ // covers:
+ // export * from 'foo';
+ expect('*');
+ if (!matchContextualKeyword('from')) {
+ throwError(lookahead.value ?
+ Messages.UnexpectedToken : Messages.MissingFromClause, lookahead.value);
+ }
+ lex();
+ src = parseModuleSpecifier();
+ consumeSemicolon();
+
+ return node.finishExportAllDeclaration(src);
+ }
+
+ function parseExportDeclaration() {
+ var node = new Node();
+ if (state.inFunctionBody) {
+ throwError(Messages.IllegalExportDeclaration);
+ }
+
+ expectKeyword('export');
+
+ if (matchKeyword('default')) {
+ return parseExportDefaultDeclaration(node);
+ }
+ if (match('*')) {
+ return parseExportAllDeclaration(node);
+ }
+ return parseExportNamedDeclaration(node);
+ }
+
+ // ECMA-262 15.2.2 Imports
+
+ function parseImportSpecifier() {
+ // import {<foo as bar>} ...;
+ var local, imported, node = new Node();
+
+ imported = parseNonComputedProperty();
+ if (matchContextualKeyword('as')) {
+ lex();
+ local = parseVariableIdentifier();
+ }
+
+ return node.finishImportSpecifier(local, imported);
+ }
+
+ function parseNamedImports() {
+ var specifiers = [];
+ // {foo, bar as bas}
+ expect('{');
+ while (!match('}')) {
+ specifiers.push(parseImportSpecifier());
+ if (!match('}')) {
+ expect(',');
+ if (match('}')) {
+ break;
+ }
+ }
+ }
+ expect('}');
+ return specifiers;
+ }
+
+ function parseImportDefaultSpecifier() {
+ // import <foo> ...;
+ var local, node = new Node();
+
+ local = parseNonComputedProperty();
+
+ return node.finishImportDefaultSpecifier(local);
+ }
+
+ function parseImportNamespaceSpecifier() {
+ // import <* as foo> ...;
+ var local, node = new Node();
+
+ expect('*');
+ if (!matchContextualKeyword('as')) {
+ throwError(Messages.NoAsAfterImportNamespace);
+ }
+ lex();
+ local = parseNonComputedProperty();
+
+ return node.finishImportNamespaceSpecifier(local);
+ }
+
+ function parseImportDeclaration() {
+ var specifiers = [], src, node = new Node();
+
+ if (state.inFunctionBody) {
+ throwError(Messages.IllegalImportDeclaration);
+ }
+
+ expectKeyword('import');
+
+ if (lookahead.type === Token.StringLiteral) {
+ // import 'foo';
+ src = parseModuleSpecifier();
+ } else {
+
+ if (match('{')) {
+ // import {bar}
+ specifiers = specifiers.concat(parseNamedImports());
+ } else if (match('*')) {
+ // import * as foo
+ specifiers.push(parseImportNamespaceSpecifier());
+ } else if (isIdentifierName(lookahead) && !matchKeyword('default')) {
+ // import foo
+ specifiers.push(parseImportDefaultSpecifier());
+ if (match(',')) {
+ lex();
+ if (match('*')) {
+ // import foo, * as foo
+ specifiers.push(parseImportNamespaceSpecifier());
+ } else if (match('{')) {
+ // import foo, {bar}
+ specifiers = specifiers.concat(parseNamedImports());
+ } else {
+ throwUnexpectedToken(lookahead);
+ }
+ }
+ } else {
+ throwUnexpectedToken(lex());
+ }
+
+ if (!matchContextualKeyword('from')) {
+ throwError(lookahead.value ?
+ Messages.UnexpectedToken : Messages.MissingFromClause, lookahead.value);
+ }
+ lex();
+ src = parseModuleSpecifier();
+ }
+
+ consumeSemicolon();
+ return node.finishImportDeclaration(specifiers, src);
+ }
+
+ // ECMA-262 15.1 Scripts
+
+ function parseScriptBody() {
+ var statement, body = [], token, directive, firstRestricted;
+
+ while (startIndex < length) {
+ token = lookahead;
+ if (token.type !== Token.StringLiteral) {
+ break;
+ }
+
+ statement = parseStatementListItem();
+ body.push(statement);
+ if (statement.expression.type !== Syntax.Literal) {
+ // this is not directive
+ break;
+ }
+ directive = source.slice(token.start + 1, token.end - 1);
+ if (directive === 'use strict') {
+ strict = true;
+ if (firstRestricted) {
+ tolerateUnexpectedToken(firstRestricted, Messages.StrictOctalLiteral);
+ }
+ } else {
+ if (!firstRestricted && token.octal) {
+ firstRestricted = token;
+ }
+ }
+ }
+
+ while (startIndex < length) {
+ statement = parseStatementListItem();
+ /* istanbul ignore if */
+ if (typeof statement === 'undefined') {
+ break;
+ }
+ body.push(statement);
+ }
+ return body;
+ }
+
+ function parseProgram() {
+ var body, node;
+
+ peek();
+ node = new Node();
+
+ body = parseScriptBody();
+ return node.finishProgram(body, state.sourceType);
+ }
+
+ function filterTokenLocation() {
+ var i, entry, token, tokens = [];
+
+ for (i = 0; i < extra.tokens.length; ++i) {
+ entry = extra.tokens[i];
+ token = {
+ type: entry.type,
+ value: entry.value
+ };
+ if (entry.regex) {
+ token.regex = {
+ pattern: entry.regex.pattern,
+ flags: entry.regex.flags
+ };
+ }
+ if (extra.range) {
+ token.range = entry.range;
+ }
+ if (extra.loc) {
+ token.loc = entry.loc;
+ }
+ tokens.push(token);
+ }
+
+ extra.tokens = tokens;
+ }
+
+ function tokenize(code, options, delegate) {
+ var toString,
+ tokens;
+
+ toString = String;
+ if (typeof code !== 'string' && !(code instanceof String)) {
+ code = toString(code);
+ }
+
+ source = code;
+ index = 0;
+ lineNumber = (source.length > 0) ? 1 : 0;
+ lineStart = 0;
+ startIndex = index;
+ startLineNumber = lineNumber;
+ startLineStart = lineStart;
+ length = source.length;
+ lookahead = null;
+ state = {
+ allowIn: true,
+ allowYield: true,
+ labelSet: {},
+ inFunctionBody: false,
+ inIteration: false,
+ inSwitch: false,
+ lastCommentStart: -1,
+ curlyStack: []
+ };
+
+ extra = {};
+
+ // Options matching.
+ options = options || {};
+
+ // Of course we collect tokens here.
+ options.tokens = true;
+ extra.tokens = [];
+ extra.tokenValues = [];
+ extra.tokenize = true;
+ extra.delegate = delegate;
+
+ // The following two fields are necessary to compute the Regex tokens.
+ extra.openParenToken = -1;
+ extra.openCurlyToken = -1;
+
+ extra.range = (typeof options.range === 'boolean') && options.range;
+ extra.loc = (typeof options.loc === 'boolean') && options.loc;
+
+ if (typeof options.comment === 'boolean' && options.comment) {
+ extra.comments = [];
+ }
+ if (typeof options.tolerant === 'boolean' && options.tolerant) {
+ extra.errors = [];
+ }
+
+ try {
+ peek();
+ if (lookahead.type === Token.EOF) {
+ return extra.tokens;
+ }
+
+ lex();
+ while (lookahead.type !== Token.EOF) {
+ try {
+ lex();
+ } catch (lexError) {
+ if (extra.errors) {
+ recordError(lexError);
+ // We have to break on the first error
+ // to avoid infinite loops.
+ break;
+ } else {
+ throw lexError;
+ }
+ }
+ }
+
+ tokens = extra.tokens;
+ if (typeof extra.errors !== 'undefined') {
+ tokens.errors = extra.errors;
+ }
+ } catch (e) {
+ throw e;
+ } finally {
+ extra = {};
+ }
+ return tokens;
+ }
+
+ function parse(code, options) {
+ var program, toString;
+
+ toString = String;
+ if (typeof code !== 'string' && !(code instanceof String)) {
+ code = toString(code);
+ }
+
+ source = code;
+ index = 0;
+ lineNumber = (source.length > 0) ? 1 : 0;
+ lineStart = 0;
+ startIndex = index;
+ startLineNumber = lineNumber;
+ startLineStart = lineStart;
+ length = source.length;
+ lookahead = null;
+ state = {
+ allowIn: true,
+ allowYield: true,
+ labelSet: {},
+ inFunctionBody: false,
+ inIteration: false,
+ inSwitch: false,
+ lastCommentStart: -1,
+ curlyStack: [],
+ sourceType: 'script'
+ };
+ strict = false;
+
+ extra = {};
+ if (typeof options !== 'undefined') {
+ extra.range = (typeof options.range === 'boolean') && options.range;
+ extra.loc = (typeof options.loc === 'boolean') && options.loc;
+ extra.attachComment = (typeof options.attachComment === 'boolean') && options.attachComment;
+
+ if (extra.loc && options.source !== null && options.source !== undefined) {
+ extra.source = toString(options.source);
+ }
+
+ if (typeof options.tokens === 'boolean' && options.tokens) {
+ extra.tokens = [];
+ }
+ if (typeof options.comment === 'boolean' && options.comment) {
+ extra.comments = [];
+ }
+ if (typeof options.tolerant === 'boolean' && options.tolerant) {
+ extra.errors = [];
+ }
+ if (extra.attachComment) {
+ extra.range = true;
+ extra.comments = [];
+ extra.bottomRightStack = [];
+ extra.trailingComments = [];
+ extra.leadingComments = [];
+ }
+ if (options.sourceType === 'module') {
+ // very restrictive condition for now
+ state.sourceType = options.sourceType;
+ strict = true;
+ }
+ }
+
+ try {
+ program = parseProgram();
+ if (typeof extra.comments !== 'undefined') {
+ program.comments = extra.comments;
+ }
+ if (typeof extra.tokens !== 'undefined') {
+ filterTokenLocation();
+ program.tokens = extra.tokens;
+ }
+ if (typeof extra.errors !== 'undefined') {
+ program.errors = extra.errors;
+ }
+ } catch (e) {
+ throw e;
+ } finally {
+ extra = {};
+ }
+
+ return program;
+ }
+
+ // Sync with *.json manifests.
+ exports.version = '2.7.3';
+
+ exports.tokenize = tokenize;
+
+ exports.parse = parse;
+
+ // Deep copy.
+ /* istanbul ignore next */
+ exports.Syntax = (function () {
+ var name, types = {};
+
+ if (typeof Object.create === 'function') {
+ types = Object.create(null);
+ }
+
+ for (name in Syntax) {
+ if (Syntax.hasOwnProperty(name)) {
+ types[name] = Syntax[name];
+ }
+ }
+
+ if (typeof Object.freeze === 'function') {
+ Object.freeze(types);
+ }
+
+ return types;
+ }());
+
+}));
+/* vim: set sw=4 ts=4 et tw=80 : */
diff --git a/node_modules/svgo/node_modules/esprima/package.json b/node_modules/svgo/node_modules/esprima/package.json
new file mode 100644
index 00000000..f2d59120
--- /dev/null
+++ b/node_modules/svgo/node_modules/esprima/package.json
@@ -0,0 +1,99 @@
+{
+ "name": "esprima",
+ "description": "ECMAScript parsing infrastructure for multipurpose analysis",
+ "homepage": "http://esprima.org",
+ "main": "esprima.js",
+ "bin": {
+ "esparse": "./bin/esparse.js",
+ "esvalidate": "./bin/esvalidate.js"
+ },
+ "version": "2.7.3",
+ "files": [
+ "bin",
+ "unit-tests.js",
+ "esprima.js"
+ ],
+ "engines": {
+ "node": ">=0.10.0"
+ },
+ "author": {
+ "name": "Ariya Hidayat",
+ "email": "ariya.hidayat@gmail.com"
+ },
+ "maintainers": [
+ {
+ "name": "Ariya Hidayat",
+ "email": "ariya.hidayat@gmail.com",
+ "web": "http://ariya.ofilabs.com"
+ }
+ ],
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/jquery/esprima.git"
+ },
+ "bugs": {
+ "url": "https://github.com/jquery/esprima/issues"
+ },
+ "license": "BSD-2-Clause",
+ "devDependencies": {
+ "codecov.io": "~0.1.6",
+ "escomplex-js": "1.2.0",
+ "eslint": "~1.7.2",
+ "everything.js": "~1.0.3",
+ "glob": "^5.0.15",
+ "istanbul": "~0.4.0",
+ "jscs": "~2.3.5",
+ "json-diff": "~0.3.1",
+ "karma": "^0.13.11",
+ "karma-chrome-launcher": "^0.2.1",
+ "karma-detect-browsers": "^2.0.2",
+ "karma-firefox-launcher": "^0.1.6",
+ "karma-ie-launcher": "^0.2.0",
+ "karma-mocha": "^0.2.0",
+ "karma-safari-launcher": "^0.1.1",
+ "karma-sauce-launcher": "^0.2.14",
+ "lodash": "^3.10.0",
+ "mocha": "^2.3.3",
+ "node-tick-processor": "~0.0.2",
+ "regenerate": "~1.2.1",
+ "temp": "~0.8.3",
+ "unicode-7.0.0": "~0.1.5"
+ },
+ "keywords": [
+ "ast",
+ "ecmascript",
+ "javascript",
+ "parser",
+ "syntax"
+ ],
+ "scripts": {
+ "check-version": "node test/check-version.js",
+ "jscs": "jscs -p crockford esprima.js && jscs -p crockford test/*.js",
+ "eslint": "node node_modules/eslint/bin/eslint.js -c .lintrc esprima.js",
+ "complexity": "node test/check-complexity.js",
+ "static-analysis": "npm run check-version && npm run jscs && npm run eslint && npm run complexity",
+ "unit-tests": "node test/unit-tests.js",
+ "grammar-tests": "node test/grammar-tests.js",
+ "regression-tests": "node test/regression-tests.js",
+ "all-tests": "npm run generate-fixtures && npm run unit-tests && npm run grammar-tests && npm run regression-tests",
+ "generate-fixtures": "node tools/generate-fixtures.js",
+ "browser-tests": "npm run generate-fixtures && cd test && karma start --single-run",
+ "saucelabs-evergreen": "cd test && karma start saucelabs-evergreen.conf.js",
+ "saucelabs-safari": "cd test && karma start saucelabs-safari.conf.js",
+ "saucelabs-ie": "cd test && karma start saucelabs-ie.conf.js",
+ "analyze-coverage": "istanbul cover test/unit-tests.js",
+ "check-coverage": "istanbul check-coverage --statement 100 --branch 100 --function 100",
+ "dynamic-analysis": "npm run analyze-coverage && npm run check-coverage",
+ "test": "npm run all-tests && npm run static-analysis && npm run dynamic-analysis",
+ "profile": "node --prof test/profile.js && mv isolate*.log v8.log && node-tick-processor",
+ "benchmark": "node test/benchmarks.js",
+ "benchmark-quick": "node test/benchmarks.js quick",
+ "codecov" : "istanbul report cobertura && codecov < ./coverage/cobertura-coverage.xml",
+ "downstream": "node test/downstream.js",
+ "travis": "npm test",
+ "circleci": "npm test && npm run codecov && npm run downstream",
+ "appveyor": "npm run all-tests && npm run browser-tests && npm run dynamic-analysis",
+ "droneio": "npm test && npm run saucelabs-evergreen && npm run saucelabs-ie && npm run saucelabs-safari",
+ "generate-regex": "node tools/generate-identifier-regex.js"
+ }
+}
diff --git a/node_modules/svgo/node_modules/js-yaml/.bin/js-yaml b/node_modules/svgo/node_modules/js-yaml/.bin/js-yaml
new file mode 120000
index 00000000..978fe612
--- /dev/null
+++ b/node_modules/svgo/node_modules/js-yaml/.bin/js-yaml
@@ -0,0 +1 @@
+../bin/js-yaml.js \ No newline at end of file
diff --git a/node_modules/svgo/node_modules/js-yaml/CHANGELOG.md b/node_modules/svgo/node_modules/js-yaml/CHANGELOG.md
new file mode 100644
index 00000000..103b1bbc
--- /dev/null
+++ b/node_modules/svgo/node_modules/js-yaml/CHANGELOG.md
@@ -0,0 +1,409 @@
+3.7.0 / 2016-11-12
+------------------
+
+- Fix parsing of quotes followed by newlines (#304, thanks to @dplepage).
+- Support polymorphism for tags (#300, thanks to @monken).
+
+
+3.6.1 / 2016-05-11
+------------------
+
+- Fix output cut on a pipe, #286.
+
+
+3.6.0 / 2016-04-16
+------------------
+
+- Dumper rewrite, fix multiple bugs with trailing `\n`.
+ Big thanks to @aepsilon!
+- Loader: fix leading/trailing newlines in block scalars, @aepsilon.
+
+
+3.5.5 / 2016-03-17
+------------------
+
+- Date parse fix: don't allow dates with on digit in month and day, #268.
+
+
+3.5.4 / 2016-03-09
+------------------
+
+- `noCompatMode` for dumper, to disable quoting YAML 1.1 values.
+
+
+3.5.3 / 2016-02-11
+------------------
+
+- Maintenance release.
+
+
+3.5.2 / 2016-01-11
+------------------
+
+- Maintenance: missed comma in bower config.
+
+
+3.5.1 / 2016-01-11
+------------------
+
+- Removed `inherit` dependency, #239.
+- Better browserify workaround for esprima load.
+- Demo rewrite.
+
+
+3.5.0 / 2016-01-10
+------------------
+
+- Dumper. Fold strings only, #217.
+- Dumper. `norefs` option, to clone linked objects, #229.
+- Loader. Throw a warning for duplicate keys, #166.
+- Improved browserify support (mark `esprima` & `Buffer` excluded).
+
+
+3.4.6 / 2015-11-26
+------------------
+
+- Use standalone `inherit` to keep browserified files clear.
+
+
+3.4.5 / 2015-11-23
+------------------
+
+- Added `lineWidth` option to dumper.
+
+
+3.4.4 / 2015-11-21
+------------------
+
+- Fixed floats dump (missed dot for scientific format), #220.
+- Allow non-printable characters inside quoted scalars, #192.
+
+
+3.4.3 / 2015-10-10
+------------------
+
+- Maintenance release - deps bump (esprima, argparse).
+
+
+3.4.2 / 2015-09-09
+------------------
+
+- Fixed serialization of duplicated entries in sequences, #205.
+ Thanks to @vogelsgesang.
+
+
+3.4.1 / 2015-09-05
+------------------
+
+- Fixed stacktrace handling in generated errors, for browsers (FF/IE).
+
+
+3.4.0 / 2015-08-23
+------------------
+
+- Fixed multiline keys dump, #197. Thanks to @tcr.
+- Don't throw on warnongs anymore. Use `onWarning` option to catch.
+- Throw error on unknown tags (was warning before).
+- Fixed heading line breaks in some scalars (regression).
+- Reworked internals of error class.
+
+
+3.3.1 / 2015-05-13
+------------------
+
+- Added `.sortKeys` dumper option, thanks to @rjmunro.
+- Fixed astral characters support, #191.
+
+
+3.3.0 / 2015-04-26
+------------------
+
+- Significantly improved long strings formatting in dumper, thanks to @isaacs.
+- Strip BOM if exists.
+
+
+3.2.7 / 2015-02-19
+------------------
+
+- Maintenance release.
+- Updated dependencies.
+- HISTORY.md -> CHANGELOG.md
+
+
+3.2.6 / 2015-02-07
+------------------
+
+- Fixed encoding of UTF-16 surrogate pairs. (e.g. "\U0001F431" CAT FACE).
+- Fixed demo dates dump (#113, thanks to @Hypercubed).
+
+
+3.2.5 / 2014-12-28
+------------------
+
+- Fixed resolving of all built-in types on empty nodes.
+- Fixed invalid warning on empty lines within quoted scalars and flow collections.
+- Fixed bug: Tag on an empty node didn't resolve in some cases.
+
+
+3.2.4 / 2014-12-19
+------------------
+
+- Fixed resolving of !!null tag on an empty node.
+
+
+3.2.3 / 2014-11-08
+------------------
+
+- Implemented dumping of objects with circular and cross references.
+- Partially fixed aliasing of constructed objects. (see issue #141 for details)
+
+
+3.2.2 / 2014-09-07
+------------------
+
+- Fixed infinite loop on unindented block scalars.
+- Rewritten base64 encode/decode in binary type, to keep code licence clear.
+
+
+3.2.1 / 2014-08-24
+------------------
+
+- Nothig new. Just fix npm publish error.
+
+
+3.2.0 / 2014-08-24
+------------------
+
+- Added input piping support to CLI.
+- Fixed typo, that could cause hand on initial indent (#139).
+
+
+3.1.0 / 2014-07-07
+------------------
+
+- 1.5x-2x speed boost.
+- Removed deprecated `require('xxx.yml')` support.
+- Significant code cleanup and refactoring.
+- Internal API changed. If you used custom types - see updated examples.
+ Others are not affected.
+- Even if the input string has no trailing line break character,
+ it will be parsed as if it has one.
+- Added benchmark scripts.
+- Moved bower files to /dist folder
+- Bugfixes.
+
+
+3.0.2 / 2014-02-27
+------------------
+
+- Fixed bug: "constructor" string parsed as `null`.
+
+
+3.0.1 / 2013-12-22
+------------------
+
+- Fixed parsing of literal scalars. (issue #108)
+- Prevented adding unnecessary spaces in object dumps. (issue #68)
+- Fixed dumping of objects with very long (> 1024 in length) keys.
+
+
+3.0.0 / 2013-12-16
+------------------
+
+- Refactored code. Changed API for custom types.
+- Removed output colors in CLI, dump json by default.
+- Removed big dependencies from browser version (esprima, buffer)
+ - load `esprima` manually, if !!js/function needed
+ - !!bin now returns Array in browser
+- AMD support.
+- Don't quote dumped strings because of `-` & `?` (if not first char).
+- __Deprecated__ loading yaml files via `require()`, as not recommended
+ behaviour for node.
+
+
+2.1.3 / 2013-10-16
+------------------
+
+- Fix wrong loading of empty block scalars.
+
+
+2.1.2 / 2013-10-07
+------------------
+
+- Fix unwanted line breaks in folded scalars.
+
+
+2.1.1 / 2013-10-02
+------------------
+
+- Dumper now respects deprecated booleans syntax from YAML 1.0/1.1
+- Fixed reader bug in JSON-like sequences/mappings.
+
+
+2.1.0 / 2013-06-05
+------------------
+
+- Add standard YAML schemas: Failsafe (`FAILSAFE_SCHEMA`),
+ JSON (`JSON_SCHEMA`) and Core (`CORE_SCHEMA`).
+- Rename `DEFAULT_SCHEMA` to `DEFAULT_FULL_SCHEMA`
+ and `SAFE_SCHEMA` to `DEFAULT_SAFE_SCHEMA`.
+- Bug fix: export `NIL` constant from the public interface.
+- Add `skipInvalid` dumper option.
+- Use `safeLoad` for `require` extension.
+
+
+2.0.5 / 2013-04-26
+------------------
+
+- Close security issue in !!js/function constructor.
+ Big thanks to @nealpoole for security audit.
+
+
+2.0.4 / 2013-04-08
+------------------
+
+- Updated .npmignore to reduce package size
+
+
+2.0.3 / 2013-02-26
+------------------
+
+- Fixed dumping of empty arrays ans objects. ([] and {} instead of null)
+
+
+2.0.2 / 2013-02-15
+------------------
+
+- Fixed input validation: tabs are printable characters.
+
+
+2.0.1 / 2013-02-09
+------------------
+
+- Fixed error, when options not passed to function cass
+
+
+2.0.0 / 2013-02-09
+------------------
+
+- Full rewrite. New architecture. Fast one-stage parsing.
+- Changed custom types API.
+- Added YAML dumper.
+
+
+1.0.3 / 2012-11-05
+------------------
+
+- Fixed utf-8 files loading.
+
+
+1.0.2 / 2012-08-02
+------------------
+
+- Pull out hand-written shims. Use ES5-Shims for old browsers support. See #44.
+- Fix timstamps incorectly parsed in local time when no time part specified.
+
+
+1.0.1 / 2012-07-07
+------------------
+
+- Fixes `TypeError: 'undefined' is not an object` under Safari. Thanks Phuong.
+- Fix timestamps incorrectly parsed in local time. Thanks @caolan. Closes #46.
+
+
+1.0.0 / 2012-07-01
+------------------
+
+- `y`, `yes`, `n`, `no`, `on`, `off` are not converted to Booleans anymore.
+ Fixes #42.
+- `require(filename)` now returns a single document and throws an Error if
+ file contains more than one document.
+- CLI was merged back from js-yaml.bin
+
+
+0.3.7 / 2012-02-28
+------------------
+
+- Fix export of `addConstructor()`. Closes #39.
+
+
+0.3.6 / 2012-02-22
+------------------
+
+- Removed AMD parts - too buggy to use. Need help to rewrite from scratch
+- Removed YUI compressor warning (renamed `double` variable). Closes #40.
+
+
+0.3.5 / 2012-01-10
+------------------
+
+- Workagound for .npmignore fuckup under windows. Thanks to airportyh.
+
+
+0.3.4 / 2011-12-24
+------------------
+
+- Fixes str[] for oldIEs support.
+- Adds better has change support for browserified demo.
+- improves compact output of Error. Closes #33.
+
+
+0.3.3 / 2011-12-20
+------------------
+
+- jsyaml executable moved to separate module.
+- adds `compact` stringification of Errors.
+
+
+0.3.2 / 2011-12-16
+------------------
+
+- Fixes ug with block style scalars. Closes #26.
+- All sources are passing JSLint now.
+- Fixes bug in Safari. Closes #28.
+- Fixes bug in Opers. Closes #29.
+- Improves browser support. Closes #20.
+- Added jsyaml executable.
+- Added !!js/function support. Closes #12.
+
+
+0.3.1 / 2011-11-18
+------------------
+
+- Added AMD support for browserified version.
+- Wrapped browserified js-yaml into closure.
+- Fixed the resolvement of non-specific tags. Closes #17.
+- Added permalinks for online demo YAML snippets. Now we have YPaste service, lol.
+- Added !!js/regexp and !!js/undefined types. Partially solves #12.
+- Fixed !!set mapping.
+- Fixed month parse in dates. Closes #19.
+
+
+0.3.0 / 2011-11-09
+------------------
+
+- Removed JS.Class dependency. Closes #3.
+- Added browserified version. Closes #13.
+- Added live demo of browserified version.
+- Ported some of the PyYAML tests. See #14.
+- Fixed timestamp bug when fraction was given.
+
+
+0.2.2 / 2011-11-06
+------------------
+
+- Fixed crash on docs without ---. Closes #8.
+- Fixed miltiline string parse
+- Fixed tests/comments for using array as key
+
+
+0.2.1 / 2011-11-02
+------------------
+
+- Fixed short file read (<4k). Closes #9.
+
+
+0.2.0 / 2011-11-02
+------------------
+
+- First public release
diff --git a/node_modules/svgo/node_modules/js-yaml/LICENSE b/node_modules/svgo/node_modules/js-yaml/LICENSE
new file mode 100644
index 00000000..09d3a29e
--- /dev/null
+++ b/node_modules/svgo/node_modules/js-yaml/LICENSE
@@ -0,0 +1,21 @@
+(The MIT License)
+
+Copyright (C) 2011-2015 by Vitaly Puzrin
+
+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/svgo/node_modules/js-yaml/README.md b/node_modules/svgo/node_modules/js-yaml/README.md
new file mode 100644
index 00000000..45c35020
--- /dev/null
+++ b/node_modules/svgo/node_modules/js-yaml/README.md
@@ -0,0 +1,295 @@
+JS-YAML - YAML 1.2 parser / writer for JavaScript
+=================================================
+
+[![Build Status](https://travis-ci.org/nodeca/js-yaml.svg?branch=master)](https://travis-ci.org/nodeca/js-yaml)
+[![NPM version](https://img.shields.io/npm/v/js-yaml.svg)](https://www.npmjs.org/package/js-yaml)
+
+__[Online Demo](http://nodeca.github.com/js-yaml/)__
+
+
+This is an implementation of [YAML](http://yaml.org/), a human friendly data
+serialization language. Started as [PyYAML](http://pyyaml.org/) port, it was
+completely rewritten from scratch. Now it's very fast, and supports 1.2 spec.
+
+
+Installation
+------------
+
+### YAML module for node.js
+
+```
+npm install js-yaml
+```
+
+
+### CLI executable
+
+If you want to inspect your YAML files from CLI, install js-yaml globally:
+
+```
+npm install -g js-yaml
+```
+
+#### Usage
+
+```
+usage: js-yaml [-h] [-v] [-c] [-t] file
+
+Positional arguments:
+ file File with YAML document(s)
+
+Optional arguments:
+ -h, --help Show this help message and exit.
+ -v, --version Show program's version number and exit.
+ -c, --compact Display errors in compact mode
+ -t, --trace Show stack trace on error
+```
+
+
+### Bundled YAML library for browsers
+
+``` html
+<!-- esprima required only for !!js/function -->
+<script src="esprima.js"></script>
+<script src="js-yaml.min.js"></script>
+<script type="text/javascript">
+var doc = jsyaml.load('greeting: hello\nname: world');
+</script>
+```
+
+Browser support was done mostly for online demo. If you find any errors - feel
+free to send pull requests with fixes. Also note, that IE and other old browsers
+needs [es5-shims](https://github.com/kriskowal/es5-shim) to operate.
+
+Notes:
+
+1. We have no resources to support browserified version. Don't expect it to be
+ well tested. Don't expect fast fixes if something goes wrong there.
+2. `!!js/function` in browser bundle will not work by default. If you really need
+ it - load `esprima` parser first (via amd or directly).
+3. `!!bin` in browser will return `Array`, because browsers do not support
+ node.js `Buffer` and adding Buffer shims is completely useless on practice.
+
+
+API
+---
+
+Here we cover the most 'useful' methods. If you need advanced details (creating
+your own tags), see [wiki](https://github.com/nodeca/js-yaml/wiki) and
+[examples](https://github.com/nodeca/js-yaml/tree/master/examples) for more
+info.
+
+``` javascript
+yaml = require('js-yaml');
+fs = require('fs');
+
+// Get document, or throw exception on error
+try {
+ var doc = yaml.safeLoad(fs.readFileSync('/home/ixti/example.yml', 'utf8'));
+ console.log(doc);
+} catch (e) {
+ console.log(e);
+}
+```
+
+
+### safeLoad (string [ , options ])
+
+**Recommended loading way.** Parses `string` as single YAML document. Returns a JavaScript
+object or throws `YAMLException` on error. By default, does not support regexps,
+functions and undefined. This method is safe for untrusted data.
+
+options:
+
+- `filename` _(default: null)_ - string to be used as a file path in
+ error/warning messages.
+- `onWarning` _(default: null)_ - function to call on warning messages.
+ Loader will throw on warnings if this function is not provided.
+- `schema` _(default: `DEFAULT_SAFE_SCHEMA`)_ - specifies a schema to use.
+ - `FAILSAFE_SCHEMA` - only strings, arrays and plain objects:
+ http://www.yaml.org/spec/1.2/spec.html#id2802346
+ - `JSON_SCHEMA` - all JSON-supported types:
+ http://www.yaml.org/spec/1.2/spec.html#id2803231
+ - `CORE_SCHEMA` - same as `JSON_SCHEMA`:
+ http://www.yaml.org/spec/1.2/spec.html#id2804923
+ - `DEFAULT_SAFE_SCHEMA` - all supported YAML types, without unsafe ones
+ (`!!js/undefined`, `!!js/regexp` and `!!js/function`):
+ http://yaml.org/type/
+ - `DEFAULT_FULL_SCHEMA` - all supported YAML types.
+- `json` _(default: false)_ - compatibility with JSON.parse behaviour. If true, then duplicate keys in a mapping will override values rather than throwing an error.
+
+NOTE: This function **does not** understand multi-document sources, it throws
+exception on those.
+
+NOTE: JS-YAML **does not** support schema-specific tag resolution restrictions.
+So, JSON schema is not as strict as defined in the YAML specification.
+It allows numbers in any notation, use `Null` and `NULL` as `null`, etc.
+Core schema also has no such restrictions. It allows binary notation for integers.
+
+
+### load (string [ , options ])
+
+**Use with care with untrusted sources**. The same as `safeLoad()` but uses
+`DEFAULT_FULL_SCHEMA` by default - adds some JavaScript-specific types:
+`!!js/function`, `!!js/regexp` and `!!js/undefined`. For untrusted sources you
+must additionally validate object structure, to avoid injections:
+
+``` javascript
+var untrusted_code = '"toString": !<tag:yaml.org,2002:js/function> "function (){very_evil_thing();}"';
+
+// I'm just converting that string, what could possibly go wrong?
+require('js-yaml').load(untrusted_code) + ''
+```
+
+
+### safeLoadAll (string, iterator [ , options ])
+
+Same as `safeLoad()`, but understands multi-document sources and apply
+`iterator` to each document.
+
+``` javascript
+var yaml = require('js-yaml');
+
+yaml.safeLoadAll(data, function (doc) {
+ console.log(doc);
+});
+```
+
+
+### loadAll (string, iterator [ , options ])
+
+Same as `safeLoadAll()` but uses `DEFAULT_FULL_SCHEMA` by default.
+
+
+### safeDump (object [ , options ])
+
+Serializes `object` as YAML document. Uses `DEFAULT_SAFE_SCHEMA`, so it will
+throw exception if you try to dump regexps or functions. However, you can
+disable exceptions by `skipInvalid` option.
+
+options:
+
+- `indent` _(default: 2)_ - indentation width to use (in spaces).
+- `skipInvalid` _(default: false)_ - do not throw on invalid types (like function
+ in the safe schema) and skip pairs and single values with such types.
+- `flowLevel` (default: -1) - specifies level of nesting, when to switch from
+ block to flow style for collections. -1 means block style everwhere
+- `styles` - "tag" => "style" map. Each tag may have own set of styles.
+- `schema` _(default: `DEFAULT_SAFE_SCHEMA`)_ specifies a schema to use.
+- `sortKeys` _(default: `false`)_ - if `true`, sort keys when dumping YAML. If a
+ function, use the function to sort the keys.
+- `lineWidth` _(default: `80`)_ - set max line width.
+- `noRefs` _(default: `false`)_ - if `true`, don't convert duplicate objects into references
+- `noCompatMode` _(default: `false`)_ - if `true` don't try to be compatible with older
+ yaml versions. Currently: don't quote "yes", "no" and so on, as required for YAML 1.1
+
+styles:
+
+``` none
+!!null
+ "canonical" => "~"
+
+!!int
+ "binary" => "0b1", "0b101010", "0b1110001111010"
+ "octal" => "01", "052", "016172"
+ "decimal" => "1", "42", "7290"
+ "hexadecimal" => "0x1", "0x2A", "0x1C7A"
+
+!!null, !!bool, !!float
+ "lowercase" => "null", "true", "false", ".nan", '.inf'
+ "uppercase" => "NULL", "TRUE", "FALSE", ".NAN", '.INF'
+ "camelcase" => "Null", "True", "False", ".NaN", '.Inf'
+```
+
+By default, !!int uses `decimal`, and !!null, !!bool, !!float use `lowercase`.
+
+
+
+### dump (object [ , options ])
+
+Same as `safeDump()` but without limits (uses `DEFAULT_FULL_SCHEMA` by default).
+
+
+Supported YAML types
+--------------------
+
+The list of standard YAML tags and corresponding JavaScipt types. See also
+[YAML tag discussion](http://pyyaml.org/wiki/YAMLTagDiscussion) and
+[YAML types repository](http://yaml.org/type/).
+
+```
+!!null '' # null
+!!bool 'yes' # bool
+!!int '3...' # number
+!!float '3.14...' # number
+!!binary '...base64...' # buffer
+!!timestamp 'YYYY-...' # date
+!!omap [ ... ] # array of key-value pairs
+!!pairs [ ... ] # array or array pairs
+!!set { ... } # array of objects with given keys and null values
+!!str '...' # string
+!!seq [ ... ] # array
+!!map { ... } # object
+```
+
+**JavaScript-specific tags**
+
+```
+!!js/regexp /pattern/gim # RegExp
+!!js/undefined '' # Undefined
+!!js/function 'function () {...}' # Function
+```
+
+Caveats
+-------
+
+Note, that you use arrays or objects as key in JS-YAML. JS does not allow objects
+or array as keys, and stringifies (by calling .toString method) them at the
+moment of adding them.
+
+``` yaml
+---
+? [ foo, bar ]
+: - baz
+? { foo: bar }
+: - baz
+ - baz
+```
+
+``` javascript
+{ "foo,bar": ["baz"], "[object Object]": ["baz", "baz"] }
+```
+
+Also, reading of properties on implicit block mapping keys is not supported yet.
+So, the following YAML document cannot be loaded.
+
+``` yaml
+&anchor foo:
+ foo: bar
+ *anchor: duplicate key
+ baz: bat
+ *anchor: duplicate key
+```
+
+
+Breaking changes in 2.x.x -> 3.x.x
+----------------------------------
+
+If you have not used __custom__ tags or loader classes and not loaded yaml
+files via `require()` - no changes needed. Just upgrade library.
+
+Otherwise, you should:
+
+1. Replace all occurences of `require('xxxx.yml')` by `fs.readFileSync()` +
+ `yaml.safeLoad()`.
+2. rewrite your custom tags constructors and custom loader
+ classes, to conform new API. See
+ [examples](https://github.com/nodeca/js-yaml/tree/master/examples) and
+ [wiki](https://github.com/nodeca/js-yaml/wiki) for details.
+
+
+License
+-------
+
+View the [LICENSE](https://github.com/nodeca/js-yaml/blob/master/LICENSE) file
+(MIT).
diff --git a/node_modules/svgo/node_modules/js-yaml/bin/js-yaml.js b/node_modules/svgo/node_modules/js-yaml/bin/js-yaml.js
new file mode 100755
index 00000000..e79186be
--- /dev/null
+++ b/node_modules/svgo/node_modules/js-yaml/bin/js-yaml.js
@@ -0,0 +1,132 @@
+#!/usr/bin/env node
+
+
+'use strict';
+
+/*eslint-disable no-console*/
+
+
+// stdlib
+var fs = require('fs');
+
+
+// 3rd-party
+var argparse = require('argparse');
+
+
+// internal
+var yaml = require('..');
+
+
+////////////////////////////////////////////////////////////////////////////////
+
+
+var cli = new argparse.ArgumentParser({
+ prog: 'js-yaml',
+ version: require('../package.json').version,
+ addHelp: true
+});
+
+
+cli.addArgument([ '-c', '--compact' ], {
+ help: 'Display errors in compact mode',
+ action: 'storeTrue'
+});
+
+
+// deprecated (not needed after we removed output colors)
+// option suppressed, but not completely removed for compatibility
+cli.addArgument([ '-j', '--to-json' ], {
+ help: argparse.Const.SUPPRESS,
+ dest: 'json',
+ action: 'storeTrue'
+});
+
+
+cli.addArgument([ '-t', '--trace' ], {
+ help: 'Show stack trace on error',
+ action: 'storeTrue'
+});
+
+cli.addArgument([ 'file' ], {
+ help: 'File to read, utf-8 encoded without BOM',
+ nargs: '?',
+ defaultValue: '-'
+});
+
+
+////////////////////////////////////////////////////////////////////////////////
+
+
+var options = cli.parseArgs();
+
+
+////////////////////////////////////////////////////////////////////////////////
+
+function readFile(filename, encoding, callback) {
+ if (options.file === '-') {
+ // read from stdin
+
+ var chunks = [];
+
+ process.stdin.on('data', function (chunk) {
+ chunks.push(chunk);
+ });
+
+ process.stdin.on('end', function () {
+ return callback(null, Buffer.concat(chunks).toString(encoding));
+ });
+ } else {
+ fs.readFile(filename, encoding, callback);
+ }
+}
+
+readFile(options.file, 'utf8', function (error, input) {
+ var output, isYaml;
+
+ if (error) {
+ if (error.code === 'ENOENT') {
+ console.error('File not found: ' + options.file);
+ process.exit(2);
+ }
+
+ console.error(
+ options.trace && error.stack ||
+ error.message ||
+ String(error));
+
+ process.exit(1);
+ }
+
+ try {
+ output = JSON.parse(input);
+ isYaml = false;
+ } catch (err) {
+ if (err instanceof SyntaxError) {
+ try {
+ output = [];
+ yaml.loadAll(input, function (doc) { output.push(doc); }, {});
+ isYaml = true;
+
+ if (output.length === 0) output = null;
+ else if (output.length === 1) output = output[0];
+
+ } catch (e) {
+ if (options.trace && err.stack) console.error(e.stack);
+ else console.error(e.toString(options.compact));
+
+ process.exit(1);
+ }
+ } else {
+ console.error(
+ options.trace && err.stack ||
+ err.message ||
+ String(err));
+
+ process.exit(1);
+ }
+ }
+
+ if (isYaml) console.log(JSON.stringify(output, null, ' '));
+ else console.log(yaml.dump(output));
+});
diff --git a/node_modules/svgo/node_modules/js-yaml/dist/js-yaml.js b/node_modules/svgo/node_modules/js-yaml/dist/js-yaml.js
new file mode 100644
index 00000000..49cb23c9
--- /dev/null
+++ b/node_modules/svgo/node_modules/js-yaml/dist/js-yaml.js
@@ -0,0 +1,3855 @@
+/* js-yaml 3.7.0 https://github.com/nodeca/js-yaml */(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.jsyaml = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
+'use strict';
+
+
+var loader = require('./js-yaml/loader');
+var dumper = require('./js-yaml/dumper');
+
+
+function deprecated(name) {
+ return function () {
+ throw new Error('Function ' + name + ' is deprecated and cannot be used.');
+ };
+}
+
+
+module.exports.Type = require('./js-yaml/type');
+module.exports.Schema = require('./js-yaml/schema');
+module.exports.FAILSAFE_SCHEMA = require('./js-yaml/schema/failsafe');
+module.exports.JSON_SCHEMA = require('./js-yaml/schema/json');
+module.exports.CORE_SCHEMA = require('./js-yaml/schema/core');
+module.exports.DEFAULT_SAFE_SCHEMA = require('./js-yaml/schema/default_safe');
+module.exports.DEFAULT_FULL_SCHEMA = require('./js-yaml/schema/default_full');
+module.exports.load = loader.load;
+module.exports.loadAll = loader.loadAll;
+module.exports.safeLoad = loader.safeLoad;
+module.exports.safeLoadAll = loader.safeLoadAll;
+module.exports.dump = dumper.dump;
+module.exports.safeDump = dumper.safeDump;
+module.exports.YAMLException = require('./js-yaml/exception');
+
+// Deprecated schema names from JS-YAML 2.0.x
+module.exports.MINIMAL_SCHEMA = require('./js-yaml/schema/failsafe');
+module.exports.SAFE_SCHEMA = require('./js-yaml/schema/default_safe');
+module.exports.DEFAULT_SCHEMA = require('./js-yaml/schema/default_full');
+
+// Deprecated functions from JS-YAML 1.x.x
+module.exports.scan = deprecated('scan');
+module.exports.parse = deprecated('parse');
+module.exports.compose = deprecated('compose');
+module.exports.addConstructor = deprecated('addConstructor');
+
+},{"./js-yaml/dumper":3,"./js-yaml/exception":4,"./js-yaml/loader":5,"./js-yaml/schema":7,"./js-yaml/schema/core":8,"./js-yaml/schema/default_full":9,"./js-yaml/schema/default_safe":10,"./js-yaml/schema/failsafe":11,"./js-yaml/schema/json":12,"./js-yaml/type":13}],2:[function(require,module,exports){
+'use strict';
+
+
+function isNothing(subject) {
+ return (typeof subject === 'undefined') || (subject === null);
+}
+
+
+function isObject(subject) {
+ return (typeof subject === 'object') && (subject !== null);
+}
+
+
+function toArray(sequence) {
+ if (Array.isArray(sequence)) return sequence;
+ else if (isNothing(sequence)) return [];
+
+ return [ sequence ];
+}
+
+
+function extend(target, source) {
+ var index, length, key, sourceKeys;
+
+ if (source) {
+ sourceKeys = Object.keys(source);
+
+ for (index = 0, length = sourceKeys.length; index < length; index += 1) {
+ key = sourceKeys[index];
+ target[key] = source[key];
+ }
+ }
+
+ return target;
+}
+
+
+function repeat(string, count) {
+ var result = '', cycle;
+
+ for (cycle = 0; cycle < count; cycle += 1) {
+ result += string;
+ }
+
+ return result;
+}
+
+
+function isNegativeZero(number) {
+ return (number === 0) && (Number.NEGATIVE_INFINITY === 1 / number);
+}
+
+
+module.exports.isNothing = isNothing;
+module.exports.isObject = isObject;
+module.exports.toArray = toArray;
+module.exports.repeat = repeat;
+module.exports.isNegativeZero = isNegativeZero;
+module.exports.extend = extend;
+
+},{}],3:[function(require,module,exports){
+'use strict';
+
+/*eslint-disable no-use-before-define*/
+
+var common = require('./common');
+var YAMLException = require('./exception');
+var DEFAULT_FULL_SCHEMA = require('./schema/default_full');
+var DEFAULT_SAFE_SCHEMA = require('./schema/default_safe');
+
+var _toString = Object.prototype.toString;
+var _hasOwnProperty = Object.prototype.hasOwnProperty;
+
+var CHAR_TAB = 0x09; /* Tab */
+var CHAR_LINE_FEED = 0x0A; /* LF */
+var CHAR_SPACE = 0x20; /* Space */
+var CHAR_EXCLAMATION = 0x21; /* ! */
+var CHAR_DOUBLE_QUOTE = 0x22; /* " */
+var CHAR_SHARP = 0x23; /* # */
+var CHAR_PERCENT = 0x25; /* % */
+var CHAR_AMPERSAND = 0x26; /* & */
+var CHAR_SINGLE_QUOTE = 0x27; /* ' */
+var CHAR_ASTERISK = 0x2A; /* * */
+var CHAR_COMMA = 0x2C; /* , */
+var CHAR_MINUS = 0x2D; /* - */
+var CHAR_COLON = 0x3A; /* : */
+var CHAR_GREATER_THAN = 0x3E; /* > */
+var CHAR_QUESTION = 0x3F; /* ? */
+var CHAR_COMMERCIAL_AT = 0x40; /* @ */
+var CHAR_LEFT_SQUARE_BRACKET = 0x5B; /* [ */
+var CHAR_RIGHT_SQUARE_BRACKET = 0x5D; /* ] */
+var CHAR_GRAVE_ACCENT = 0x60; /* ` */
+var CHAR_LEFT_CURLY_BRACKET = 0x7B; /* { */
+var CHAR_VERTICAL_LINE = 0x7C; /* | */
+var CHAR_RIGHT_CURLY_BRACKET = 0x7D; /* } */
+
+var ESCAPE_SEQUENCES = {};
+
+ESCAPE_SEQUENCES[0x00] = '\\0';
+ESCAPE_SEQUENCES[0x07] = '\\a';
+ESCAPE_SEQUENCES[0x08] = '\\b';
+ESCAPE_SEQUENCES[0x09] = '\\t';
+ESCAPE_SEQUENCES[0x0A] = '\\n';
+ESCAPE_SEQUENCES[0x0B] = '\\v';
+ESCAPE_SEQUENCES[0x0C] = '\\f';
+ESCAPE_SEQUENCES[0x0D] = '\\r';
+ESCAPE_SEQUENCES[0x1B] = '\\e';
+ESCAPE_SEQUENCES[0x22] = '\\"';
+ESCAPE_SEQUENCES[0x5C] = '\\\\';
+ESCAPE_SEQUENCES[0x85] = '\\N';
+ESCAPE_SEQUENCES[0xA0] = '\\_';
+ESCAPE_SEQUENCES[0x2028] = '\\L';
+ESCAPE_SEQUENCES[0x2029] = '\\P';
+
+var DEPRECATED_BOOLEANS_SYNTAX = [
+ 'y', 'Y', 'yes', 'Yes', 'YES', 'on', 'On', 'ON',
+ 'n', 'N', 'no', 'No', 'NO', 'off', 'Off', 'OFF'
+];
+
+function compileStyleMap(schema, map) {
+ var result, keys, index, length, tag, style, type;
+
+ if (map === null) return {};
+
+ result = {};
+ keys = Object.keys(map);
+
+ for (index = 0, length = keys.length; index < length; index += 1) {
+ tag = keys[index];
+ style = String(map[tag]);
+
+ if (tag.slice(0, 2) === '!!') {
+ tag = 'tag:yaml.org,2002:' + tag.slice(2);
+ }
+ type = schema.compiledTypeMap['fallback'][tag];
+
+ if (type && _hasOwnProperty.call(type.styleAliases, style)) {
+ style = type.styleAliases[style];
+ }
+
+ result[tag] = style;
+ }
+
+ return result;
+}
+
+function encodeHex(character) {
+ var string, handle, length;
+
+ string = character.toString(16).toUpperCase();
+
+ if (character <= 0xFF) {
+ handle = 'x';
+ length = 2;
+ } else if (character <= 0xFFFF) {
+ handle = 'u';
+ length = 4;
+ } else if (character <= 0xFFFFFFFF) {
+ handle = 'U';
+ length = 8;
+ } else {
+ throw new YAMLException('code point within a string may not be greater than 0xFFFFFFFF');
+ }
+
+ return '\\' + handle + common.repeat('0', length - string.length) + string;
+}
+
+function State(options) {
+ this.schema = options['schema'] || DEFAULT_FULL_SCHEMA;
+ this.indent = Math.max(1, (options['indent'] || 2));
+ this.skipInvalid = options['skipInvalid'] || false;
+ this.flowLevel = (common.isNothing(options['flowLevel']) ? -1 : options['flowLevel']);
+ this.styleMap = compileStyleMap(this.schema, options['styles'] || null);
+ this.sortKeys = options['sortKeys'] || false;
+ this.lineWidth = options['lineWidth'] || 80;
+ this.noRefs = options['noRefs'] || false;
+ this.noCompatMode = options['noCompatMode'] || false;
+
+ this.implicitTypes = this.schema.compiledImplicit;
+ this.explicitTypes = this.schema.compiledExplicit;
+
+ this.tag = null;
+ this.result = '';
+
+ this.duplicates = [];
+ this.usedDuplicates = null;
+}
+
+// Indents every line in a string. Empty lines (\n only) are not indented.
+function indentString(string, spaces) {
+ var ind = common.repeat(' ', spaces),
+ position = 0,
+ next = -1,
+ result = '',
+ line,
+ length = string.length;
+
+ while (position < length) {
+ next = string.indexOf('\n', position);
+ if (next === -1) {
+ line = string.slice(position);
+ position = length;
+ } else {
+ line = string.slice(position, next + 1);
+ position = next + 1;
+ }
+
+ if (line.length && line !== '\n') result += ind;
+
+ result += line;
+ }
+
+ return result;
+}
+
+function generateNextLine(state, level) {
+ return '\n' + common.repeat(' ', state.indent * level);
+}
+
+function testImplicitResolving(state, str) {
+ var index, length, type;
+
+ for (index = 0, length = state.implicitTypes.length; index < length; index += 1) {
+ type = state.implicitTypes[index];
+
+ if (type.resolve(str)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// [33] s-white ::= s-space | s-tab
+function isWhitespace(c) {
+ return c === CHAR_SPACE || c === CHAR_TAB;
+}
+
+// Returns true if the character can be printed without escaping.
+// From YAML 1.2: "any allowed characters known to be non-printable
+// should also be escaped. [However,] This isn’t mandatory"
+// Derived from nb-char - \t - #x85 - #xA0 - #x2028 - #x2029.
+function isPrintable(c) {
+ return (0x00020 <= c && c <= 0x00007E)
+ || ((0x000A1 <= c && c <= 0x00D7FF) && c !== 0x2028 && c !== 0x2029)
+ || ((0x0E000 <= c && c <= 0x00FFFD) && c !== 0xFEFF /* BOM */)
+ || (0x10000 <= c && c <= 0x10FFFF);
+}
+
+// Simplified test for values allowed after the first character in plain style.
+function isPlainSafe(c) {
+ // Uses a subset of nb-char - c-flow-indicator - ":" - "#"
+ // where nb-char ::= c-printable - b-char - c-byte-order-mark.
+ return isPrintable(c) && c !== 0xFEFF
+ // - c-flow-indicator
+ && c !== CHAR_COMMA
+ && c !== CHAR_LEFT_SQUARE_BRACKET
+ && c !== CHAR_RIGHT_SQUARE_BRACKET
+ && c !== CHAR_LEFT_CURLY_BRACKET
+ && c !== CHAR_RIGHT_CURLY_BRACKET
+ // - ":" - "#"
+ && c !== CHAR_COLON
+ && c !== CHAR_SHARP;
+}
+
+// Simplified test for values allowed as the first character in plain style.
+function isPlainSafeFirst(c) {
+ // Uses a subset of ns-char - c-indicator
+ // where ns-char = nb-char - s-white.
+ return isPrintable(c) && c !== 0xFEFF
+ && !isWhitespace(c) // - s-white
+ // - (c-indicator ::=
+ // “-” | “?” | “:” | “,” | “[” | “]” | “{” | “}”
+ && c !== CHAR_MINUS
+ && c !== CHAR_QUESTION
+ && c !== CHAR_COLON
+ && c !== CHAR_COMMA
+ && c !== CHAR_LEFT_SQUARE_BRACKET
+ && c !== CHAR_RIGHT_SQUARE_BRACKET
+ && c !== CHAR_LEFT_CURLY_BRACKET
+ && c !== CHAR_RIGHT_CURLY_BRACKET
+ // | “#” | “&” | “*” | “!” | “|” | “>” | “'” | “"”
+ && c !== CHAR_SHARP
+ && c !== CHAR_AMPERSAND
+ && c !== CHAR_ASTERISK
+ && c !== CHAR_EXCLAMATION
+ && c !== CHAR_VERTICAL_LINE
+ && c !== CHAR_GREATER_THAN
+ && c !== CHAR_SINGLE_QUOTE
+ && c !== CHAR_DOUBLE_QUOTE
+ // | “%” | “@” | “`”)
+ && c !== CHAR_PERCENT
+ && c !== CHAR_COMMERCIAL_AT
+ && c !== CHAR_GRAVE_ACCENT;
+}
+
+var STYLE_PLAIN = 1,
+ STYLE_SINGLE = 2,
+ STYLE_LITERAL = 3,
+ STYLE_FOLDED = 4,
+ STYLE_DOUBLE = 5;
+
+// Determines which scalar styles are possible and returns the preferred style.
+// lineWidth = -1 => no limit.
+// Pre-conditions: str.length > 0.
+// Post-conditions:
+// STYLE_PLAIN or STYLE_SINGLE => no \n are in the string.
+// STYLE_LITERAL => no lines are suitable for folding (or lineWidth is -1).
+// STYLE_FOLDED => a line > lineWidth and can be folded (and lineWidth != -1).
+function chooseScalarStyle(string, singleLineOnly, indentPerLevel, lineWidth, testAmbiguousType) {
+ var i;
+ var char;
+ var hasLineBreak = false;
+ var hasFoldableLine = false; // only checked if shouldTrackWidth
+ var shouldTrackWidth = lineWidth !== -1;
+ var previousLineBreak = -1; // count the first line correctly
+ var plain = isPlainSafeFirst(string.charCodeAt(0))
+ && !isWhitespace(string.charCodeAt(string.length - 1));
+
+ if (singleLineOnly) {
+ // Case: no block styles.
+ // Check for disallowed characters to rule out plain and single.
+ for (i = 0; i < string.length; i++) {
+ char = string.charCodeAt(i);
+ if (!isPrintable(char)) {
+ return STYLE_DOUBLE;
+ }
+ plain = plain && isPlainSafe(char);
+ }
+ } else {
+ // Case: block styles permitted.
+ for (i = 0; i < string.length; i++) {
+ char = string.charCodeAt(i);
+ if (char === CHAR_LINE_FEED) {
+ hasLineBreak = true;
+ // Check if any line can be folded.
+ if (shouldTrackWidth) {
+ hasFoldableLine = hasFoldableLine ||
+ // Foldable line = too long, and not more-indented.
+ (i - previousLineBreak - 1 > lineWidth &&
+ string[previousLineBreak + 1] !== ' ');
+ previousLineBreak = i;
+ }
+ } else if (!isPrintable(char)) {
+ return STYLE_DOUBLE;
+ }
+ plain = plain && isPlainSafe(char);
+ }
+ // in case the end is missing a \n
+ hasFoldableLine = hasFoldableLine || (shouldTrackWidth &&
+ (i - previousLineBreak - 1 > lineWidth &&
+ string[previousLineBreak + 1] !== ' '));
+ }
+ // Although every style can represent \n without escaping, prefer block styles
+ // for multiline, since they're more readable and they don't add empty lines.
+ // Also prefer folding a super-long line.
+ if (!hasLineBreak && !hasFoldableLine) {
+ // Strings interpretable as another type have to be quoted;
+ // e.g. the string 'true' vs. the boolean true.
+ return plain && !testAmbiguousType(string)
+ ? STYLE_PLAIN : STYLE_SINGLE;
+ }
+ // Edge case: block indentation indicator can only have one digit.
+ if (string[0] === ' ' && indentPerLevel > 9) {
+ return STYLE_DOUBLE;
+ }
+ // At this point we know block styles are valid.
+ // Prefer literal style unless we want to fold.
+ return hasFoldableLine ? STYLE_FOLDED : STYLE_LITERAL;
+}
+
+// Note: line breaking/folding is implemented for only the folded style.
+// NB. We drop the last trailing newline (if any) of a returned block scalar
+// since the dumper adds its own newline. This always works:
+// • No ending newline => unaffected; already using strip "-" chomping.
+// • Ending newline => removed then restored.
+// Importantly, this keeps the "+" chomp indicator from gaining an extra line.
+function writeScalar(state, string, level, iskey) {
+ state.dump = (function () {
+ if (string.length === 0) {
+ return "''";
+ }
+ if (!state.noCompatMode &&
+ DEPRECATED_BOOLEANS_SYNTAX.indexOf(string) !== -1) {
+ return "'" + string + "'";
+ }
+
+ var indent = state.indent * Math.max(1, level); // no 0-indent scalars
+ // As indentation gets deeper, let the width decrease monotonically
+ // to the lower bound min(state.lineWidth, 40).
+ // Note that this implies
+ // state.lineWidth ≤ 40 + state.indent: width is fixed at the lower bound.
+ // state.lineWidth > 40 + state.indent: width decreases until the lower bound.
+ // This behaves better than a constant minimum width which disallows narrower options,
+ // or an indent threshold which causes the width to suddenly increase.
+ var lineWidth = state.lineWidth === -1
+ ? -1 : Math.max(Math.min(state.lineWidth, 40), state.lineWidth - indent);
+
+ // Without knowing if keys are implicit/explicit, assume implicit for safety.
+ var singleLineOnly = iskey
+ // No block styles in flow mode.
+ || (state.flowLevel > -1 && level >= state.flowLevel);
+ function testAmbiguity(string) {
+ return testImplicitResolving(state, string);
+ }
+
+ switch (chooseScalarStyle(string, singleLineOnly, state.indent, lineWidth, testAmbiguity)) {
+ case STYLE_PLAIN:
+ return string;
+ case STYLE_SINGLE:
+ return "'" + string.replace(/'/g, "''") + "'";
+ case STYLE_LITERAL:
+ return '|' + blockHeader(string, state.indent)
+ + dropEndingNewline(indentString(string, indent));
+ case STYLE_FOLDED:
+ return '>' + blockHeader(string, state.indent)
+ + dropEndingNewline(indentString(foldString(string, lineWidth), indent));
+ case STYLE_DOUBLE:
+ return '"' + escapeString(string, lineWidth) + '"';
+ default:
+ throw new YAMLException('impossible error: invalid scalar style');
+ }
+ }());
+}
+
+// Pre-conditions: string is valid for a block scalar, 1 <= indentPerLevel <= 9.
+function blockHeader(string, indentPerLevel) {
+ var indentIndicator = (string[0] === ' ') ? String(indentPerLevel) : '';
+
+ // note the special case: the string '\n' counts as a "trailing" empty line.
+ var clip = string[string.length - 1] === '\n';
+ var keep = clip && (string[string.length - 2] === '\n' || string === '\n');
+ var chomp = keep ? '+' : (clip ? '' : '-');
+
+ return indentIndicator + chomp + '\n';
+}
+
+// (See the note for writeScalar.)
+function dropEndingNewline(string) {
+ return string[string.length - 1] === '\n' ? string.slice(0, -1) : string;
+}
+
+// Note: a long line without a suitable break point will exceed the width limit.
+// Pre-conditions: every char in str isPrintable, str.length > 0, width > 0.
+function foldString(string, width) {
+ // In folded style, $k$ consecutive newlines output as $k+1$ newlines—
+ // unless they're before or after a more-indented line, or at the very
+ // beginning or end, in which case $k$ maps to $k$.
+ // Therefore, parse each chunk as newline(s) followed by a content line.
+ var lineRe = /(\n+)([^\n]*)/g;
+
+ // first line (possibly an empty line)
+ var result = (function () {
+ var nextLF = string.indexOf('\n');
+ nextLF = nextLF !== -1 ? nextLF : string.length;
+ lineRe.lastIndex = nextLF;
+ return foldLine(string.slice(0, nextLF), width);
+ }());
+ // If we haven't reached the first content line yet, don't add an extra \n.
+ var prevMoreIndented = string[0] === '\n' || string[0] === ' ';
+ var moreIndented;
+
+ // rest of the lines
+ var match;
+ while ((match = lineRe.exec(string))) {
+ var prefix = match[1], line = match[2];
+ moreIndented = (line[0] === ' ');
+ result += prefix
+ + (!prevMoreIndented && !moreIndented && line !== ''
+ ? '\n' : '')
+ + foldLine(line, width);
+ prevMoreIndented = moreIndented;
+ }
+
+ return result;
+}
+
+// Greedy line breaking.
+// Picks the longest line under the limit each time,
+// otherwise settles for the shortest line over the limit.
+// NB. More-indented lines *cannot* be folded, as that would add an extra \n.
+function foldLine(line, width) {
+ if (line === '' || line[0] === ' ') return line;
+
+ // Since a more-indented line adds a \n, breaks can't be followed by a space.
+ var breakRe = / [^ ]/g; // note: the match index will always be <= length-2.
+ var match;
+ // start is an inclusive index. end, curr, and next are exclusive.
+ var start = 0, end, curr = 0, next = 0;
+ var result = '';
+
+ // Invariants: 0 <= start <= length-1.
+ // 0 <= curr <= next <= max(0, length-2). curr - start <= width.
+ // Inside the loop:
+ // A match implies length >= 2, so curr and next are <= length-2.
+ while ((match = breakRe.exec(line))) {
+ next = match.index;
+ // maintain invariant: curr - start <= width
+ if (next - start > width) {
+ end = (curr > start) ? curr : next; // derive end <= length-2
+ result += '\n' + line.slice(start, end);
+ // skip the space that was output as \n
+ start = end + 1; // derive start <= length-1
+ }
+ curr = next;
+ }
+
+ // By the invariants, start <= length-1, so there is something left over.
+ // It is either the whole string or a part starting from non-whitespace.
+ result += '\n';
+ // Insert a break if the remainder is too long and there is a break available.
+ if (line.length - start > width && curr > start) {
+ result += line.slice(start, curr) + '\n' + line.slice(curr + 1);
+ } else {
+ result += line.slice(start);
+ }
+
+ return result.slice(1); // drop extra \n joiner
+}
+
+// Escapes a double-quoted string.
+function escapeString(string) {
+ var result = '';
+ var char;
+ var escapeSeq;
+
+ for (var i = 0; i < string.length; i++) {
+ char = string.charCodeAt(i);
+ escapeSeq = ESCAPE_SEQUENCES[char];
+ result += !escapeSeq && isPrintable(char)
+ ? string[i]
+ : escapeSeq || encodeHex(char);
+ }
+
+ return result;
+}
+
+function writeFlowSequence(state, level, object) {
+ var _result = '',
+ _tag = state.tag,
+ index,
+ length;
+
+ for (index = 0, length = object.length; index < length; index += 1) {
+ // Write only valid elements.
+ if (writeNode(state, level, object[index], false, false)) {
+ if (index !== 0) _result += ', ';
+ _result += state.dump;
+ }
+ }
+
+ state.tag = _tag;
+ state.dump = '[' + _result + ']';
+}
+
+function writeBlockSequence(state, level, object, compact) {
+ var _result = '',
+ _tag = state.tag,
+ index,
+ length;
+
+ for (index = 0, length = object.length; index < length; index += 1) {
+ // Write only valid elements.
+ if (writeNode(state, level + 1, object[index], true, true)) {
+ if (!compact || index !== 0) {
+ _result += generateNextLine(state, level);
+ }
+ _result += '- ' + state.dump;
+ }
+ }
+
+ state.tag = _tag;
+ state.dump = _result || '[]'; // Empty sequence if no valid values.
+}
+
+function writeFlowMapping(state, level, object) {
+ var _result = '',
+ _tag = state.tag,
+ objectKeyList = Object.keys(object),
+ index,
+ length,
+ objectKey,
+ objectValue,
+ pairBuffer;
+
+ for (index = 0, length = objectKeyList.length; index < length; index += 1) {
+ pairBuffer = '';
+
+ if (index !== 0) pairBuffer += ', ';
+
+ objectKey = objectKeyList[index];
+ objectValue = object[objectKey];
+
+ if (!writeNode(state, level, objectKey, false, false)) {
+ continue; // Skip this pair because of invalid key;
+ }
+
+ if (state.dump.length > 1024) pairBuffer += '? ';
+
+ pairBuffer += state.dump + ': ';
+
+ if (!writeNode(state, level, objectValue, false, false)) {
+ continue; // Skip this pair because of invalid value.
+ }
+
+ pairBuffer += state.dump;
+
+ // Both key and value are valid.
+ _result += pairBuffer;
+ }
+
+ state.tag = _tag;
+ state.dump = '{' + _result + '}';
+}
+
+function writeBlockMapping(state, level, object, compact) {
+ var _result = '',
+ _tag = state.tag,
+ objectKeyList = Object.keys(object),
+ index,
+ length,
+ objectKey,
+ objectValue,
+ explicitPair,
+ pairBuffer;
+
+ // Allow sorting keys so that the output file is deterministic
+ if (state.sortKeys === true) {
+ // Default sorting
+ objectKeyList.sort();
+ } else if (typeof state.sortKeys === 'function') {
+ // Custom sort function
+ objectKeyList.sort(state.sortKeys);
+ } else if (state.sortKeys) {
+ // Something is wrong
+ throw new YAMLException('sortKeys must be a boolean or a function');
+ }
+
+ for (index = 0, length = objectKeyList.length; index < length; index += 1) {
+ pairBuffer = '';
+
+ if (!compact || index !== 0) {
+ pairBuffer += generateNextLine(state, level);
+ }
+
+ objectKey = objectKeyList[index];
+ objectValue = object[objectKey];
+
+ if (!writeNode(state, level + 1, objectKey, true, true, true)) {
+ continue; // Skip this pair because of invalid key.
+ }
+
+ explicitPair = (state.tag !== null && state.tag !== '?') ||
+ (state.dump && state.dump.length > 1024);
+
+ if (explicitPair) {
+ if (state.dump && CHAR_LINE_FEED === state.dump.charCodeAt(0)) {
+ pairBuffer += '?';
+ } else {
+ pairBuffer += '? ';
+ }
+ }
+
+ pairBuffer += state.dump;
+
+ if (explicitPair) {
+ pairBuffer += generateNextLine(state, level);
+ }
+
+ if (!writeNode(state, level + 1, objectValue, true, explicitPair)) {
+ continue; // Skip this pair because of invalid value.
+ }
+
+ if (state.dump && CHAR_LINE_FEED === state.dump.charCodeAt(0)) {
+ pairBuffer += ':';
+ } else {
+ pairBuffer += ': ';
+ }
+
+ pairBuffer += state.dump;
+
+ // Both key and value are valid.
+ _result += pairBuffer;
+ }
+
+ state.tag = _tag;
+ state.dump = _result || '{}'; // Empty mapping if no valid pairs.
+}
+
+function detectType(state, object, explicit) {
+ var _result, typeList, index, length, type, style;
+
+ typeList = explicit ? state.explicitTypes : state.implicitTypes;
+
+ for (index = 0, length = typeList.length; index < length; index += 1) {
+ type = typeList[index];
+
+ if ((type.instanceOf || type.predicate) &&
+ (!type.instanceOf || ((typeof object === 'object') && (object instanceof type.instanceOf))) &&
+ (!type.predicate || type.predicate(object))) {
+
+ state.tag = explicit ? type.tag : '?';
+
+ if (type.represent) {
+ style = state.styleMap[type.tag] || type.defaultStyle;
+
+ if (_toString.call(type.represent) === '[object Function]') {
+ _result = type.represent(object, style);
+ } else if (_hasOwnProperty.call(type.represent, style)) {
+ _result = type.represent[style](object, style);
+ } else {
+ throw new YAMLException('!<' + type.tag + '> tag resolver accepts not "' + style + '" style');
+ }
+
+ state.dump = _result;
+ }
+
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// Serializes `object` and writes it to global `result`.
+// Returns true on success, or false on invalid object.
+//
+function writeNode(state, level, object, block, compact, iskey) {
+ state.tag = null;
+ state.dump = object;
+
+ if (!detectType(state, object, false)) {
+ detectType(state, object, true);
+ }
+
+ var type = _toString.call(state.dump);
+
+ if (block) {
+ block = (state.flowLevel < 0 || state.flowLevel > level);
+ }
+
+ var objectOrArray = type === '[object Object]' || type === '[object Array]',
+ duplicateIndex,
+ duplicate;
+
+ if (objectOrArray) {
+ duplicateIndex = state.duplicates.indexOf(object);
+ duplicate = duplicateIndex !== -1;
+ }
+
+ if ((state.tag !== null && state.tag !== '?') || duplicate || (state.indent !== 2 && level > 0)) {
+ compact = false;
+ }
+
+ if (duplicate && state.usedDuplicates[duplicateIndex]) {
+ state.dump = '*ref_' + duplicateIndex;
+ } else {
+ if (objectOrArray && duplicate && !state.usedDuplicates[duplicateIndex]) {
+ state.usedDuplicates[duplicateIndex] = true;
+ }
+ if (type === '[object Object]') {
+ if (block && (Object.keys(state.dump).length !== 0)) {
+ writeBlockMapping(state, level, state.dump, compact);
+ if (duplicate) {
+ state.dump = '&ref_' + duplicateIndex + state.dump;
+ }
+ } else {
+ writeFlowMapping(state, level, state.dump);
+ if (duplicate) {
+ state.dump = '&ref_' + duplicateIndex + ' ' + state.dump;
+ }
+ }
+ } else if (type === '[object Array]') {
+ if (block && (state.dump.length !== 0)) {
+ writeBlockSequence(state, level, state.dump, compact);
+ if (duplicate) {
+ state.dump = '&ref_' + duplicateIndex + state.dump;
+ }
+ } else {
+ writeFlowSequence(state, level, state.dump);
+ if (duplicate) {
+ state.dump = '&ref_' + duplicateIndex + ' ' + state.dump;
+ }
+ }
+ } else if (type === '[object String]') {
+ if (state.tag !== '?') {
+ writeScalar(state, state.dump, level, iskey);
+ }
+ } else {
+ if (state.skipInvalid) return false;
+ throw new YAMLException('unacceptable kind of an object to dump ' + type);
+ }
+
+ if (state.tag !== null && state.tag !== '?') {
+ state.dump = '!<' + state.tag + '> ' + state.dump;
+ }
+ }
+
+ return true;
+}
+
+function getDuplicateReferences(object, state) {
+ var objects = [],
+ duplicatesIndexes = [],
+ index,
+ length;
+
+ inspectNode(object, objects, duplicatesIndexes);
+
+ for (index = 0, length = duplicatesIndexes.length; index < length; index += 1) {
+ state.duplicates.push(objects[duplicatesIndexes[index]]);
+ }
+ state.usedDuplicates = new Array(length);
+}
+
+function inspectNode(object, objects, duplicatesIndexes) {
+ var objectKeyList,
+ index,
+ length;
+
+ if (object !== null && typeof object === 'object') {
+ index = objects.indexOf(object);
+ if (index !== -1) {
+ if (duplicatesIndexes.indexOf(index) === -1) {
+ duplicatesIndexes.push(index);
+ }
+ } else {
+ objects.push(object);
+
+ if (Array.isArray(object)) {
+ for (index = 0, length = object.length; index < length; index += 1) {
+ inspectNode(object[index], objects, duplicatesIndexes);
+ }
+ } else {
+ objectKeyList = Object.keys(object);
+
+ for (index = 0, length = objectKeyList.length; index < length; index += 1) {
+ inspectNode(object[objectKeyList[index]], objects, duplicatesIndexes);
+ }
+ }
+ }
+ }
+}
+
+function dump(input, options) {
+ options = options || {};
+
+ var state = new State(options);
+
+ if (!state.noRefs) getDuplicateReferences(input, state);
+
+ if (writeNode(state, 0, input, true, true)) return state.dump + '\n';
+
+ return '';
+}
+
+function safeDump(input, options) {
+ return dump(input, common.extend({ schema: DEFAULT_SAFE_SCHEMA }, options));
+}
+
+module.exports.dump = dump;
+module.exports.safeDump = safeDump;
+
+},{"./common":2,"./exception":4,"./schema/default_full":9,"./schema/default_safe":10}],4:[function(require,module,exports){
+// YAML error class. http://stackoverflow.com/questions/8458984
+//
+'use strict';
+
+function YAMLException(reason, mark) {
+ // Super constructor
+ Error.call(this);
+
+ // Include stack trace in error object
+ if (Error.captureStackTrace) {
+ // Chrome and NodeJS
+ Error.captureStackTrace(this, this.constructor);
+ } else {
+ // FF, IE 10+ and Safari 6+. Fallback for others
+ this.stack = (new Error()).stack || '';
+ }
+
+ this.name = 'YAMLException';
+ this.reason = reason;
+ this.mark = mark;
+ this.message = (this.reason || '(unknown reason)') + (this.mark ? ' ' + this.mark.toString() : '');
+}
+
+
+// Inherit from Error
+YAMLException.prototype = Object.create(Error.prototype);
+YAMLException.prototype.constructor = YAMLException;
+
+
+YAMLException.prototype.toString = function toString(compact) {
+ var result = this.name + ': ';
+
+ result += this.reason || '(unknown reason)';
+
+ if (!compact && this.mark) {
+ result += ' ' + this.mark.toString();
+ }
+
+ return result;
+};
+
+
+module.exports = YAMLException;
+
+},{}],5:[function(require,module,exports){
+'use strict';
+
+/*eslint-disable max-len,no-use-before-define*/
+
+var common = require('./common');
+var YAMLException = require('./exception');
+var Mark = require('./mark');
+var DEFAULT_SAFE_SCHEMA = require('./schema/default_safe');
+var DEFAULT_FULL_SCHEMA = require('./schema/default_full');
+
+
+var _hasOwnProperty = Object.prototype.hasOwnProperty;
+
+
+var CONTEXT_FLOW_IN = 1;
+var CONTEXT_FLOW_OUT = 2;
+var CONTEXT_BLOCK_IN = 3;
+var CONTEXT_BLOCK_OUT = 4;
+
+
+var CHOMPING_CLIP = 1;
+var CHOMPING_STRIP = 2;
+var CHOMPING_KEEP = 3;
+
+
+var PATTERN_NON_PRINTABLE = /[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x84\x86-\x9F\uFFFE\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]/;
+var PATTERN_NON_ASCII_LINE_BREAKS = /[\x85\u2028\u2029]/;
+var PATTERN_FLOW_INDICATORS = /[,\[\]\{\}]/;
+var PATTERN_TAG_HANDLE = /^(?:!|!!|![a-z\-]+!)$/i;
+var PATTERN_TAG_URI = /^(?:!|[^,\[\]\{\}])(?:%[0-9a-f]{2}|[0-9a-z\-#;\/\?:@&=\+\$,_\.!~\*'\(\)\[\]])*$/i;
+
+
+function is_EOL(c) {
+ return (c === 0x0A/* LF */) || (c === 0x0D/* CR */);
+}
+
+function is_WHITE_SPACE(c) {
+ return (c === 0x09/* Tab */) || (c === 0x20/* Space */);
+}
+
+function is_WS_OR_EOL(c) {
+ return (c === 0x09/* Tab */) ||
+ (c === 0x20/* Space */) ||
+ (c === 0x0A/* LF */) ||
+ (c === 0x0D/* CR */);
+}
+
+function is_FLOW_INDICATOR(c) {
+ return c === 0x2C/* , */ ||
+ c === 0x5B/* [ */ ||
+ c === 0x5D/* ] */ ||
+ c === 0x7B/* { */ ||
+ c === 0x7D/* } */;
+}
+
+function fromHexCode(c) {
+ var lc;
+
+ if ((0x30/* 0 */ <= c) && (c <= 0x39/* 9 */)) {
+ return c - 0x30;
+ }
+
+ /*eslint-disable no-bitwise*/
+ lc = c | 0x20;
+
+ if ((0x61/* a */ <= lc) && (lc <= 0x66/* f */)) {
+ return lc - 0x61 + 10;
+ }
+
+ return -1;
+}
+
+function escapedHexLen(c) {
+ if (c === 0x78/* x */) { return 2; }
+ if (c === 0x75/* u */) { return 4; }
+ if (c === 0x55/* U */) { return 8; }
+ return 0;
+}
+
+function fromDecimalCode(c) {
+ if ((0x30/* 0 */ <= c) && (c <= 0x39/* 9 */)) {
+ return c - 0x30;
+ }
+
+ return -1;
+}
+
+function simpleEscapeSequence(c) {
+ return (c === 0x30/* 0 */) ? '\x00' :
+ (c === 0x61/* a */) ? '\x07' :
+ (c === 0x62/* b */) ? '\x08' :
+ (c === 0x74/* t */) ? '\x09' :
+ (c === 0x09/* Tab */) ? '\x09' :
+ (c === 0x6E/* n */) ? '\x0A' :
+ (c === 0x76/* v */) ? '\x0B' :
+ (c === 0x66/* f */) ? '\x0C' :
+ (c === 0x72/* r */) ? '\x0D' :
+ (c === 0x65/* e */) ? '\x1B' :
+ (c === 0x20/* Space */) ? ' ' :
+ (c === 0x22/* " */) ? '\x22' :
+ (c === 0x2F/* / */) ? '/' :
+ (c === 0x5C/* \ */) ? '\x5C' :
+ (c === 0x4E/* N */) ? '\x85' :
+ (c === 0x5F/* _ */) ? '\xA0' :
+ (c === 0x4C/* L */) ? '\u2028' :
+ (c === 0x50/* P */) ? '\u2029' : '';
+}
+
+function charFromCodepoint(c) {
+ if (c <= 0xFFFF) {
+ return String.fromCharCode(c);
+ }
+ // Encode UTF-16 surrogate pair
+ // https://en.wikipedia.org/wiki/UTF-16#Code_points_U.2B010000_to_U.2B10FFFF
+ return String.fromCharCode(((c - 0x010000) >> 10) + 0xD800,
+ ((c - 0x010000) & 0x03FF) + 0xDC00);
+}
+
+var simpleEscapeCheck = new Array(256); // integer, for fast access
+var simpleEscapeMap = new Array(256);
+for (var i = 0; i < 256; i++) {
+ simpleEscapeCheck[i] = simpleEscapeSequence(i) ? 1 : 0;
+ simpleEscapeMap[i] = simpleEscapeSequence(i);
+}
+
+
+function State(input, options) {
+ this.input = input;
+
+ this.filename = options['filename'] || null;
+ this.schema = options['schema'] || DEFAULT_FULL_SCHEMA;
+ this.onWarning = options['onWarning'] || null;
+ this.legacy = options['legacy'] || false;
+ this.json = options['json'] || false;
+ this.listener = options['listener'] || null;
+
+ this.implicitTypes = this.schema.compiledImplicit;
+ this.typeMap = this.schema.compiledTypeMap;
+
+ this.length = input.length;
+ this.position = 0;
+ this.line = 0;
+ this.lineStart = 0;
+ this.lineIndent = 0;
+
+ this.documents = [];
+
+ /*
+ this.version;
+ this.checkLineBreaks;
+ this.tagMap;
+ this.anchorMap;
+ this.tag;
+ this.anchor;
+ this.kind;
+ this.result;*/
+
+}
+
+
+function generateError(state, message) {
+ return new YAMLException(
+ message,
+ new Mark(state.filename, state.input, state.position, state.line, (state.position - state.lineStart)));
+}
+
+function throwError(state, message) {
+ throw generateError(state, message);
+}
+
+function throwWarning(state, message) {
+ if (state.onWarning) {
+ state.onWarning.call(null, generateError(state, message));
+ }
+}
+
+
+var directiveHandlers = {
+
+ YAML: function handleYamlDirective(state, name, args) {
+
+ var match, major, minor;
+
+ if (state.version !== null) {
+ throwError(state, 'duplication of %YAML directive');
+ }
+
+ if (args.length !== 1) {
+ throwError(state, 'YAML directive accepts exactly one argument');
+ }
+
+ match = /^([0-9]+)\.([0-9]+)$/.exec(args[0]);
+
+ if (match === null) {
+ throwError(state, 'ill-formed argument of the YAML directive');
+ }
+
+ major = parseInt(match[1], 10);
+ minor = parseInt(match[2], 10);
+
+ if (major !== 1) {
+ throwError(state, 'unacceptable YAML version of the document');
+ }
+
+ state.version = args[0];
+ state.checkLineBreaks = (minor < 2);
+
+ if (minor !== 1 && minor !== 2) {
+ throwWarning(state, 'unsupported YAML version of the document');
+ }
+ },
+
+ TAG: function handleTagDirective(state, name, args) {
+
+ var handle, prefix;
+
+ if (args.length !== 2) {
+ throwError(state, 'TAG directive accepts exactly two arguments');
+ }
+
+ handle = args[0];
+ prefix = args[1];
+
+ if (!PATTERN_TAG_HANDLE.test(handle)) {
+ throwError(state, 'ill-formed tag handle (first argument) of the TAG directive');
+ }
+
+ if (_hasOwnProperty.call(state.tagMap, handle)) {
+ throwError(state, 'there is a previously declared suffix for "' + handle + '" tag handle');
+ }
+
+ if (!PATTERN_TAG_URI.test(prefix)) {
+ throwError(state, 'ill-formed tag prefix (second argument) of the TAG directive');
+ }
+
+ state.tagMap[handle] = prefix;
+ }
+};
+
+
+function captureSegment(state, start, end, checkJson) {
+ var _position, _length, _character, _result;
+
+ if (start < end) {
+ _result = state.input.slice(start, end);
+
+ if (checkJson) {
+ for (_position = 0, _length = _result.length;
+ _position < _length;
+ _position += 1) {
+ _character = _result.charCodeAt(_position);
+ if (!(_character === 0x09 ||
+ (0x20 <= _character && _character <= 0x10FFFF))) {
+ throwError(state, 'expected valid JSON character');
+ }
+ }
+ } else if (PATTERN_NON_PRINTABLE.test(_result)) {
+ throwError(state, 'the stream contains non-printable characters');
+ }
+
+ state.result += _result;
+ }
+}
+
+function mergeMappings(state, destination, source, overridableKeys) {
+ var sourceKeys, key, index, quantity;
+
+ if (!common.isObject(source)) {
+ throwError(state, 'cannot merge mappings; the provided source object is unacceptable');
+ }
+
+ sourceKeys = Object.keys(source);
+
+ for (index = 0, quantity = sourceKeys.length; index < quantity; index += 1) {
+ key = sourceKeys[index];
+
+ if (!_hasOwnProperty.call(destination, key)) {
+ destination[key] = source[key];
+ overridableKeys[key] = true;
+ }
+ }
+}
+
+function storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, valueNode) {
+ var index, quantity;
+
+ keyNode = String(keyNode);
+
+ if (_result === null) {
+ _result = {};
+ }
+
+ if (keyTag === 'tag:yaml.org,2002:merge') {
+ if (Array.isArray(valueNode)) {
+ for (index = 0, quantity = valueNode.length; index < quantity; index += 1) {
+ mergeMappings(state, _result, valueNode[index], overridableKeys);
+ }
+ } else {
+ mergeMappings(state, _result, valueNode, overridableKeys);
+ }
+ } else {
+ if (!state.json &&
+ !_hasOwnProperty.call(overridableKeys, keyNode) &&
+ _hasOwnProperty.call(_result, keyNode)) {
+ throwError(state, 'duplicated mapping key');
+ }
+ _result[keyNode] = valueNode;
+ delete overridableKeys[keyNode];
+ }
+
+ return _result;
+}
+
+function readLineBreak(state) {
+ var ch;
+
+ ch = state.input.charCodeAt(state.position);
+
+ if (ch === 0x0A/* LF */) {
+ state.position++;
+ } else if (ch === 0x0D/* CR */) {
+ state.position++;
+ if (state.input.charCodeAt(state.position) === 0x0A/* LF */) {
+ state.position++;
+ }
+ } else {
+ throwError(state, 'a line break is expected');
+ }
+
+ state.line += 1;
+ state.lineStart = state.position;
+}
+
+function skipSeparationSpace(state, allowComments, checkIndent) {
+ var lineBreaks = 0,
+ ch = state.input.charCodeAt(state.position);
+
+ while (ch !== 0) {
+ while (is_WHITE_SPACE(ch)) {
+ ch = state.input.charCodeAt(++state.position);
+ }
+
+ if (allowComments && ch === 0x23/* # */) {
+ do {
+ ch = state.input.charCodeAt(++state.position);
+ } while (ch !== 0x0A/* LF */ && ch !== 0x0D/* CR */ && ch !== 0);
+ }
+
+ if (is_EOL(ch)) {
+ readLineBreak(state);
+
+ ch = state.input.charCodeAt(state.position);
+ lineBreaks++;
+ state.lineIndent = 0;
+
+ while (ch === 0x20/* Space */) {
+ state.lineIndent++;
+ ch = state.input.charCodeAt(++state.position);
+ }
+ } else {
+ break;
+ }
+ }
+
+ if (checkIndent !== -1 && lineBreaks !== 0 && state.lineIndent < checkIndent) {
+ throwWarning(state, 'deficient indentation');
+ }
+
+ return lineBreaks;
+}
+
+function testDocumentSeparator(state) {
+ var _position = state.position,
+ ch;
+
+ ch = state.input.charCodeAt(_position);
+
+ // Condition state.position === state.lineStart is tested
+ // in parent on each call, for efficiency. No needs to test here again.
+ if ((ch === 0x2D/* - */ || ch === 0x2E/* . */) &&
+ ch === state.input.charCodeAt(_position + 1) &&
+ ch === state.input.charCodeAt(_position + 2)) {
+
+ _position += 3;
+
+ ch = state.input.charCodeAt(_position);
+
+ if (ch === 0 || is_WS_OR_EOL(ch)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+function writeFoldedLines(state, count) {
+ if (count === 1) {
+ state.result += ' ';
+ } else if (count > 1) {
+ state.result += common.repeat('\n', count - 1);
+ }
+}
+
+
+function readPlainScalar(state, nodeIndent, withinFlowCollection) {
+ var preceding,
+ following,
+ captureStart,
+ captureEnd,
+ hasPendingContent,
+ _line,
+ _lineStart,
+ _lineIndent,
+ _kind = state.kind,
+ _result = state.result,
+ ch;
+
+ ch = state.input.charCodeAt(state.position);
+
+ if (is_WS_OR_EOL(ch) ||
+ is_FLOW_INDICATOR(ch) ||
+ ch === 0x23/* # */ ||
+ ch === 0x26/* & */ ||
+ ch === 0x2A/* * */ ||
+ ch === 0x21/* ! */ ||
+ ch === 0x7C/* | */ ||
+ ch === 0x3E/* > */ ||
+ ch === 0x27/* ' */ ||
+ ch === 0x22/* " */ ||
+ ch === 0x25/* % */ ||
+ ch === 0x40/* @ */ ||
+ ch === 0x60/* ` */) {
+ return false;
+ }
+
+ if (ch === 0x3F/* ? */ || ch === 0x2D/* - */) {
+ following = state.input.charCodeAt(state.position + 1);
+
+ if (is_WS_OR_EOL(following) ||
+ withinFlowCollection && is_FLOW_INDICATOR(following)) {
+ return false;
+ }
+ }
+
+ state.kind = 'scalar';
+ state.result = '';
+ captureStart = captureEnd = state.position;
+ hasPendingContent = false;
+
+ while (ch !== 0) {
+ if (ch === 0x3A/* : */) {
+ following = state.input.charCodeAt(state.position + 1);
+
+ if (is_WS_OR_EOL(following) ||
+ withinFlowCollection && is_FLOW_INDICATOR(following)) {
+ break;
+ }
+
+ } else if (ch === 0x23/* # */) {
+ preceding = state.input.charCodeAt(state.position - 1);
+
+ if (is_WS_OR_EOL(preceding)) {
+ break;
+ }
+
+ } else if ((state.position === state.lineStart && testDocumentSeparator(state)) ||
+ withinFlowCollection && is_FLOW_INDICATOR(ch)) {
+ break;
+
+ } else if (is_EOL(ch)) {
+ _line = state.line;
+ _lineStart = state.lineStart;
+ _lineIndent = state.lineIndent;
+ skipSeparationSpace(state, false, -1);
+
+ if (state.lineIndent >= nodeIndent) {
+ hasPendingContent = true;
+ ch = state.input.charCodeAt(state.position);
+ continue;
+ } else {
+ state.position = captureEnd;
+ state.line = _line;
+ state.lineStart = _lineStart;
+ state.lineIndent = _lineIndent;
+ break;
+ }
+ }
+
+ if (hasPendingContent) {
+ captureSegment(state, captureStart, captureEnd, false);
+ writeFoldedLines(state, state.line - _line);
+ captureStart = captureEnd = state.position;
+ hasPendingContent = false;
+ }
+
+ if (!is_WHITE_SPACE(ch)) {
+ captureEnd = state.position + 1;
+ }
+
+ ch = state.input.charCodeAt(++state.position);
+ }
+
+ captureSegment(state, captureStart, captureEnd, false);
+
+ if (state.result) {
+ return true;
+ }
+
+ state.kind = _kind;
+ state.result = _result;
+ return false;
+}
+
+function readSingleQuotedScalar(state, nodeIndent) {
+ var ch,
+ captureStart, captureEnd;
+
+ ch = state.input.charCodeAt(state.position);
+
+ if (ch !== 0x27/* ' */) {
+ return false;
+ }
+
+ state.kind = 'scalar';
+ state.result = '';
+ state.position++;
+ captureStart = captureEnd = state.position;
+
+ while ((ch = state.input.charCodeAt(state.position)) !== 0) {
+ if (ch === 0x27/* ' */) {
+ captureSegment(state, captureStart, state.position, true);
+ ch = state.input.charCodeAt(++state.position);
+
+ if (ch === 0x27/* ' */) {
+ captureStart = state.position;
+ state.position++;
+ captureEnd = state.position;
+ } else {
+ return true;
+ }
+
+ } else if (is_EOL(ch)) {
+ captureSegment(state, captureStart, captureEnd, true);
+ writeFoldedLines(state, skipSeparationSpace(state, false, nodeIndent));
+ captureStart = captureEnd = state.position;
+
+ } else if (state.position === state.lineStart && testDocumentSeparator(state)) {
+ throwError(state, 'unexpected end of the document within a single quoted scalar');
+
+ } else {
+ state.position++;
+ captureEnd = state.position;
+ }
+ }
+
+ throwError(state, 'unexpected end of the stream within a single quoted scalar');
+}
+
+function readDoubleQuotedScalar(state, nodeIndent) {
+ var captureStart,
+ captureEnd,
+ hexLength,
+ hexResult,
+ tmp,
+ ch;
+
+ ch = state.input.charCodeAt(state.position);
+
+ if (ch !== 0x22/* " */) {
+ return false;
+ }
+
+ state.kind = 'scalar';
+ state.result = '';
+ state.position++;
+ captureStart = captureEnd = state.position;
+
+ while ((ch = state.input.charCodeAt(state.position)) !== 0) {
+ if (ch === 0x22/* " */) {
+ captureSegment(state, captureStart, state.position, true);
+ state.position++;
+ return true;
+
+ } else if (ch === 0x5C/* \ */) {
+ captureSegment(state, captureStart, state.position, true);
+ ch = state.input.charCodeAt(++state.position);
+
+ if (is_EOL(ch)) {
+ skipSeparationSpace(state, false, nodeIndent);
+
+ // TODO: rework to inline fn with no type cast?
+ } else if (ch < 256 && simpleEscapeCheck[ch]) {
+ state.result += simpleEscapeMap[ch];
+ state.position++;
+
+ } else if ((tmp = escapedHexLen(ch)) > 0) {
+ hexLength = tmp;
+ hexResult = 0;
+
+ for (; hexLength > 0; hexLength--) {
+ ch = state.input.charCodeAt(++state.position);
+
+ if ((tmp = fromHexCode(ch)) >= 0) {
+ hexResult = (hexResult << 4) + tmp;
+
+ } else {
+ throwError(state, 'expected hexadecimal character');
+ }
+ }
+
+ state.result += charFromCodepoint(hexResult);
+
+ state.position++;
+
+ } else {
+ throwError(state, 'unknown escape sequence');
+ }
+
+ captureStart = captureEnd = state.position;
+
+ } else if (is_EOL(ch)) {
+ captureSegment(state, captureStart, captureEnd, true);
+ writeFoldedLines(state, skipSeparationSpace(state, false, nodeIndent));
+ captureStart = captureEnd = state.position;
+
+ } else if (state.position === state.lineStart && testDocumentSeparator(state)) {
+ throwError(state, 'unexpected end of the document within a double quoted scalar');
+
+ } else {
+ state.position++;
+ captureEnd = state.position;
+ }
+ }
+
+ throwError(state, 'unexpected end of the stream within a double quoted scalar');
+}
+
+function readFlowCollection(state, nodeIndent) {
+ var readNext = true,
+ _line,
+ _tag = state.tag,
+ _result,
+ _anchor = state.anchor,
+ following,
+ terminator,
+ isPair,
+ isExplicitPair,
+ isMapping,
+ overridableKeys = {},
+ keyNode,
+ keyTag,
+ valueNode,
+ ch;
+
+ ch = state.input.charCodeAt(state.position);
+
+ if (ch === 0x5B/* [ */) {
+ terminator = 0x5D;/* ] */
+ isMapping = false;
+ _result = [];
+ } else if (ch === 0x7B/* { */) {
+ terminator = 0x7D;/* } */
+ isMapping = true;
+ _result = {};
+ } else {
+ return false;
+ }
+
+ if (state.anchor !== null) {
+ state.anchorMap[state.anchor] = _result;
+ }
+
+ ch = state.input.charCodeAt(++state.position);
+
+ while (ch !== 0) {
+ skipSeparationSpace(state, true, nodeIndent);
+
+ ch = state.input.charCodeAt(state.position);
+
+ if (ch === terminator) {
+ state.position++;
+ state.tag = _tag;
+ state.anchor = _anchor;
+ state.kind = isMapping ? 'mapping' : 'sequence';
+ state.result = _result;
+ return true;
+ } else if (!readNext) {
+ throwError(state, 'missed comma between flow collection entries');
+ }
+
+ keyTag = keyNode = valueNode = null;
+ isPair = isExplicitPair = false;
+
+ if (ch === 0x3F/* ? */) {
+ following = state.input.charCodeAt(state.position + 1);
+
+ if (is_WS_OR_EOL(following)) {
+ isPair = isExplicitPair = true;
+ state.position++;
+ skipSeparationSpace(state, true, nodeIndent);
+ }
+ }
+
+ _line = state.line;
+ composeNode(state, nodeIndent, CONTEXT_FLOW_IN, false, true);
+ keyTag = state.tag;
+ keyNode = state.result;
+ skipSeparationSpace(state, true, nodeIndent);
+
+ ch = state.input.charCodeAt(state.position);
+
+ if ((isExplicitPair || state.line === _line) && ch === 0x3A/* : */) {
+ isPair = true;
+ ch = state.input.charCodeAt(++state.position);
+ skipSeparationSpace(state, true, nodeIndent);
+ composeNode(state, nodeIndent, CONTEXT_FLOW_IN, false, true);
+ valueNode = state.result;
+ }
+
+ if (isMapping) {
+ storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, valueNode);
+ } else if (isPair) {
+ _result.push(storeMappingPair(state, null, overridableKeys, keyTag, keyNode, valueNode));
+ } else {
+ _result.push(keyNode);
+ }
+
+ skipSeparationSpace(state, true, nodeIndent);
+
+ ch = state.input.charCodeAt(state.position);
+
+ if (ch === 0x2C/* , */) {
+ readNext = true;
+ ch = state.input.charCodeAt(++state.position);
+ } else {
+ readNext = false;
+ }
+ }
+
+ throwError(state, 'unexpected end of the stream within a flow collection');
+}
+
+function readBlockScalar(state, nodeIndent) {
+ var captureStart,
+ folding,
+ chomping = CHOMPING_CLIP,
+ didReadContent = false,
+ detectedIndent = false,
+ textIndent = nodeIndent,
+ emptyLines = 0,
+ atMoreIndented = false,
+ tmp,
+ ch;
+
+ ch = state.input.charCodeAt(state.position);
+
+ if (ch === 0x7C/* | */) {
+ folding = false;
+ } else if (ch === 0x3E/* > */) {
+ folding = true;
+ } else {
+ return false;
+ }
+
+ state.kind = 'scalar';
+ state.result = '';
+
+ while (ch !== 0) {
+ ch = state.input.charCodeAt(++state.position);
+
+ if (ch === 0x2B/* + */ || ch === 0x2D/* - */) {
+ if (CHOMPING_CLIP === chomping) {
+ chomping = (ch === 0x2B/* + */) ? CHOMPING_KEEP : CHOMPING_STRIP;
+ } else {
+ throwError(state, 'repeat of a chomping mode identifier');
+ }
+
+ } else if ((tmp = fromDecimalCode(ch)) >= 0) {
+ if (tmp === 0) {
+ throwError(state, 'bad explicit indentation width of a block scalar; it cannot be less than one');
+ } else if (!detectedIndent) {
+ textIndent = nodeIndent + tmp - 1;
+ detectedIndent = true;
+ } else {
+ throwError(state, 'repeat of an indentation width identifier');
+ }
+
+ } else {
+ break;
+ }
+ }
+
+ if (is_WHITE_SPACE(ch)) {
+ do { ch = state.input.charCodeAt(++state.position); }
+ while (is_WHITE_SPACE(ch));
+
+ if (ch === 0x23/* # */) {
+ do { ch = state.input.charCodeAt(++state.position); }
+ while (!is_EOL(ch) && (ch !== 0));
+ }
+ }
+
+ while (ch !== 0) {
+ readLineBreak(state);
+ state.lineIndent = 0;
+
+ ch = state.input.charCodeAt(state.position);
+
+ while ((!detectedIndent || state.lineIndent < textIndent) &&
+ (ch === 0x20/* Space */)) {
+ state.lineIndent++;
+ ch = state.input.charCodeAt(++state.position);
+ }
+
+ if (!detectedIndent && state.lineIndent > textIndent) {
+ textIndent = state.lineIndent;
+ }
+
+ if (is_EOL(ch)) {
+ emptyLines++;
+ continue;
+ }
+
+ // End of the scalar.
+ if (state.lineIndent < textIndent) {
+
+ // Perform the chomping.
+ if (chomping === CHOMPING_KEEP) {
+ state.result += common.repeat('\n', didReadContent ? 1 + emptyLines : emptyLines);
+ } else if (chomping === CHOMPING_CLIP) {
+ if (didReadContent) { // i.e. only if the scalar is not empty.
+ state.result += '\n';
+ }
+ }
+
+ // Break this `while` cycle and go to the funciton's epilogue.
+ break;
+ }
+
+ // Folded style: use fancy rules to handle line breaks.
+ if (folding) {
+
+ // Lines starting with white space characters (more-indented lines) are not folded.
+ if (is_WHITE_SPACE(ch)) {
+ atMoreIndented = true;
+ // except for the first content line (cf. Example 8.1)
+ state.result += common.repeat('\n', didReadContent ? 1 + emptyLines : emptyLines);
+
+ // End of more-indented block.
+ } else if (atMoreIndented) {
+ atMoreIndented = false;
+ state.result += common.repeat('\n', emptyLines + 1);
+
+ // Just one line break - perceive as the same line.
+ } else if (emptyLines === 0) {
+ if (didReadContent) { // i.e. only if we have already read some scalar content.
+ state.result += ' ';
+ }
+
+ // Several line breaks - perceive as different lines.
+ } else {
+ state.result += common.repeat('\n', emptyLines);
+ }
+
+ // Literal style: just add exact number of line breaks between content lines.
+ } else {
+ // Keep all line breaks except the header line break.
+ state.result += common.repeat('\n', didReadContent ? 1 + emptyLines : emptyLines);
+ }
+
+ didReadContent = true;
+ detectedIndent = true;
+ emptyLines = 0;
+ captureStart = state.position;
+
+ while (!is_EOL(ch) && (ch !== 0)) {
+ ch = state.input.charCodeAt(++state.position);
+ }
+
+ captureSegment(state, captureStart, state.position, false);
+ }
+
+ return true;
+}
+
+function readBlockSequence(state, nodeIndent) {
+ var _line,
+ _tag = state.tag,
+ _anchor = state.anchor,
+ _result = [],
+ following,
+ detected = false,
+ ch;
+
+ if (state.anchor !== null) {
+ state.anchorMap[state.anchor] = _result;
+ }
+
+ ch = state.input.charCodeAt(state.position);
+
+ while (ch !== 0) {
+
+ if (ch !== 0x2D/* - */) {
+ break;
+ }
+
+ following = state.input.charCodeAt(state.position + 1);
+
+ if (!is_WS_OR_EOL(following)) {
+ break;
+ }
+
+ detected = true;
+ state.position++;
+
+ if (skipSeparationSpace(state, true, -1)) {
+ if (state.lineIndent <= nodeIndent) {
+ _result.push(null);
+ ch = state.input.charCodeAt(state.position);
+ continue;
+ }
+ }
+
+ _line = state.line;
+ composeNode(state, nodeIndent, CONTEXT_BLOCK_IN, false, true);
+ _result.push(state.result);
+ skipSeparationSpace(state, true, -1);
+
+ ch = state.input.charCodeAt(state.position);
+
+ if ((state.line === _line || state.lineIndent > nodeIndent) && (ch !== 0)) {
+ throwError(state, 'bad indentation of a sequence entry');
+ } else if (state.lineIndent < nodeIndent) {
+ break;
+ }
+ }
+
+ if (detected) {
+ state.tag = _tag;
+ state.anchor = _anchor;
+ state.kind = 'sequence';
+ state.result = _result;
+ return true;
+ }
+ return false;
+}
+
+function readBlockMapping(state, nodeIndent, flowIndent) {
+ var following,
+ allowCompact,
+ _line,
+ _tag = state.tag,
+ _anchor = state.anchor,
+ _result = {},
+ overridableKeys = {},
+ keyTag = null,
+ keyNode = null,
+ valueNode = null,
+ atExplicitKey = false,
+ detected = false,
+ ch;
+
+ if (state.anchor !== null) {
+ state.anchorMap[state.anchor] = _result;
+ }
+
+ ch = state.input.charCodeAt(state.position);
+
+ while (ch !== 0) {
+ following = state.input.charCodeAt(state.position + 1);
+ _line = state.line; // Save the current line.
+
+ //
+ // Explicit notation case. There are two separate blocks:
+ // first for the key (denoted by "?") and second for the value (denoted by ":")
+ //
+ if ((ch === 0x3F/* ? */ || ch === 0x3A/* : */) && is_WS_OR_EOL(following)) {
+
+ if (ch === 0x3F/* ? */) {
+ if (atExplicitKey) {
+ storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, null);
+ keyTag = keyNode = valueNode = null;
+ }
+
+ detected = true;
+ atExplicitKey = true;
+ allowCompact = true;
+
+ } else if (atExplicitKey) {
+ // i.e. 0x3A/* : */ === character after the explicit key.
+ atExplicitKey = false;
+ allowCompact = true;
+
+ } else {
+ throwError(state, 'incomplete explicit mapping pair; a key node is missed');
+ }
+
+ state.position += 1;
+ ch = following;
+
+ //
+ // Implicit notation case. Flow-style node as the key first, then ":", and the value.
+ //
+ } else if (composeNode(state, flowIndent, CONTEXT_FLOW_OUT, false, true)) {
+
+ if (state.line === _line) {
+ ch = state.input.charCodeAt(state.position);
+
+ while (is_WHITE_SPACE(ch)) {
+ ch = state.input.charCodeAt(++state.position);
+ }
+
+ if (ch === 0x3A/* : */) {
+ ch = state.input.charCodeAt(++state.position);
+
+ if (!is_WS_OR_EOL(ch)) {
+ throwError(state, 'a whitespace character is expected after the key-value separator within a block mapping');
+ }
+
+ if (atExplicitKey) {
+ storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, null);
+ keyTag = keyNode = valueNode = null;
+ }
+
+ detected = true;
+ atExplicitKey = false;
+ allowCompact = false;
+ keyTag = state.tag;
+ keyNode = state.result;
+
+ } else if (detected) {
+ throwError(state, 'can not read an implicit mapping pair; a colon is missed');
+
+ } else {
+ state.tag = _tag;
+ state.anchor = _anchor;
+ return true; // Keep the result of `composeNode`.
+ }
+
+ } else if (detected) {
+ throwError(state, 'can not read a block mapping entry; a multiline key may not be an implicit key');
+
+ } else {
+ state.tag = _tag;
+ state.anchor = _anchor;
+ return true; // Keep the result of `composeNode`.
+ }
+
+ } else {
+ break; // Reading is done. Go to the epilogue.
+ }
+
+ //
+ // Common reading code for both explicit and implicit notations.
+ //
+ if (state.line === _line || state.lineIndent > nodeIndent) {
+ if (composeNode(state, nodeIndent, CONTEXT_BLOCK_OUT, true, allowCompact)) {
+ if (atExplicitKey) {
+ keyNode = state.result;
+ } else {
+ valueNode = state.result;
+ }
+ }
+
+ if (!atExplicitKey) {
+ storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, valueNode);
+ keyTag = keyNode = valueNode = null;
+ }
+
+ skipSeparationSpace(state, true, -1);
+ ch = state.input.charCodeAt(state.position);
+ }
+
+ if (state.lineIndent > nodeIndent && (ch !== 0)) {
+ throwError(state, 'bad indentation of a mapping entry');
+ } else if (state.lineIndent < nodeIndent) {
+ break;
+ }
+ }
+
+ //
+ // Epilogue.
+ //
+
+ // Special case: last mapping's node contains only the key in explicit notation.
+ if (atExplicitKey) {
+ storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, null);
+ }
+
+ // Expose the resulting mapping.
+ if (detected) {
+ state.tag = _tag;
+ state.anchor = _anchor;
+ state.kind = 'mapping';
+ state.result = _result;
+ }
+
+ return detected;
+}
+
+function readTagProperty(state) {
+ var _position,
+ isVerbatim = false,
+ isNamed = false,
+ tagHandle,
+ tagName,
+ ch;
+
+ ch = state.input.charCodeAt(state.position);
+
+ if (ch !== 0x21/* ! */) return false;
+
+ if (state.tag !== null) {
+ throwError(state, 'duplication of a tag property');
+ }
+
+ ch = state.input.charCodeAt(++state.position);
+
+ if (ch === 0x3C/* < */) {
+ isVerbatim = true;
+ ch = state.input.charCodeAt(++state.position);
+
+ } else if (ch === 0x21/* ! */) {
+ isNamed = true;
+ tagHandle = '!!';
+ ch = state.input.charCodeAt(++state.position);
+
+ } else {
+ tagHandle = '!';
+ }
+
+ _position = state.position;
+
+ if (isVerbatim) {
+ do { ch = state.input.charCodeAt(++state.position); }
+ while (ch !== 0 && ch !== 0x3E/* > */);
+
+ if (state.position < state.length) {
+ tagName = state.input.slice(_position, state.position);
+ ch = state.input.charCodeAt(++state.position);
+ } else {
+ throwError(state, 'unexpected end of the stream within a verbatim tag');
+ }
+ } else {
+ while (ch !== 0 && !is_WS_OR_EOL(ch)) {
+
+ if (ch === 0x21/* ! */) {
+ if (!isNamed) {
+ tagHandle = state.input.slice(_position - 1, state.position + 1);
+
+ if (!PATTERN_TAG_HANDLE.test(tagHandle)) {
+ throwError(state, 'named tag handle cannot contain such characters');
+ }
+
+ isNamed = true;
+ _position = state.position + 1;
+ } else {
+ throwError(state, 'tag suffix cannot contain exclamation marks');
+ }
+ }
+
+ ch = state.input.charCodeAt(++state.position);
+ }
+
+ tagName = state.input.slice(_position, state.position);
+
+ if (PATTERN_FLOW_INDICATORS.test(tagName)) {
+ throwError(state, 'tag suffix cannot contain flow indicator characters');
+ }
+ }
+
+ if (tagName && !PATTERN_TAG_URI.test(tagName)) {
+ throwError(state, 'tag name cannot contain such characters: ' + tagName);
+ }
+
+ if (isVerbatim) {
+ state.tag = tagName;
+
+ } else if (_hasOwnProperty.call(state.tagMap, tagHandle)) {
+ state.tag = state.tagMap[tagHandle] + tagName;
+
+ } else if (tagHandle === '!') {
+ state.tag = '!' + tagName;
+
+ } else if (tagHandle === '!!') {
+ state.tag = 'tag:yaml.org,2002:' + tagName;
+
+ } else {
+ throwError(state, 'undeclared tag handle "' + tagHandle + '"');
+ }
+
+ return true;
+}
+
+function readAnchorProperty(state) {
+ var _position,
+ ch;
+
+ ch = state.input.charCodeAt(state.position);
+
+ if (ch !== 0x26/* & */) return false;
+
+ if (state.anchor !== null) {
+ throwError(state, 'duplication of an anchor property');
+ }
+
+ ch = state.input.charCodeAt(++state.position);
+ _position = state.position;
+
+ while (ch !== 0 && !is_WS_OR_EOL(ch) && !is_FLOW_INDICATOR(ch)) {
+ ch = state.input.charCodeAt(++state.position);
+ }
+
+ if (state.position === _position) {
+ throwError(state, 'name of an anchor node must contain at least one character');
+ }
+
+ state.anchor = state.input.slice(_position, state.position);
+ return true;
+}
+
+function readAlias(state) {
+ var _position, alias,
+ ch;
+
+ ch = state.input.charCodeAt(state.position);
+
+ if (ch !== 0x2A/* * */) return false;
+
+ ch = state.input.charCodeAt(++state.position);
+ _position = state.position;
+
+ while (ch !== 0 && !is_WS_OR_EOL(ch) && !is_FLOW_INDICATOR(ch)) {
+ ch = state.input.charCodeAt(++state.position);
+ }
+
+ if (state.position === _position) {
+ throwError(state, 'name of an alias node must contain at least one character');
+ }
+
+ alias = state.input.slice(_position, state.position);
+
+ if (!state.anchorMap.hasOwnProperty(alias)) {
+ throwError(state, 'unidentified alias "' + alias + '"');
+ }
+
+ state.result = state.anchorMap[alias];
+ skipSeparationSpace(state, true, -1);
+ return true;
+}
+
+function composeNode(state, parentIndent, nodeContext, allowToSeek, allowCompact) {
+ var allowBlockStyles,
+ allowBlockScalars,
+ allowBlockCollections,
+ indentStatus = 1, // 1: this>parent, 0: this=parent, -1: this<parent
+ atNewLine = false,
+ hasContent = false,
+ typeIndex,
+ typeQuantity,
+ type,
+ flowIndent,
+ blockIndent;
+
+ if (state.listener !== null) {
+ state.listener('open', state);
+ }
+
+ state.tag = null;
+ state.anchor = null;
+ state.kind = null;
+ state.result = null;
+
+ allowBlockStyles = allowBlockScalars = allowBlockCollections =
+ CONTEXT_BLOCK_OUT === nodeContext ||
+ CONTEXT_BLOCK_IN === nodeContext;
+
+ if (allowToSeek) {
+ if (skipSeparationSpace(state, true, -1)) {
+ atNewLine = true;
+
+ if (state.lineIndent > parentIndent) {
+ indentStatus = 1;
+ } else if (state.lineIndent === parentIndent) {
+ indentStatus = 0;
+ } else if (state.lineIndent < parentIndent) {
+ indentStatus = -1;
+ }
+ }
+ }
+
+ if (indentStatus === 1) {
+ while (readTagProperty(state) || readAnchorProperty(state)) {
+ if (skipSeparationSpace(state, true, -1)) {
+ atNewLine = true;
+ allowBlockCollections = allowBlockStyles;
+
+ if (state.lineIndent > parentIndent) {
+ indentStatus = 1;
+ } else if (state.lineIndent === parentIndent) {
+ indentStatus = 0;
+ } else if (state.lineIndent < parentIndent) {
+ indentStatus = -1;
+ }
+ } else {
+ allowBlockCollections = false;
+ }
+ }
+ }
+
+ if (allowBlockCollections) {
+ allowBlockCollections = atNewLine || allowCompact;
+ }
+
+ if (indentStatus === 1 || CONTEXT_BLOCK_OUT === nodeContext) {
+ if (CONTEXT_FLOW_IN === nodeContext || CONTEXT_FLOW_OUT === nodeContext) {
+ flowIndent = parentIndent;
+ } else {
+ flowIndent = parentIndent + 1;
+ }
+
+ blockIndent = state.position - state.lineStart;
+
+ if (indentStatus === 1) {
+ if (allowBlockCollections &&
+ (readBlockSequence(state, blockIndent) ||
+ readBlockMapping(state, blockIndent, flowIndent)) ||
+ readFlowCollection(state, flowIndent)) {
+ hasContent = true;
+ } else {
+ if ((allowBlockScalars && readBlockScalar(state, flowIndent)) ||
+ readSingleQuotedScalar(state, flowIndent) ||
+ readDoubleQuotedScalar(state, flowIndent)) {
+ hasContent = true;
+
+ } else if (readAlias(state)) {
+ hasContent = true;
+
+ if (state.tag !== null || state.anchor !== null) {
+ throwError(state, 'alias node should not have any properties');
+ }
+
+ } else if (readPlainScalar(state, flowIndent, CONTEXT_FLOW_IN === nodeContext)) {
+ hasContent = true;
+
+ if (state.tag === null) {
+ state.tag = '?';
+ }
+ }
+
+ if (state.anchor !== null) {
+ state.anchorMap[state.anchor] = state.result;
+ }
+ }
+ } else if (indentStatus === 0) {
+ // Special case: block sequences are allowed to have same indentation level as the parent.
+ // http://www.yaml.org/spec/1.2/spec.html#id2799784
+ hasContent = allowBlockCollections && readBlockSequence(state, blockIndent);
+ }
+ }
+
+ if (state.tag !== null && state.tag !== '!') {
+ if (state.tag === '?') {
+ for (typeIndex = 0, typeQuantity = state.implicitTypes.length;
+ typeIndex < typeQuantity;
+ typeIndex += 1) {
+ type = state.implicitTypes[typeIndex];
+
+ // Implicit resolving is not allowed for non-scalar types, and '?'
+ // non-specific tag is only assigned to plain scalars. So, it isn't
+ // needed to check for 'kind' conformity.
+
+ if (type.resolve(state.result)) { // `state.result` updated in resolver if matched
+ state.result = type.construct(state.result);
+ state.tag = type.tag;
+ if (state.anchor !== null) {
+ state.anchorMap[state.anchor] = state.result;
+ }
+ break;
+ }
+ }
+ } else if (_hasOwnProperty.call(state.typeMap[state.kind || 'fallback'], state.tag)) {
+ type = state.typeMap[state.kind || 'fallback'][state.tag];
+
+ if (state.result !== null && type.kind !== state.kind) {
+ throwError(state, 'unacceptable node kind for !<' + state.tag + '> tag; it should be "' + type.kind + '", not "' + state.kind + '"');
+ }
+
+ if (!type.resolve(state.result)) { // `state.result` updated in resolver if matched
+ throwError(state, 'cannot resolve a node with !<' + state.tag + '> explicit tag');
+ } else {
+ state.result = type.construct(state.result);
+ if (state.anchor !== null) {
+ state.anchorMap[state.anchor] = state.result;
+ }
+ }
+ } else {
+ throwError(state, 'unknown tag !<' + state.tag + '>');
+ }
+ }
+
+ if (state.listener !== null) {
+ state.listener('close', state);
+ }
+ return state.tag !== null || state.anchor !== null || hasContent;
+}
+
+function readDocument(state) {
+ var documentStart = state.position,
+ _position,
+ directiveName,
+ directiveArgs,
+ hasDirectives = false,
+ ch;
+
+ state.version = null;
+ state.checkLineBreaks = state.legacy;
+ state.tagMap = {};
+ state.anchorMap = {};
+
+ while ((ch = state.input.charCodeAt(state.position)) !== 0) {
+ skipSeparationSpace(state, true, -1);
+
+ ch = state.input.charCodeAt(state.position);
+
+ if (state.lineIndent > 0 || ch !== 0x25/* % */) {
+ break;
+ }
+
+ hasDirectives = true;
+ ch = state.input.charCodeAt(++state.position);
+ _position = state.position;
+
+ while (ch !== 0 && !is_WS_OR_EOL(ch)) {
+ ch = state.input.charCodeAt(++state.position);
+ }
+
+ directiveName = state.input.slice(_position, state.position);
+ directiveArgs = [];
+
+ if (directiveName.length < 1) {
+ throwError(state, 'directive name must not be less than one character in length');
+ }
+
+ while (ch !== 0) {
+ while (is_WHITE_SPACE(ch)) {
+ ch = state.input.charCodeAt(++state.position);
+ }
+
+ if (ch === 0x23/* # */) {
+ do { ch = state.input.charCodeAt(++state.position); }
+ while (ch !== 0 && !is_EOL(ch));
+ break;
+ }
+
+ if (is_EOL(ch)) break;
+
+ _position = state.position;
+
+ while (ch !== 0 && !is_WS_OR_EOL(ch)) {
+ ch = state.input.charCodeAt(++state.position);
+ }
+
+ directiveArgs.push(state.input.slice(_position, state.position));
+ }
+
+ if (ch !== 0) readLineBreak(state);
+
+ if (_hasOwnProperty.call(directiveHandlers, directiveName)) {
+ directiveHandlers[directiveName](state, directiveName, directiveArgs);
+ } else {
+ throwWarning(state, 'unknown document directive "' + directiveName + '"');
+ }
+ }
+
+ skipSeparationSpace(state, true, -1);
+
+ if (state.lineIndent === 0 &&
+ state.input.charCodeAt(state.position) === 0x2D/* - */ &&
+ state.input.charCodeAt(state.position + 1) === 0x2D/* - */ &&
+ state.input.charCodeAt(state.position + 2) === 0x2D/* - */) {
+ state.position += 3;
+ skipSeparationSpace(state, true, -1);
+
+ } else if (hasDirectives) {
+ throwError(state, 'directives end mark is expected');
+ }
+
+ composeNode(state, state.lineIndent - 1, CONTEXT_BLOCK_OUT, false, true);
+ skipSeparationSpace(state, true, -1);
+
+ if (state.checkLineBreaks &&
+ PATTERN_NON_ASCII_LINE_BREAKS.test(state.input.slice(documentStart, state.position))) {
+ throwWarning(state, 'non-ASCII line breaks are interpreted as content');
+ }
+
+ state.documents.push(state.result);
+
+ if (state.position === state.lineStart && testDocumentSeparator(state)) {
+
+ if (state.input.charCodeAt(state.position) === 0x2E/* . */) {
+ state.position += 3;
+ skipSeparationSpace(state, true, -1);
+ }
+ return;
+ }
+
+ if (state.position < (state.length - 1)) {
+ throwError(state, 'end of the stream or a document separator is expected');
+ } else {
+ return;
+ }
+}
+
+
+function loadDocuments(input, options) {
+ input = String(input);
+ options = options || {};
+
+ if (input.length !== 0) {
+
+ // Add tailing `\n` if not exists
+ if (input.charCodeAt(input.length - 1) !== 0x0A/* LF */ &&
+ input.charCodeAt(input.length - 1) !== 0x0D/* CR */) {
+ input += '\n';
+ }
+
+ // Strip BOM
+ if (input.charCodeAt(0) === 0xFEFF) {
+ input = input.slice(1);
+ }
+ }
+
+ var state = new State(input, options);
+
+ // Use 0 as string terminator. That significantly simplifies bounds check.
+ state.input += '\0';
+
+ while (state.input.charCodeAt(state.position) === 0x20/* Space */) {
+ state.lineIndent += 1;
+ state.position += 1;
+ }
+
+ while (state.position < (state.length - 1)) {
+ readDocument(state);
+ }
+
+ return state.documents;
+}
+
+
+function loadAll(input, iterator, options) {
+ var documents = loadDocuments(input, options), index, length;
+
+ for (index = 0, length = documents.length; index < length; index += 1) {
+ iterator(documents[index]);
+ }
+}
+
+
+function load(input, options) {
+ var documents = loadDocuments(input, options);
+
+ if (documents.length === 0) {
+ /*eslint-disable no-undefined*/
+ return undefined;
+ } else if (documents.length === 1) {
+ return documents[0];
+ }
+ throw new YAMLException('expected a single document in the stream, but found more');
+}
+
+
+function safeLoadAll(input, output, options) {
+ loadAll(input, output, common.extend({ schema: DEFAULT_SAFE_SCHEMA }, options));
+}
+
+
+function safeLoad(input, options) {
+ return load(input, common.extend({ schema: DEFAULT_SAFE_SCHEMA }, options));
+}
+
+
+module.exports.loadAll = loadAll;
+module.exports.load = load;
+module.exports.safeLoadAll = safeLoadAll;
+module.exports.safeLoad = safeLoad;
+
+},{"./common":2,"./exception":4,"./mark":6,"./schema/default_full":9,"./schema/default_safe":10}],6:[function(require,module,exports){
+'use strict';
+
+
+var common = require('./common');
+
+
+function Mark(name, buffer, position, line, column) {
+ this.name = name;
+ this.buffer = buffer;
+ this.position = position;
+ this.line = line;
+ this.column = column;
+}
+
+
+Mark.prototype.getSnippet = function getSnippet(indent, maxLength) {
+ var head, start, tail, end, snippet;
+
+ if (!this.buffer) return null;
+
+ indent = indent || 4;
+ maxLength = maxLength || 75;
+
+ head = '';
+ start = this.position;
+
+ while (start > 0 && '\x00\r\n\x85\u2028\u2029'.indexOf(this.buffer.charAt(start - 1)) === -1) {
+ start -= 1;
+ if (this.position - start > (maxLength / 2 - 1)) {
+ head = ' ... ';
+ start += 5;
+ break;
+ }
+ }
+
+ tail = '';
+ end = this.position;
+
+ while (end < this.buffer.length && '\x00\r\n\x85\u2028\u2029'.indexOf(this.buffer.charAt(end)) === -1) {
+ end += 1;
+ if (end - this.position > (maxLength / 2 - 1)) {
+ tail = ' ... ';
+ end -= 5;
+ break;
+ }
+ }
+
+ snippet = this.buffer.slice(start, end);
+
+ return common.repeat(' ', indent) + head + snippet + tail + '\n' +
+ common.repeat(' ', indent + this.position - start + head.length) + '^';
+};
+
+
+Mark.prototype.toString = function toString(compact) {
+ var snippet, where = '';
+
+ if (this.name) {
+ where += 'in "' + this.name + '" ';
+ }
+
+ where += 'at line ' + (this.line + 1) + ', column ' + (this.column + 1);
+
+ if (!compact) {
+ snippet = this.getSnippet();
+
+ if (snippet) {
+ where += ':\n' + snippet;
+ }
+ }
+
+ return where;
+};
+
+
+module.exports = Mark;
+
+},{"./common":2}],7:[function(require,module,exports){
+'use strict';
+
+/*eslint-disable max-len*/
+
+var common = require('./common');
+var YAMLException = require('./exception');
+var Type = require('./type');
+
+
+function compileList(schema, name, result) {
+ var exclude = [];
+
+ schema.include.forEach(function (includedSchema) {
+ result = compileList(includedSchema, name, result);
+ });
+
+ schema[name].forEach(function (currentType) {
+ result.forEach(function (previousType, previousIndex) {
+ if (previousType.tag === currentType.tag && previousType.kind === currentType.kind) {
+ exclude.push(previousIndex);
+ }
+ });
+
+ result.push(currentType);
+ });
+
+ return result.filter(function (type, index) {
+ return exclude.indexOf(index) === -1;
+ });
+}
+
+
+function compileMap(/* lists... */) {
+ var result = {
+ scalar: {},
+ sequence: {},
+ mapping: {},
+ fallback: {}
+ }, index, length;
+
+ function collectType(type) {
+ result[type.kind][type.tag] = result['fallback'][type.tag] = type;
+ }
+
+ for (index = 0, length = arguments.length; index < length; index += 1) {
+ arguments[index].forEach(collectType);
+ }
+ return result;
+}
+
+
+function Schema(definition) {
+ this.include = definition.include || [];
+ this.implicit = definition.implicit || [];
+ this.explicit = definition.explicit || [];
+
+ this.implicit.forEach(function (type) {
+ if (type.loadKind && type.loadKind !== 'scalar') {
+ throw new YAMLException('There is a non-scalar type in the implicit list of a schema. Implicit resolving of such types is not supported.');
+ }
+ });
+
+ this.compiledImplicit = compileList(this, 'implicit', []);
+ this.compiledExplicit = compileList(this, 'explicit', []);
+ this.compiledTypeMap = compileMap(this.compiledImplicit, this.compiledExplicit);
+}
+
+
+Schema.DEFAULT = null;
+
+
+Schema.create = function createSchema() {
+ var schemas, types;
+
+ switch (arguments.length) {
+ case 1:
+ schemas = Schema.DEFAULT;
+ types = arguments[0];
+ break;
+
+ case 2:
+ schemas = arguments[0];
+ types = arguments[1];
+ break;
+
+ default:
+ throw new YAMLException('Wrong number of arguments for Schema.create function');
+ }
+
+ schemas = common.toArray(schemas);
+ types = common.toArray(types);
+
+ if (!schemas.every(function (schema) { return schema instanceof Schema; })) {
+ throw new YAMLException('Specified list of super schemas (or a single Schema object) contains a non-Schema object.');
+ }
+
+ if (!types.every(function (type) { return type instanceof Type; })) {
+ throw new YAMLException('Specified list of YAML types (or a single Type object) contains a non-Type object.');
+ }
+
+ return new Schema({
+ include: schemas,
+ explicit: types
+ });
+};
+
+
+module.exports = Schema;
+
+},{"./common":2,"./exception":4,"./type":13}],8:[function(require,module,exports){
+// Standard YAML's Core schema.
+// http://www.yaml.org/spec/1.2/spec.html#id2804923
+//
+// NOTE: JS-YAML does not support schema-specific tag resolution restrictions.
+// So, Core schema has no distinctions from JSON schema is JS-YAML.
+
+
+'use strict';
+
+
+var Schema = require('../schema');
+
+
+module.exports = new Schema({
+ include: [
+ require('./json')
+ ]
+});
+
+},{"../schema":7,"./json":12}],9:[function(require,module,exports){
+// JS-YAML's default schema for `load` function.
+// It is not described in the YAML specification.
+//
+// This schema is based on JS-YAML's default safe schema and includes
+// JavaScript-specific types: !!js/undefined, !!js/regexp and !!js/function.
+//
+// Also this schema is used as default base schema at `Schema.create` function.
+
+
+'use strict';
+
+
+var Schema = require('../schema');
+
+
+module.exports = Schema.DEFAULT = new Schema({
+ include: [
+ require('./default_safe')
+ ],
+ explicit: [
+ require('../type/js/undefined'),
+ require('../type/js/regexp'),
+ require('../type/js/function')
+ ]
+});
+
+},{"../schema":7,"../type/js/function":18,"../type/js/regexp":19,"../type/js/undefined":20,"./default_safe":10}],10:[function(require,module,exports){
+// JS-YAML's default schema for `safeLoad` function.
+// It is not described in the YAML specification.
+//
+// This schema is based on standard YAML's Core schema and includes most of
+// extra types described at YAML tag repository. (http://yaml.org/type/)
+
+
+'use strict';
+
+
+var Schema = require('../schema');
+
+
+module.exports = new Schema({
+ include: [
+ require('./core')
+ ],
+ implicit: [
+ require('../type/timestamp'),
+ require('../type/merge')
+ ],
+ explicit: [
+ require('../type/binary'),
+ require('../type/omap'),
+ require('../type/pairs'),
+ require('../type/set')
+ ]
+});
+
+},{"../schema":7,"../type/binary":14,"../type/merge":22,"../type/omap":24,"../type/pairs":25,"../type/set":27,"../type/timestamp":29,"./core":8}],11:[function(require,module,exports){
+// Standard YAML's Failsafe schema.
+// http://www.yaml.org/spec/1.2/spec.html#id2802346
+
+
+'use strict';
+
+
+var Schema = require('../schema');
+
+
+module.exports = new Schema({
+ explicit: [
+ require('../type/str'),
+ require('../type/seq'),
+ require('../type/map')
+ ]
+});
+
+},{"../schema":7,"../type/map":21,"../type/seq":26,"../type/str":28}],12:[function(require,module,exports){
+// Standard YAML's JSON schema.
+// http://www.yaml.org/spec/1.2/spec.html#id2803231
+//
+// NOTE: JS-YAML does not support schema-specific tag resolution restrictions.
+// So, this schema is not such strict as defined in the YAML specification.
+// It allows numbers in binary notaion, use `Null` and `NULL` as `null`, etc.
+
+
+'use strict';
+
+
+var Schema = require('../schema');
+
+
+module.exports = new Schema({
+ include: [
+ require('./failsafe')
+ ],
+ implicit: [
+ require('../type/null'),
+ require('../type/bool'),
+ require('../type/int'),
+ require('../type/float')
+ ]
+});
+
+},{"../schema":7,"../type/bool":15,"../type/float":16,"../type/int":17,"../type/null":23,"./failsafe":11}],13:[function(require,module,exports){
+'use strict';
+
+var YAMLException = require('./exception');
+
+var TYPE_CONSTRUCTOR_OPTIONS = [
+ 'kind',
+ 'resolve',
+ 'construct',
+ 'instanceOf',
+ 'predicate',
+ 'represent',
+ 'defaultStyle',
+ 'styleAliases'
+];
+
+var YAML_NODE_KINDS = [
+ 'scalar',
+ 'sequence',
+ 'mapping'
+];
+
+function compileStyleAliases(map) {
+ var result = {};
+
+ if (map !== null) {
+ Object.keys(map).forEach(function (style) {
+ map[style].forEach(function (alias) {
+ result[String(alias)] = style;
+ });
+ });
+ }
+
+ return result;
+}
+
+function Type(tag, options) {
+ options = options || {};
+
+ Object.keys(options).forEach(function (name) {
+ if (TYPE_CONSTRUCTOR_OPTIONS.indexOf(name) === -1) {
+ throw new YAMLException('Unknown option "' + name + '" is met in definition of "' + tag + '" YAML type.');
+ }
+ });
+
+ // TODO: Add tag format check.
+ this.tag = tag;
+ this.kind = options['kind'] || null;
+ this.resolve = options['resolve'] || function () { return true; };
+ this.construct = options['construct'] || function (data) { return data; };
+ this.instanceOf = options['instanceOf'] || null;
+ this.predicate = options['predicate'] || null;
+ this.represent = options['represent'] || null;
+ this.defaultStyle = options['defaultStyle'] || null;
+ this.styleAliases = compileStyleAliases(options['styleAliases'] || null);
+
+ if (YAML_NODE_KINDS.indexOf(this.kind) === -1) {
+ throw new YAMLException('Unknown kind "' + this.kind + '" is specified for "' + tag + '" YAML type.');
+ }
+}
+
+module.exports = Type;
+
+},{"./exception":4}],14:[function(require,module,exports){
+'use strict';
+
+/*eslint-disable no-bitwise*/
+
+var NodeBuffer;
+
+try {
+ // A trick for browserified version, to not include `Buffer` shim
+ var _require = require;
+ NodeBuffer = _require('buffer').Buffer;
+} catch (__) {}
+
+var Type = require('../type');
+
+
+// [ 64, 65, 66 ] -> [ padding, CR, LF ]
+var BASE64_MAP = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\n\r';
+
+
+function resolveYamlBinary(data) {
+ if (data === null) return false;
+
+ var code, idx, bitlen = 0, max = data.length, map = BASE64_MAP;
+
+ // Convert one by one.
+ for (idx = 0; idx < max; idx++) {
+ code = map.indexOf(data.charAt(idx));
+
+ // Skip CR/LF
+ if (code > 64) continue;
+
+ // Fail on illegal characters
+ if (code < 0) return false;
+
+ bitlen += 6;
+ }
+
+ // If there are any bits left, source was corrupted
+ return (bitlen % 8) === 0;
+}
+
+function constructYamlBinary(data) {
+ var idx, tailbits,
+ input = data.replace(/[\r\n=]/g, ''), // remove CR/LF & padding to simplify scan
+ max = input.length,
+ map = BASE64_MAP,
+ bits = 0,
+ result = [];
+
+ // Collect by 6*4 bits (3 bytes)
+
+ for (idx = 0; idx < max; idx++) {
+ if ((idx % 4 === 0) && idx) {
+ result.push((bits >> 16) & 0xFF);
+ result.push((bits >> 8) & 0xFF);
+ result.push(bits & 0xFF);
+ }
+
+ bits = (bits << 6) | map.indexOf(input.charAt(idx));
+ }
+
+ // Dump tail
+
+ tailbits = (max % 4) * 6;
+
+ if (tailbits === 0) {
+ result.push((bits >> 16) & 0xFF);
+ result.push((bits >> 8) & 0xFF);
+ result.push(bits & 0xFF);
+ } else if (tailbits === 18) {
+ result.push((bits >> 10) & 0xFF);
+ result.push((bits >> 2) & 0xFF);
+ } else if (tailbits === 12) {
+ result.push((bits >> 4) & 0xFF);
+ }
+
+ // Wrap into Buffer for NodeJS and leave Array for browser
+ if (NodeBuffer) return new NodeBuffer(result);
+
+ return result;
+}
+
+function representYamlBinary(object /*, style*/) {
+ var result = '', bits = 0, idx, tail,
+ max = object.length,
+ map = BASE64_MAP;
+
+ // Convert every three bytes to 4 ASCII characters.
+
+ for (idx = 0; idx < max; idx++) {
+ if ((idx % 3 === 0) && idx) {
+ result += map[(bits >> 18) & 0x3F];
+ result += map[(bits >> 12) & 0x3F];
+ result += map[(bits >> 6) & 0x3F];
+ result += map[bits & 0x3F];
+ }
+
+ bits = (bits << 8) + object[idx];
+ }
+
+ // Dump tail
+
+ tail = max % 3;
+
+ if (tail === 0) {
+ result += map[(bits >> 18) & 0x3F];
+ result += map[(bits >> 12) & 0x3F];
+ result += map[(bits >> 6) & 0x3F];
+ result += map[bits & 0x3F];
+ } else if (tail === 2) {
+ result += map[(bits >> 10) & 0x3F];
+ result += map[(bits >> 4) & 0x3F];
+ result += map[(bits << 2) & 0x3F];
+ result += map[64];
+ } else if (tail === 1) {
+ result += map[(bits >> 2) & 0x3F];
+ result += map[(bits << 4) & 0x3F];
+ result += map[64];
+ result += map[64];
+ }
+
+ return result;
+}
+
+function isBinary(object) {
+ return NodeBuffer && NodeBuffer.isBuffer(object);
+}
+
+module.exports = new Type('tag:yaml.org,2002:binary', {
+ kind: 'scalar',
+ resolve: resolveYamlBinary,
+ construct: constructYamlBinary,
+ predicate: isBinary,
+ represent: representYamlBinary
+});
+
+},{"../type":13}],15:[function(require,module,exports){
+'use strict';
+
+var Type = require('../type');
+
+function resolveYamlBoolean(data) {
+ if (data === null) return false;
+
+ var max = data.length;
+
+ return (max === 4 && (data === 'true' || data === 'True' || data === 'TRUE')) ||
+ (max === 5 && (data === 'false' || data === 'False' || data === 'FALSE'));
+}
+
+function constructYamlBoolean(data) {
+ return data === 'true' ||
+ data === 'True' ||
+ data === 'TRUE';
+}
+
+function isBoolean(object) {
+ return Object.prototype.toString.call(object) === '[object Boolean]';
+}
+
+module.exports = new Type('tag:yaml.org,2002:bool', {
+ kind: 'scalar',
+ resolve: resolveYamlBoolean,
+ construct: constructYamlBoolean,
+ predicate: isBoolean,
+ represent: {
+ lowercase: function (object) { return object ? 'true' : 'false'; },
+ uppercase: function (object) { return object ? 'TRUE' : 'FALSE'; },
+ camelcase: function (object) { return object ? 'True' : 'False'; }
+ },
+ defaultStyle: 'lowercase'
+});
+
+},{"../type":13}],16:[function(require,module,exports){
+'use strict';
+
+var common = require('../common');
+var Type = require('../type');
+
+var YAML_FLOAT_PATTERN = new RegExp(
+ '^(?:[-+]?(?:[0-9][0-9_]*)\\.[0-9_]*(?:[eE][-+][0-9]+)?' +
+ '|\\.[0-9_]+(?:[eE][-+][0-9]+)?' +
+ '|[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]*' +
+ '|[-+]?\\.(?:inf|Inf|INF)' +
+ '|\\.(?:nan|NaN|NAN))$');
+
+function resolveYamlFloat(data) {
+ if (data === null) return false;
+
+ if (!YAML_FLOAT_PATTERN.test(data)) return false;
+
+ return true;
+}
+
+function constructYamlFloat(data) {
+ var value, sign, base, digits;
+
+ value = data.replace(/_/g, '').toLowerCase();
+ sign = value[0] === '-' ? -1 : 1;
+ digits = [];
+
+ if ('+-'.indexOf(value[0]) >= 0) {
+ value = value.slice(1);
+ }
+
+ if (value === '.inf') {
+ return (sign === 1) ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY;
+
+ } else if (value === '.nan') {
+ return NaN;
+
+ } else if (value.indexOf(':') >= 0) {
+ value.split(':').forEach(function (v) {
+ digits.unshift(parseFloat(v, 10));
+ });
+
+ value = 0.0;
+ base = 1;
+
+ digits.forEach(function (d) {
+ value += d * base;
+ base *= 60;
+ });
+
+ return sign * value;
+
+ }
+ return sign * parseFloat(value, 10);
+}
+
+
+var SCIENTIFIC_WITHOUT_DOT = /^[-+]?[0-9]+e/;
+
+function representYamlFloat(object, style) {
+ var res;
+
+ if (isNaN(object)) {
+ switch (style) {
+ case 'lowercase': return '.nan';
+ case 'uppercase': return '.NAN';
+ case 'camelcase': return '.NaN';
+ }
+ } else if (Number.POSITIVE_INFINITY === object) {
+ switch (style) {
+ case 'lowercase': return '.inf';
+ case 'uppercase': return '.INF';
+ case 'camelcase': return '.Inf';
+ }
+ } else if (Number.NEGATIVE_INFINITY === object) {
+ switch (style) {
+ case 'lowercase': return '-.inf';
+ case 'uppercase': return '-.INF';
+ case 'camelcase': return '-.Inf';
+ }
+ } else if (common.isNegativeZero(object)) {
+ return '-0.0';
+ }
+
+ res = object.toString(10);
+
+ // JS stringifier can build scientific format without dots: 5e-100,
+ // while YAML requres dot: 5.e-100. Fix it with simple hack
+
+ return SCIENTIFIC_WITHOUT_DOT.test(res) ? res.replace('e', '.e') : res;
+}
+
+function isFloat(object) {
+ return (Object.prototype.toString.call(object) === '[object Number]') &&
+ (object % 1 !== 0 || common.isNegativeZero(object));
+}
+
+module.exports = new Type('tag:yaml.org,2002:float', {
+ kind: 'scalar',
+ resolve: resolveYamlFloat,
+ construct: constructYamlFloat,
+ predicate: isFloat,
+ represent: representYamlFloat,
+ defaultStyle: 'lowercase'
+});
+
+},{"../common":2,"../type":13}],17:[function(require,module,exports){
+'use strict';
+
+var common = require('../common');
+var Type = require('../type');
+
+function isHexCode(c) {
+ return ((0x30/* 0 */ <= c) && (c <= 0x39/* 9 */)) ||
+ ((0x41/* A */ <= c) && (c <= 0x46/* F */)) ||
+ ((0x61/* a */ <= c) && (c <= 0x66/* f */));
+}
+
+function isOctCode(c) {
+ return ((0x30/* 0 */ <= c) && (c <= 0x37/* 7 */));
+}
+
+function isDecCode(c) {
+ return ((0x30/* 0 */ <= c) && (c <= 0x39/* 9 */));
+}
+
+function resolveYamlInteger(data) {
+ if (data === null) return false;
+
+ var max = data.length,
+ index = 0,
+ hasDigits = false,
+ ch;
+
+ if (!max) return false;
+
+ ch = data[index];
+
+ // sign
+ if (ch === '-' || ch === '+') {
+ ch = data[++index];
+ }
+
+ if (ch === '0') {
+ // 0
+ if (index + 1 === max) return true;
+ ch = data[++index];
+
+ // base 2, base 8, base 16
+
+ if (ch === 'b') {
+ // base 2
+ index++;
+
+ for (; index < max; index++) {
+ ch = data[index];
+ if (ch === '_') continue;
+ if (ch !== '0' && ch !== '1') return false;
+ hasDigits = true;
+ }
+ return hasDigits;
+ }
+
+
+ if (ch === 'x') {
+ // base 16
+ index++;
+
+ for (; index < max; index++) {
+ ch = data[index];
+ if (ch === '_') continue;
+ if (!isHexCode(data.charCodeAt(index))) return false;
+ hasDigits = true;
+ }
+ return hasDigits;
+ }
+
+ // base 8
+ for (; index < max; index++) {
+ ch = data[index];
+ if (ch === '_') continue;
+ if (!isOctCode(data.charCodeAt(index))) return false;
+ hasDigits = true;
+ }
+ return hasDigits;
+ }
+
+ // base 10 (except 0) or base 60
+
+ for (; index < max; index++) {
+ ch = data[index];
+ if (ch === '_') continue;
+ if (ch === ':') break;
+ if (!isDecCode(data.charCodeAt(index))) {
+ return false;
+ }
+ hasDigits = true;
+ }
+
+ if (!hasDigits) return false;
+
+ // if !base60 - done;
+ if (ch !== ':') return true;
+
+ // base60 almost not used, no needs to optimize
+ return /^(:[0-5]?[0-9])+$/.test(data.slice(index));
+}
+
+function constructYamlInteger(data) {
+ var value = data, sign = 1, ch, base, digits = [];
+
+ if (value.indexOf('_') !== -1) {
+ value = value.replace(/_/g, '');
+ }
+
+ ch = value[0];
+
+ if (ch === '-' || ch === '+') {
+ if (ch === '-') sign = -1;
+ value = value.slice(1);
+ ch = value[0];
+ }
+
+ if (value === '0') return 0;
+
+ if (ch === '0') {
+ if (value[1] === 'b') return sign * parseInt(value.slice(2), 2);
+ if (value[1] === 'x') return sign * parseInt(value, 16);
+ return sign * parseInt(value, 8);
+ }
+
+ if (value.indexOf(':') !== -1) {
+ value.split(':').forEach(function (v) {
+ digits.unshift(parseInt(v, 10));
+ });
+
+ value = 0;
+ base = 1;
+
+ digits.forEach(function (d) {
+ value += (d * base);
+ base *= 60;
+ });
+
+ return sign * value;
+
+ }
+
+ return sign * parseInt(value, 10);
+}
+
+function isInteger(object) {
+ return (Object.prototype.toString.call(object)) === '[object Number]' &&
+ (object % 1 === 0 && !common.isNegativeZero(object));
+}
+
+module.exports = new Type('tag:yaml.org,2002:int', {
+ kind: 'scalar',
+ resolve: resolveYamlInteger,
+ construct: constructYamlInteger,
+ predicate: isInteger,
+ represent: {
+ binary: function (object) { return '0b' + object.toString(2); },
+ octal: function (object) { return '0' + object.toString(8); },
+ decimal: function (object) { return object.toString(10); },
+ hexadecimal: function (object) { return '0x' + object.toString(16).toUpperCase(); }
+ },
+ defaultStyle: 'decimal',
+ styleAliases: {
+ binary: [ 2, 'bin' ],
+ octal: [ 8, 'oct' ],
+ decimal: [ 10, 'dec' ],
+ hexadecimal: [ 16, 'hex' ]
+ }
+});
+
+},{"../common":2,"../type":13}],18:[function(require,module,exports){
+'use strict';
+
+var esprima;
+
+// Browserified version does not have esprima
+//
+// 1. For node.js just require module as deps
+// 2. For browser try to require mudule via external AMD system.
+// If not found - try to fallback to window.esprima. If not
+// found too - then fail to parse.
+//
+try {
+ // workaround to exclude package from browserify list.
+ var _require = require;
+ esprima = _require('esprima');
+} catch (_) {
+ /*global window */
+ if (typeof window !== 'undefined') esprima = window.esprima;
+}
+
+var Type = require('../../type');
+
+function resolveJavascriptFunction(data) {
+ if (data === null) return false;
+
+ try {
+ var source = '(' + data + ')',
+ ast = esprima.parse(source, { range: true });
+
+ if (ast.type !== 'Program' ||
+ ast.body.length !== 1 ||
+ ast.body[0].type !== 'ExpressionStatement' ||
+ ast.body[0].expression.type !== 'FunctionExpression') {
+ return false;
+ }
+
+ return true;
+ } catch (err) {
+ return false;
+ }
+}
+
+function constructJavascriptFunction(data) {
+ /*jslint evil:true*/
+
+ var source = '(' + data + ')',
+ ast = esprima.parse(source, { range: true }),
+ params = [],
+ body;
+
+ if (ast.type !== 'Program' ||
+ ast.body.length !== 1 ||
+ ast.body[0].type !== 'ExpressionStatement' ||
+ ast.body[0].expression.type !== 'FunctionExpression') {
+ throw new Error('Failed to resolve function');
+ }
+
+ ast.body[0].expression.params.forEach(function (param) {
+ params.push(param.name);
+ });
+
+ body = ast.body[0].expression.body.range;
+
+ // Esprima's ranges include the first '{' and the last '}' characters on
+ // function expressions. So cut them out.
+ /*eslint-disable no-new-func*/
+ return new Function(params, source.slice(body[0] + 1, body[1] - 1));
+}
+
+function representJavascriptFunction(object /*, style*/) {
+ return object.toString();
+}
+
+function isFunction(object) {
+ return Object.prototype.toString.call(object) === '[object Function]';
+}
+
+module.exports = new Type('tag:yaml.org,2002:js/function', {
+ kind: 'scalar',
+ resolve: resolveJavascriptFunction,
+ construct: constructJavascriptFunction,
+ predicate: isFunction,
+ represent: representJavascriptFunction
+});
+
+},{"../../type":13}],19:[function(require,module,exports){
+'use strict';
+
+var Type = require('../../type');
+
+function resolveJavascriptRegExp(data) {
+ if (data === null) return false;
+ if (data.length === 0) return false;
+
+ var regexp = data,
+ tail = /\/([gim]*)$/.exec(data),
+ modifiers = '';
+
+ // if regexp starts with '/' it can have modifiers and must be properly closed
+ // `/foo/gim` - modifiers tail can be maximum 3 chars
+ if (regexp[0] === '/') {
+ if (tail) modifiers = tail[1];
+
+ if (modifiers.length > 3) return false;
+ // if expression starts with /, is should be properly terminated
+ if (regexp[regexp.length - modifiers.length - 1] !== '/') return false;
+ }
+
+ return true;
+}
+
+function constructJavascriptRegExp(data) {
+ var regexp = data,
+ tail = /\/([gim]*)$/.exec(data),
+ modifiers = '';
+
+ // `/foo/gim` - tail can be maximum 4 chars
+ if (regexp[0] === '/') {
+ if (tail) modifiers = tail[1];
+ regexp = regexp.slice(1, regexp.length - modifiers.length - 1);
+ }
+
+ return new RegExp(regexp, modifiers);
+}
+
+function representJavascriptRegExp(object /*, style*/) {
+ var result = '/' + object.source + '/';
+
+ if (object.global) result += 'g';
+ if (object.multiline) result += 'm';
+ if (object.ignoreCase) result += 'i';
+
+ return result;
+}
+
+function isRegExp(object) {
+ return Object.prototype.toString.call(object) === '[object RegExp]';
+}
+
+module.exports = new Type('tag:yaml.org,2002:js/regexp', {
+ kind: 'scalar',
+ resolve: resolveJavascriptRegExp,
+ construct: constructJavascriptRegExp,
+ predicate: isRegExp,
+ represent: representJavascriptRegExp
+});
+
+},{"../../type":13}],20:[function(require,module,exports){
+'use strict';
+
+var Type = require('../../type');
+
+function resolveJavascriptUndefined() {
+ return true;
+}
+
+function constructJavascriptUndefined() {
+ /*eslint-disable no-undefined*/
+ return undefined;
+}
+
+function representJavascriptUndefined() {
+ return '';
+}
+
+function isUndefined(object) {
+ return typeof object === 'undefined';
+}
+
+module.exports = new Type('tag:yaml.org,2002:js/undefined', {
+ kind: 'scalar',
+ resolve: resolveJavascriptUndefined,
+ construct: constructJavascriptUndefined,
+ predicate: isUndefined,
+ represent: representJavascriptUndefined
+});
+
+},{"../../type":13}],21:[function(require,module,exports){
+'use strict';
+
+var Type = require('../type');
+
+module.exports = new Type('tag:yaml.org,2002:map', {
+ kind: 'mapping',
+ construct: function (data) { return data !== null ? data : {}; }
+});
+
+},{"../type":13}],22:[function(require,module,exports){
+'use strict';
+
+var Type = require('../type');
+
+function resolveYamlMerge(data) {
+ return data === '<<' || data === null;
+}
+
+module.exports = new Type('tag:yaml.org,2002:merge', {
+ kind: 'scalar',
+ resolve: resolveYamlMerge
+});
+
+},{"../type":13}],23:[function(require,module,exports){
+'use strict';
+
+var Type = require('../type');
+
+function resolveYamlNull(data) {
+ if (data === null) return true;
+
+ var max = data.length;
+
+ return (max === 1 && data === '~') ||
+ (max === 4 && (data === 'null' || data === 'Null' || data === 'NULL'));
+}
+
+function constructYamlNull() {
+ return null;
+}
+
+function isNull(object) {
+ return object === null;
+}
+
+module.exports = new Type('tag:yaml.org,2002:null', {
+ kind: 'scalar',
+ resolve: resolveYamlNull,
+ construct: constructYamlNull,
+ predicate: isNull,
+ represent: {
+ canonical: function () { return '~'; },
+ lowercase: function () { return 'null'; },
+ uppercase: function () { return 'NULL'; },
+ camelcase: function () { return 'Null'; }
+ },
+ defaultStyle: 'lowercase'
+});
+
+},{"../type":13}],24:[function(require,module,exports){
+'use strict';
+
+var Type = require('../type');
+
+var _hasOwnProperty = Object.prototype.hasOwnProperty;
+var _toString = Object.prototype.toString;
+
+function resolveYamlOmap(data) {
+ if (data === null) return true;
+
+ var objectKeys = [], index, length, pair, pairKey, pairHasKey,
+ object = data;
+
+ for (index = 0, length = object.length; index < length; index += 1) {
+ pair = object[index];
+ pairHasKey = false;
+
+ if (_toString.call(pair) !== '[object Object]') return false;
+
+ for (pairKey in pair) {
+ if (_hasOwnProperty.call(pair, pairKey)) {
+ if (!pairHasKey) pairHasKey = true;
+ else return false;
+ }
+ }
+
+ if (!pairHasKey) return false;
+
+ if (objectKeys.indexOf(pairKey) === -1) objectKeys.push(pairKey);
+ else return false;
+ }
+
+ return true;
+}
+
+function constructYamlOmap(data) {
+ return data !== null ? data : [];
+}
+
+module.exports = new Type('tag:yaml.org,2002:omap', {
+ kind: 'sequence',
+ resolve: resolveYamlOmap,
+ construct: constructYamlOmap
+});
+
+},{"../type":13}],25:[function(require,module,exports){
+'use strict';
+
+var Type = require('../type');
+
+var _toString = Object.prototype.toString;
+
+function resolveYamlPairs(data) {
+ if (data === null) return true;
+
+ var index, length, pair, keys, result,
+ object = data;
+
+ result = new Array(object.length);
+
+ for (index = 0, length = object.length; index < length; index += 1) {
+ pair = object[index];
+
+ if (_toString.call(pair) !== '[object Object]') return false;
+
+ keys = Object.keys(pair);
+
+ if (keys.length !== 1) return false;
+
+ result[index] = [ keys[0], pair[keys[0]] ];
+ }
+
+ return true;
+}
+
+function constructYamlPairs(data) {
+ if (data === null) return [];
+
+ var index, length, pair, keys, result,
+ object = data;
+
+ result = new Array(object.length);
+
+ for (index = 0, length = object.length; index < length; index += 1) {
+ pair = object[index];
+
+ keys = Object.keys(pair);
+
+ result[index] = [ keys[0], pair[keys[0]] ];
+ }
+
+ return result;
+}
+
+module.exports = new Type('tag:yaml.org,2002:pairs', {
+ kind: 'sequence',
+ resolve: resolveYamlPairs,
+ construct: constructYamlPairs
+});
+
+},{"../type":13}],26:[function(require,module,exports){
+'use strict';
+
+var Type = require('../type');
+
+module.exports = new Type('tag:yaml.org,2002:seq', {
+ kind: 'sequence',
+ construct: function (data) { return data !== null ? data : []; }
+});
+
+},{"../type":13}],27:[function(require,module,exports){
+'use strict';
+
+var Type = require('../type');
+
+var _hasOwnProperty = Object.prototype.hasOwnProperty;
+
+function resolveYamlSet(data) {
+ if (data === null) return true;
+
+ var key, object = data;
+
+ for (key in object) {
+ if (_hasOwnProperty.call(object, key)) {
+ if (object[key] !== null) return false;
+ }
+ }
+
+ return true;
+}
+
+function constructYamlSet(data) {
+ return data !== null ? data : {};
+}
+
+module.exports = new Type('tag:yaml.org,2002:set', {
+ kind: 'mapping',
+ resolve: resolveYamlSet,
+ construct: constructYamlSet
+});
+
+},{"../type":13}],28:[function(require,module,exports){
+'use strict';
+
+var Type = require('../type');
+
+module.exports = new Type('tag:yaml.org,2002:str', {
+ kind: 'scalar',
+ construct: function (data) { return data !== null ? data : ''; }
+});
+
+},{"../type":13}],29:[function(require,module,exports){
+'use strict';
+
+var Type = require('../type');
+
+var YAML_DATE_REGEXP = new RegExp(
+ '^([0-9][0-9][0-9][0-9])' + // [1] year
+ '-([0-9][0-9])' + // [2] month
+ '-([0-9][0-9])$'); // [3] day
+
+var YAML_TIMESTAMP_REGEXP = new RegExp(
+ '^([0-9][0-9][0-9][0-9])' + // [1] year
+ '-([0-9][0-9]?)' + // [2] month
+ '-([0-9][0-9]?)' + // [3] day
+ '(?:[Tt]|[ \\t]+)' + // ...
+ '([0-9][0-9]?)' + // [4] hour
+ ':([0-9][0-9])' + // [5] minute
+ ':([0-9][0-9])' + // [6] second
+ '(?:\\.([0-9]*))?' + // [7] fraction
+ '(?:[ \\t]*(Z|([-+])([0-9][0-9]?)' + // [8] tz [9] tz_sign [10] tz_hour
+ '(?::([0-9][0-9]))?))?$'); // [11] tz_minute
+
+function resolveYamlTimestamp(data) {
+ if (data === null) return false;
+ if (YAML_DATE_REGEXP.exec(data) !== null) return true;
+ if (YAML_TIMESTAMP_REGEXP.exec(data) !== null) return true;
+ return false;
+}
+
+function constructYamlTimestamp(data) {
+ var match, year, month, day, hour, minute, second, fraction = 0,
+ delta = null, tz_hour, tz_minute, date;
+
+ match = YAML_DATE_REGEXP.exec(data);
+ if (match === null) match = YAML_TIMESTAMP_REGEXP.exec(data);
+
+ if (match === null) throw new Error('Date resolve error');
+
+ // match: [1] year [2] month [3] day
+
+ year = +(match[1]);
+ month = +(match[2]) - 1; // JS month starts with 0
+ day = +(match[3]);
+
+ if (!match[4]) { // no hour
+ return new Date(Date.UTC(year, month, day));
+ }
+
+ // match: [4] hour [5] minute [6] second [7] fraction
+
+ hour = +(match[4]);
+ minute = +(match[5]);
+ second = +(match[6]);
+
+ if (match[7]) {
+ fraction = match[7].slice(0, 3);
+ while (fraction.length < 3) { // milli-seconds
+ fraction += '0';
+ }
+ fraction = +fraction;
+ }
+
+ // match: [8] tz [9] tz_sign [10] tz_hour [11] tz_minute
+
+ if (match[9]) {
+ tz_hour = +(match[10]);
+ tz_minute = +(match[11] || 0);
+ delta = (tz_hour * 60 + tz_minute) * 60000; // delta in mili-seconds
+ if (match[9] === '-') delta = -delta;
+ }
+
+ date = new Date(Date.UTC(year, month, day, hour, minute, second, fraction));
+
+ if (delta) date.setTime(date.getTime() - delta);
+
+ return date;
+}
+
+function representYamlTimestamp(object /*, style*/) {
+ return object.toISOString();
+}
+
+module.exports = new Type('tag:yaml.org,2002:timestamp', {
+ kind: 'scalar',
+ resolve: resolveYamlTimestamp,
+ construct: constructYamlTimestamp,
+ instanceOf: Date,
+ represent: representYamlTimestamp
+});
+
+},{"../type":13}],"/":[function(require,module,exports){
+'use strict';
+
+
+var yaml = require('./lib/js-yaml.js');
+
+
+module.exports = yaml;
+
+},{"./lib/js-yaml.js":1}]},{},[])("/")
+}); \ No newline at end of file
diff --git a/node_modules/svgo/node_modules/js-yaml/dist/js-yaml.min.js b/node_modules/svgo/node_modules/js-yaml/dist/js-yaml.min.js
new file mode 100644
index 00000000..211c64ce
--- /dev/null
+++ b/node_modules/svgo/node_modules/js-yaml/dist/js-yaml.min.js
@@ -0,0 +1,3 @@
+/* js-yaml 3.7.0 https://github.com/nodeca/js-yaml */
+!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var t;t="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,t.jsyaml=e()}}(function(){return function e(t,n,i){function r(a,s){if(!n[a]){if(!t[a]){var c="function"==typeof require&&require;if(!s&&c)return c(a,!0);if(o)return o(a,!0);var u=new Error("Cannot find module '"+a+"'");throw u.code="MODULE_NOT_FOUND",u}var l=n[a]={exports:{}};t[a][0].call(l.exports,function(e){var n=t[a][1][e];return r(n?n:e)},l,l.exports,e,t,n,i)}return n[a].exports}for(var o="function"==typeof require&&require,a=0;a<i.length;a++)r(i[a]);return r}({1:[function(e,t,n){"use strict";function i(e){return function(){throw new Error("Function "+e+" is deprecated and cannot be used.")}}var r=e("./js-yaml/loader"),o=e("./js-yaml/dumper");t.exports.Type=e("./js-yaml/type"),t.exports.Schema=e("./js-yaml/schema"),t.exports.FAILSAFE_SCHEMA=e("./js-yaml/schema/failsafe"),t.exports.JSON_SCHEMA=e("./js-yaml/schema/json"),t.exports.CORE_SCHEMA=e("./js-yaml/schema/core"),t.exports.DEFAULT_SAFE_SCHEMA=e("./js-yaml/schema/default_safe"),t.exports.DEFAULT_FULL_SCHEMA=e("./js-yaml/schema/default_full"),t.exports.load=r.load,t.exports.loadAll=r.loadAll,t.exports.safeLoad=r.safeLoad,t.exports.safeLoadAll=r.safeLoadAll,t.exports.dump=o.dump,t.exports.safeDump=o.safeDump,t.exports.YAMLException=e("./js-yaml/exception"),t.exports.MINIMAL_SCHEMA=e("./js-yaml/schema/failsafe"),t.exports.SAFE_SCHEMA=e("./js-yaml/schema/default_safe"),t.exports.DEFAULT_SCHEMA=e("./js-yaml/schema/default_full"),t.exports.scan=i("scan"),t.exports.parse=i("parse"),t.exports.compose=i("compose"),t.exports.addConstructor=i("addConstructor")},{"./js-yaml/dumper":3,"./js-yaml/exception":4,"./js-yaml/loader":5,"./js-yaml/schema":7,"./js-yaml/schema/core":8,"./js-yaml/schema/default_full":9,"./js-yaml/schema/default_safe":10,"./js-yaml/schema/failsafe":11,"./js-yaml/schema/json":12,"./js-yaml/type":13}],2:[function(e,t,n){"use strict";function i(e){return"undefined"==typeof e||null===e}function r(e){return"object"==typeof e&&null!==e}function o(e){return Array.isArray(e)?e:i(e)?[]:[e]}function a(e,t){var n,i,r,o;if(t)for(o=Object.keys(t),n=0,i=o.length;n<i;n+=1)r=o[n],e[r]=t[r];return e}function s(e,t){var n,i="";for(n=0;n<t;n+=1)i+=e;return i}function c(e){return 0===e&&Number.NEGATIVE_INFINITY===1/e}t.exports.isNothing=i,t.exports.isObject=r,t.exports.toArray=o,t.exports.repeat=s,t.exports.isNegativeZero=c,t.exports.extend=a},{}],3:[function(e,t,n){"use strict";function i(e,t){var n,i,r,o,a,s,c;if(null===t)return{};for(n={},i=Object.keys(t),r=0,o=i.length;r<o;r+=1)a=i[r],s=String(t[a]),"!!"===a.slice(0,2)&&(a="tag:yaml.org,2002:"+a.slice(2)),c=e.compiledTypeMap.fallback[a],c&&L.call(c.styleAliases,s)&&(s=c.styleAliases[s]),n[a]=s;return n}function r(e){var t,n,i;if(t=e.toString(16).toUpperCase(),e<=255)n="x",i=2;else if(e<=65535)n="u",i=4;else{if(!(e<=4294967295))throw new N("code point within a string may not be greater than 0xFFFFFFFF");n="U",i=8}return"\\"+n+F.repeat("0",i-t.length)+t}function o(e){this.schema=e.schema||M,this.indent=Math.max(1,e.indent||2),this.skipInvalid=e.skipInvalid||!1,this.flowLevel=F.isNothing(e.flowLevel)?-1:e.flowLevel,this.styleMap=i(this.schema,e.styles||null),this.sortKeys=e.sortKeys||!1,this.lineWidth=e.lineWidth||80,this.noRefs=e.noRefs||!1,this.noCompatMode=e.noCompatMode||!1,this.implicitTypes=this.schema.compiledImplicit,this.explicitTypes=this.schema.compiledExplicit,this.tag=null,this.result="",this.duplicates=[],this.usedDuplicates=null}function a(e,t){for(var n,i=F.repeat(" ",t),r=0,o=-1,a="",s=e.length;r<s;)o=e.indexOf("\n",r),o===-1?(n=e.slice(r),r=s):(n=e.slice(r,o+1),r=o+1),n.length&&"\n"!==n&&(a+=i),a+=n;return a}function s(e,t){return"\n"+F.repeat(" ",e.indent*t)}function c(e,t){var n,i,r;for(n=0,i=e.implicitTypes.length;n<i;n+=1)if(r=e.implicitTypes[n],r.resolve(t))return!0;return!1}function u(e){return e===q||e===D}function l(e){return 32<=e&&e<=126||161<=e&&e<=55295&&8232!==e&&8233!==e||57344<=e&&e<=65533&&65279!==e||65536<=e&&e<=1114111}function p(e){return l(e)&&65279!==e&&e!==H&&e!==Q&&e!==X&&e!==te&&e!==ie&&e!==V&&e!==P}function f(e){return l(e)&&65279!==e&&!u(e)&&e!==G&&e!==z&&e!==V&&e!==H&&e!==Q&&e!==X&&e!==te&&e!==ie&&e!==P&&e!==B&&e!==$&&e!==Y&&e!==ne&&e!==Z&&e!==K&&e!==R&&e!==W&&e!==J&&e!==ee}function d(e,t,n,i,r){var o,a,s=!1,c=!1,d=i!==-1,h=-1,m=f(e.charCodeAt(0))&&!u(e.charCodeAt(e.length-1));if(t)for(o=0;o<e.length;o++){if(a=e.charCodeAt(o),!l(a))return le;m=m&&p(a)}else{for(o=0;o<e.length;o++){if(a=e.charCodeAt(o),a===U)s=!0,d&&(c=c||o-h-1>i&&" "!==e[h+1],h=o);else if(!l(a))return le;m=m&&p(a)}c=c||d&&o-h-1>i&&" "!==e[h+1]}return s||c?" "===e[0]&&n>9?le:c?ue:ce:m&&!r(e)?ae:se}function h(e,t,n,i){e.dump=function(){function r(t){return c(e,t)}if(0===t.length)return"''";if(!e.noCompatMode&&oe.indexOf(t)!==-1)return"'"+t+"'";var o=e.indent*Math.max(1,n),s=e.lineWidth===-1?-1:Math.max(Math.min(e.lineWidth,40),e.lineWidth-o),u=i||e.flowLevel>-1&&n>=e.flowLevel;switch(d(t,u,e.indent,s,r)){case ae:return t;case se:return"'"+t.replace(/'/g,"''")+"'";case ce:return"|"+m(t,e.indent)+g(a(t,o));case ue:return">"+m(t,e.indent)+g(a(y(t,s),o));case le:return'"'+v(t,s)+'"';default:throw new N("impossible error: invalid scalar style")}}()}function m(e,t){var n=" "===e[0]?String(t):"",i="\n"===e[e.length-1],r=i&&("\n"===e[e.length-2]||"\n"===e),o=r?"+":i?"":"-";return n+o+"\n"}function g(e){return"\n"===e[e.length-1]?e.slice(0,-1):e}function y(e,t){for(var n,i,r=/(\n+)([^\n]*)/g,o=function(){var n=e.indexOf("\n");return n=n!==-1?n:e.length,r.lastIndex=n,x(e.slice(0,n),t)}(),a="\n"===e[0]||" "===e[0];i=r.exec(e);){var s=i[1],c=i[2];n=" "===c[0],o+=s+(a||n||""===c?"":"\n")+x(c,t),a=n}return o}function x(e,t){if(""===e||" "===e[0])return e;for(var n,i,r=/ [^ ]/g,o=0,a=0,s=0,c="";n=r.exec(e);)s=n.index,s-o>t&&(i=a>o?a:s,c+="\n"+e.slice(o,i),o=i+1),a=s;return c+="\n",c+=e.length-o>t&&a>o?e.slice(o,a)+"\n"+e.slice(a+1):e.slice(o),c.slice(1)}function v(e){for(var t,n,i="",o=0;o<e.length;o++)t=e.charCodeAt(o),n=re[t],i+=!n&&l(t)?e[o]:n||r(t);return i}function A(e,t,n){var i,r,o="",a=e.tag;for(i=0,r=n.length;i<r;i+=1)j(e,t,n[i],!1,!1)&&(0!==i&&(o+=", "),o+=e.dump);e.tag=a,e.dump="["+o+"]"}function b(e,t,n,i){var r,o,a="",c=e.tag;for(r=0,o=n.length;r<o;r+=1)j(e,t+1,n[r],!0,!0)&&(i&&0===r||(a+=s(e,t)),a+="- "+e.dump);e.tag=c,e.dump=a||"[]"}function w(e,t,n){var i,r,o,a,s,c="",u=e.tag,l=Object.keys(n);for(i=0,r=l.length;i<r;i+=1)s="",0!==i&&(s+=", "),o=l[i],a=n[o],j(e,t,o,!1,!1)&&(e.dump.length>1024&&(s+="? "),s+=e.dump+": ",j(e,t,a,!1,!1)&&(s+=e.dump,c+=s));e.tag=u,e.dump="{"+c+"}"}function C(e,t,n,i){var r,o,a,c,u,l,p="",f=e.tag,d=Object.keys(n);if(e.sortKeys===!0)d.sort();else if("function"==typeof e.sortKeys)d.sort(e.sortKeys);else if(e.sortKeys)throw new N("sortKeys must be a boolean or a function");for(r=0,o=d.length;r<o;r+=1)l="",i&&0===r||(l+=s(e,t)),a=d[r],c=n[a],j(e,t+1,a,!0,!0,!0)&&(u=null!==e.tag&&"?"!==e.tag||e.dump&&e.dump.length>1024,u&&(l+=e.dump&&U===e.dump.charCodeAt(0)?"?":"? "),l+=e.dump,u&&(l+=s(e,t)),j(e,t+1,c,!0,u)&&(l+=e.dump&&U===e.dump.charCodeAt(0)?":":": ",l+=e.dump,p+=l));e.tag=f,e.dump=p||"{}"}function k(e,t,n){var i,r,o,a,s,c;for(r=n?e.explicitTypes:e.implicitTypes,o=0,a=r.length;o<a;o+=1)if(s=r[o],(s.instanceOf||s.predicate)&&(!s.instanceOf||"object"==typeof t&&t instanceof s.instanceOf)&&(!s.predicate||s.predicate(t))){if(e.tag=n?s.tag:"?",s.represent){if(c=e.styleMap[s.tag]||s.defaultStyle,"[object Function]"===T.call(s.represent))i=s.represent(t,c);else{if(!L.call(s.represent,c))throw new N("!<"+s.tag+'> tag resolver accepts not "'+c+'" style');i=s.represent[c](t,c)}e.dump=i}return!0}return!1}function j(e,t,n,i,r,o){e.tag=null,e.dump=n,k(e,n,!1)||k(e,n,!0);var a=T.call(e.dump);i&&(i=e.flowLevel<0||e.flowLevel>t);var s,c,u="[object Object]"===a||"[object Array]"===a;if(u&&(s=e.duplicates.indexOf(n),c=s!==-1),(null!==e.tag&&"?"!==e.tag||c||2!==e.indent&&t>0)&&(r=!1),c&&e.usedDuplicates[s])e.dump="*ref_"+s;else{if(u&&c&&!e.usedDuplicates[s]&&(e.usedDuplicates[s]=!0),"[object Object]"===a)i&&0!==Object.keys(e.dump).length?(C(e,t,e.dump,r),c&&(e.dump="&ref_"+s+e.dump)):(w(e,t,e.dump),c&&(e.dump="&ref_"+s+" "+e.dump));else if("[object Array]"===a)i&&0!==e.dump.length?(b(e,t,e.dump,r),c&&(e.dump="&ref_"+s+e.dump)):(A(e,t,e.dump),c&&(e.dump="&ref_"+s+" "+e.dump));else{if("[object String]"!==a){if(e.skipInvalid)return!1;throw new N("unacceptable kind of an object to dump "+a)}"?"!==e.tag&&h(e,e.dump,t,o)}null!==e.tag&&"?"!==e.tag&&(e.dump="!<"+e.tag+"> "+e.dump)}return!0}function I(e,t){var n,i,r=[],o=[];for(S(e,r,o),n=0,i=o.length;n<i;n+=1)t.duplicates.push(r[o[n]]);t.usedDuplicates=new Array(i)}function S(e,t,n){var i,r,o;if(null!==e&&"object"==typeof e)if(r=t.indexOf(e),r!==-1)n.indexOf(r)===-1&&n.push(r);else if(t.push(e),Array.isArray(e))for(r=0,o=e.length;r<o;r+=1)S(e[r],t,n);else for(i=Object.keys(e),r=0,o=i.length;r<o;r+=1)S(e[i[r]],t,n)}function O(e,t){t=t||{};var n=new o(t);return n.noRefs||I(e,n),j(n,0,e,!0,!0)?n.dump+"\n":""}function E(e,t){return O(e,F.extend({schema:_},t))}var F=e("./common"),N=e("./exception"),M=e("./schema/default_full"),_=e("./schema/default_safe"),T=Object.prototype.toString,L=Object.prototype.hasOwnProperty,D=9,U=10,q=32,Y=33,R=34,P=35,W=37,B=38,K=39,$=42,H=44,G=45,V=58,Z=62,z=63,J=64,Q=91,X=93,ee=96,te=123,ne=124,ie=125,re={};re[0]="\\0",re[7]="\\a",re[8]="\\b",re[9]="\\t",re[10]="\\n",re[11]="\\v",re[12]="\\f",re[13]="\\r",re[27]="\\e",re[34]='\\"',re[92]="\\\\",re[133]="\\N",re[160]="\\_",re[8232]="\\L",re[8233]="\\P";var oe=["y","Y","yes","Yes","YES","on","On","ON","n","N","no","No","NO","off","Off","OFF"],ae=1,se=2,ce=3,ue=4,le=5;t.exports.dump=O,t.exports.safeDump=E},{"./common":2,"./exception":4,"./schema/default_full":9,"./schema/default_safe":10}],4:[function(e,t,n){"use strict";function i(e,t){Error.call(this),Error.captureStackTrace?Error.captureStackTrace(this,this.constructor):this.stack=(new Error).stack||"",this.name="YAMLException",this.reason=e,this.mark=t,this.message=(this.reason||"(unknown reason)")+(this.mark?" "+this.mark.toString():"")}i.prototype=Object.create(Error.prototype),i.prototype.constructor=i,i.prototype.toString=function(e){var t=this.name+": ";return t+=this.reason||"(unknown reason)",!e&&this.mark&&(t+=" "+this.mark.toString()),t},t.exports=i},{}],5:[function(e,t,n){"use strict";function i(e){return 10===e||13===e}function r(e){return 9===e||32===e}function o(e){return 9===e||32===e||10===e||13===e}function a(e){return 44===e||91===e||93===e||123===e||125===e}function s(e){var t;return 48<=e&&e<=57?e-48:(t=32|e,97<=t&&t<=102?t-97+10:-1)}function c(e){return 120===e?2:117===e?4:85===e?8:0}function u(e){return 48<=e&&e<=57?e-48:-1}function l(e){return 48===e?"\0":97===e?"":98===e?"\b":116===e?"\t":9===e?"\t":110===e?"\n":118===e?"\v":102===e?"\f":114===e?"\r":101===e?"":32===e?" ":34===e?'"':47===e?"/":92===e?"\\":78===e?"…":95===e?" ":76===e?"\u2028":80===e?"\u2029":""}function p(e){return e<=65535?String.fromCharCode(e):String.fromCharCode((e-65536>>10)+55296,(e-65536&1023)+56320)}function f(e,t){this.input=e,this.filename=t.filename||null,this.schema=t.schema||K,this.onWarning=t.onWarning||null,this.legacy=t.legacy||!1,this.json=t.json||!1,this.listener=t.listener||null,this.implicitTypes=this.schema.compiledImplicit,this.typeMap=this.schema.compiledTypeMap,this.length=e.length,this.position=0,this.line=0,this.lineStart=0,this.lineIndent=0,this.documents=[]}function d(e,t){return new P(t,new W(e.filename,e.input,e.position,e.line,e.position-e.lineStart))}function h(e,t){throw d(e,t)}function m(e,t){e.onWarning&&e.onWarning.call(null,d(e,t))}function g(e,t,n,i){var r,o,a,s;if(t<n){if(s=e.input.slice(t,n),i)for(r=0,o=s.length;r<o;r+=1)a=s.charCodeAt(r),9===a||32<=a&&a<=1114111||h(e,"expected valid JSON character");else X.test(s)&&h(e,"the stream contains non-printable characters");e.result+=s}}function y(e,t,n,i){var r,o,a,s;for(R.isObject(n)||h(e,"cannot merge mappings; the provided source object is unacceptable"),r=Object.keys(n),a=0,s=r.length;a<s;a+=1)o=r[a],$.call(t,o)||(t[o]=n[o],i[o]=!0)}function x(e,t,n,i,r,o){var a,s;if(r=String(r),null===t&&(t={}),"tag:yaml.org,2002:merge"===i)if(Array.isArray(o))for(a=0,s=o.length;a<s;a+=1)y(e,t,o[a],n);else y(e,t,o,n);else e.json||$.call(n,r)||!$.call(t,r)||h(e,"duplicated mapping key"),t[r]=o,delete n[r];return t}function v(e){var t;t=e.input.charCodeAt(e.position),10===t?e.position++:13===t?(e.position++,10===e.input.charCodeAt(e.position)&&e.position++):h(e,"a line break is expected"),e.line+=1,e.lineStart=e.position}function A(e,t,n){for(var o=0,a=e.input.charCodeAt(e.position);0!==a;){for(;r(a);)a=e.input.charCodeAt(++e.position);if(t&&35===a)do a=e.input.charCodeAt(++e.position);while(10!==a&&13!==a&&0!==a);if(!i(a))break;for(v(e),a=e.input.charCodeAt(e.position),o++,e.lineIndent=0;32===a;)e.lineIndent++,a=e.input.charCodeAt(++e.position)}return n!==-1&&0!==o&&e.lineIndent<n&&m(e,"deficient indentation"),o}function b(e){var t,n=e.position;return t=e.input.charCodeAt(n),!(45!==t&&46!==t||t!==e.input.charCodeAt(n+1)||t!==e.input.charCodeAt(n+2)||(n+=3,t=e.input.charCodeAt(n),0!==t&&!o(t)))}function w(e,t){1===t?e.result+=" ":t>1&&(e.result+=R.repeat("\n",t-1))}function C(e,t,n){var s,c,u,l,p,f,d,h,m,y=e.kind,x=e.result;if(m=e.input.charCodeAt(e.position),o(m)||a(m)||35===m||38===m||42===m||33===m||124===m||62===m||39===m||34===m||37===m||64===m||96===m)return!1;if((63===m||45===m)&&(c=e.input.charCodeAt(e.position+1),o(c)||n&&a(c)))return!1;for(e.kind="scalar",e.result="",u=l=e.position,p=!1;0!==m;){if(58===m){if(c=e.input.charCodeAt(e.position+1),o(c)||n&&a(c))break}else if(35===m){if(s=e.input.charCodeAt(e.position-1),o(s))break}else{if(e.position===e.lineStart&&b(e)||n&&a(m))break;if(i(m)){if(f=e.line,d=e.lineStart,h=e.lineIndent,A(e,!1,-1),e.lineIndent>=t){p=!0,m=e.input.charCodeAt(e.position);continue}e.position=l,e.line=f,e.lineStart=d,e.lineIndent=h;break}}p&&(g(e,u,l,!1),w(e,e.line-f),u=l=e.position,p=!1),r(m)||(l=e.position+1),m=e.input.charCodeAt(++e.position)}return g(e,u,l,!1),!!e.result||(e.kind=y,e.result=x,!1)}function k(e,t){var n,r,o;if(n=e.input.charCodeAt(e.position),39!==n)return!1;for(e.kind="scalar",e.result="",e.position++,r=o=e.position;0!==(n=e.input.charCodeAt(e.position));)if(39===n){if(g(e,r,e.position,!0),n=e.input.charCodeAt(++e.position),39!==n)return!0;r=e.position,e.position++,o=e.position}else i(n)?(g(e,r,o,!0),w(e,A(e,!1,t)),r=o=e.position):e.position===e.lineStart&&b(e)?h(e,"unexpected end of the document within a single quoted scalar"):(e.position++,o=e.position);h(e,"unexpected end of the stream within a single quoted scalar")}function j(e,t){var n,r,o,a,u,l;if(l=e.input.charCodeAt(e.position),34!==l)return!1;for(e.kind="scalar",e.result="",e.position++,n=r=e.position;0!==(l=e.input.charCodeAt(e.position));){if(34===l)return g(e,n,e.position,!0),e.position++,!0;if(92===l){if(g(e,n,e.position,!0),l=e.input.charCodeAt(++e.position),i(l))A(e,!1,t);else if(l<256&&re[l])e.result+=oe[l],e.position++;else if((u=c(l))>0){for(o=u,a=0;o>0;o--)l=e.input.charCodeAt(++e.position),(u=s(l))>=0?a=(a<<4)+u:h(e,"expected hexadecimal character");e.result+=p(a),e.position++}else h(e,"unknown escape sequence");n=r=e.position}else i(l)?(g(e,n,r,!0),w(e,A(e,!1,t)),n=r=e.position):e.position===e.lineStart&&b(e)?h(e,"unexpected end of the document within a double quoted scalar"):(e.position++,r=e.position)}h(e,"unexpected end of the stream within a double quoted scalar")}function I(e,t){var n,i,r,a,s,c,u,l,p,f,d,m=!0,g=e.tag,y=e.anchor,v={};if(d=e.input.charCodeAt(e.position),91===d)a=93,u=!1,i=[];else{if(123!==d)return!1;a=125,u=!0,i={}}for(null!==e.anchor&&(e.anchorMap[e.anchor]=i),d=e.input.charCodeAt(++e.position);0!==d;){if(A(e,!0,t),d=e.input.charCodeAt(e.position),d===a)return e.position++,e.tag=g,e.anchor=y,e.kind=u?"mapping":"sequence",e.result=i,!0;m||h(e,"missed comma between flow collection entries"),p=l=f=null,s=c=!1,63===d&&(r=e.input.charCodeAt(e.position+1),o(r)&&(s=c=!0,e.position++,A(e,!0,t))),n=e.line,_(e,t,H,!1,!0),p=e.tag,l=e.result,A(e,!0,t),d=e.input.charCodeAt(e.position),!c&&e.line!==n||58!==d||(s=!0,d=e.input.charCodeAt(++e.position),A(e,!0,t),_(e,t,H,!1,!0),f=e.result),u?x(e,i,v,p,l,f):s?i.push(x(e,null,v,p,l,f)):i.push(l),A(e,!0,t),d=e.input.charCodeAt(e.position),44===d?(m=!0,d=e.input.charCodeAt(++e.position)):m=!1}h(e,"unexpected end of the stream within a flow collection")}function S(e,t){var n,o,a,s,c=z,l=!1,p=!1,f=t,d=0,m=!1;if(s=e.input.charCodeAt(e.position),124===s)o=!1;else{if(62!==s)return!1;o=!0}for(e.kind="scalar",e.result="";0!==s;)if(s=e.input.charCodeAt(++e.position),43===s||45===s)z===c?c=43===s?Q:J:h(e,"repeat of a chomping mode identifier");else{if(!((a=u(s))>=0))break;0===a?h(e,"bad explicit indentation width of a block scalar; it cannot be less than one"):p?h(e,"repeat of an indentation width identifier"):(f=t+a-1,p=!0)}if(r(s)){do s=e.input.charCodeAt(++e.position);while(r(s));if(35===s)do s=e.input.charCodeAt(++e.position);while(!i(s)&&0!==s)}for(;0!==s;){for(v(e),e.lineIndent=0,s=e.input.charCodeAt(e.position);(!p||e.lineIndent<f)&&32===s;)e.lineIndent++,s=e.input.charCodeAt(++e.position);if(!p&&e.lineIndent>f&&(f=e.lineIndent),i(s))d++;else{if(e.lineIndent<f){c===Q?e.result+=R.repeat("\n",l?1+d:d):c===z&&l&&(e.result+="\n");break}for(o?r(s)?(m=!0,e.result+=R.repeat("\n",l?1+d:d)):m?(m=!1,e.result+=R.repeat("\n",d+1)):0===d?l&&(e.result+=" "):e.result+=R.repeat("\n",d):e.result+=R.repeat("\n",l?1+d:d),l=!0,p=!0,d=0,n=e.position;!i(s)&&0!==s;)s=e.input.charCodeAt(++e.position);g(e,n,e.position,!1)}}return!0}function O(e,t){var n,i,r,a=e.tag,s=e.anchor,c=[],u=!1;for(null!==e.anchor&&(e.anchorMap[e.anchor]=c),r=e.input.charCodeAt(e.position);0!==r&&45===r&&(i=e.input.charCodeAt(e.position+1),o(i));)if(u=!0,e.position++,A(e,!0,-1)&&e.lineIndent<=t)c.push(null),r=e.input.charCodeAt(e.position);else if(n=e.line,_(e,t,V,!1,!0),c.push(e.result),A(e,!0,-1),r=e.input.charCodeAt(e.position),(e.line===n||e.lineIndent>t)&&0!==r)h(e,"bad indentation of a sequence entry");else if(e.lineIndent<t)break;return!!u&&(e.tag=a,e.anchor=s,e.kind="sequence",e.result=c,!0)}function E(e,t,n){var i,a,s,c,u=e.tag,l=e.anchor,p={},f={},d=null,m=null,g=null,y=!1,v=!1;for(null!==e.anchor&&(e.anchorMap[e.anchor]=p),c=e.input.charCodeAt(e.position);0!==c;){if(i=e.input.charCodeAt(e.position+1),s=e.line,63!==c&&58!==c||!o(i)){if(!_(e,n,G,!1,!0))break;if(e.line===s){for(c=e.input.charCodeAt(e.position);r(c);)c=e.input.charCodeAt(++e.position);if(58===c)c=e.input.charCodeAt(++e.position),o(c)||h(e,"a whitespace character is expected after the key-value separator within a block mapping"),y&&(x(e,p,f,d,m,null),d=m=g=null),v=!0,y=!1,a=!1,d=e.tag,m=e.result;else{if(!v)return e.tag=u,e.anchor=l,!0;h(e,"can not read an implicit mapping pair; a colon is missed")}}else{if(!v)return e.tag=u,e.anchor=l,!0;h(e,"can not read a block mapping entry; a multiline key may not be an implicit key")}}else 63===c?(y&&(x(e,p,f,d,m,null),d=m=g=null),v=!0,y=!0,a=!0):y?(y=!1,a=!0):h(e,"incomplete explicit mapping pair; a key node is missed"),e.position+=1,c=i;if((e.line===s||e.lineIndent>t)&&(_(e,t,Z,!0,a)&&(y?m=e.result:g=e.result),y||(x(e,p,f,d,m,g),d=m=g=null),A(e,!0,-1),c=e.input.charCodeAt(e.position)),e.lineIndent>t&&0!==c)h(e,"bad indentation of a mapping entry");else if(e.lineIndent<t)break}return y&&x(e,p,f,d,m,null),v&&(e.tag=u,e.anchor=l,e.kind="mapping",e.result=p),v}function F(e){var t,n,i,r,a=!1,s=!1;if(r=e.input.charCodeAt(e.position),33!==r)return!1;if(null!==e.tag&&h(e,"duplication of a tag property"),r=e.input.charCodeAt(++e.position),60===r?(a=!0,r=e.input.charCodeAt(++e.position)):33===r?(s=!0,n="!!",r=e.input.charCodeAt(++e.position)):n="!",t=e.position,a){do r=e.input.charCodeAt(++e.position);while(0!==r&&62!==r);e.position<e.length?(i=e.input.slice(t,e.position),r=e.input.charCodeAt(++e.position)):h(e,"unexpected end of the stream within a verbatim tag")}else{for(;0!==r&&!o(r);)33===r&&(s?h(e,"tag suffix cannot contain exclamation marks"):(n=e.input.slice(t-1,e.position+1),ne.test(n)||h(e,"named tag handle cannot contain such characters"),s=!0,t=e.position+1)),r=e.input.charCodeAt(++e.position);i=e.input.slice(t,e.position),te.test(i)&&h(e,"tag suffix cannot contain flow indicator characters")}return i&&!ie.test(i)&&h(e,"tag name cannot contain such characters: "+i),a?e.tag=i:$.call(e.tagMap,n)?e.tag=e.tagMap[n]+i:"!"===n?e.tag="!"+i:"!!"===n?e.tag="tag:yaml.org,2002:"+i:h(e,'undeclared tag handle "'+n+'"'),!0}function N(e){var t,n;if(n=e.input.charCodeAt(e.position),38!==n)return!1;for(null!==e.anchor&&h(e,"duplication of an anchor property"),n=e.input.charCodeAt(++e.position),t=e.position;0!==n&&!o(n)&&!a(n);)n=e.input.charCodeAt(++e.position);return e.position===t&&h(e,"name of an anchor node must contain at least one character"),e.anchor=e.input.slice(t,e.position),!0}function M(e){var t,n,i;if(i=e.input.charCodeAt(e.position),42!==i)return!1;for(i=e.input.charCodeAt(++e.position),t=e.position;0!==i&&!o(i)&&!a(i);)i=e.input.charCodeAt(++e.position);return e.position===t&&h(e,"name of an alias node must contain at least one character"),n=e.input.slice(t,e.position),e.anchorMap.hasOwnProperty(n)||h(e,'unidentified alias "'+n+'"'),e.result=e.anchorMap[n],A(e,!0,-1),!0}function _(e,t,n,i,r){var o,a,s,c,u,l,p,f,d=1,m=!1,g=!1;if(null!==e.listener&&e.listener("open",e),e.tag=null,e.anchor=null,e.kind=null,e.result=null,o=a=s=Z===n||V===n,i&&A(e,!0,-1)&&(m=!0,e.lineIndent>t?d=1:e.lineIndent===t?d=0:e.lineIndent<t&&(d=-1)),1===d)for(;F(e)||N(e);)A(e,!0,-1)?(m=!0,s=o,e.lineIndent>t?d=1:e.lineIndent===t?d=0:e.lineIndent<t&&(d=-1)):s=!1;if(s&&(s=m||r),1!==d&&Z!==n||(p=H===n||G===n?t:t+1,f=e.position-e.lineStart,1===d?s&&(O(e,f)||E(e,f,p))||I(e,p)?g=!0:(a&&S(e,p)||k(e,p)||j(e,p)?g=!0:M(e)?(g=!0,null===e.tag&&null===e.anchor||h(e,"alias node should not have any properties")):C(e,p,H===n)&&(g=!0,null===e.tag&&(e.tag="?")),null!==e.anchor&&(e.anchorMap[e.anchor]=e.result)):0===d&&(g=s&&O(e,f))),null!==e.tag&&"!"!==e.tag)if("?"===e.tag){for(c=0,u=e.implicitTypes.length;c<u;c+=1)if(l=e.implicitTypes[c],l.resolve(e.result)){e.result=l.construct(e.result),e.tag=l.tag,null!==e.anchor&&(e.anchorMap[e.anchor]=e.result);break}}else $.call(e.typeMap[e.kind||"fallback"],e.tag)?(l=e.typeMap[e.kind||"fallback"][e.tag],null!==e.result&&l.kind!==e.kind&&h(e,"unacceptable node kind for !<"+e.tag+'> tag; it should be "'+l.kind+'", not "'+e.kind+'"'),l.resolve(e.result)?(e.result=l.construct(e.result),null!==e.anchor&&(e.anchorMap[e.anchor]=e.result)):h(e,"cannot resolve a node with !<"+e.tag+"> explicit tag")):h(e,"unknown tag !<"+e.tag+">");return null!==e.listener&&e.listener("close",e),null!==e.tag||null!==e.anchor||g}function T(e){var t,n,a,s,c=e.position,u=!1;for(e.version=null,e.checkLineBreaks=e.legacy,e.tagMap={},e.anchorMap={};0!==(s=e.input.charCodeAt(e.position))&&(A(e,!0,-1),s=e.input.charCodeAt(e.position),!(e.lineIndent>0||37!==s));){for(u=!0,s=e.input.charCodeAt(++e.position),t=e.position;0!==s&&!o(s);)s=e.input.charCodeAt(++e.position);for(n=e.input.slice(t,e.position),a=[],n.length<1&&h(e,"directive name must not be less than one character in length");0!==s;){for(;r(s);)s=e.input.charCodeAt(++e.position);if(35===s){do s=e.input.charCodeAt(++e.position);while(0!==s&&!i(s));break}if(i(s))break;for(t=e.position;0!==s&&!o(s);)s=e.input.charCodeAt(++e.position);a.push(e.input.slice(t,e.position))}0!==s&&v(e),$.call(se,n)?se[n](e,n,a):m(e,'unknown document directive "'+n+'"')}return A(e,!0,-1),0===e.lineIndent&&45===e.input.charCodeAt(e.position)&&45===e.input.charCodeAt(e.position+1)&&45===e.input.charCodeAt(e.position+2)?(e.position+=3,A(e,!0,-1)):u&&h(e,"directives end mark is expected"),_(e,e.lineIndent-1,Z,!1,!0),A(e,!0,-1),e.checkLineBreaks&&ee.test(e.input.slice(c,e.position))&&m(e,"non-ASCII line breaks are interpreted as content"),e.documents.push(e.result),e.position===e.lineStart&&b(e)?void(46===e.input.charCodeAt(e.position)&&(e.position+=3,A(e,!0,-1))):void(e.position<e.length-1&&h(e,"end of the stream or a document separator is expected"))}function L(e,t){e=String(e),t=t||{},0!==e.length&&(10!==e.charCodeAt(e.length-1)&&13!==e.charCodeAt(e.length-1)&&(e+="\n"),65279===e.charCodeAt(0)&&(e=e.slice(1)));var n=new f(e,t);for(n.input+="\0";32===n.input.charCodeAt(n.position);)n.lineIndent+=1,n.position+=1;for(;n.position<n.length-1;)T(n);return n.documents}function D(e,t,n){var i,r,o=L(e,n);for(i=0,r=o.length;i<r;i+=1)t(o[i])}function U(e,t){var n=L(e,t);if(0!==n.length){if(1===n.length)return n[0];throw new P("expected a single document in the stream, but found more")}}function q(e,t,n){D(e,t,R.extend({schema:B},n))}function Y(e,t){return U(e,R.extend({schema:B},t))}for(var R=e("./common"),P=e("./exception"),W=e("./mark"),B=e("./schema/default_safe"),K=e("./schema/default_full"),$=Object.prototype.hasOwnProperty,H=1,G=2,V=3,Z=4,z=1,J=2,Q=3,X=/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x84\x86-\x9F\uFFFE\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]/,ee=/[\x85\u2028\u2029]/,te=/[,\[\]\{\}]/,ne=/^(?:!|!!|![a-z\-]+!)$/i,ie=/^(?:!|[^,\[\]\{\}])(?:%[0-9a-f]{2}|[0-9a-z\-#;\/\?:@&=\+\$,_\.!~\*'\(\)\[\]])*$/i,re=new Array(256),oe=new Array(256),ae=0;ae<256;ae++)re[ae]=l(ae)?1:0,oe[ae]=l(ae);var se={YAML:function(e,t,n){var i,r,o;null!==e.version&&h(e,"duplication of %YAML directive"),1!==n.length&&h(e,"YAML directive accepts exactly one argument"),i=/^([0-9]+)\.([0-9]+)$/.exec(n[0]),null===i&&h(e,"ill-formed argument of the YAML directive"),r=parseInt(i[1],10),o=parseInt(i[2],10),1!==r&&h(e,"unacceptable YAML version of the document"),e.version=n[0],e.checkLineBreaks=o<2,1!==o&&2!==o&&m(e,"unsupported YAML version of the document")},TAG:function(e,t,n){var i,r;2!==n.length&&h(e,"TAG directive accepts exactly two arguments"),i=n[0],r=n[1],ne.test(i)||h(e,"ill-formed tag handle (first argument) of the TAG directive"),$.call(e.tagMap,i)&&h(e,'there is a previously declared suffix for "'+i+'" tag handle'),ie.test(r)||h(e,"ill-formed tag prefix (second argument) of the TAG directive"),e.tagMap[i]=r}};t.exports.loadAll=D,t.exports.load=U,t.exports.safeLoadAll=q,t.exports.safeLoad=Y},{"./common":2,"./exception":4,"./mark":6,"./schema/default_full":9,"./schema/default_safe":10}],6:[function(e,t,n){"use strict";function i(e,t,n,i,r){this.name=e,this.buffer=t,this.position=n,this.line=i,this.column=r}var r=e("./common");i.prototype.getSnippet=function(e,t){var n,i,o,a,s;if(!this.buffer)return null;for(e=e||4,t=t||75,n="",i=this.position;i>0&&"\0\r\n…\u2028\u2029".indexOf(this.buffer.charAt(i-1))===-1;)if(i-=1,this.position-i>t/2-1){n=" ... ",i+=5;break}for(o="",a=this.position;a<this.buffer.length&&"\0\r\n…\u2028\u2029".indexOf(this.buffer.charAt(a))===-1;)if(a+=1,a-this.position>t/2-1){o=" ... ",a-=5;break}return s=this.buffer.slice(i,a),r.repeat(" ",e)+n+s+o+"\n"+r.repeat(" ",e+this.position-i+n.length)+"^"},i.prototype.toString=function(e){var t,n="";return this.name&&(n+='in "'+this.name+'" '),n+="at line "+(this.line+1)+", column "+(this.column+1),e||(t=this.getSnippet(),t&&(n+=":\n"+t)),n},t.exports=i},{"./common":2}],7:[function(e,t,n){"use strict";function i(e,t,n){var r=[];return e.include.forEach(function(e){n=i(e,t,n)}),e[t].forEach(function(e){n.forEach(function(t,n){t.tag===e.tag&&t.kind===e.kind&&r.push(n)}),n.push(e)}),n.filter(function(e,t){return r.indexOf(t)===-1})}function r(){function e(e){i[e.kind][e.tag]=i.fallback[e.tag]=e}var t,n,i={scalar:{},sequence:{},mapping:{},fallback:{}};for(t=0,n=arguments.length;t<n;t+=1)arguments[t].forEach(e);return i}function o(e){this.include=e.include||[],this.implicit=e.implicit||[],this.explicit=e.explicit||[],this.implicit.forEach(function(e){if(e.loadKind&&"scalar"!==e.loadKind)throw new s("There is a non-scalar type in the implicit list of a schema. Implicit resolving of such types is not supported.")}),this.compiledImplicit=i(this,"implicit",[]),this.compiledExplicit=i(this,"explicit",[]),this.compiledTypeMap=r(this.compiledImplicit,this.compiledExplicit)}var a=e("./common"),s=e("./exception"),c=e("./type");o.DEFAULT=null,o.create=function(){var e,t;switch(arguments.length){case 1:e=o.DEFAULT,t=arguments[0];break;case 2:e=arguments[0],t=arguments[1];break;default:throw new s("Wrong number of arguments for Schema.create function")}if(e=a.toArray(e),t=a.toArray(t),!e.every(function(e){return e instanceof o}))throw new s("Specified list of super schemas (or a single Schema object) contains a non-Schema object.");if(!t.every(function(e){return e instanceof c}))throw new s("Specified list of YAML types (or a single Type object) contains a non-Type object.");return new o({include:e,explicit:t})},t.exports=o},{"./common":2,"./exception":4,"./type":13}],8:[function(e,t,n){"use strict";var i=e("../schema");t.exports=new i({include:[e("./json")]})},{"../schema":7,"./json":12}],9:[function(e,t,n){"use strict";var i=e("../schema");t.exports=i.DEFAULT=new i({include:[e("./default_safe")],explicit:[e("../type/js/undefined"),e("../type/js/regexp"),e("../type/js/function")]})},{"../schema":7,"../type/js/function":18,"../type/js/regexp":19,"../type/js/undefined":20,"./default_safe":10}],10:[function(e,t,n){"use strict";var i=e("../schema");t.exports=new i({include:[e("./core")],implicit:[e("../type/timestamp"),e("../type/merge")],explicit:[e("../type/binary"),e("../type/omap"),e("../type/pairs"),e("../type/set")]})},{"../schema":7,"../type/binary":14,"../type/merge":22,"../type/omap":24,"../type/pairs":25,"../type/set":27,"../type/timestamp":29,"./core":8}],11:[function(e,t,n){"use strict";var i=e("../schema");t.exports=new i({explicit:[e("../type/str"),e("../type/seq"),e("../type/map")]})},{"../schema":7,"../type/map":21,"../type/seq":26,"../type/str":28}],12:[function(e,t,n){"use strict";var i=e("../schema");t.exports=new i({include:[e("./failsafe")],implicit:[e("../type/null"),e("../type/bool"),e("../type/int"),e("../type/float")]})},{"../schema":7,"../type/bool":15,"../type/float":16,"../type/int":17,"../type/null":23,"./failsafe":11}],13:[function(e,t,n){"use strict";function i(e){var t={};return null!==e&&Object.keys(e).forEach(function(n){e[n].forEach(function(e){t[String(e)]=n})}),t}function r(e,t){if(t=t||{},Object.keys(t).forEach(function(t){if(a.indexOf(t)===-1)throw new o('Unknown option "'+t+'" is met in definition of "'+e+'" YAML type.')}),this.tag=e,this.kind=t.kind||null,this.resolve=t.resolve||function(){return!0},this.construct=t.construct||function(e){return e},this.instanceOf=t.instanceOf||null,this.predicate=t.predicate||null,this.represent=t.represent||null,this.defaultStyle=t.defaultStyle||null,this.styleAliases=i(t.styleAliases||null),s.indexOf(this.kind)===-1)throw new o('Unknown kind "'+this.kind+'" is specified for "'+e+'" YAML type.')}var o=e("./exception"),a=["kind","resolve","construct","instanceOf","predicate","represent","defaultStyle","styleAliases"],s=["scalar","sequence","mapping"];t.exports=r},{"./exception":4}],14:[function(e,t,n){"use strict";function i(e){if(null===e)return!1;var t,n,i=0,r=e.length,o=l;for(n=0;n<r;n++)if(t=o.indexOf(e.charAt(n)),!(t>64)){if(t<0)return!1;i+=6}return i%8===0}function r(e){var t,n,i=e.replace(/[\r\n=]/g,""),r=i.length,o=l,a=0,c=[];for(t=0;t<r;t++)t%4===0&&t&&(c.push(a>>16&255),c.push(a>>8&255),c.push(255&a)),a=a<<6|o.indexOf(i.charAt(t));return n=r%4*6,0===n?(c.push(a>>16&255),c.push(a>>8&255),c.push(255&a)):18===n?(c.push(a>>10&255),c.push(a>>2&255)):12===n&&c.push(a>>4&255),s?new s(c):c}function o(e){var t,n,i="",r=0,o=e.length,a=l;for(t=0;t<o;t++)t%3===0&&t&&(i+=a[r>>18&63],i+=a[r>>12&63],i+=a[r>>6&63],i+=a[63&r]),r=(r<<8)+e[t];return n=o%3,0===n?(i+=a[r>>18&63],i+=a[r>>12&63],i+=a[r>>6&63],i+=a[63&r]):2===n?(i+=a[r>>10&63],i+=a[r>>4&63],
+i+=a[r<<2&63],i+=a[64]):1===n&&(i+=a[r>>2&63],i+=a[r<<4&63],i+=a[64],i+=a[64]),i}function a(e){return s&&s.isBuffer(e)}var s;try{var c=e;s=c("buffer").Buffer}catch(e){}var u=e("../type"),l="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\n\r";t.exports=new u("tag:yaml.org,2002:binary",{kind:"scalar",resolve:i,construct:r,predicate:a,represent:o})},{"../type":13}],15:[function(e,t,n){"use strict";function i(e){if(null===e)return!1;var t=e.length;return 4===t&&("true"===e||"True"===e||"TRUE"===e)||5===t&&("false"===e||"False"===e||"FALSE"===e)}function r(e){return"true"===e||"True"===e||"TRUE"===e}function o(e){return"[object Boolean]"===Object.prototype.toString.call(e)}var a=e("../type");t.exports=new a("tag:yaml.org,2002:bool",{kind:"scalar",resolve:i,construct:r,predicate:o,represent:{lowercase:function(e){return e?"true":"false"},uppercase:function(e){return e?"TRUE":"FALSE"},camelcase:function(e){return e?"True":"False"}},defaultStyle:"lowercase"})},{"../type":13}],16:[function(e,t,n){"use strict";function i(e){return null!==e&&!!u.test(e)}function r(e){var t,n,i,r;return t=e.replace(/_/g,"").toLowerCase(),n="-"===t[0]?-1:1,r=[],"+-".indexOf(t[0])>=0&&(t=t.slice(1)),".inf"===t?1===n?Number.POSITIVE_INFINITY:Number.NEGATIVE_INFINITY:".nan"===t?NaN:t.indexOf(":")>=0?(t.split(":").forEach(function(e){r.unshift(parseFloat(e,10))}),t=0,i=1,r.forEach(function(e){t+=e*i,i*=60}),n*t):n*parseFloat(t,10)}function o(e,t){var n;if(isNaN(e))switch(t){case"lowercase":return".nan";case"uppercase":return".NAN";case"camelcase":return".NaN"}else if(Number.POSITIVE_INFINITY===e)switch(t){case"lowercase":return".inf";case"uppercase":return".INF";case"camelcase":return".Inf"}else if(Number.NEGATIVE_INFINITY===e)switch(t){case"lowercase":return"-.inf";case"uppercase":return"-.INF";case"camelcase":return"-.Inf"}else if(s.isNegativeZero(e))return"-0.0";return n=e.toString(10),l.test(n)?n.replace("e",".e"):n}function a(e){return"[object Number]"===Object.prototype.toString.call(e)&&(e%1!==0||s.isNegativeZero(e))}var s=e("../common"),c=e("../type"),u=new RegExp("^(?:[-+]?(?:[0-9][0-9_]*)\\.[0-9_]*(?:[eE][-+][0-9]+)?|\\.[0-9_]+(?:[eE][-+][0-9]+)?|[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]*|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"),l=/^[-+]?[0-9]+e/;t.exports=new c("tag:yaml.org,2002:float",{kind:"scalar",resolve:i,construct:r,predicate:a,represent:o,defaultStyle:"lowercase"})},{"../common":2,"../type":13}],17:[function(e,t,n){"use strict";function i(e){return 48<=e&&e<=57||65<=e&&e<=70||97<=e&&e<=102}function r(e){return 48<=e&&e<=55}function o(e){return 48<=e&&e<=57}function a(e){if(null===e)return!1;var t,n=e.length,a=0,s=!1;if(!n)return!1;if(t=e[a],"-"!==t&&"+"!==t||(t=e[++a]),"0"===t){if(a+1===n)return!0;if(t=e[++a],"b"===t){for(a++;a<n;a++)if(t=e[a],"_"!==t){if("0"!==t&&"1"!==t)return!1;s=!0}return s}if("x"===t){for(a++;a<n;a++)if(t=e[a],"_"!==t){if(!i(e.charCodeAt(a)))return!1;s=!0}return s}for(;a<n;a++)if(t=e[a],"_"!==t){if(!r(e.charCodeAt(a)))return!1;s=!0}return s}for(;a<n;a++)if(t=e[a],"_"!==t){if(":"===t)break;if(!o(e.charCodeAt(a)))return!1;s=!0}return!!s&&(":"!==t||/^(:[0-5]?[0-9])+$/.test(e.slice(a)))}function s(e){var t,n,i=e,r=1,o=[];return i.indexOf("_")!==-1&&(i=i.replace(/_/g,"")),t=i[0],"-"!==t&&"+"!==t||("-"===t&&(r=-1),i=i.slice(1),t=i[0]),"0"===i?0:"0"===t?"b"===i[1]?r*parseInt(i.slice(2),2):"x"===i[1]?r*parseInt(i,16):r*parseInt(i,8):i.indexOf(":")!==-1?(i.split(":").forEach(function(e){o.unshift(parseInt(e,10))}),i=0,n=1,o.forEach(function(e){i+=e*n,n*=60}),r*i):r*parseInt(i,10)}function c(e){return"[object Number]"===Object.prototype.toString.call(e)&&e%1===0&&!u.isNegativeZero(e)}var u=e("../common"),l=e("../type");t.exports=new l("tag:yaml.org,2002:int",{kind:"scalar",resolve:a,construct:s,predicate:c,represent:{binary:function(e){return"0b"+e.toString(2)},octal:function(e){return"0"+e.toString(8)},decimal:function(e){return e.toString(10)},hexadecimal:function(e){return"0x"+e.toString(16).toUpperCase()}},defaultStyle:"decimal",styleAliases:{binary:[2,"bin"],octal:[8,"oct"],decimal:[10,"dec"],hexadecimal:[16,"hex"]}})},{"../common":2,"../type":13}],18:[function(e,t,n){"use strict";function i(e){if(null===e)return!1;try{var t="("+e+")",n=s.parse(t,{range:!0});return"Program"===n.type&&1===n.body.length&&"ExpressionStatement"===n.body[0].type&&"FunctionExpression"===n.body[0].expression.type}catch(e){return!1}}function r(e){var t,n="("+e+")",i=s.parse(n,{range:!0}),r=[];if("Program"!==i.type||1!==i.body.length||"ExpressionStatement"!==i.body[0].type||"FunctionExpression"!==i.body[0].expression.type)throw new Error("Failed to resolve function");return i.body[0].expression.params.forEach(function(e){r.push(e.name)}),t=i.body[0].expression.body.range,new Function(r,n.slice(t[0]+1,t[1]-1))}function o(e){return e.toString()}function a(e){return"[object Function]"===Object.prototype.toString.call(e)}var s;try{var c=e;s=c("esprima")}catch(e){"undefined"!=typeof window&&(s=window.esprima)}var u=e("../../type");t.exports=new u("tag:yaml.org,2002:js/function",{kind:"scalar",resolve:i,construct:r,predicate:a,represent:o})},{"../../type":13}],19:[function(e,t,n){"use strict";function i(e){if(null===e)return!1;if(0===e.length)return!1;var t=e,n=/\/([gim]*)$/.exec(e),i="";if("/"===t[0]){if(n&&(i=n[1]),i.length>3)return!1;if("/"!==t[t.length-i.length-1])return!1}return!0}function r(e){var t=e,n=/\/([gim]*)$/.exec(e),i="";return"/"===t[0]&&(n&&(i=n[1]),t=t.slice(1,t.length-i.length-1)),new RegExp(t,i)}function o(e){var t="/"+e.source+"/";return e.global&&(t+="g"),e.multiline&&(t+="m"),e.ignoreCase&&(t+="i"),t}function a(e){return"[object RegExp]"===Object.prototype.toString.call(e)}var s=e("../../type");t.exports=new s("tag:yaml.org,2002:js/regexp",{kind:"scalar",resolve:i,construct:r,predicate:a,represent:o})},{"../../type":13}],20:[function(e,t,n){"use strict";function i(){return!0}function r(){}function o(){return""}function a(e){return"undefined"==typeof e}var s=e("../../type");t.exports=new s("tag:yaml.org,2002:js/undefined",{kind:"scalar",resolve:i,construct:r,predicate:a,represent:o})},{"../../type":13}],21:[function(e,t,n){"use strict";var i=e("../type");t.exports=new i("tag:yaml.org,2002:map",{kind:"mapping",construct:function(e){return null!==e?e:{}}})},{"../type":13}],22:[function(e,t,n){"use strict";function i(e){return"<<"===e||null===e}var r=e("../type");t.exports=new r("tag:yaml.org,2002:merge",{kind:"scalar",resolve:i})},{"../type":13}],23:[function(e,t,n){"use strict";function i(e){if(null===e)return!0;var t=e.length;return 1===t&&"~"===e||4===t&&("null"===e||"Null"===e||"NULL"===e)}function r(){return null}function o(e){return null===e}var a=e("../type");t.exports=new a("tag:yaml.org,2002:null",{kind:"scalar",resolve:i,construct:r,predicate:o,represent:{canonical:function(){return"~"},lowercase:function(){return"null"},uppercase:function(){return"NULL"},camelcase:function(){return"Null"}},defaultStyle:"lowercase"})},{"../type":13}],24:[function(e,t,n){"use strict";function i(e){if(null===e)return!0;var t,n,i,r,o,c=[],u=e;for(t=0,n=u.length;t<n;t+=1){if(i=u[t],o=!1,"[object Object]"!==s.call(i))return!1;for(r in i)if(a.call(i,r)){if(o)return!1;o=!0}if(!o)return!1;if(c.indexOf(r)!==-1)return!1;c.push(r)}return!0}function r(e){return null!==e?e:[]}var o=e("../type"),a=Object.prototype.hasOwnProperty,s=Object.prototype.toString;t.exports=new o("tag:yaml.org,2002:omap",{kind:"sequence",resolve:i,construct:r})},{"../type":13}],25:[function(e,t,n){"use strict";function i(e){if(null===e)return!0;var t,n,i,r,o,s=e;for(o=new Array(s.length),t=0,n=s.length;t<n;t+=1){if(i=s[t],"[object Object]"!==a.call(i))return!1;if(r=Object.keys(i),1!==r.length)return!1;o[t]=[r[0],i[r[0]]]}return!0}function r(e){if(null===e)return[];var t,n,i,r,o,a=e;for(o=new Array(a.length),t=0,n=a.length;t<n;t+=1)i=a[t],r=Object.keys(i),o[t]=[r[0],i[r[0]]];return o}var o=e("../type"),a=Object.prototype.toString;t.exports=new o("tag:yaml.org,2002:pairs",{kind:"sequence",resolve:i,construct:r})},{"../type":13}],26:[function(e,t,n){"use strict";var i=e("../type");t.exports=new i("tag:yaml.org,2002:seq",{kind:"sequence",construct:function(e){return null!==e?e:[]}})},{"../type":13}],27:[function(e,t,n){"use strict";function i(e){if(null===e)return!0;var t,n=e;for(t in n)if(a.call(n,t)&&null!==n[t])return!1;return!0}function r(e){return null!==e?e:{}}var o=e("../type"),a=Object.prototype.hasOwnProperty;t.exports=new o("tag:yaml.org,2002:set",{kind:"mapping",resolve:i,construct:r})},{"../type":13}],28:[function(e,t,n){"use strict";var i=e("../type");t.exports=new i("tag:yaml.org,2002:str",{kind:"scalar",construct:function(e){return null!==e?e:""}})},{"../type":13}],29:[function(e,t,n){"use strict";function i(e){return null!==e&&(null!==s.exec(e)||null!==c.exec(e))}function r(e){var t,n,i,r,o,a,u,l,p,f,d=0,h=null;if(t=s.exec(e),null===t&&(t=c.exec(e)),null===t)throw new Error("Date resolve error");if(n=+t[1],i=+t[2]-1,r=+t[3],!t[4])return new Date(Date.UTC(n,i,r));if(o=+t[4],a=+t[5],u=+t[6],t[7]){for(d=t[7].slice(0,3);d.length<3;)d+="0";d=+d}return t[9]&&(l=+t[10],p=+(t[11]||0),h=6e4*(60*l+p),"-"===t[9]&&(h=-h)),f=new Date(Date.UTC(n,i,r,o,a,u,d)),h&&f.setTime(f.getTime()-h),f}function o(e){return e.toISOString()}var a=e("../type"),s=new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9])-([0-9][0-9])$"),c=new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9]?)-([0-9][0-9]?)(?:[Tt]|[ \\t]+)([0-9][0-9]?):([0-9][0-9]):([0-9][0-9])(?:\\.([0-9]*))?(?:[ \\t]*(Z|([-+])([0-9][0-9]?)(?::([0-9][0-9]))?))?$");t.exports=new a("tag:yaml.org,2002:timestamp",{kind:"scalar",resolve:i,construct:r,instanceOf:Date,represent:o})},{"../type":13}],"/":[function(e,t,n){"use strict";var i=e("./lib/js-yaml.js");t.exports=i},{"./lib/js-yaml.js":1}]},{},[])("/")});
diff --git a/node_modules/svgo/node_modules/js-yaml/index.js b/node_modules/svgo/node_modules/js-yaml/index.js
new file mode 100644
index 00000000..13744352
--- /dev/null
+++ b/node_modules/svgo/node_modules/js-yaml/index.js
@@ -0,0 +1,7 @@
+'use strict';
+
+
+var yaml = require('./lib/js-yaml.js');
+
+
+module.exports = yaml;
diff --git a/node_modules/svgo/node_modules/js-yaml/lib/js-yaml.js b/node_modules/svgo/node_modules/js-yaml/lib/js-yaml.js
new file mode 100644
index 00000000..f0e92818
--- /dev/null
+++ b/node_modules/svgo/node_modules/js-yaml/lib/js-yaml.js
@@ -0,0 +1,39 @@
+'use strict';
+
+
+var loader = require('./js-yaml/loader');
+var dumper = require('./js-yaml/dumper');
+
+
+function deprecated(name) {
+ return function () {
+ throw new Error('Function ' + name + ' is deprecated and cannot be used.');
+ };
+}
+
+
+module.exports.Type = require('./js-yaml/type');
+module.exports.Schema = require('./js-yaml/schema');
+module.exports.FAILSAFE_SCHEMA = require('./js-yaml/schema/failsafe');
+module.exports.JSON_SCHEMA = require('./js-yaml/schema/json');
+module.exports.CORE_SCHEMA = require('./js-yaml/schema/core');
+module.exports.DEFAULT_SAFE_SCHEMA = require('./js-yaml/schema/default_safe');
+module.exports.DEFAULT_FULL_SCHEMA = require('./js-yaml/schema/default_full');
+module.exports.load = loader.load;
+module.exports.loadAll = loader.loadAll;
+module.exports.safeLoad = loader.safeLoad;
+module.exports.safeLoadAll = loader.safeLoadAll;
+module.exports.dump = dumper.dump;
+module.exports.safeDump = dumper.safeDump;
+module.exports.YAMLException = require('./js-yaml/exception');
+
+// Deprecated schema names from JS-YAML 2.0.x
+module.exports.MINIMAL_SCHEMA = require('./js-yaml/schema/failsafe');
+module.exports.SAFE_SCHEMA = require('./js-yaml/schema/default_safe');
+module.exports.DEFAULT_SCHEMA = require('./js-yaml/schema/default_full');
+
+// Deprecated functions from JS-YAML 1.x.x
+module.exports.scan = deprecated('scan');
+module.exports.parse = deprecated('parse');
+module.exports.compose = deprecated('compose');
+module.exports.addConstructor = deprecated('addConstructor');
diff --git a/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/common.js b/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/common.js
new file mode 100644
index 00000000..25ef7d8e
--- /dev/null
+++ b/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/common.js
@@ -0,0 +1,59 @@
+'use strict';
+
+
+function isNothing(subject) {
+ return (typeof subject === 'undefined') || (subject === null);
+}
+
+
+function isObject(subject) {
+ return (typeof subject === 'object') && (subject !== null);
+}
+
+
+function toArray(sequence) {
+ if (Array.isArray(sequence)) return sequence;
+ else if (isNothing(sequence)) return [];
+
+ return [ sequence ];
+}
+
+
+function extend(target, source) {
+ var index, length, key, sourceKeys;
+
+ if (source) {
+ sourceKeys = Object.keys(source);
+
+ for (index = 0, length = sourceKeys.length; index < length; index += 1) {
+ key = sourceKeys[index];
+ target[key] = source[key];
+ }
+ }
+
+ return target;
+}
+
+
+function repeat(string, count) {
+ var result = '', cycle;
+
+ for (cycle = 0; cycle < count; cycle += 1) {
+ result += string;
+ }
+
+ return result;
+}
+
+
+function isNegativeZero(number) {
+ return (number === 0) && (Number.NEGATIVE_INFINITY === 1 / number);
+}
+
+
+module.exports.isNothing = isNothing;
+module.exports.isObject = isObject;
+module.exports.toArray = toArray;
+module.exports.repeat = repeat;
+module.exports.isNegativeZero = isNegativeZero;
+module.exports.extend = extend;
diff --git a/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/dumper.js b/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/dumper.js
new file mode 100644
index 00000000..203f436b
--- /dev/null
+++ b/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/dumper.js
@@ -0,0 +1,801 @@
+'use strict';
+
+/*eslint-disable no-use-before-define*/
+
+var common = require('./common');
+var YAMLException = require('./exception');
+var DEFAULT_FULL_SCHEMA = require('./schema/default_full');
+var DEFAULT_SAFE_SCHEMA = require('./schema/default_safe');
+
+var _toString = Object.prototype.toString;
+var _hasOwnProperty = Object.prototype.hasOwnProperty;
+
+var CHAR_TAB = 0x09; /* Tab */
+var CHAR_LINE_FEED = 0x0A; /* LF */
+var CHAR_SPACE = 0x20; /* Space */
+var CHAR_EXCLAMATION = 0x21; /* ! */
+var CHAR_DOUBLE_QUOTE = 0x22; /* " */
+var CHAR_SHARP = 0x23; /* # */
+var CHAR_PERCENT = 0x25; /* % */
+var CHAR_AMPERSAND = 0x26; /* & */
+var CHAR_SINGLE_QUOTE = 0x27; /* ' */
+var CHAR_ASTERISK = 0x2A; /* * */
+var CHAR_COMMA = 0x2C; /* , */
+var CHAR_MINUS = 0x2D; /* - */
+var CHAR_COLON = 0x3A; /* : */
+var CHAR_GREATER_THAN = 0x3E; /* > */
+var CHAR_QUESTION = 0x3F; /* ? */
+var CHAR_COMMERCIAL_AT = 0x40; /* @ */
+var CHAR_LEFT_SQUARE_BRACKET = 0x5B; /* [ */
+var CHAR_RIGHT_SQUARE_BRACKET = 0x5D; /* ] */
+var CHAR_GRAVE_ACCENT = 0x60; /* ` */
+var CHAR_LEFT_CURLY_BRACKET = 0x7B; /* { */
+var CHAR_VERTICAL_LINE = 0x7C; /* | */
+var CHAR_RIGHT_CURLY_BRACKET = 0x7D; /* } */
+
+var ESCAPE_SEQUENCES = {};
+
+ESCAPE_SEQUENCES[0x00] = '\\0';
+ESCAPE_SEQUENCES[0x07] = '\\a';
+ESCAPE_SEQUENCES[0x08] = '\\b';
+ESCAPE_SEQUENCES[0x09] = '\\t';
+ESCAPE_SEQUENCES[0x0A] = '\\n';
+ESCAPE_SEQUENCES[0x0B] = '\\v';
+ESCAPE_SEQUENCES[0x0C] = '\\f';
+ESCAPE_SEQUENCES[0x0D] = '\\r';
+ESCAPE_SEQUENCES[0x1B] = '\\e';
+ESCAPE_SEQUENCES[0x22] = '\\"';
+ESCAPE_SEQUENCES[0x5C] = '\\\\';
+ESCAPE_SEQUENCES[0x85] = '\\N';
+ESCAPE_SEQUENCES[0xA0] = '\\_';
+ESCAPE_SEQUENCES[0x2028] = '\\L';
+ESCAPE_SEQUENCES[0x2029] = '\\P';
+
+var DEPRECATED_BOOLEANS_SYNTAX = [
+ 'y', 'Y', 'yes', 'Yes', 'YES', 'on', 'On', 'ON',
+ 'n', 'N', 'no', 'No', 'NO', 'off', 'Off', 'OFF'
+];
+
+function compileStyleMap(schema, map) {
+ var result, keys, index, length, tag, style, type;
+
+ if (map === null) return {};
+
+ result = {};
+ keys = Object.keys(map);
+
+ for (index = 0, length = keys.length; index < length; index += 1) {
+ tag = keys[index];
+ style = String(map[tag]);
+
+ if (tag.slice(0, 2) === '!!') {
+ tag = 'tag:yaml.org,2002:' + tag.slice(2);
+ }
+ type = schema.compiledTypeMap['fallback'][tag];
+
+ if (type && _hasOwnProperty.call(type.styleAliases, style)) {
+ style = type.styleAliases[style];
+ }
+
+ result[tag] = style;
+ }
+
+ return result;
+}
+
+function encodeHex(character) {
+ var string, handle, length;
+
+ string = character.toString(16).toUpperCase();
+
+ if (character <= 0xFF) {
+ handle = 'x';
+ length = 2;
+ } else if (character <= 0xFFFF) {
+ handle = 'u';
+ length = 4;
+ } else if (character <= 0xFFFFFFFF) {
+ handle = 'U';
+ length = 8;
+ } else {
+ throw new YAMLException('code point within a string may not be greater than 0xFFFFFFFF');
+ }
+
+ return '\\' + handle + common.repeat('0', length - string.length) + string;
+}
+
+function State(options) {
+ this.schema = options['schema'] || DEFAULT_FULL_SCHEMA;
+ this.indent = Math.max(1, (options['indent'] || 2));
+ this.skipInvalid = options['skipInvalid'] || false;
+ this.flowLevel = (common.isNothing(options['flowLevel']) ? -1 : options['flowLevel']);
+ this.styleMap = compileStyleMap(this.schema, options['styles'] || null);
+ this.sortKeys = options['sortKeys'] || false;
+ this.lineWidth = options['lineWidth'] || 80;
+ this.noRefs = options['noRefs'] || false;
+ this.noCompatMode = options['noCompatMode'] || false;
+
+ this.implicitTypes = this.schema.compiledImplicit;
+ this.explicitTypes = this.schema.compiledExplicit;
+
+ this.tag = null;
+ this.result = '';
+
+ this.duplicates = [];
+ this.usedDuplicates = null;
+}
+
+// Indents every line in a string. Empty lines (\n only) are not indented.
+function indentString(string, spaces) {
+ var ind = common.repeat(' ', spaces),
+ position = 0,
+ next = -1,
+ result = '',
+ line,
+ length = string.length;
+
+ while (position < length) {
+ next = string.indexOf('\n', position);
+ if (next === -1) {
+ line = string.slice(position);
+ position = length;
+ } else {
+ line = string.slice(position, next + 1);
+ position = next + 1;
+ }
+
+ if (line.length && line !== '\n') result += ind;
+
+ result += line;
+ }
+
+ return result;
+}
+
+function generateNextLine(state, level) {
+ return '\n' + common.repeat(' ', state.indent * level);
+}
+
+function testImplicitResolving(state, str) {
+ var index, length, type;
+
+ for (index = 0, length = state.implicitTypes.length; index < length; index += 1) {
+ type = state.implicitTypes[index];
+
+ if (type.resolve(str)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// [33] s-white ::= s-space | s-tab
+function isWhitespace(c) {
+ return c === CHAR_SPACE || c === CHAR_TAB;
+}
+
+// Returns true if the character can be printed without escaping.
+// From YAML 1.2: "any allowed characters known to be non-printable
+// should also be escaped. [However,] This isn’t mandatory"
+// Derived from nb-char - \t - #x85 - #xA0 - #x2028 - #x2029.
+function isPrintable(c) {
+ return (0x00020 <= c && c <= 0x00007E)
+ || ((0x000A1 <= c && c <= 0x00D7FF) && c !== 0x2028 && c !== 0x2029)
+ || ((0x0E000 <= c && c <= 0x00FFFD) && c !== 0xFEFF /* BOM */)
+ || (0x10000 <= c && c <= 0x10FFFF);
+}
+
+// Simplified test for values allowed after the first character in plain style.
+function isPlainSafe(c) {
+ // Uses a subset of nb-char - c-flow-indicator - ":" - "#"
+ // where nb-char ::= c-printable - b-char - c-byte-order-mark.
+ return isPrintable(c) && c !== 0xFEFF
+ // - c-flow-indicator
+ && c !== CHAR_COMMA
+ && c !== CHAR_LEFT_SQUARE_BRACKET
+ && c !== CHAR_RIGHT_SQUARE_BRACKET
+ && c !== CHAR_LEFT_CURLY_BRACKET
+ && c !== CHAR_RIGHT_CURLY_BRACKET
+ // - ":" - "#"
+ && c !== CHAR_COLON
+ && c !== CHAR_SHARP;
+}
+
+// Simplified test for values allowed as the first character in plain style.
+function isPlainSafeFirst(c) {
+ // Uses a subset of ns-char - c-indicator
+ // where ns-char = nb-char - s-white.
+ return isPrintable(c) && c !== 0xFEFF
+ && !isWhitespace(c) // - s-white
+ // - (c-indicator ::=
+ // “-” | “?” | “:” | “,” | “[” | “]” | “{” | “}”
+ && c !== CHAR_MINUS
+ && c !== CHAR_QUESTION
+ && c !== CHAR_COLON
+ && c !== CHAR_COMMA
+ && c !== CHAR_LEFT_SQUARE_BRACKET
+ && c !== CHAR_RIGHT_SQUARE_BRACKET
+ && c !== CHAR_LEFT_CURLY_BRACKET
+ && c !== CHAR_RIGHT_CURLY_BRACKET
+ // | “#” | “&” | “*” | “!” | “|” | “>” | “'” | “"”
+ && c !== CHAR_SHARP
+ && c !== CHAR_AMPERSAND
+ && c !== CHAR_ASTERISK
+ && c !== CHAR_EXCLAMATION
+ && c !== CHAR_VERTICAL_LINE
+ && c !== CHAR_GREATER_THAN
+ && c !== CHAR_SINGLE_QUOTE
+ && c !== CHAR_DOUBLE_QUOTE
+ // | “%” | “@” | “`”)
+ && c !== CHAR_PERCENT
+ && c !== CHAR_COMMERCIAL_AT
+ && c !== CHAR_GRAVE_ACCENT;
+}
+
+var STYLE_PLAIN = 1,
+ STYLE_SINGLE = 2,
+ STYLE_LITERAL = 3,
+ STYLE_FOLDED = 4,
+ STYLE_DOUBLE = 5;
+
+// Determines which scalar styles are possible and returns the preferred style.
+// lineWidth = -1 => no limit.
+// Pre-conditions: str.length > 0.
+// Post-conditions:
+// STYLE_PLAIN or STYLE_SINGLE => no \n are in the string.
+// STYLE_LITERAL => no lines are suitable for folding (or lineWidth is -1).
+// STYLE_FOLDED => a line > lineWidth and can be folded (and lineWidth != -1).
+function chooseScalarStyle(string, singleLineOnly, indentPerLevel, lineWidth, testAmbiguousType) {
+ var i;
+ var char;
+ var hasLineBreak = false;
+ var hasFoldableLine = false; // only checked if shouldTrackWidth
+ var shouldTrackWidth = lineWidth !== -1;
+ var previousLineBreak = -1; // count the first line correctly
+ var plain = isPlainSafeFirst(string.charCodeAt(0))
+ && !isWhitespace(string.charCodeAt(string.length - 1));
+
+ if (singleLineOnly) {
+ // Case: no block styles.
+ // Check for disallowed characters to rule out plain and single.
+ for (i = 0; i < string.length; i++) {
+ char = string.charCodeAt(i);
+ if (!isPrintable(char)) {
+ return STYLE_DOUBLE;
+ }
+ plain = plain && isPlainSafe(char);
+ }
+ } else {
+ // Case: block styles permitted.
+ for (i = 0; i < string.length; i++) {
+ char = string.charCodeAt(i);
+ if (char === CHAR_LINE_FEED) {
+ hasLineBreak = true;
+ // Check if any line can be folded.
+ if (shouldTrackWidth) {
+ hasFoldableLine = hasFoldableLine ||
+ // Foldable line = too long, and not more-indented.
+ (i - previousLineBreak - 1 > lineWidth &&
+ string[previousLineBreak + 1] !== ' ');
+ previousLineBreak = i;
+ }
+ } else if (!isPrintable(char)) {
+ return STYLE_DOUBLE;
+ }
+ plain = plain && isPlainSafe(char);
+ }
+ // in case the end is missing a \n
+ hasFoldableLine = hasFoldableLine || (shouldTrackWidth &&
+ (i - previousLineBreak - 1 > lineWidth &&
+ string[previousLineBreak + 1] !== ' '));
+ }
+ // Although every style can represent \n without escaping, prefer block styles
+ // for multiline, since they're more readable and they don't add empty lines.
+ // Also prefer folding a super-long line.
+ if (!hasLineBreak && !hasFoldableLine) {
+ // Strings interpretable as another type have to be quoted;
+ // e.g. the string 'true' vs. the boolean true.
+ return plain && !testAmbiguousType(string)
+ ? STYLE_PLAIN : STYLE_SINGLE;
+ }
+ // Edge case: block indentation indicator can only have one digit.
+ if (string[0] === ' ' && indentPerLevel > 9) {
+ return STYLE_DOUBLE;
+ }
+ // At this point we know block styles are valid.
+ // Prefer literal style unless we want to fold.
+ return hasFoldableLine ? STYLE_FOLDED : STYLE_LITERAL;
+}
+
+// Note: line breaking/folding is implemented for only the folded style.
+// NB. We drop the last trailing newline (if any) of a returned block scalar
+// since the dumper adds its own newline. This always works:
+// • No ending newline => unaffected; already using strip "-" chomping.
+// • Ending newline => removed then restored.
+// Importantly, this keeps the "+" chomp indicator from gaining an extra line.
+function writeScalar(state, string, level, iskey) {
+ state.dump = (function () {
+ if (string.length === 0) {
+ return "''";
+ }
+ if (!state.noCompatMode &&
+ DEPRECATED_BOOLEANS_SYNTAX.indexOf(string) !== -1) {
+ return "'" + string + "'";
+ }
+
+ var indent = state.indent * Math.max(1, level); // no 0-indent scalars
+ // As indentation gets deeper, let the width decrease monotonically
+ // to the lower bound min(state.lineWidth, 40).
+ // Note that this implies
+ // state.lineWidth ≤ 40 + state.indent: width is fixed at the lower bound.
+ // state.lineWidth > 40 + state.indent: width decreases until the lower bound.
+ // This behaves better than a constant minimum width which disallows narrower options,
+ // or an indent threshold which causes the width to suddenly increase.
+ var lineWidth = state.lineWidth === -1
+ ? -1 : Math.max(Math.min(state.lineWidth, 40), state.lineWidth - indent);
+
+ // Without knowing if keys are implicit/explicit, assume implicit for safety.
+ var singleLineOnly = iskey
+ // No block styles in flow mode.
+ || (state.flowLevel > -1 && level >= state.flowLevel);
+ function testAmbiguity(string) {
+ return testImplicitResolving(state, string);
+ }
+
+ switch (chooseScalarStyle(string, singleLineOnly, state.indent, lineWidth, testAmbiguity)) {
+ case STYLE_PLAIN:
+ return string;
+ case STYLE_SINGLE:
+ return "'" + string.replace(/'/g, "''") + "'";
+ case STYLE_LITERAL:
+ return '|' + blockHeader(string, state.indent)
+ + dropEndingNewline(indentString(string, indent));
+ case STYLE_FOLDED:
+ return '>' + blockHeader(string, state.indent)
+ + dropEndingNewline(indentString(foldString(string, lineWidth), indent));
+ case STYLE_DOUBLE:
+ return '"' + escapeString(string, lineWidth) + '"';
+ default:
+ throw new YAMLException('impossible error: invalid scalar style');
+ }
+ }());
+}
+
+// Pre-conditions: string is valid for a block scalar, 1 <= indentPerLevel <= 9.
+function blockHeader(string, indentPerLevel) {
+ var indentIndicator = (string[0] === ' ') ? String(indentPerLevel) : '';
+
+ // note the special case: the string '\n' counts as a "trailing" empty line.
+ var clip = string[string.length - 1] === '\n';
+ var keep = clip && (string[string.length - 2] === '\n' || string === '\n');
+ var chomp = keep ? '+' : (clip ? '' : '-');
+
+ return indentIndicator + chomp + '\n';
+}
+
+// (See the note for writeScalar.)
+function dropEndingNewline(string) {
+ return string[string.length - 1] === '\n' ? string.slice(0, -1) : string;
+}
+
+// Note: a long line without a suitable break point will exceed the width limit.
+// Pre-conditions: every char in str isPrintable, str.length > 0, width > 0.
+function foldString(string, width) {
+ // In folded style, $k$ consecutive newlines output as $k+1$ newlines—
+ // unless they're before or after a more-indented line, or at the very
+ // beginning or end, in which case $k$ maps to $k$.
+ // Therefore, parse each chunk as newline(s) followed by a content line.
+ var lineRe = /(\n+)([^\n]*)/g;
+
+ // first line (possibly an empty line)
+ var result = (function () {
+ var nextLF = string.indexOf('\n');
+ nextLF = nextLF !== -1 ? nextLF : string.length;
+ lineRe.lastIndex = nextLF;
+ return foldLine(string.slice(0, nextLF), width);
+ }());
+ // If we haven't reached the first content line yet, don't add an extra \n.
+ var prevMoreIndented = string[0] === '\n' || string[0] === ' ';
+ var moreIndented;
+
+ // rest of the lines
+ var match;
+ while ((match = lineRe.exec(string))) {
+ var prefix = match[1], line = match[2];
+ moreIndented = (line[0] === ' ');
+ result += prefix
+ + (!prevMoreIndented && !moreIndented && line !== ''
+ ? '\n' : '')
+ + foldLine(line, width);
+ prevMoreIndented = moreIndented;
+ }
+
+ return result;
+}
+
+// Greedy line breaking.
+// Picks the longest line under the limit each time,
+// otherwise settles for the shortest line over the limit.
+// NB. More-indented lines *cannot* be folded, as that would add an extra \n.
+function foldLine(line, width) {
+ if (line === '' || line[0] === ' ') return line;
+
+ // Since a more-indented line adds a \n, breaks can't be followed by a space.
+ var breakRe = / [^ ]/g; // note: the match index will always be <= length-2.
+ var match;
+ // start is an inclusive index. end, curr, and next are exclusive.
+ var start = 0, end, curr = 0, next = 0;
+ var result = '';
+
+ // Invariants: 0 <= start <= length-1.
+ // 0 <= curr <= next <= max(0, length-2). curr - start <= width.
+ // Inside the loop:
+ // A match implies length >= 2, so curr and next are <= length-2.
+ while ((match = breakRe.exec(line))) {
+ next = match.index;
+ // maintain invariant: curr - start <= width
+ if (next - start > width) {
+ end = (curr > start) ? curr : next; // derive end <= length-2
+ result += '\n' + line.slice(start, end);
+ // skip the space that was output as \n
+ start = end + 1; // derive start <= length-1
+ }
+ curr = next;
+ }
+
+ // By the invariants, start <= length-1, so there is something left over.
+ // It is either the whole string or a part starting from non-whitespace.
+ result += '\n';
+ // Insert a break if the remainder is too long and there is a break available.
+ if (line.length - start > width && curr > start) {
+ result += line.slice(start, curr) + '\n' + line.slice(curr + 1);
+ } else {
+ result += line.slice(start);
+ }
+
+ return result.slice(1); // drop extra \n joiner
+}
+
+// Escapes a double-quoted string.
+function escapeString(string) {
+ var result = '';
+ var char;
+ var escapeSeq;
+
+ for (var i = 0; i < string.length; i++) {
+ char = string.charCodeAt(i);
+ escapeSeq = ESCAPE_SEQUENCES[char];
+ result += !escapeSeq && isPrintable(char)
+ ? string[i]
+ : escapeSeq || encodeHex(char);
+ }
+
+ return result;
+}
+
+function writeFlowSequence(state, level, object) {
+ var _result = '',
+ _tag = state.tag,
+ index,
+ length;
+
+ for (index = 0, length = object.length; index < length; index += 1) {
+ // Write only valid elements.
+ if (writeNode(state, level, object[index], false, false)) {
+ if (index !== 0) _result += ', ';
+ _result += state.dump;
+ }
+ }
+
+ state.tag = _tag;
+ state.dump = '[' + _result + ']';
+}
+
+function writeBlockSequence(state, level, object, compact) {
+ var _result = '',
+ _tag = state.tag,
+ index,
+ length;
+
+ for (index = 0, length = object.length; index < length; index += 1) {
+ // Write only valid elements.
+ if (writeNode(state, level + 1, object[index], true, true)) {
+ if (!compact || index !== 0) {
+ _result += generateNextLine(state, level);
+ }
+ _result += '- ' + state.dump;
+ }
+ }
+
+ state.tag = _tag;
+ state.dump = _result || '[]'; // Empty sequence if no valid values.
+}
+
+function writeFlowMapping(state, level, object) {
+ var _result = '',
+ _tag = state.tag,
+ objectKeyList = Object.keys(object),
+ index,
+ length,
+ objectKey,
+ objectValue,
+ pairBuffer;
+
+ for (index = 0, length = objectKeyList.length; index < length; index += 1) {
+ pairBuffer = '';
+
+ if (index !== 0) pairBuffer += ', ';
+
+ objectKey = objectKeyList[index];
+ objectValue = object[objectKey];
+
+ if (!writeNode(state, level, objectKey, false, false)) {
+ continue; // Skip this pair because of invalid key;
+ }
+
+ if (state.dump.length > 1024) pairBuffer += '? ';
+
+ pairBuffer += state.dump + ': ';
+
+ if (!writeNode(state, level, objectValue, false, false)) {
+ continue; // Skip this pair because of invalid value.
+ }
+
+ pairBuffer += state.dump;
+
+ // Both key and value are valid.
+ _result += pairBuffer;
+ }
+
+ state.tag = _tag;
+ state.dump = '{' + _result + '}';
+}
+
+function writeBlockMapping(state, level, object, compact) {
+ var _result = '',
+ _tag = state.tag,
+ objectKeyList = Object.keys(object),
+ index,
+ length,
+ objectKey,
+ objectValue,
+ explicitPair,
+ pairBuffer;
+
+ // Allow sorting keys so that the output file is deterministic
+ if (state.sortKeys === true) {
+ // Default sorting
+ objectKeyList.sort();
+ } else if (typeof state.sortKeys === 'function') {
+ // Custom sort function
+ objectKeyList.sort(state.sortKeys);
+ } else if (state.sortKeys) {
+ // Something is wrong
+ throw new YAMLException('sortKeys must be a boolean or a function');
+ }
+
+ for (index = 0, length = objectKeyList.length; index < length; index += 1) {
+ pairBuffer = '';
+
+ if (!compact || index !== 0) {
+ pairBuffer += generateNextLine(state, level);
+ }
+
+ objectKey = objectKeyList[index];
+ objectValue = object[objectKey];
+
+ if (!writeNode(state, level + 1, objectKey, true, true, true)) {
+ continue; // Skip this pair because of invalid key.
+ }
+
+ explicitPair = (state.tag !== null && state.tag !== '?') ||
+ (state.dump && state.dump.length > 1024);
+
+ if (explicitPair) {
+ if (state.dump && CHAR_LINE_FEED === state.dump.charCodeAt(0)) {
+ pairBuffer += '?';
+ } else {
+ pairBuffer += '? ';
+ }
+ }
+
+ pairBuffer += state.dump;
+
+ if (explicitPair) {
+ pairBuffer += generateNextLine(state, level);
+ }
+
+ if (!writeNode(state, level + 1, objectValue, true, explicitPair)) {
+ continue; // Skip this pair because of invalid value.
+ }
+
+ if (state.dump && CHAR_LINE_FEED === state.dump.charCodeAt(0)) {
+ pairBuffer += ':';
+ } else {
+ pairBuffer += ': ';
+ }
+
+ pairBuffer += state.dump;
+
+ // Both key and value are valid.
+ _result += pairBuffer;
+ }
+
+ state.tag = _tag;
+ state.dump = _result || '{}'; // Empty mapping if no valid pairs.
+}
+
+function detectType(state, object, explicit) {
+ var _result, typeList, index, length, type, style;
+
+ typeList = explicit ? state.explicitTypes : state.implicitTypes;
+
+ for (index = 0, length = typeList.length; index < length; index += 1) {
+ type = typeList[index];
+
+ if ((type.instanceOf || type.predicate) &&
+ (!type.instanceOf || ((typeof object === 'object') && (object instanceof type.instanceOf))) &&
+ (!type.predicate || type.predicate(object))) {
+
+ state.tag = explicit ? type.tag : '?';
+
+ if (type.represent) {
+ style = state.styleMap[type.tag] || type.defaultStyle;
+
+ if (_toString.call(type.represent) === '[object Function]') {
+ _result = type.represent(object, style);
+ } else if (_hasOwnProperty.call(type.represent, style)) {
+ _result = type.represent[style](object, style);
+ } else {
+ throw new YAMLException('!<' + type.tag + '> tag resolver accepts not "' + style + '" style');
+ }
+
+ state.dump = _result;
+ }
+
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// Serializes `object` and writes it to global `result`.
+// Returns true on success, or false on invalid object.
+//
+function writeNode(state, level, object, block, compact, iskey) {
+ state.tag = null;
+ state.dump = object;
+
+ if (!detectType(state, object, false)) {
+ detectType(state, object, true);
+ }
+
+ var type = _toString.call(state.dump);
+
+ if (block) {
+ block = (state.flowLevel < 0 || state.flowLevel > level);
+ }
+
+ var objectOrArray = type === '[object Object]' || type === '[object Array]',
+ duplicateIndex,
+ duplicate;
+
+ if (objectOrArray) {
+ duplicateIndex = state.duplicates.indexOf(object);
+ duplicate = duplicateIndex !== -1;
+ }
+
+ if ((state.tag !== null && state.tag !== '?') || duplicate || (state.indent !== 2 && level > 0)) {
+ compact = false;
+ }
+
+ if (duplicate && state.usedDuplicates[duplicateIndex]) {
+ state.dump = '*ref_' + duplicateIndex;
+ } else {
+ if (objectOrArray && duplicate && !state.usedDuplicates[duplicateIndex]) {
+ state.usedDuplicates[duplicateIndex] = true;
+ }
+ if (type === '[object Object]') {
+ if (block && (Object.keys(state.dump).length !== 0)) {
+ writeBlockMapping(state, level, state.dump, compact);
+ if (duplicate) {
+ state.dump = '&ref_' + duplicateIndex + state.dump;
+ }
+ } else {
+ writeFlowMapping(state, level, state.dump);
+ if (duplicate) {
+ state.dump = '&ref_' + duplicateIndex + ' ' + state.dump;
+ }
+ }
+ } else if (type === '[object Array]') {
+ if (block && (state.dump.length !== 0)) {
+ writeBlockSequence(state, level, state.dump, compact);
+ if (duplicate) {
+ state.dump = '&ref_' + duplicateIndex + state.dump;
+ }
+ } else {
+ writeFlowSequence(state, level, state.dump);
+ if (duplicate) {
+ state.dump = '&ref_' + duplicateIndex + ' ' + state.dump;
+ }
+ }
+ } else if (type === '[object String]') {
+ if (state.tag !== '?') {
+ writeScalar(state, state.dump, level, iskey);
+ }
+ } else {
+ if (state.skipInvalid) return false;
+ throw new YAMLException('unacceptable kind of an object to dump ' + type);
+ }
+
+ if (state.tag !== null && state.tag !== '?') {
+ state.dump = '!<' + state.tag + '> ' + state.dump;
+ }
+ }
+
+ return true;
+}
+
+function getDuplicateReferences(object, state) {
+ var objects = [],
+ duplicatesIndexes = [],
+ index,
+ length;
+
+ inspectNode(object, objects, duplicatesIndexes);
+
+ for (index = 0, length = duplicatesIndexes.length; index < length; index += 1) {
+ state.duplicates.push(objects[duplicatesIndexes[index]]);
+ }
+ state.usedDuplicates = new Array(length);
+}
+
+function inspectNode(object, objects, duplicatesIndexes) {
+ var objectKeyList,
+ index,
+ length;
+
+ if (object !== null && typeof object === 'object') {
+ index = objects.indexOf(object);
+ if (index !== -1) {
+ if (duplicatesIndexes.indexOf(index) === -1) {
+ duplicatesIndexes.push(index);
+ }
+ } else {
+ objects.push(object);
+
+ if (Array.isArray(object)) {
+ for (index = 0, length = object.length; index < length; index += 1) {
+ inspectNode(object[index], objects, duplicatesIndexes);
+ }
+ } else {
+ objectKeyList = Object.keys(object);
+
+ for (index = 0, length = objectKeyList.length; index < length; index += 1) {
+ inspectNode(object[objectKeyList[index]], objects, duplicatesIndexes);
+ }
+ }
+ }
+ }
+}
+
+function dump(input, options) {
+ options = options || {};
+
+ var state = new State(options);
+
+ if (!state.noRefs) getDuplicateReferences(input, state);
+
+ if (writeNode(state, 0, input, true, true)) return state.dump + '\n';
+
+ return '';
+}
+
+function safeDump(input, options) {
+ return dump(input, common.extend({ schema: DEFAULT_SAFE_SCHEMA }, options));
+}
+
+module.exports.dump = dump;
+module.exports.safeDump = safeDump;
diff --git a/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/exception.js b/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/exception.js
new file mode 100644
index 00000000..cf4e6252
--- /dev/null
+++ b/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/exception.js
@@ -0,0 +1,43 @@
+// YAML error class. http://stackoverflow.com/questions/8458984
+//
+'use strict';
+
+function YAMLException(reason, mark) {
+ // Super constructor
+ Error.call(this);
+
+ // Include stack trace in error object
+ if (Error.captureStackTrace) {
+ // Chrome and NodeJS
+ Error.captureStackTrace(this, this.constructor);
+ } else {
+ // FF, IE 10+ and Safari 6+. Fallback for others
+ this.stack = (new Error()).stack || '';
+ }
+
+ this.name = 'YAMLException';
+ this.reason = reason;
+ this.mark = mark;
+ this.message = (this.reason || '(unknown reason)') + (this.mark ? ' ' + this.mark.toString() : '');
+}
+
+
+// Inherit from Error
+YAMLException.prototype = Object.create(Error.prototype);
+YAMLException.prototype.constructor = YAMLException;
+
+
+YAMLException.prototype.toString = function toString(compact) {
+ var result = this.name + ': ';
+
+ result += this.reason || '(unknown reason)';
+
+ if (!compact && this.mark) {
+ result += ' ' + this.mark.toString();
+ }
+
+ return result;
+};
+
+
+module.exports = YAMLException;
diff --git a/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/loader.js b/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/loader.js
new file mode 100644
index 00000000..70e1a565
--- /dev/null
+++ b/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/loader.js
@@ -0,0 +1,1587 @@
+'use strict';
+
+/*eslint-disable max-len,no-use-before-define*/
+
+var common = require('./common');
+var YAMLException = require('./exception');
+var Mark = require('./mark');
+var DEFAULT_SAFE_SCHEMA = require('./schema/default_safe');
+var DEFAULT_FULL_SCHEMA = require('./schema/default_full');
+
+
+var _hasOwnProperty = Object.prototype.hasOwnProperty;
+
+
+var CONTEXT_FLOW_IN = 1;
+var CONTEXT_FLOW_OUT = 2;
+var CONTEXT_BLOCK_IN = 3;
+var CONTEXT_BLOCK_OUT = 4;
+
+
+var CHOMPING_CLIP = 1;
+var CHOMPING_STRIP = 2;
+var CHOMPING_KEEP = 3;
+
+
+var PATTERN_NON_PRINTABLE = /[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x84\x86-\x9F\uFFFE\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]/;
+var PATTERN_NON_ASCII_LINE_BREAKS = /[\x85\u2028\u2029]/;
+var PATTERN_FLOW_INDICATORS = /[,\[\]\{\}]/;
+var PATTERN_TAG_HANDLE = /^(?:!|!!|![a-z\-]+!)$/i;
+var PATTERN_TAG_URI = /^(?:!|[^,\[\]\{\}])(?:%[0-9a-f]{2}|[0-9a-z\-#;\/\?:@&=\+\$,_\.!~\*'\(\)\[\]])*$/i;
+
+
+function is_EOL(c) {
+ return (c === 0x0A/* LF */) || (c === 0x0D/* CR */);
+}
+
+function is_WHITE_SPACE(c) {
+ return (c === 0x09/* Tab */) || (c === 0x20/* Space */);
+}
+
+function is_WS_OR_EOL(c) {
+ return (c === 0x09/* Tab */) ||
+ (c === 0x20/* Space */) ||
+ (c === 0x0A/* LF */) ||
+ (c === 0x0D/* CR */);
+}
+
+function is_FLOW_INDICATOR(c) {
+ return c === 0x2C/* , */ ||
+ c === 0x5B/* [ */ ||
+ c === 0x5D/* ] */ ||
+ c === 0x7B/* { */ ||
+ c === 0x7D/* } */;
+}
+
+function fromHexCode(c) {
+ var lc;
+
+ if ((0x30/* 0 */ <= c) && (c <= 0x39/* 9 */)) {
+ return c - 0x30;
+ }
+
+ /*eslint-disable no-bitwise*/
+ lc = c | 0x20;
+
+ if ((0x61/* a */ <= lc) && (lc <= 0x66/* f */)) {
+ return lc - 0x61 + 10;
+ }
+
+ return -1;
+}
+
+function escapedHexLen(c) {
+ if (c === 0x78/* x */) { return 2; }
+ if (c === 0x75/* u */) { return 4; }
+ if (c === 0x55/* U */) { return 8; }
+ return 0;
+}
+
+function fromDecimalCode(c) {
+ if ((0x30/* 0 */ <= c) && (c <= 0x39/* 9 */)) {
+ return c - 0x30;
+ }
+
+ return -1;
+}
+
+function simpleEscapeSequence(c) {
+ return (c === 0x30/* 0 */) ? '\x00' :
+ (c === 0x61/* a */) ? '\x07' :
+ (c === 0x62/* b */) ? '\x08' :
+ (c === 0x74/* t */) ? '\x09' :
+ (c === 0x09/* Tab */) ? '\x09' :
+ (c === 0x6E/* n */) ? '\x0A' :
+ (c === 0x76/* v */) ? '\x0B' :
+ (c === 0x66/* f */) ? '\x0C' :
+ (c === 0x72/* r */) ? '\x0D' :
+ (c === 0x65/* e */) ? '\x1B' :
+ (c === 0x20/* Space */) ? ' ' :
+ (c === 0x22/* " */) ? '\x22' :
+ (c === 0x2F/* / */) ? '/' :
+ (c === 0x5C/* \ */) ? '\x5C' :
+ (c === 0x4E/* N */) ? '\x85' :
+ (c === 0x5F/* _ */) ? '\xA0' :
+ (c === 0x4C/* L */) ? '\u2028' :
+ (c === 0x50/* P */) ? '\u2029' : '';
+}
+
+function charFromCodepoint(c) {
+ if (c <= 0xFFFF) {
+ return String.fromCharCode(c);
+ }
+ // Encode UTF-16 surrogate pair
+ // https://en.wikipedia.org/wiki/UTF-16#Code_points_U.2B010000_to_U.2B10FFFF
+ return String.fromCharCode(((c - 0x010000) >> 10) + 0xD800,
+ ((c - 0x010000) & 0x03FF) + 0xDC00);
+}
+
+var simpleEscapeCheck = new Array(256); // integer, for fast access
+var simpleEscapeMap = new Array(256);
+for (var i = 0; i < 256; i++) {
+ simpleEscapeCheck[i] = simpleEscapeSequence(i) ? 1 : 0;
+ simpleEscapeMap[i] = simpleEscapeSequence(i);
+}
+
+
+function State(input, options) {
+ this.input = input;
+
+ this.filename = options['filename'] || null;
+ this.schema = options['schema'] || DEFAULT_FULL_SCHEMA;
+ this.onWarning = options['onWarning'] || null;
+ this.legacy = options['legacy'] || false;
+ this.json = options['json'] || false;
+ this.listener = options['listener'] || null;
+
+ this.implicitTypes = this.schema.compiledImplicit;
+ this.typeMap = this.schema.compiledTypeMap;
+
+ this.length = input.length;
+ this.position = 0;
+ this.line = 0;
+ this.lineStart = 0;
+ this.lineIndent = 0;
+
+ this.documents = [];
+
+ /*
+ this.version;
+ this.checkLineBreaks;
+ this.tagMap;
+ this.anchorMap;
+ this.tag;
+ this.anchor;
+ this.kind;
+ this.result;*/
+
+}
+
+
+function generateError(state, message) {
+ return new YAMLException(
+ message,
+ new Mark(state.filename, state.input, state.position, state.line, (state.position - state.lineStart)));
+}
+
+function throwError(state, message) {
+ throw generateError(state, message);
+}
+
+function throwWarning(state, message) {
+ if (state.onWarning) {
+ state.onWarning.call(null, generateError(state, message));
+ }
+}
+
+
+var directiveHandlers = {
+
+ YAML: function handleYamlDirective(state, name, args) {
+
+ var match, major, minor;
+
+ if (state.version !== null) {
+ throwError(state, 'duplication of %YAML directive');
+ }
+
+ if (args.length !== 1) {
+ throwError(state, 'YAML directive accepts exactly one argument');
+ }
+
+ match = /^([0-9]+)\.([0-9]+)$/.exec(args[0]);
+
+ if (match === null) {
+ throwError(state, 'ill-formed argument of the YAML directive');
+ }
+
+ major = parseInt(match[1], 10);
+ minor = parseInt(match[2], 10);
+
+ if (major !== 1) {
+ throwError(state, 'unacceptable YAML version of the document');
+ }
+
+ state.version = args[0];
+ state.checkLineBreaks = (minor < 2);
+
+ if (minor !== 1 && minor !== 2) {
+ throwWarning(state, 'unsupported YAML version of the document');
+ }
+ },
+
+ TAG: function handleTagDirective(state, name, args) {
+
+ var handle, prefix;
+
+ if (args.length !== 2) {
+ throwError(state, 'TAG directive accepts exactly two arguments');
+ }
+
+ handle = args[0];
+ prefix = args[1];
+
+ if (!PATTERN_TAG_HANDLE.test(handle)) {
+ throwError(state, 'ill-formed tag handle (first argument) of the TAG directive');
+ }
+
+ if (_hasOwnProperty.call(state.tagMap, handle)) {
+ throwError(state, 'there is a previously declared suffix for "' + handle + '" tag handle');
+ }
+
+ if (!PATTERN_TAG_URI.test(prefix)) {
+ throwError(state, 'ill-formed tag prefix (second argument) of the TAG directive');
+ }
+
+ state.tagMap[handle] = prefix;
+ }
+};
+
+
+function captureSegment(state, start, end, checkJson) {
+ var _position, _length, _character, _result;
+
+ if (start < end) {
+ _result = state.input.slice(start, end);
+
+ if (checkJson) {
+ for (_position = 0, _length = _result.length;
+ _position < _length;
+ _position += 1) {
+ _character = _result.charCodeAt(_position);
+ if (!(_character === 0x09 ||
+ (0x20 <= _character && _character <= 0x10FFFF))) {
+ throwError(state, 'expected valid JSON character');
+ }
+ }
+ } else if (PATTERN_NON_PRINTABLE.test(_result)) {
+ throwError(state, 'the stream contains non-printable characters');
+ }
+
+ state.result += _result;
+ }
+}
+
+function mergeMappings(state, destination, source, overridableKeys) {
+ var sourceKeys, key, index, quantity;
+
+ if (!common.isObject(source)) {
+ throwError(state, 'cannot merge mappings; the provided source object is unacceptable');
+ }
+
+ sourceKeys = Object.keys(source);
+
+ for (index = 0, quantity = sourceKeys.length; index < quantity; index += 1) {
+ key = sourceKeys[index];
+
+ if (!_hasOwnProperty.call(destination, key)) {
+ destination[key] = source[key];
+ overridableKeys[key] = true;
+ }
+ }
+}
+
+function storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, valueNode) {
+ var index, quantity;
+
+ keyNode = String(keyNode);
+
+ if (_result === null) {
+ _result = {};
+ }
+
+ if (keyTag === 'tag:yaml.org,2002:merge') {
+ if (Array.isArray(valueNode)) {
+ for (index = 0, quantity = valueNode.length; index < quantity; index += 1) {
+ mergeMappings(state, _result, valueNode[index], overridableKeys);
+ }
+ } else {
+ mergeMappings(state, _result, valueNode, overridableKeys);
+ }
+ } else {
+ if (!state.json &&
+ !_hasOwnProperty.call(overridableKeys, keyNode) &&
+ _hasOwnProperty.call(_result, keyNode)) {
+ throwError(state, 'duplicated mapping key');
+ }
+ _result[keyNode] = valueNode;
+ delete overridableKeys[keyNode];
+ }
+
+ return _result;
+}
+
+function readLineBreak(state) {
+ var ch;
+
+ ch = state.input.charCodeAt(state.position);
+
+ if (ch === 0x0A/* LF */) {
+ state.position++;
+ } else if (ch === 0x0D/* CR */) {
+ state.position++;
+ if (state.input.charCodeAt(state.position) === 0x0A/* LF */) {
+ state.position++;
+ }
+ } else {
+ throwError(state, 'a line break is expected');
+ }
+
+ state.line += 1;
+ state.lineStart = state.position;
+}
+
+function skipSeparationSpace(state, allowComments, checkIndent) {
+ var lineBreaks = 0,
+ ch = state.input.charCodeAt(state.position);
+
+ while (ch !== 0) {
+ while (is_WHITE_SPACE(ch)) {
+ ch = state.input.charCodeAt(++state.position);
+ }
+
+ if (allowComments && ch === 0x23/* # */) {
+ do {
+ ch = state.input.charCodeAt(++state.position);
+ } while (ch !== 0x0A/* LF */ && ch !== 0x0D/* CR */ && ch !== 0);
+ }
+
+ if (is_EOL(ch)) {
+ readLineBreak(state);
+
+ ch = state.input.charCodeAt(state.position);
+ lineBreaks++;
+ state.lineIndent = 0;
+
+ while (ch === 0x20/* Space */) {
+ state.lineIndent++;
+ ch = state.input.charCodeAt(++state.position);
+ }
+ } else {
+ break;
+ }
+ }
+
+ if (checkIndent !== -1 && lineBreaks !== 0 && state.lineIndent < checkIndent) {
+ throwWarning(state, 'deficient indentation');
+ }
+
+ return lineBreaks;
+}
+
+function testDocumentSeparator(state) {
+ var _position = state.position,
+ ch;
+
+ ch = state.input.charCodeAt(_position);
+
+ // Condition state.position === state.lineStart is tested
+ // in parent on each call, for efficiency. No needs to test here again.
+ if ((ch === 0x2D/* - */ || ch === 0x2E/* . */) &&
+ ch === state.input.charCodeAt(_position + 1) &&
+ ch === state.input.charCodeAt(_position + 2)) {
+
+ _position += 3;
+
+ ch = state.input.charCodeAt(_position);
+
+ if (ch === 0 || is_WS_OR_EOL(ch)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+function writeFoldedLines(state, count) {
+ if (count === 1) {
+ state.result += ' ';
+ } else if (count > 1) {
+ state.result += common.repeat('\n', count - 1);
+ }
+}
+
+
+function readPlainScalar(state, nodeIndent, withinFlowCollection) {
+ var preceding,
+ following,
+ captureStart,
+ captureEnd,
+ hasPendingContent,
+ _line,
+ _lineStart,
+ _lineIndent,
+ _kind = state.kind,
+ _result = state.result,
+ ch;
+
+ ch = state.input.charCodeAt(state.position);
+
+ if (is_WS_OR_EOL(ch) ||
+ is_FLOW_INDICATOR(ch) ||
+ ch === 0x23/* # */ ||
+ ch === 0x26/* & */ ||
+ ch === 0x2A/* * */ ||
+ ch === 0x21/* ! */ ||
+ ch === 0x7C/* | */ ||
+ ch === 0x3E/* > */ ||
+ ch === 0x27/* ' */ ||
+ ch === 0x22/* " */ ||
+ ch === 0x25/* % */ ||
+ ch === 0x40/* @ */ ||
+ ch === 0x60/* ` */) {
+ return false;
+ }
+
+ if (ch === 0x3F/* ? */ || ch === 0x2D/* - */) {
+ following = state.input.charCodeAt(state.position + 1);
+
+ if (is_WS_OR_EOL(following) ||
+ withinFlowCollection && is_FLOW_INDICATOR(following)) {
+ return false;
+ }
+ }
+
+ state.kind = 'scalar';
+ state.result = '';
+ captureStart = captureEnd = state.position;
+ hasPendingContent = false;
+
+ while (ch !== 0) {
+ if (ch === 0x3A/* : */) {
+ following = state.input.charCodeAt(state.position + 1);
+
+ if (is_WS_OR_EOL(following) ||
+ withinFlowCollection && is_FLOW_INDICATOR(following)) {
+ break;
+ }
+
+ } else if (ch === 0x23/* # */) {
+ preceding = state.input.charCodeAt(state.position - 1);
+
+ if (is_WS_OR_EOL(preceding)) {
+ break;
+ }
+
+ } else if ((state.position === state.lineStart && testDocumentSeparator(state)) ||
+ withinFlowCollection && is_FLOW_INDICATOR(ch)) {
+ break;
+
+ } else if (is_EOL(ch)) {
+ _line = state.line;
+ _lineStart = state.lineStart;
+ _lineIndent = state.lineIndent;
+ skipSeparationSpace(state, false, -1);
+
+ if (state.lineIndent >= nodeIndent) {
+ hasPendingContent = true;
+ ch = state.input.charCodeAt(state.position);
+ continue;
+ } else {
+ state.position = captureEnd;
+ state.line = _line;
+ state.lineStart = _lineStart;
+ state.lineIndent = _lineIndent;
+ break;
+ }
+ }
+
+ if (hasPendingContent) {
+ captureSegment(state, captureStart, captureEnd, false);
+ writeFoldedLines(state, state.line - _line);
+ captureStart = captureEnd = state.position;
+ hasPendingContent = false;
+ }
+
+ if (!is_WHITE_SPACE(ch)) {
+ captureEnd = state.position + 1;
+ }
+
+ ch = state.input.charCodeAt(++state.position);
+ }
+
+ captureSegment(state, captureStart, captureEnd, false);
+
+ if (state.result) {
+ return true;
+ }
+
+ state.kind = _kind;
+ state.result = _result;
+ return false;
+}
+
+function readSingleQuotedScalar(state, nodeIndent) {
+ var ch,
+ captureStart, captureEnd;
+
+ ch = state.input.charCodeAt(state.position);
+
+ if (ch !== 0x27/* ' */) {
+ return false;
+ }
+
+ state.kind = 'scalar';
+ state.result = '';
+ state.position++;
+ captureStart = captureEnd = state.position;
+
+ while ((ch = state.input.charCodeAt(state.position)) !== 0) {
+ if (ch === 0x27/* ' */) {
+ captureSegment(state, captureStart, state.position, true);
+ ch = state.input.charCodeAt(++state.position);
+
+ if (ch === 0x27/* ' */) {
+ captureStart = state.position;
+ state.position++;
+ captureEnd = state.position;
+ } else {
+ return true;
+ }
+
+ } else if (is_EOL(ch)) {
+ captureSegment(state, captureStart, captureEnd, true);
+ writeFoldedLines(state, skipSeparationSpace(state, false, nodeIndent));
+ captureStart = captureEnd = state.position;
+
+ } else if (state.position === state.lineStart && testDocumentSeparator(state)) {
+ throwError(state, 'unexpected end of the document within a single quoted scalar');
+
+ } else {
+ state.position++;
+ captureEnd = state.position;
+ }
+ }
+
+ throwError(state, 'unexpected end of the stream within a single quoted scalar');
+}
+
+function readDoubleQuotedScalar(state, nodeIndent) {
+ var captureStart,
+ captureEnd,
+ hexLength,
+ hexResult,
+ tmp,
+ ch;
+
+ ch = state.input.charCodeAt(state.position);
+
+ if (ch !== 0x22/* " */) {
+ return false;
+ }
+
+ state.kind = 'scalar';
+ state.result = '';
+ state.position++;
+ captureStart = captureEnd = state.position;
+
+ while ((ch = state.input.charCodeAt(state.position)) !== 0) {
+ if (ch === 0x22/* " */) {
+ captureSegment(state, captureStart, state.position, true);
+ state.position++;
+ return true;
+
+ } else if (ch === 0x5C/* \ */) {
+ captureSegment(state, captureStart, state.position, true);
+ ch = state.input.charCodeAt(++state.position);
+
+ if (is_EOL(ch)) {
+ skipSeparationSpace(state, false, nodeIndent);
+
+ // TODO: rework to inline fn with no type cast?
+ } else if (ch < 256 && simpleEscapeCheck[ch]) {
+ state.result += simpleEscapeMap[ch];
+ state.position++;
+
+ } else if ((tmp = escapedHexLen(ch)) > 0) {
+ hexLength = tmp;
+ hexResult = 0;
+
+ for (; hexLength > 0; hexLength--) {
+ ch = state.input.charCodeAt(++state.position);
+
+ if ((tmp = fromHexCode(ch)) >= 0) {
+ hexResult = (hexResult << 4) + tmp;
+
+ } else {
+ throwError(state, 'expected hexadecimal character');
+ }
+ }
+
+ state.result += charFromCodepoint(hexResult);
+
+ state.position++;
+
+ } else {
+ throwError(state, 'unknown escape sequence');
+ }
+
+ captureStart = captureEnd = state.position;
+
+ } else if (is_EOL(ch)) {
+ captureSegment(state, captureStart, captureEnd, true);
+ writeFoldedLines(state, skipSeparationSpace(state, false, nodeIndent));
+ captureStart = captureEnd = state.position;
+
+ } else if (state.position === state.lineStart && testDocumentSeparator(state)) {
+ throwError(state, 'unexpected end of the document within a double quoted scalar');
+
+ } else {
+ state.position++;
+ captureEnd = state.position;
+ }
+ }
+
+ throwError(state, 'unexpected end of the stream within a double quoted scalar');
+}
+
+function readFlowCollection(state, nodeIndent) {
+ var readNext = true,
+ _line,
+ _tag = state.tag,
+ _result,
+ _anchor = state.anchor,
+ following,
+ terminator,
+ isPair,
+ isExplicitPair,
+ isMapping,
+ overridableKeys = {},
+ keyNode,
+ keyTag,
+ valueNode,
+ ch;
+
+ ch = state.input.charCodeAt(state.position);
+
+ if (ch === 0x5B/* [ */) {
+ terminator = 0x5D;/* ] */
+ isMapping = false;
+ _result = [];
+ } else if (ch === 0x7B/* { */) {
+ terminator = 0x7D;/* } */
+ isMapping = true;
+ _result = {};
+ } else {
+ return false;
+ }
+
+ if (state.anchor !== null) {
+ state.anchorMap[state.anchor] = _result;
+ }
+
+ ch = state.input.charCodeAt(++state.position);
+
+ while (ch !== 0) {
+ skipSeparationSpace(state, true, nodeIndent);
+
+ ch = state.input.charCodeAt(state.position);
+
+ if (ch === terminator) {
+ state.position++;
+ state.tag = _tag;
+ state.anchor = _anchor;
+ state.kind = isMapping ? 'mapping' : 'sequence';
+ state.result = _result;
+ return true;
+ } else if (!readNext) {
+ throwError(state, 'missed comma between flow collection entries');
+ }
+
+ keyTag = keyNode = valueNode = null;
+ isPair = isExplicitPair = false;
+
+ if (ch === 0x3F/* ? */) {
+ following = state.input.charCodeAt(state.position + 1);
+
+ if (is_WS_OR_EOL(following)) {
+ isPair = isExplicitPair = true;
+ state.position++;
+ skipSeparationSpace(state, true, nodeIndent);
+ }
+ }
+
+ _line = state.line;
+ composeNode(state, nodeIndent, CONTEXT_FLOW_IN, false, true);
+ keyTag = state.tag;
+ keyNode = state.result;
+ skipSeparationSpace(state, true, nodeIndent);
+
+ ch = state.input.charCodeAt(state.position);
+
+ if ((isExplicitPair || state.line === _line) && ch === 0x3A/* : */) {
+ isPair = true;
+ ch = state.input.charCodeAt(++state.position);
+ skipSeparationSpace(state, true, nodeIndent);
+ composeNode(state, nodeIndent, CONTEXT_FLOW_IN, false, true);
+ valueNode = state.result;
+ }
+
+ if (isMapping) {
+ storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, valueNode);
+ } else if (isPair) {
+ _result.push(storeMappingPair(state, null, overridableKeys, keyTag, keyNode, valueNode));
+ } else {
+ _result.push(keyNode);
+ }
+
+ skipSeparationSpace(state, true, nodeIndent);
+
+ ch = state.input.charCodeAt(state.position);
+
+ if (ch === 0x2C/* , */) {
+ readNext = true;
+ ch = state.input.charCodeAt(++state.position);
+ } else {
+ readNext = false;
+ }
+ }
+
+ throwError(state, 'unexpected end of the stream within a flow collection');
+}
+
+function readBlockScalar(state, nodeIndent) {
+ var captureStart,
+ folding,
+ chomping = CHOMPING_CLIP,
+ didReadContent = false,
+ detectedIndent = false,
+ textIndent = nodeIndent,
+ emptyLines = 0,
+ atMoreIndented = false,
+ tmp,
+ ch;
+
+ ch = state.input.charCodeAt(state.position);
+
+ if (ch === 0x7C/* | */) {
+ folding = false;
+ } else if (ch === 0x3E/* > */) {
+ folding = true;
+ } else {
+ return false;
+ }
+
+ state.kind = 'scalar';
+ state.result = '';
+
+ while (ch !== 0) {
+ ch = state.input.charCodeAt(++state.position);
+
+ if (ch === 0x2B/* + */ || ch === 0x2D/* - */) {
+ if (CHOMPING_CLIP === chomping) {
+ chomping = (ch === 0x2B/* + */) ? CHOMPING_KEEP : CHOMPING_STRIP;
+ } else {
+ throwError(state, 'repeat of a chomping mode identifier');
+ }
+
+ } else if ((tmp = fromDecimalCode(ch)) >= 0) {
+ if (tmp === 0) {
+ throwError(state, 'bad explicit indentation width of a block scalar; it cannot be less than one');
+ } else if (!detectedIndent) {
+ textIndent = nodeIndent + tmp - 1;
+ detectedIndent = true;
+ } else {
+ throwError(state, 'repeat of an indentation width identifier');
+ }
+
+ } else {
+ break;
+ }
+ }
+
+ if (is_WHITE_SPACE(ch)) {
+ do { ch = state.input.charCodeAt(++state.position); }
+ while (is_WHITE_SPACE(ch));
+
+ if (ch === 0x23/* # */) {
+ do { ch = state.input.charCodeAt(++state.position); }
+ while (!is_EOL(ch) && (ch !== 0));
+ }
+ }
+
+ while (ch !== 0) {
+ readLineBreak(state);
+ state.lineIndent = 0;
+
+ ch = state.input.charCodeAt(state.position);
+
+ while ((!detectedIndent || state.lineIndent < textIndent) &&
+ (ch === 0x20/* Space */)) {
+ state.lineIndent++;
+ ch = state.input.charCodeAt(++state.position);
+ }
+
+ if (!detectedIndent && state.lineIndent > textIndent) {
+ textIndent = state.lineIndent;
+ }
+
+ if (is_EOL(ch)) {
+ emptyLines++;
+ continue;
+ }
+
+ // End of the scalar.
+ if (state.lineIndent < textIndent) {
+
+ // Perform the chomping.
+ if (chomping === CHOMPING_KEEP) {
+ state.result += common.repeat('\n', didReadContent ? 1 + emptyLines : emptyLines);
+ } else if (chomping === CHOMPING_CLIP) {
+ if (didReadContent) { // i.e. only if the scalar is not empty.
+ state.result += '\n';
+ }
+ }
+
+ // Break this `while` cycle and go to the funciton's epilogue.
+ break;
+ }
+
+ // Folded style: use fancy rules to handle line breaks.
+ if (folding) {
+
+ // Lines starting with white space characters (more-indented lines) are not folded.
+ if (is_WHITE_SPACE(ch)) {
+ atMoreIndented = true;
+ // except for the first content line (cf. Example 8.1)
+ state.result += common.repeat('\n', didReadContent ? 1 + emptyLines : emptyLines);
+
+ // End of more-indented block.
+ } else if (atMoreIndented) {
+ atMoreIndented = false;
+ state.result += common.repeat('\n', emptyLines + 1);
+
+ // Just one line break - perceive as the same line.
+ } else if (emptyLines === 0) {
+ if (didReadContent) { // i.e. only if we have already read some scalar content.
+ state.result += ' ';
+ }
+
+ // Several line breaks - perceive as different lines.
+ } else {
+ state.result += common.repeat('\n', emptyLines);
+ }
+
+ // Literal style: just add exact number of line breaks between content lines.
+ } else {
+ // Keep all line breaks except the header line break.
+ state.result += common.repeat('\n', didReadContent ? 1 + emptyLines : emptyLines);
+ }
+
+ didReadContent = true;
+ detectedIndent = true;
+ emptyLines = 0;
+ captureStart = state.position;
+
+ while (!is_EOL(ch) && (ch !== 0)) {
+ ch = state.input.charCodeAt(++state.position);
+ }
+
+ captureSegment(state, captureStart, state.position, false);
+ }
+
+ return true;
+}
+
+function readBlockSequence(state, nodeIndent) {
+ var _line,
+ _tag = state.tag,
+ _anchor = state.anchor,
+ _result = [],
+ following,
+ detected = false,
+ ch;
+
+ if (state.anchor !== null) {
+ state.anchorMap[state.anchor] = _result;
+ }
+
+ ch = state.input.charCodeAt(state.position);
+
+ while (ch !== 0) {
+
+ if (ch !== 0x2D/* - */) {
+ break;
+ }
+
+ following = state.input.charCodeAt(state.position + 1);
+
+ if (!is_WS_OR_EOL(following)) {
+ break;
+ }
+
+ detected = true;
+ state.position++;
+
+ if (skipSeparationSpace(state, true, -1)) {
+ if (state.lineIndent <= nodeIndent) {
+ _result.push(null);
+ ch = state.input.charCodeAt(state.position);
+ continue;
+ }
+ }
+
+ _line = state.line;
+ composeNode(state, nodeIndent, CONTEXT_BLOCK_IN, false, true);
+ _result.push(state.result);
+ skipSeparationSpace(state, true, -1);
+
+ ch = state.input.charCodeAt(state.position);
+
+ if ((state.line === _line || state.lineIndent > nodeIndent) && (ch !== 0)) {
+ throwError(state, 'bad indentation of a sequence entry');
+ } else if (state.lineIndent < nodeIndent) {
+ break;
+ }
+ }
+
+ if (detected) {
+ state.tag = _tag;
+ state.anchor = _anchor;
+ state.kind = 'sequence';
+ state.result = _result;
+ return true;
+ }
+ return false;
+}
+
+function readBlockMapping(state, nodeIndent, flowIndent) {
+ var following,
+ allowCompact,
+ _line,
+ _tag = state.tag,
+ _anchor = state.anchor,
+ _result = {},
+ overridableKeys = {},
+ keyTag = null,
+ keyNode = null,
+ valueNode = null,
+ atExplicitKey = false,
+ detected = false,
+ ch;
+
+ if (state.anchor !== null) {
+ state.anchorMap[state.anchor] = _result;
+ }
+
+ ch = state.input.charCodeAt(state.position);
+
+ while (ch !== 0) {
+ following = state.input.charCodeAt(state.position + 1);
+ _line = state.line; // Save the current line.
+
+ //
+ // Explicit notation case. There are two separate blocks:
+ // first for the key (denoted by "?") and second for the value (denoted by ":")
+ //
+ if ((ch === 0x3F/* ? */ || ch === 0x3A/* : */) && is_WS_OR_EOL(following)) {
+
+ if (ch === 0x3F/* ? */) {
+ if (atExplicitKey) {
+ storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, null);
+ keyTag = keyNode = valueNode = null;
+ }
+
+ detected = true;
+ atExplicitKey = true;
+ allowCompact = true;
+
+ } else if (atExplicitKey) {
+ // i.e. 0x3A/* : */ === character after the explicit key.
+ atExplicitKey = false;
+ allowCompact = true;
+
+ } else {
+ throwError(state, 'incomplete explicit mapping pair; a key node is missed');
+ }
+
+ state.position += 1;
+ ch = following;
+
+ //
+ // Implicit notation case. Flow-style node as the key first, then ":", and the value.
+ //
+ } else if (composeNode(state, flowIndent, CONTEXT_FLOW_OUT, false, true)) {
+
+ if (state.line === _line) {
+ ch = state.input.charCodeAt(state.position);
+
+ while (is_WHITE_SPACE(ch)) {
+ ch = state.input.charCodeAt(++state.position);
+ }
+
+ if (ch === 0x3A/* : */) {
+ ch = state.input.charCodeAt(++state.position);
+
+ if (!is_WS_OR_EOL(ch)) {
+ throwError(state, 'a whitespace character is expected after the key-value separator within a block mapping');
+ }
+
+ if (atExplicitKey) {
+ storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, null);
+ keyTag = keyNode = valueNode = null;
+ }
+
+ detected = true;
+ atExplicitKey = false;
+ allowCompact = false;
+ keyTag = state.tag;
+ keyNode = state.result;
+
+ } else if (detected) {
+ throwError(state, 'can not read an implicit mapping pair; a colon is missed');
+
+ } else {
+ state.tag = _tag;
+ state.anchor = _anchor;
+ return true; // Keep the result of `composeNode`.
+ }
+
+ } else if (detected) {
+ throwError(state, 'can not read a block mapping entry; a multiline key may not be an implicit key');
+
+ } else {
+ state.tag = _tag;
+ state.anchor = _anchor;
+ return true; // Keep the result of `composeNode`.
+ }
+
+ } else {
+ break; // Reading is done. Go to the epilogue.
+ }
+
+ //
+ // Common reading code for both explicit and implicit notations.
+ //
+ if (state.line === _line || state.lineIndent > nodeIndent) {
+ if (composeNode(state, nodeIndent, CONTEXT_BLOCK_OUT, true, allowCompact)) {
+ if (atExplicitKey) {
+ keyNode = state.result;
+ } else {
+ valueNode = state.result;
+ }
+ }
+
+ if (!atExplicitKey) {
+ storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, valueNode);
+ keyTag = keyNode = valueNode = null;
+ }
+
+ skipSeparationSpace(state, true, -1);
+ ch = state.input.charCodeAt(state.position);
+ }
+
+ if (state.lineIndent > nodeIndent && (ch !== 0)) {
+ throwError(state, 'bad indentation of a mapping entry');
+ } else if (state.lineIndent < nodeIndent) {
+ break;
+ }
+ }
+
+ //
+ // Epilogue.
+ //
+
+ // Special case: last mapping's node contains only the key in explicit notation.
+ if (atExplicitKey) {
+ storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, null);
+ }
+
+ // Expose the resulting mapping.
+ if (detected) {
+ state.tag = _tag;
+ state.anchor = _anchor;
+ state.kind = 'mapping';
+ state.result = _result;
+ }
+
+ return detected;
+}
+
+function readTagProperty(state) {
+ var _position,
+ isVerbatim = false,
+ isNamed = false,
+ tagHandle,
+ tagName,
+ ch;
+
+ ch = state.input.charCodeAt(state.position);
+
+ if (ch !== 0x21/* ! */) return false;
+
+ if (state.tag !== null) {
+ throwError(state, 'duplication of a tag property');
+ }
+
+ ch = state.input.charCodeAt(++state.position);
+
+ if (ch === 0x3C/* < */) {
+ isVerbatim = true;
+ ch = state.input.charCodeAt(++state.position);
+
+ } else if (ch === 0x21/* ! */) {
+ isNamed = true;
+ tagHandle = '!!';
+ ch = state.input.charCodeAt(++state.position);
+
+ } else {
+ tagHandle = '!';
+ }
+
+ _position = state.position;
+
+ if (isVerbatim) {
+ do { ch = state.input.charCodeAt(++state.position); }
+ while (ch !== 0 && ch !== 0x3E/* > */);
+
+ if (state.position < state.length) {
+ tagName = state.input.slice(_position, state.position);
+ ch = state.input.charCodeAt(++state.position);
+ } else {
+ throwError(state, 'unexpected end of the stream within a verbatim tag');
+ }
+ } else {
+ while (ch !== 0 && !is_WS_OR_EOL(ch)) {
+
+ if (ch === 0x21/* ! */) {
+ if (!isNamed) {
+ tagHandle = state.input.slice(_position - 1, state.position + 1);
+
+ if (!PATTERN_TAG_HANDLE.test(tagHandle)) {
+ throwError(state, 'named tag handle cannot contain such characters');
+ }
+
+ isNamed = true;
+ _position = state.position + 1;
+ } else {
+ throwError(state, 'tag suffix cannot contain exclamation marks');
+ }
+ }
+
+ ch = state.input.charCodeAt(++state.position);
+ }
+
+ tagName = state.input.slice(_position, state.position);
+
+ if (PATTERN_FLOW_INDICATORS.test(tagName)) {
+ throwError(state, 'tag suffix cannot contain flow indicator characters');
+ }
+ }
+
+ if (tagName && !PATTERN_TAG_URI.test(tagName)) {
+ throwError(state, 'tag name cannot contain such characters: ' + tagName);
+ }
+
+ if (isVerbatim) {
+ state.tag = tagName;
+
+ } else if (_hasOwnProperty.call(state.tagMap, tagHandle)) {
+ state.tag = state.tagMap[tagHandle] + tagName;
+
+ } else if (tagHandle === '!') {
+ state.tag = '!' + tagName;
+
+ } else if (tagHandle === '!!') {
+ state.tag = 'tag:yaml.org,2002:' + tagName;
+
+ } else {
+ throwError(state, 'undeclared tag handle "' + tagHandle + '"');
+ }
+
+ return true;
+}
+
+function readAnchorProperty(state) {
+ var _position,
+ ch;
+
+ ch = state.input.charCodeAt(state.position);
+
+ if (ch !== 0x26/* & */) return false;
+
+ if (state.anchor !== null) {
+ throwError(state, 'duplication of an anchor property');
+ }
+
+ ch = state.input.charCodeAt(++state.position);
+ _position = state.position;
+
+ while (ch !== 0 && !is_WS_OR_EOL(ch) && !is_FLOW_INDICATOR(ch)) {
+ ch = state.input.charCodeAt(++state.position);
+ }
+
+ if (state.position === _position) {
+ throwError(state, 'name of an anchor node must contain at least one character');
+ }
+
+ state.anchor = state.input.slice(_position, state.position);
+ return true;
+}
+
+function readAlias(state) {
+ var _position, alias,
+ ch;
+
+ ch = state.input.charCodeAt(state.position);
+
+ if (ch !== 0x2A/* * */) return false;
+
+ ch = state.input.charCodeAt(++state.position);
+ _position = state.position;
+
+ while (ch !== 0 && !is_WS_OR_EOL(ch) && !is_FLOW_INDICATOR(ch)) {
+ ch = state.input.charCodeAt(++state.position);
+ }
+
+ if (state.position === _position) {
+ throwError(state, 'name of an alias node must contain at least one character');
+ }
+
+ alias = state.input.slice(_position, state.position);
+
+ if (!state.anchorMap.hasOwnProperty(alias)) {
+ throwError(state, 'unidentified alias "' + alias + '"');
+ }
+
+ state.result = state.anchorMap[alias];
+ skipSeparationSpace(state, true, -1);
+ return true;
+}
+
+function composeNode(state, parentIndent, nodeContext, allowToSeek, allowCompact) {
+ var allowBlockStyles,
+ allowBlockScalars,
+ allowBlockCollections,
+ indentStatus = 1, // 1: this>parent, 0: this=parent, -1: this<parent
+ atNewLine = false,
+ hasContent = false,
+ typeIndex,
+ typeQuantity,
+ type,
+ flowIndent,
+ blockIndent;
+
+ if (state.listener !== null) {
+ state.listener('open', state);
+ }
+
+ state.tag = null;
+ state.anchor = null;
+ state.kind = null;
+ state.result = null;
+
+ allowBlockStyles = allowBlockScalars = allowBlockCollections =
+ CONTEXT_BLOCK_OUT === nodeContext ||
+ CONTEXT_BLOCK_IN === nodeContext;
+
+ if (allowToSeek) {
+ if (skipSeparationSpace(state, true, -1)) {
+ atNewLine = true;
+
+ if (state.lineIndent > parentIndent) {
+ indentStatus = 1;
+ } else if (state.lineIndent === parentIndent) {
+ indentStatus = 0;
+ } else if (state.lineIndent < parentIndent) {
+ indentStatus = -1;
+ }
+ }
+ }
+
+ if (indentStatus === 1) {
+ while (readTagProperty(state) || readAnchorProperty(state)) {
+ if (skipSeparationSpace(state, true, -1)) {
+ atNewLine = true;
+ allowBlockCollections = allowBlockStyles;
+
+ if (state.lineIndent > parentIndent) {
+ indentStatus = 1;
+ } else if (state.lineIndent === parentIndent) {
+ indentStatus = 0;
+ } else if (state.lineIndent < parentIndent) {
+ indentStatus = -1;
+ }
+ } else {
+ allowBlockCollections = false;
+ }
+ }
+ }
+
+ if (allowBlockCollections) {
+ allowBlockCollections = atNewLine || allowCompact;
+ }
+
+ if (indentStatus === 1 || CONTEXT_BLOCK_OUT === nodeContext) {
+ if (CONTEXT_FLOW_IN === nodeContext || CONTEXT_FLOW_OUT === nodeContext) {
+ flowIndent = parentIndent;
+ } else {
+ flowIndent = parentIndent + 1;
+ }
+
+ blockIndent = state.position - state.lineStart;
+
+ if (indentStatus === 1) {
+ if (allowBlockCollections &&
+ (readBlockSequence(state, blockIndent) ||
+ readBlockMapping(state, blockIndent, flowIndent)) ||
+ readFlowCollection(state, flowIndent)) {
+ hasContent = true;
+ } else {
+ if ((allowBlockScalars && readBlockScalar(state, flowIndent)) ||
+ readSingleQuotedScalar(state, flowIndent) ||
+ readDoubleQuotedScalar(state, flowIndent)) {
+ hasContent = true;
+
+ } else if (readAlias(state)) {
+ hasContent = true;
+
+ if (state.tag !== null || state.anchor !== null) {
+ throwError(state, 'alias node should not have any properties');
+ }
+
+ } else if (readPlainScalar(state, flowIndent, CONTEXT_FLOW_IN === nodeContext)) {
+ hasContent = true;
+
+ if (state.tag === null) {
+ state.tag = '?';
+ }
+ }
+
+ if (state.anchor !== null) {
+ state.anchorMap[state.anchor] = state.result;
+ }
+ }
+ } else if (indentStatus === 0) {
+ // Special case: block sequences are allowed to have same indentation level as the parent.
+ // http://www.yaml.org/spec/1.2/spec.html#id2799784
+ hasContent = allowBlockCollections && readBlockSequence(state, blockIndent);
+ }
+ }
+
+ if (state.tag !== null && state.tag !== '!') {
+ if (state.tag === '?') {
+ for (typeIndex = 0, typeQuantity = state.implicitTypes.length;
+ typeIndex < typeQuantity;
+ typeIndex += 1) {
+ type = state.implicitTypes[typeIndex];
+
+ // Implicit resolving is not allowed for non-scalar types, and '?'
+ // non-specific tag is only assigned to plain scalars. So, it isn't
+ // needed to check for 'kind' conformity.
+
+ if (type.resolve(state.result)) { // `state.result` updated in resolver if matched
+ state.result = type.construct(state.result);
+ state.tag = type.tag;
+ if (state.anchor !== null) {
+ state.anchorMap[state.anchor] = state.result;
+ }
+ break;
+ }
+ }
+ } else if (_hasOwnProperty.call(state.typeMap[state.kind || 'fallback'], state.tag)) {
+ type = state.typeMap[state.kind || 'fallback'][state.tag];
+
+ if (state.result !== null && type.kind !== state.kind) {
+ throwError(state, 'unacceptable node kind for !<' + state.tag + '> tag; it should be "' + type.kind + '", not "' + state.kind + '"');
+ }
+
+ if (!type.resolve(state.result)) { // `state.result` updated in resolver if matched
+ throwError(state, 'cannot resolve a node with !<' + state.tag + '> explicit tag');
+ } else {
+ state.result = type.construct(state.result);
+ if (state.anchor !== null) {
+ state.anchorMap[state.anchor] = state.result;
+ }
+ }
+ } else {
+ throwError(state, 'unknown tag !<' + state.tag + '>');
+ }
+ }
+
+ if (state.listener !== null) {
+ state.listener('close', state);
+ }
+ return state.tag !== null || state.anchor !== null || hasContent;
+}
+
+function readDocument(state) {
+ var documentStart = state.position,
+ _position,
+ directiveName,
+ directiveArgs,
+ hasDirectives = false,
+ ch;
+
+ state.version = null;
+ state.checkLineBreaks = state.legacy;
+ state.tagMap = {};
+ state.anchorMap = {};
+
+ while ((ch = state.input.charCodeAt(state.position)) !== 0) {
+ skipSeparationSpace(state, true, -1);
+
+ ch = state.input.charCodeAt(state.position);
+
+ if (state.lineIndent > 0 || ch !== 0x25/* % */) {
+ break;
+ }
+
+ hasDirectives = true;
+ ch = state.input.charCodeAt(++state.position);
+ _position = state.position;
+
+ while (ch !== 0 && !is_WS_OR_EOL(ch)) {
+ ch = state.input.charCodeAt(++state.position);
+ }
+
+ directiveName = state.input.slice(_position, state.position);
+ directiveArgs = [];
+
+ if (directiveName.length < 1) {
+ throwError(state, 'directive name must not be less than one character in length');
+ }
+
+ while (ch !== 0) {
+ while (is_WHITE_SPACE(ch)) {
+ ch = state.input.charCodeAt(++state.position);
+ }
+
+ if (ch === 0x23/* # */) {
+ do { ch = state.input.charCodeAt(++state.position); }
+ while (ch !== 0 && !is_EOL(ch));
+ break;
+ }
+
+ if (is_EOL(ch)) break;
+
+ _position = state.position;
+
+ while (ch !== 0 && !is_WS_OR_EOL(ch)) {
+ ch = state.input.charCodeAt(++state.position);
+ }
+
+ directiveArgs.push(state.input.slice(_position, state.position));
+ }
+
+ if (ch !== 0) readLineBreak(state);
+
+ if (_hasOwnProperty.call(directiveHandlers, directiveName)) {
+ directiveHandlers[directiveName](state, directiveName, directiveArgs);
+ } else {
+ throwWarning(state, 'unknown document directive "' + directiveName + '"');
+ }
+ }
+
+ skipSeparationSpace(state, true, -1);
+
+ if (state.lineIndent === 0 &&
+ state.input.charCodeAt(state.position) === 0x2D/* - */ &&
+ state.input.charCodeAt(state.position + 1) === 0x2D/* - */ &&
+ state.input.charCodeAt(state.position + 2) === 0x2D/* - */) {
+ state.position += 3;
+ skipSeparationSpace(state, true, -1);
+
+ } else if (hasDirectives) {
+ throwError(state, 'directives end mark is expected');
+ }
+
+ composeNode(state, state.lineIndent - 1, CONTEXT_BLOCK_OUT, false, true);
+ skipSeparationSpace(state, true, -1);
+
+ if (state.checkLineBreaks &&
+ PATTERN_NON_ASCII_LINE_BREAKS.test(state.input.slice(documentStart, state.position))) {
+ throwWarning(state, 'non-ASCII line breaks are interpreted as content');
+ }
+
+ state.documents.push(state.result);
+
+ if (state.position === state.lineStart && testDocumentSeparator(state)) {
+
+ if (state.input.charCodeAt(state.position) === 0x2E/* . */) {
+ state.position += 3;
+ skipSeparationSpace(state, true, -1);
+ }
+ return;
+ }
+
+ if (state.position < (state.length - 1)) {
+ throwError(state, 'end of the stream or a document separator is expected');
+ } else {
+ return;
+ }
+}
+
+
+function loadDocuments(input, options) {
+ input = String(input);
+ options = options || {};
+
+ if (input.length !== 0) {
+
+ // Add tailing `\n` if not exists
+ if (input.charCodeAt(input.length - 1) !== 0x0A/* LF */ &&
+ input.charCodeAt(input.length - 1) !== 0x0D/* CR */) {
+ input += '\n';
+ }
+
+ // Strip BOM
+ if (input.charCodeAt(0) === 0xFEFF) {
+ input = input.slice(1);
+ }
+ }
+
+ var state = new State(input, options);
+
+ // Use 0 as string terminator. That significantly simplifies bounds check.
+ state.input += '\0';
+
+ while (state.input.charCodeAt(state.position) === 0x20/* Space */) {
+ state.lineIndent += 1;
+ state.position += 1;
+ }
+
+ while (state.position < (state.length - 1)) {
+ readDocument(state);
+ }
+
+ return state.documents;
+}
+
+
+function loadAll(input, iterator, options) {
+ var documents = loadDocuments(input, options), index, length;
+
+ for (index = 0, length = documents.length; index < length; index += 1) {
+ iterator(documents[index]);
+ }
+}
+
+
+function load(input, options) {
+ var documents = loadDocuments(input, options);
+
+ if (documents.length === 0) {
+ /*eslint-disable no-undefined*/
+ return undefined;
+ } else if (documents.length === 1) {
+ return documents[0];
+ }
+ throw new YAMLException('expected a single document in the stream, but found more');
+}
+
+
+function safeLoadAll(input, output, options) {
+ loadAll(input, output, common.extend({ schema: DEFAULT_SAFE_SCHEMA }, options));
+}
+
+
+function safeLoad(input, options) {
+ return load(input, common.extend({ schema: DEFAULT_SAFE_SCHEMA }, options));
+}
+
+
+module.exports.loadAll = loadAll;
+module.exports.load = load;
+module.exports.safeLoadAll = safeLoadAll;
+module.exports.safeLoad = safeLoad;
diff --git a/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/mark.js b/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/mark.js
new file mode 100644
index 00000000..47b265c2
--- /dev/null
+++ b/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/mark.js
@@ -0,0 +1,76 @@
+'use strict';
+
+
+var common = require('./common');
+
+
+function Mark(name, buffer, position, line, column) {
+ this.name = name;
+ this.buffer = buffer;
+ this.position = position;
+ this.line = line;
+ this.column = column;
+}
+
+
+Mark.prototype.getSnippet = function getSnippet(indent, maxLength) {
+ var head, start, tail, end, snippet;
+
+ if (!this.buffer) return null;
+
+ indent = indent || 4;
+ maxLength = maxLength || 75;
+
+ head = '';
+ start = this.position;
+
+ while (start > 0 && '\x00\r\n\x85\u2028\u2029'.indexOf(this.buffer.charAt(start - 1)) === -1) {
+ start -= 1;
+ if (this.position - start > (maxLength / 2 - 1)) {
+ head = ' ... ';
+ start += 5;
+ break;
+ }
+ }
+
+ tail = '';
+ end = this.position;
+
+ while (end < this.buffer.length && '\x00\r\n\x85\u2028\u2029'.indexOf(this.buffer.charAt(end)) === -1) {
+ end += 1;
+ if (end - this.position > (maxLength / 2 - 1)) {
+ tail = ' ... ';
+ end -= 5;
+ break;
+ }
+ }
+
+ snippet = this.buffer.slice(start, end);
+
+ return common.repeat(' ', indent) + head + snippet + tail + '\n' +
+ common.repeat(' ', indent + this.position - start + head.length) + '^';
+};
+
+
+Mark.prototype.toString = function toString(compact) {
+ var snippet, where = '';
+
+ if (this.name) {
+ where += 'in "' + this.name + '" ';
+ }
+
+ where += 'at line ' + (this.line + 1) + ', column ' + (this.column + 1);
+
+ if (!compact) {
+ snippet = this.getSnippet();
+
+ if (snippet) {
+ where += ':\n' + snippet;
+ }
+ }
+
+ return where;
+};
+
+
+module.exports = Mark;
diff --git a/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/schema.js b/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/schema.js
new file mode 100644
index 00000000..ca7cf47e
--- /dev/null
+++ b/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/schema.js
@@ -0,0 +1,108 @@
+'use strict';
+
+/*eslint-disable max-len*/
+
+var common = require('./common');
+var YAMLException = require('./exception');
+var Type = require('./type');
+
+
+function compileList(schema, name, result) {
+ var exclude = [];
+
+ schema.include.forEach(function (includedSchema) {
+ result = compileList(includedSchema, name, result);
+ });
+
+ schema[name].forEach(function (currentType) {
+ result.forEach(function (previousType, previousIndex) {
+ if (previousType.tag === currentType.tag && previousType.kind === currentType.kind) {
+ exclude.push(previousIndex);
+ }
+ });
+
+ result.push(currentType);
+ });
+
+ return result.filter(function (type, index) {
+ return exclude.indexOf(index) === -1;
+ });
+}
+
+
+function compileMap(/* lists... */) {
+ var result = {
+ scalar: {},
+ sequence: {},
+ mapping: {},
+ fallback: {}
+ }, index, length;
+
+ function collectType(type) {
+ result[type.kind][type.tag] = result['fallback'][type.tag] = type;
+ }
+
+ for (index = 0, length = arguments.length; index < length; index += 1) {
+ arguments[index].forEach(collectType);
+ }
+ return result;
+}
+
+
+function Schema(definition) {
+ this.include = definition.include || [];
+ this.implicit = definition.implicit || [];
+ this.explicit = definition.explicit || [];
+
+ this.implicit.forEach(function (type) {
+ if (type.loadKind && type.loadKind !== 'scalar') {
+ throw new YAMLException('There is a non-scalar type in the implicit list of a schema. Implicit resolving of such types is not supported.');
+ }
+ });
+
+ this.compiledImplicit = compileList(this, 'implicit', []);
+ this.compiledExplicit = compileList(this, 'explicit', []);
+ this.compiledTypeMap = compileMap(this.compiledImplicit, this.compiledExplicit);
+}
+
+
+Schema.DEFAULT = null;
+
+
+Schema.create = function createSchema() {
+ var schemas, types;
+
+ switch (arguments.length) {
+ case 1:
+ schemas = Schema.DEFAULT;
+ types = arguments[0];
+ break;
+
+ case 2:
+ schemas = arguments[0];
+ types = arguments[1];
+ break;
+
+ default:
+ throw new YAMLException('Wrong number of arguments for Schema.create function');
+ }
+
+ schemas = common.toArray(schemas);
+ types = common.toArray(types);
+
+ if (!schemas.every(function (schema) { return schema instanceof Schema; })) {
+ throw new YAMLException('Specified list of super schemas (or a single Schema object) contains a non-Schema object.');
+ }
+
+ if (!types.every(function (type) { return type instanceof Type; })) {
+ throw new YAMLException('Specified list of YAML types (or a single Type object) contains a non-Type object.');
+ }
+
+ return new Schema({
+ include: schemas,
+ explicit: types
+ });
+};
+
+
+module.exports = Schema;
diff --git a/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/schema/core.js b/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/schema/core.js
new file mode 100644
index 00000000..206daab5
--- /dev/null
+++ b/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/schema/core.js
@@ -0,0 +1,18 @@
+// Standard YAML's Core schema.
+// http://www.yaml.org/spec/1.2/spec.html#id2804923
+//
+// NOTE: JS-YAML does not support schema-specific tag resolution restrictions.
+// So, Core schema has no distinctions from JSON schema is JS-YAML.
+
+
+'use strict';
+
+
+var Schema = require('../schema');
+
+
+module.exports = new Schema({
+ include: [
+ require('./json')
+ ]
+});
diff --git a/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/schema/default_full.js b/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/schema/default_full.js
new file mode 100644
index 00000000..a55ef42a
--- /dev/null
+++ b/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/schema/default_full.js
@@ -0,0 +1,25 @@
+// JS-YAML's default schema for `load` function.
+// It is not described in the YAML specification.
+//
+// This schema is based on JS-YAML's default safe schema and includes
+// JavaScript-specific types: !!js/undefined, !!js/regexp and !!js/function.
+//
+// Also this schema is used as default base schema at `Schema.create` function.
+
+
+'use strict';
+
+
+var Schema = require('../schema');
+
+
+module.exports = Schema.DEFAULT = new Schema({
+ include: [
+ require('./default_safe')
+ ],
+ explicit: [
+ require('../type/js/undefined'),
+ require('../type/js/regexp'),
+ require('../type/js/function')
+ ]
+});
diff --git a/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/schema/default_safe.js b/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/schema/default_safe.js
new file mode 100644
index 00000000..11d89bbf
--- /dev/null
+++ b/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/schema/default_safe.js
@@ -0,0 +1,28 @@
+// JS-YAML's default schema for `safeLoad` function.
+// It is not described in the YAML specification.
+//
+// This schema is based on standard YAML's Core schema and includes most of
+// extra types described at YAML tag repository. (http://yaml.org/type/)
+
+
+'use strict';
+
+
+var Schema = require('../schema');
+
+
+module.exports = new Schema({
+ include: [
+ require('./core')
+ ],
+ implicit: [
+ require('../type/timestamp'),
+ require('../type/merge')
+ ],
+ explicit: [
+ require('../type/binary'),
+ require('../type/omap'),
+ require('../type/pairs'),
+ require('../type/set')
+ ]
+});
diff --git a/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/schema/failsafe.js b/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/schema/failsafe.js
new file mode 100644
index 00000000..b7a33eb7
--- /dev/null
+++ b/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/schema/failsafe.js
@@ -0,0 +1,17 @@
+// Standard YAML's Failsafe schema.
+// http://www.yaml.org/spec/1.2/spec.html#id2802346
+
+
+'use strict';
+
+
+var Schema = require('../schema');
+
+
+module.exports = new Schema({
+ explicit: [
+ require('../type/str'),
+ require('../type/seq'),
+ require('../type/map')
+ ]
+});
diff --git a/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/schema/json.js b/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/schema/json.js
new file mode 100644
index 00000000..5be3dbf8
--- /dev/null
+++ b/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/schema/json.js
@@ -0,0 +1,25 @@
+// Standard YAML's JSON schema.
+// http://www.yaml.org/spec/1.2/spec.html#id2803231
+//
+// NOTE: JS-YAML does not support schema-specific tag resolution restrictions.
+// So, this schema is not such strict as defined in the YAML specification.
+// It allows numbers in binary notaion, use `Null` and `NULL` as `null`, etc.
+
+
+'use strict';
+
+
+var Schema = require('../schema');
+
+
+module.exports = new Schema({
+ include: [
+ require('./failsafe')
+ ],
+ implicit: [
+ require('../type/null'),
+ require('../type/bool'),
+ require('../type/int'),
+ require('../type/float')
+ ]
+});
diff --git a/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/type.js b/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/type.js
new file mode 100644
index 00000000..90b702ac
--- /dev/null
+++ b/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/type.js
@@ -0,0 +1,61 @@
+'use strict';
+
+var YAMLException = require('./exception');
+
+var TYPE_CONSTRUCTOR_OPTIONS = [
+ 'kind',
+ 'resolve',
+ 'construct',
+ 'instanceOf',
+ 'predicate',
+ 'represent',
+ 'defaultStyle',
+ 'styleAliases'
+];
+
+var YAML_NODE_KINDS = [
+ 'scalar',
+ 'sequence',
+ 'mapping'
+];
+
+function compileStyleAliases(map) {
+ var result = {};
+
+ if (map !== null) {
+ Object.keys(map).forEach(function (style) {
+ map[style].forEach(function (alias) {
+ result[String(alias)] = style;
+ });
+ });
+ }
+
+ return result;
+}
+
+function Type(tag, options) {
+ options = options || {};
+
+ Object.keys(options).forEach(function (name) {
+ if (TYPE_CONSTRUCTOR_OPTIONS.indexOf(name) === -1) {
+ throw new YAMLException('Unknown option "' + name + '" is met in definition of "' + tag + '" YAML type.');
+ }
+ });
+
+ // TODO: Add tag format check.
+ this.tag = tag;
+ this.kind = options['kind'] || null;
+ this.resolve = options['resolve'] || function () { return true; };
+ this.construct = options['construct'] || function (data) { return data; };
+ this.instanceOf = options['instanceOf'] || null;
+ this.predicate = options['predicate'] || null;
+ this.represent = options['represent'] || null;
+ this.defaultStyle = options['defaultStyle'] || null;
+ this.styleAliases = compileStyleAliases(options['styleAliases'] || null);
+
+ if (YAML_NODE_KINDS.indexOf(this.kind) === -1) {
+ throw new YAMLException('Unknown kind "' + this.kind + '" is specified for "' + tag + '" YAML type.');
+ }
+}
+
+module.exports = Type;
diff --git a/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/type/binary.js b/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/type/binary.js
new file mode 100644
index 00000000..205629f7
--- /dev/null
+++ b/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/type/binary.js
@@ -0,0 +1,135 @@
+'use strict';
+
+/*eslint-disable no-bitwise*/
+
+var NodeBuffer;
+
+try {
+ // A trick for browserified version, to not include `Buffer` shim
+ var _require = require;
+ NodeBuffer = _require('buffer').Buffer;
+} catch (__) {}
+
+var Type = require('../type');
+
+
+// [ 64, 65, 66 ] -> [ padding, CR, LF ]
+var BASE64_MAP = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\n\r';
+
+
+function resolveYamlBinary(data) {
+ if (data === null) return false;
+
+ var code, idx, bitlen = 0, max = data.length, map = BASE64_MAP;
+
+ // Convert one by one.
+ for (idx = 0; idx < max; idx++) {
+ code = map.indexOf(data.charAt(idx));
+
+ // Skip CR/LF
+ if (code > 64) continue;
+
+ // Fail on illegal characters
+ if (code < 0) return false;
+
+ bitlen += 6;
+ }
+
+ // If there are any bits left, source was corrupted
+ return (bitlen % 8) === 0;
+}
+
+function constructYamlBinary(data) {
+ var idx, tailbits,
+ input = data.replace(/[\r\n=]/g, ''), // remove CR/LF & padding to simplify scan
+ max = input.length,
+ map = BASE64_MAP,
+ bits = 0,
+ result = [];
+
+ // Collect by 6*4 bits (3 bytes)
+
+ for (idx = 0; idx < max; idx++) {
+ if ((idx % 4 === 0) && idx) {
+ result.push((bits >> 16) & 0xFF);
+ result.push((bits >> 8) & 0xFF);
+ result.push(bits & 0xFF);
+ }
+
+ bits = (bits << 6) | map.indexOf(input.charAt(idx));
+ }
+
+ // Dump tail
+
+ tailbits = (max % 4) * 6;
+
+ if (tailbits === 0) {
+ result.push((bits >> 16) & 0xFF);
+ result.push((bits >> 8) & 0xFF);
+ result.push(bits & 0xFF);
+ } else if (tailbits === 18) {
+ result.push((bits >> 10) & 0xFF);
+ result.push((bits >> 2) & 0xFF);
+ } else if (tailbits === 12) {
+ result.push((bits >> 4) & 0xFF);
+ }
+
+ // Wrap into Buffer for NodeJS and leave Array for browser
+ if (NodeBuffer) return new NodeBuffer(result);
+
+ return result;
+}
+
+function representYamlBinary(object /*, style*/) {
+ var result = '', bits = 0, idx, tail,
+ max = object.length,
+ map = BASE64_MAP;
+
+ // Convert every three bytes to 4 ASCII characters.
+
+ for (idx = 0; idx < max; idx++) {
+ if ((idx % 3 === 0) && idx) {
+ result += map[(bits >> 18) & 0x3F];
+ result += map[(bits >> 12) & 0x3F];
+ result += map[(bits >> 6) & 0x3F];
+ result += map[bits & 0x3F];
+ }
+
+ bits = (bits << 8) + object[idx];
+ }
+
+ // Dump tail
+
+ tail = max % 3;
+
+ if (tail === 0) {
+ result += map[(bits >> 18) & 0x3F];
+ result += map[(bits >> 12) & 0x3F];
+ result += map[(bits >> 6) & 0x3F];
+ result += map[bits & 0x3F];
+ } else if (tail === 2) {
+ result += map[(bits >> 10) & 0x3F];
+ result += map[(bits >> 4) & 0x3F];
+ result += map[(bits << 2) & 0x3F];
+ result += map[64];
+ } else if (tail === 1) {
+ result += map[(bits >> 2) & 0x3F];
+ result += map[(bits << 4) & 0x3F];
+ result += map[64];
+ result += map[64];
+ }
+
+ return result;
+}
+
+function isBinary(object) {
+ return NodeBuffer && NodeBuffer.isBuffer(object);
+}
+
+module.exports = new Type('tag:yaml.org,2002:binary', {
+ kind: 'scalar',
+ resolve: resolveYamlBinary,
+ construct: constructYamlBinary,
+ predicate: isBinary,
+ represent: representYamlBinary
+});
diff --git a/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/type/bool.js b/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/type/bool.js
new file mode 100644
index 00000000..cb774593
--- /dev/null
+++ b/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/type/bool.js
@@ -0,0 +1,35 @@
+'use strict';
+
+var Type = require('../type');
+
+function resolveYamlBoolean(data) {
+ if (data === null) return false;
+
+ var max = data.length;
+
+ return (max === 4 && (data === 'true' || data === 'True' || data === 'TRUE')) ||
+ (max === 5 && (data === 'false' || data === 'False' || data === 'FALSE'));
+}
+
+function constructYamlBoolean(data) {
+ return data === 'true' ||
+ data === 'True' ||
+ data === 'TRUE';
+}
+
+function isBoolean(object) {
+ return Object.prototype.toString.call(object) === '[object Boolean]';
+}
+
+module.exports = new Type('tag:yaml.org,2002:bool', {
+ kind: 'scalar',
+ resolve: resolveYamlBoolean,
+ construct: constructYamlBoolean,
+ predicate: isBoolean,
+ represent: {
+ lowercase: function (object) { return object ? 'true' : 'false'; },
+ uppercase: function (object) { return object ? 'TRUE' : 'FALSE'; },
+ camelcase: function (object) { return object ? 'True' : 'False'; }
+ },
+ defaultStyle: 'lowercase'
+});
diff --git a/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/type/float.js b/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/type/float.js
new file mode 100644
index 00000000..76871547
--- /dev/null
+++ b/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/type/float.js
@@ -0,0 +1,105 @@
+'use strict';
+
+var common = require('../common');
+var Type = require('../type');
+
+var YAML_FLOAT_PATTERN = new RegExp(
+ '^(?:[-+]?(?:[0-9][0-9_]*)\\.[0-9_]*(?:[eE][-+][0-9]+)?' +
+ '|\\.[0-9_]+(?:[eE][-+][0-9]+)?' +
+ '|[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]*' +
+ '|[-+]?\\.(?:inf|Inf|INF)' +
+ '|\\.(?:nan|NaN|NAN))$');
+
+function resolveYamlFloat(data) {
+ if (data === null) return false;
+
+ if (!YAML_FLOAT_PATTERN.test(data)) return false;
+
+ return true;
+}
+
+function constructYamlFloat(data) {
+ var value, sign, base, digits;
+
+ value = data.replace(/_/g, '').toLowerCase();
+ sign = value[0] === '-' ? -1 : 1;
+ digits = [];
+
+ if ('+-'.indexOf(value[0]) >= 0) {
+ value = value.slice(1);
+ }
+
+ if (value === '.inf') {
+ return (sign === 1) ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY;
+
+ } else if (value === '.nan') {
+ return NaN;
+
+ } else if (value.indexOf(':') >= 0) {
+ value.split(':').forEach(function (v) {
+ digits.unshift(parseFloat(v, 10));
+ });
+
+ value = 0.0;
+ base = 1;
+
+ digits.forEach(function (d) {
+ value += d * base;
+ base *= 60;
+ });
+
+ return sign * value;
+
+ }
+ return sign * parseFloat(value, 10);
+}
+
+
+var SCIENTIFIC_WITHOUT_DOT = /^[-+]?[0-9]+e/;
+
+function representYamlFloat(object, style) {
+ var res;
+
+ if (isNaN(object)) {
+ switch (style) {
+ case 'lowercase': return '.nan';
+ case 'uppercase': return '.NAN';
+ case 'camelcase': return '.NaN';
+ }
+ } else if (Number.POSITIVE_INFINITY === object) {
+ switch (style) {
+ case 'lowercase': return '.inf';
+ case 'uppercase': return '.INF';
+ case 'camelcase': return '.Inf';
+ }
+ } else if (Number.NEGATIVE_INFINITY === object) {
+ switch (style) {
+ case 'lowercase': return '-.inf';
+ case 'uppercase': return '-.INF';
+ case 'camelcase': return '-.Inf';
+ }
+ } else if (common.isNegativeZero(object)) {
+ return '-0.0';
+ }
+
+ res = object.toString(10);
+
+ // JS stringifier can build scientific format without dots: 5e-100,
+ // while YAML requres dot: 5.e-100. Fix it with simple hack
+
+ return SCIENTIFIC_WITHOUT_DOT.test(res) ? res.replace('e', '.e') : res;
+}
+
+function isFloat(object) {
+ return (Object.prototype.toString.call(object) === '[object Number]') &&
+ (object % 1 !== 0 || common.isNegativeZero(object));
+}
+
+module.exports = new Type('tag:yaml.org,2002:float', {
+ kind: 'scalar',
+ resolve: resolveYamlFloat,
+ construct: constructYamlFloat,
+ predicate: isFloat,
+ represent: representYamlFloat,
+ defaultStyle: 'lowercase'
+});
diff --git a/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/type/int.js b/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/type/int.js
new file mode 100644
index 00000000..a3c49650
--- /dev/null
+++ b/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/type/int.js
@@ -0,0 +1,168 @@
+'use strict';
+
+var common = require('../common');
+var Type = require('../type');
+
+function isHexCode(c) {
+ return ((0x30/* 0 */ <= c) && (c <= 0x39/* 9 */)) ||
+ ((0x41/* A */ <= c) && (c <= 0x46/* F */)) ||
+ ((0x61/* a */ <= c) && (c <= 0x66/* f */));
+}
+
+function isOctCode(c) {
+ return ((0x30/* 0 */ <= c) && (c <= 0x37/* 7 */));
+}
+
+function isDecCode(c) {
+ return ((0x30/* 0 */ <= c) && (c <= 0x39/* 9 */));
+}
+
+function resolveYamlInteger(data) {
+ if (data === null) return false;
+
+ var max = data.length,
+ index = 0,
+ hasDigits = false,
+ ch;
+
+ if (!max) return false;
+
+ ch = data[index];
+
+ // sign
+ if (ch === '-' || ch === '+') {
+ ch = data[++index];
+ }
+
+ if (ch === '0') {
+ // 0
+ if (index + 1 === max) return true;
+ ch = data[++index];
+
+ // base 2, base 8, base 16
+
+ if (ch === 'b') {
+ // base 2
+ index++;
+
+ for (; index < max; index++) {
+ ch = data[index];
+ if (ch === '_') continue;
+ if (ch !== '0' && ch !== '1') return false;
+ hasDigits = true;
+ }
+ return hasDigits;
+ }
+
+
+ if (ch === 'x') {
+ // base 16
+ index++;
+
+ for (; index < max; index++) {
+ ch = data[index];
+ if (ch === '_') continue;
+ if (!isHexCode(data.charCodeAt(index))) return false;
+ hasDigits = true;
+ }
+ return hasDigits;
+ }
+
+ // base 8
+ for (; index < max; index++) {
+ ch = data[index];
+ if (ch === '_') continue;
+ if (!isOctCode(data.charCodeAt(index))) return false;
+ hasDigits = true;
+ }
+ return hasDigits;
+ }
+
+ // base 10 (except 0) or base 60
+
+ for (; index < max; index++) {
+ ch = data[index];
+ if (ch === '_') continue;
+ if (ch === ':') break;
+ if (!isDecCode(data.charCodeAt(index))) {
+ return false;
+ }
+ hasDigits = true;
+ }
+
+ if (!hasDigits) return false;
+
+ // if !base60 - done;
+ if (ch !== ':') return true;
+
+ // base60 almost not used, no needs to optimize
+ return /^(:[0-5]?[0-9])+$/.test(data.slice(index));
+}
+
+function constructYamlInteger(data) {
+ var value = data, sign = 1, ch, base, digits = [];
+
+ if (value.indexOf('_') !== -1) {
+ value = value.replace(/_/g, '');
+ }
+
+ ch = value[0];
+
+ if (ch === '-' || ch === '+') {
+ if (ch === '-') sign = -1;
+ value = value.slice(1);
+ ch = value[0];
+ }
+
+ if (value === '0') return 0;
+
+ if (ch === '0') {
+ if (value[1] === 'b') return sign * parseInt(value.slice(2), 2);
+ if (value[1] === 'x') return sign * parseInt(value, 16);
+ return sign * parseInt(value, 8);
+ }
+
+ if (value.indexOf(':') !== -1) {
+ value.split(':').forEach(function (v) {
+ digits.unshift(parseInt(v, 10));
+ });
+
+ value = 0;
+ base = 1;
+
+ digits.forEach(function (d) {
+ value += (d * base);
+ base *= 60;
+ });
+
+ return sign * value;
+
+ }
+
+ return sign * parseInt(value, 10);
+}
+
+function isInteger(object) {
+ return (Object.prototype.toString.call(object)) === '[object Number]' &&
+ (object % 1 === 0 && !common.isNegativeZero(object));
+}
+
+module.exports = new Type('tag:yaml.org,2002:int', {
+ kind: 'scalar',
+ resolve: resolveYamlInteger,
+ construct: constructYamlInteger,
+ predicate: isInteger,
+ represent: {
+ binary: function (object) { return '0b' + object.toString(2); },
+ octal: function (object) { return '0' + object.toString(8); },
+ decimal: function (object) { return object.toString(10); },
+ hexadecimal: function (object) { return '0x' + object.toString(16).toUpperCase(); }
+ },
+ defaultStyle: 'decimal',
+ styleAliases: {
+ binary: [ 2, 'bin' ],
+ octal: [ 8, 'oct' ],
+ decimal: [ 10, 'dec' ],
+ hexadecimal: [ 16, 'hex' ]
+ }
+});
diff --git a/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/type/js/function.js b/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/type/js/function.js
new file mode 100644
index 00000000..c6a42d00
--- /dev/null
+++ b/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/type/js/function.js
@@ -0,0 +1,84 @@
+'use strict';
+
+var esprima;
+
+// Browserified version does not have esprima
+//
+// 1. For node.js just require module as deps
+// 2. For browser try to require mudule via external AMD system.
+// If not found - try to fallback to window.esprima. If not
+// found too - then fail to parse.
+//
+try {
+ // workaround to exclude package from browserify list.
+ var _require = require;
+ esprima = _require('esprima');
+} catch (_) {
+ /*global window */
+ if (typeof window !== 'undefined') esprima = window.esprima;
+}
+
+var Type = require('../../type');
+
+function resolveJavascriptFunction(data) {
+ if (data === null) return false;
+
+ try {
+ var source = '(' + data + ')',
+ ast = esprima.parse(source, { range: true });
+
+ if (ast.type !== 'Program' ||
+ ast.body.length !== 1 ||
+ ast.body[0].type !== 'ExpressionStatement' ||
+ ast.body[0].expression.type !== 'FunctionExpression') {
+ return false;
+ }
+
+ return true;
+ } catch (err) {
+ return false;
+ }
+}
+
+function constructJavascriptFunction(data) {
+ /*jslint evil:true*/
+
+ var source = '(' + data + ')',
+ ast = esprima.parse(source, { range: true }),
+ params = [],
+ body;
+
+ if (ast.type !== 'Program' ||
+ ast.body.length !== 1 ||
+ ast.body[0].type !== 'ExpressionStatement' ||
+ ast.body[0].expression.type !== 'FunctionExpression') {
+ throw new Error('Failed to resolve function');
+ }
+
+ ast.body[0].expression.params.forEach(function (param) {
+ params.push(param.name);
+ });
+
+ body = ast.body[0].expression.body.range;
+
+ // Esprima's ranges include the first '{' and the last '}' characters on
+ // function expressions. So cut them out.
+ /*eslint-disable no-new-func*/
+ return new Function(params, source.slice(body[0] + 1, body[1] - 1));
+}
+
+function representJavascriptFunction(object /*, style*/) {
+ return object.toString();
+}
+
+function isFunction(object) {
+ return Object.prototype.toString.call(object) === '[object Function]';
+}
+
+module.exports = new Type('tag:yaml.org,2002:js/function', {
+ kind: 'scalar',
+ resolve: resolveJavascriptFunction,
+ construct: constructJavascriptFunction,
+ predicate: isFunction,
+ represent: representJavascriptFunction
+});
diff --git a/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/type/js/regexp.js b/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/type/js/regexp.js
new file mode 100644
index 00000000..43fa4701
--- /dev/null
+++ b/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/type/js/regexp.js
@@ -0,0 +1,60 @@
+'use strict';
+
+var Type = require('../../type');
+
+function resolveJavascriptRegExp(data) {
+ if (data === null) return false;
+ if (data.length === 0) return false;
+
+ var regexp = data,
+ tail = /\/([gim]*)$/.exec(data),
+ modifiers = '';
+
+ // if regexp starts with '/' it can have modifiers and must be properly closed
+ // `/foo/gim` - modifiers tail can be maximum 3 chars
+ if (regexp[0] === '/') {
+ if (tail) modifiers = tail[1];
+
+ if (modifiers.length > 3) return false;
+ // if expression starts with /, is should be properly terminated
+ if (regexp[regexp.length - modifiers.length - 1] !== '/') return false;
+ }
+
+ return true;
+}
+
+function constructJavascriptRegExp(data) {
+ var regexp = data,
+ tail = /\/([gim]*)$/.exec(data),
+ modifiers = '';
+
+ // `/foo/gim` - tail can be maximum 4 chars
+ if (regexp[0] === '/') {
+ if (tail) modifiers = tail[1];
+ regexp = regexp.slice(1, regexp.length - modifiers.length - 1);
+ }
+
+ return new RegExp(regexp, modifiers);
+}
+
+function representJavascriptRegExp(object /*, style*/) {
+ var result = '/' + object.source + '/';
+
+ if (object.global) result += 'g';
+ if (object.multiline) result += 'm';
+ if (object.ignoreCase) result += 'i';
+
+ return result;
+}
+
+function isRegExp(object) {
+ return Object.prototype.toString.call(object) === '[object RegExp]';
+}
+
+module.exports = new Type('tag:yaml.org,2002:js/regexp', {
+ kind: 'scalar',
+ resolve: resolveJavascriptRegExp,
+ construct: constructJavascriptRegExp,
+ predicate: isRegExp,
+ represent: representJavascriptRegExp
+});
diff --git a/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/type/js/undefined.js b/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/type/js/undefined.js
new file mode 100644
index 00000000..95b5569f
--- /dev/null
+++ b/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/type/js/undefined.js
@@ -0,0 +1,28 @@
+'use strict';
+
+var Type = require('../../type');
+
+function resolveJavascriptUndefined() {
+ return true;
+}
+
+function constructJavascriptUndefined() {
+ /*eslint-disable no-undefined*/
+ return undefined;
+}
+
+function representJavascriptUndefined() {
+ return '';
+}
+
+function isUndefined(object) {
+ return typeof object === 'undefined';
+}
+
+module.exports = new Type('tag:yaml.org,2002:js/undefined', {
+ kind: 'scalar',
+ resolve: resolveJavascriptUndefined,
+ construct: constructJavascriptUndefined,
+ predicate: isUndefined,
+ represent: representJavascriptUndefined
+});
diff --git a/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/type/map.js b/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/type/map.js
new file mode 100644
index 00000000..f327beeb
--- /dev/null
+++ b/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/type/map.js
@@ -0,0 +1,8 @@
+'use strict';
+
+var Type = require('../type');
+
+module.exports = new Type('tag:yaml.org,2002:map', {
+ kind: 'mapping',
+ construct: function (data) { return data !== null ? data : {}; }
+});
diff --git a/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/type/merge.js b/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/type/merge.js
new file mode 100644
index 00000000..ae08a864
--- /dev/null
+++ b/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/type/merge.js
@@ -0,0 +1,12 @@
+'use strict';
+
+var Type = require('../type');
+
+function resolveYamlMerge(data) {
+ return data === '<<' || data === null;
+}
+
+module.exports = new Type('tag:yaml.org,2002:merge', {
+ kind: 'scalar',
+ resolve: resolveYamlMerge
+});
diff --git a/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/type/null.js b/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/type/null.js
new file mode 100644
index 00000000..6874daa6
--- /dev/null
+++ b/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/type/null.js
@@ -0,0 +1,34 @@
+'use strict';
+
+var Type = require('../type');
+
+function resolveYamlNull(data) {
+ if (data === null) return true;
+
+ var max = data.length;
+
+ return (max === 1 && data === '~') ||
+ (max === 4 && (data === 'null' || data === 'Null' || data === 'NULL'));
+}
+
+function constructYamlNull() {
+ return null;
+}
+
+function isNull(object) {
+ return object === null;
+}
+
+module.exports = new Type('tag:yaml.org,2002:null', {
+ kind: 'scalar',
+ resolve: resolveYamlNull,
+ construct: constructYamlNull,
+ predicate: isNull,
+ represent: {
+ canonical: function () { return '~'; },
+ lowercase: function () { return 'null'; },
+ uppercase: function () { return 'NULL'; },
+ camelcase: function () { return 'Null'; }
+ },
+ defaultStyle: 'lowercase'
+});
diff --git a/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/type/omap.js b/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/type/omap.js
new file mode 100644
index 00000000..b2b5323b
--- /dev/null
+++ b/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/type/omap.js
@@ -0,0 +1,44 @@
+'use strict';
+
+var Type = require('../type');
+
+var _hasOwnProperty = Object.prototype.hasOwnProperty;
+var _toString = Object.prototype.toString;
+
+function resolveYamlOmap(data) {
+ if (data === null) return true;
+
+ var objectKeys = [], index, length, pair, pairKey, pairHasKey,
+ object = data;
+
+ for (index = 0, length = object.length; index < length; index += 1) {
+ pair = object[index];
+ pairHasKey = false;
+
+ if (_toString.call(pair) !== '[object Object]') return false;
+
+ for (pairKey in pair) {
+ if (_hasOwnProperty.call(pair, pairKey)) {
+ if (!pairHasKey) pairHasKey = true;
+ else return false;
+ }
+ }
+
+ if (!pairHasKey) return false;
+
+ if (objectKeys.indexOf(pairKey) === -1) objectKeys.push(pairKey);
+ else return false;
+ }
+
+ return true;
+}
+
+function constructYamlOmap(data) {
+ return data !== null ? data : [];
+}
+
+module.exports = new Type('tag:yaml.org,2002:omap', {
+ kind: 'sequence',
+ resolve: resolveYamlOmap,
+ construct: constructYamlOmap
+});
diff --git a/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/type/pairs.js b/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/type/pairs.js
new file mode 100644
index 00000000..74b52403
--- /dev/null
+++ b/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/type/pairs.js
@@ -0,0 +1,53 @@
+'use strict';
+
+var Type = require('../type');
+
+var _toString = Object.prototype.toString;
+
+function resolveYamlPairs(data) {
+ if (data === null) return true;
+
+ var index, length, pair, keys, result,
+ object = data;
+
+ result = new Array(object.length);
+
+ for (index = 0, length = object.length; index < length; index += 1) {
+ pair = object[index];
+
+ if (_toString.call(pair) !== '[object Object]') return false;
+
+ keys = Object.keys(pair);
+
+ if (keys.length !== 1) return false;
+
+ result[index] = [ keys[0], pair[keys[0]] ];
+ }
+
+ return true;
+}
+
+function constructYamlPairs(data) {
+ if (data === null) return [];
+
+ var index, length, pair, keys, result,
+ object = data;
+
+ result = new Array(object.length);
+
+ for (index = 0, length = object.length; index < length; index += 1) {
+ pair = object[index];
+
+ keys = Object.keys(pair);
+
+ result[index] = [ keys[0], pair[keys[0]] ];
+ }
+
+ return result;
+}
+
+module.exports = new Type('tag:yaml.org,2002:pairs', {
+ kind: 'sequence',
+ resolve: resolveYamlPairs,
+ construct: constructYamlPairs
+});
diff --git a/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/type/seq.js b/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/type/seq.js
new file mode 100644
index 00000000..be8f77f2
--- /dev/null
+++ b/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/type/seq.js
@@ -0,0 +1,8 @@
+'use strict';
+
+var Type = require('../type');
+
+module.exports = new Type('tag:yaml.org,2002:seq', {
+ kind: 'sequence',
+ construct: function (data) { return data !== null ? data : []; }
+});
diff --git a/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/type/set.js b/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/type/set.js
new file mode 100644
index 00000000..f885a329
--- /dev/null
+++ b/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/type/set.js
@@ -0,0 +1,29 @@
+'use strict';
+
+var Type = require('../type');
+
+var _hasOwnProperty = Object.prototype.hasOwnProperty;
+
+function resolveYamlSet(data) {
+ if (data === null) return true;
+
+ var key, object = data;
+
+ for (key in object) {
+ if (_hasOwnProperty.call(object, key)) {
+ if (object[key] !== null) return false;
+ }
+ }
+
+ return true;
+}
+
+function constructYamlSet(data) {
+ return data !== null ? data : {};
+}
+
+module.exports = new Type('tag:yaml.org,2002:set', {
+ kind: 'mapping',
+ resolve: resolveYamlSet,
+ construct: constructYamlSet
+});
diff --git a/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/type/str.js b/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/type/str.js
new file mode 100644
index 00000000..27acc106
--- /dev/null
+++ b/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/type/str.js
@@ -0,0 +1,8 @@
+'use strict';
+
+var Type = require('../type');
+
+module.exports = new Type('tag:yaml.org,2002:str', {
+ kind: 'scalar',
+ construct: function (data) { return data !== null ? data : ''; }
+});
diff --git a/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/type/timestamp.js b/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/type/timestamp.js
new file mode 100644
index 00000000..8fa9c586
--- /dev/null
+++ b/node_modules/svgo/node_modules/js-yaml/lib/js-yaml/type/timestamp.js
@@ -0,0 +1,88 @@
+'use strict';
+
+var Type = require('../type');
+
+var YAML_DATE_REGEXP = new RegExp(
+ '^([0-9][0-9][0-9][0-9])' + // [1] year
+ '-([0-9][0-9])' + // [2] month
+ '-([0-9][0-9])$'); // [3] day
+
+var YAML_TIMESTAMP_REGEXP = new RegExp(
+ '^([0-9][0-9][0-9][0-9])' + // [1] year
+ '-([0-9][0-9]?)' + // [2] month
+ '-([0-9][0-9]?)' + // [3] day
+ '(?:[Tt]|[ \\t]+)' + // ...
+ '([0-9][0-9]?)' + // [4] hour
+ ':([0-9][0-9])' + // [5] minute
+ ':([0-9][0-9])' + // [6] second
+ '(?:\\.([0-9]*))?' + // [7] fraction
+ '(?:[ \\t]*(Z|([-+])([0-9][0-9]?)' + // [8] tz [9] tz_sign [10] tz_hour
+ '(?::([0-9][0-9]))?))?$'); // [11] tz_minute
+
+function resolveYamlTimestamp(data) {
+ if (data === null) return false;
+ if (YAML_DATE_REGEXP.exec(data) !== null) return true;
+ if (YAML_TIMESTAMP_REGEXP.exec(data) !== null) return true;
+ return false;
+}
+
+function constructYamlTimestamp(data) {
+ var match, year, month, day, hour, minute, second, fraction = 0,
+ delta = null, tz_hour, tz_minute, date;
+
+ match = YAML_DATE_REGEXP.exec(data);
+ if (match === null) match = YAML_TIMESTAMP_REGEXP.exec(data);
+
+ if (match === null) throw new Error('Date resolve error');
+
+ // match: [1] year [2] month [3] day
+
+ year = +(match[1]);
+ month = +(match[2]) - 1; // JS month starts with 0
+ day = +(match[3]);
+
+ if (!match[4]) { // no hour
+ return new Date(Date.UTC(year, month, day));
+ }
+
+ // match: [4] hour [5] minute [6] second [7] fraction
+
+ hour = +(match[4]);
+ minute = +(match[5]);
+ second = +(match[6]);
+
+ if (match[7]) {
+ fraction = match[7].slice(0, 3);
+ while (fraction.length < 3) { // milli-seconds
+ fraction += '0';
+ }
+ fraction = +fraction;
+ }
+
+ // match: [8] tz [9] tz_sign [10] tz_hour [11] tz_minute
+
+ if (match[9]) {
+ tz_hour = +(match[10]);
+ tz_minute = +(match[11] || 0);
+ delta = (tz_hour * 60 + tz_minute) * 60000; // delta in mili-seconds
+ if (match[9] === '-') delta = -delta;
+ }
+
+ date = new Date(Date.UTC(year, month, day, hour, minute, second, fraction));
+
+ if (delta) date.setTime(date.getTime() - delta);
+
+ return date;
+}
+
+function representYamlTimestamp(object /*, style*/) {
+ return object.toISOString();
+}
+
+module.exports = new Type('tag:yaml.org,2002:timestamp', {
+ kind: 'scalar',
+ resolve: resolveYamlTimestamp,
+ construct: constructYamlTimestamp,
+ instanceOf: Date,
+ represent: representYamlTimestamp
+});
diff --git a/node_modules/svgo/node_modules/js-yaml/node_modules/.bin/esparse b/node_modules/svgo/node_modules/js-yaml/node_modules/.bin/esparse
new file mode 120000
index 00000000..d3e4b572
--- /dev/null
+++ b/node_modules/svgo/node_modules/js-yaml/node_modules/.bin/esparse
@@ -0,0 +1 @@
+../../../esprima/bin/esparse.js \ No newline at end of file
diff --git a/node_modules/svgo/node_modules/js-yaml/node_modules/.bin/esvalidate b/node_modules/svgo/node_modules/js-yaml/node_modules/.bin/esvalidate
new file mode 120000
index 00000000..f8ef4b99
--- /dev/null
+++ b/node_modules/svgo/node_modules/js-yaml/node_modules/.bin/esvalidate
@@ -0,0 +1 @@
+../../../esprima/bin/esvalidate.js \ No newline at end of file
diff --git a/node_modules/svgo/node_modules/js-yaml/package.json b/node_modules/svgo/node_modules/js-yaml/package.json
new file mode 100644
index 00000000..1c6deb19
--- /dev/null
+++ b/node_modules/svgo/node_modules/js-yaml/package.json
@@ -0,0 +1,46 @@
+{
+ "name": "js-yaml",
+ "version": "3.7.0",
+ "description": "YAML 1.2 parser and serializer",
+ "keywords": [
+ "yaml",
+ "parser",
+ "serializer",
+ "pyyaml"
+ ],
+ "homepage": "https://github.com/nodeca/js-yaml",
+ "author": "Vladimir Zapparov <dervus.grim@gmail.com>",
+ "contributors": [
+ "Aleksey V Zapparov <ixti@member.fsf.org> (http://www.ixti.net/)",
+ "Vitaly Puzrin <vitaly@rcdesign.ru> (https://github.com/puzrin)",
+ "Martin Grenfell <martin.grenfell@gmail.com> (http://got-ravings.blogspot.com)"
+ ],
+ "license": "MIT",
+ "repository": "nodeca/js-yaml",
+ "files": [
+ "index.js",
+ "lib/",
+ "bin/",
+ "dist/"
+ ],
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ },
+ "dependencies": {
+ "argparse": "^1.0.7",
+ "esprima": "^2.6.0"
+ },
+ "devDependencies": {
+ "ansi": "*",
+ "benchmark": "*",
+ "browserify": "^13.0.0",
+ "codemirror": "^5.13.4",
+ "eslint": "^2.8.0",
+ "istanbul": "*",
+ "mocha": "*",
+ "uglify-js": "^2.6.1"
+ },
+ "scripts": {
+ "test": "make test"
+ }
+}
diff --git a/node_modules/svgo/package.json b/node_modules/svgo/package.json
new file mode 100644
index 00000000..be1eee49
--- /dev/null
+++ b/node_modules/svgo/package.json
@@ -0,0 +1,70 @@
+{
+ "name": "svgo",
+ "version": "0.7.2",
+ "description": "Nodejs-based tool for optimizing SVG vector graphics files",
+ "keywords": [
+ "svgo",
+ "svg",
+ "optimize",
+ "minify"
+ ],
+ "homepage": "https://github.com/svg/svgo",
+ "bugs": {
+ "url": "https://github.com/svg/svgo/issues",
+ "email": "kir@soulshine.in"
+ },
+ "author": {
+ "name": "Kir Belevich",
+ "email": "kir@soulshine.in",
+ "url": "https://github.com/deepsweet"
+ },
+ "contributors": [
+ {
+ "name": "Sergey Belov",
+ "email": "peimei@ya.ru",
+ "url": "http://github.com/arikon"
+ },
+ {
+ "name": "Lev Solntsev",
+ "email": "lev.sun@ya.ru",
+ "url": "http://github.com/GreLI"
+ }
+ ],
+ "repository": {
+ "type": "git",
+ "url": "git://github.com/svg/svgo.git"
+ },
+ "main": "./lib/svgo.js",
+ "bin": {
+ "svgo": "./bin/svgo"
+ },
+ "directories": {
+ "bin": "./bin",
+ "lib": "./lib",
+ "example": "./examples"
+ },
+ "scripts": {
+ "test": "set NODE_ENV=test && mocha",
+ "jshint": "jshint --show-non-errors ."
+ },
+ "dependencies": {
+ "sax": "~1.2.1",
+ "coa": "~1.0.1",
+ "js-yaml": "~3.7.0",
+ "colors": "~1.1.2",
+ "whet.extend": "~0.9.9",
+ "mkdirp": "~0.5.1",
+ "csso": "~2.3.1"
+ },
+ "devDependencies": {
+ "mocha": "~3.2.0",
+ "should": "11.2.0",
+ "istanbul": "~0.4.5",
+ "mocha-istanbul": "~0.3.0",
+ "coveralls": "~2.11.14"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ },
+ "license": "MIT"
+}
diff --git a/node_modules/svgo/plugins/_collections.js b/node_modules/svgo/plugins/_collections.js
new file mode 100644
index 00000000..8ff3d1fb
--- /dev/null
+++ b/node_modules/svgo/plugins/_collections.js
@@ -0,0 +1,2529 @@
+'use strict';
+
+// http://www.w3.org/TR/SVG/intro.html#Definitions
+exports.elemsGroups = {
+ animation: ['animate', 'animateColor', 'animateMotion', 'animateTransform', 'set'],
+ descriptive: ['desc', 'metadata', 'title'],
+ shape: ['circle', 'ellipse', 'line', 'path', 'polygon', 'polyline', 'rect'],
+ structural: ['defs', 'g', 'svg', 'symbol', 'use'],
+ paintServer: ['solidColor', 'linearGradient', 'radialGradient', 'meshGradient', 'pattern', 'hatch'],
+ nonRendering: ['linearGradient', 'radialGradient', 'pattern', 'clipPath', 'mask', 'marker', 'symbol', 'filter', 'solidColor'],
+ container: ['a', 'defs', 'g', 'marker', 'mask', 'missing-glyph', 'pattern', 'svg', 'switch', 'symbol', 'foreignObject'],
+ textContent: ['altGlyph', 'altGlyphDef', 'altGlyphItem', 'glyph', 'glyphRef', 'textPath', 'text', 'tref', 'tspan'],
+ textContentChild: ['altGlyph', 'textPath', 'tref', 'tspan'],
+ lightSource: ['feDiffuseLighting', 'feSpecularLighting', 'feDistantLight', 'fePointLight', 'feSpotLight'],
+ filterPrimitive: ['feBlend', 'feColorMatrix', 'feComponentTransfer', 'feComposite', 'feConvolveMatrix', 'feDiffuseLighting', 'feDisplacementMap', 'feFlood', 'feGaussianBlur', 'feImage', 'feMerge', 'feMorphology', 'feOffset', 'feSpecularLighting', 'feTile', 'feTurbulence']
+};
+
+exports.pathElems = ['path', 'glyph', 'missing-glyph'];
+
+// http://www.w3.org/TR/SVG/intro.html#Definitions
+exports.attrsGroups = {
+ animationAddition: ['additive', 'accumulate'],
+ animationAttributeTarget: ['attributeType', 'attributeName'],
+ animationEvent: ['onbegin', 'onend', 'onrepeat', 'onload'],
+ animationTiming: ['begin', 'dur', 'end', 'min', 'max', 'restart', 'repeatCount', 'repeatDur', 'fill'],
+ animationValue: ['calcMode', 'values', 'keyTimes', 'keySplines', 'from', 'to', 'by'],
+ conditionalProcessing: ['requiredFeatures', 'requiredExtensions', 'systemLanguage'],
+ core: ['id', 'tabindex', 'xml:base', 'xml:lang', 'xml:space'],
+ graphicalEvent: ['onfocusin', 'onfocusout', 'onactivate', 'onclick', 'onmousedown', 'onmouseup', 'onmouseover', 'onmousemove', 'onmouseout', 'onload'],
+ presentation: [
+ 'alignment-baseline',
+ 'baseline-shift',
+ 'buffered-rendering',
+ 'clip',
+ 'clip-path',
+ 'clip-rule',
+ 'color',
+ 'color-interpolation',
+ 'color-interpolation-filters',
+ 'color-profile',
+ 'color-rendering',
+ 'cursor',
+ 'direction',
+ 'display',
+ 'dominant-baseline',
+ 'enable-background',
+ 'fill',
+ 'fill-opacity',
+ 'fill-rule',
+ 'filter',
+ 'flood-color',
+ 'flood-opacity',
+ 'font-family',
+ 'font-size',
+ 'font-size-adjust',
+ 'font-stretch',
+ 'font-style',
+ 'font-variant',
+ 'font-weight',
+ 'glyph-orientation-horizontal',
+ 'glyph-orientation-vertical',
+ 'image-rendering',
+ 'kerning',
+ 'letter-spacing',
+ 'lighting-color',
+ 'marker-end',
+ 'marker-mid',
+ 'marker-start',
+ 'mask',
+ 'opacity',
+ 'overflow',
+ 'pointer-events',
+ 'shape-rendering',
+ 'solid-color',
+ 'solid-opacity',
+ 'stop-color',
+ 'stop-opacity',
+ 'stroke',
+ 'stroke-dasharray',
+ 'stroke-dashoffset',
+ 'stroke-linecap',
+ 'stroke-linejoin',
+ 'stroke-miterlimit',
+ 'stroke-opacity',
+ 'stroke-width',
+ 'paint-order',
+ 'text-anchor',
+ 'text-decoration',
+ 'text-overflow',
+ 'white-space',
+ 'text-rendering',
+ 'unicode-bidi',
+ 'vector-effect',
+ 'viewport-fill',
+ 'viewport-fill-opacity',
+ 'visibility',
+ 'white-space',
+ 'word-spacing',
+ 'writing-mode'
+ ],
+ xlink: ['xlink:href', 'xlink:show', 'xlink:actuate', 'xlink:type', 'xlink:role', 'xlink:arcrole', 'xlink:title'],
+ documentEvent: ['onunload', 'onabort', 'onerror', 'onresize', 'onscroll', 'onzoom'],
+ filterPrimitive: ['x', 'y', 'width', 'height', 'result'],
+ transferFunction: ['type', 'tableValues', 'slope', 'intercept', 'amplitude', 'exponent', 'offset']
+};
+
+exports.attrsGroupsDefaults = {
+ core: {'xml:space': 'preserve'},
+ filterPrimitive: {x: '0', y: '0', width: '100%', height: '100%'},
+ presentation: {
+ clip: 'auto',
+ 'clip-path': 'none',
+ 'clip-rule': 'nonzero',
+ mask: 'none',
+ opacity: '1',
+ 'solid-color': '#000',
+ 'solid-opacity': '1',
+ 'stop-color': '#000',
+ 'stop-opacity': '1',
+ 'fill-opacity': '1',
+ 'fill-rule': 'nonzero',
+ fill: '#000',
+ stroke: 'none',
+ 'stroke-width': '1',
+ 'stroke-linecap': 'butt',
+ 'stroke-linejoin': 'miter',
+ 'stroke-miterlimit': '4',
+ 'stroke-dasharray': 'none',
+ 'stroke-dashoffset': '0',
+ 'stroke-opacity': '1',
+ 'paint-order': 'normal',
+ 'vector-effect': 'none',
+ 'viewport-fill': 'none',
+ 'viewport-fill-opacity': '1',
+ display: 'inline',
+ visibility: 'visible',
+ 'marker-start': 'none',
+ 'marker-mid': 'none',
+ 'marker-end': 'none',
+ 'color-interpolation': 'sRGB',
+ 'color-interpolation-filters': 'linearRGB',
+ 'color-rendering': 'auto',
+ 'shape-rendering': 'auto',
+ 'text-rendering': 'auto',
+ 'image-rendering': 'auto',
+ 'buffered-rendering': 'auto',
+ 'font-style': 'normal',
+ 'font-variant': 'normal',
+ 'font-weight': 'normal',
+ 'font-stretch': 'normal',
+ 'font-size': 'medium',
+ 'font-size-adjust': 'none',
+ kerning: 'auto',
+ 'letter-spacing': 'normal',
+ 'word-spacing': 'normal',
+ 'text-decoration': 'none',
+ 'text-anchor': 'start',
+ 'text-overflow': 'clip',
+ 'writing-mode': 'lr-tb',
+ 'glyph-orientation-vertical': 'auto',
+ 'glyph-orientation-horizontal': '0deg',
+ direction: 'ltr',
+ 'unicode-bidi': 'normal',
+ 'dominant-baseline': 'auto',
+ 'alignment-baseline': 'baseline',
+ 'baseline-shift': 'baseline'
+ },
+ transferFunction: {slope: '1', intercept: '0', amplitude: '1', exponent: '1', offset: '0'}
+};
+
+// http://www.w3.org/TR/SVG/eltindex.html
+exports.elems = {
+ a: {
+ attrsGroups: [
+ 'conditionalProcessing',
+ 'core',
+ 'graphicalEvent',
+ 'presentation',
+ 'xlink'
+ ],
+ attrs: [
+ 'class',
+ 'style',
+ 'externalResourcesRequired',
+ 'transform',
+ 'target'
+ ],
+ defaults: {
+ target: '_self'
+ },
+ contentGroups: [
+ 'animation',
+ 'descriptive',
+ 'shape',
+ 'structural',
+ 'paintServer'
+ ],
+ content: [
+ 'a',
+ 'altGlyphDef',
+ 'clipPath',
+ 'color-profile',
+ 'cursor',
+ 'filter',
+ 'font',
+ 'font-face',
+ 'foreignObject',
+ 'image',
+ 'marker',
+ 'mask',
+ 'pattern',
+ 'script',
+ 'style',
+ 'switch',
+ 'text',
+ 'view'
+ ]
+ },
+ altGlyph: {
+ attrsGroups: [
+ 'conditionalProcessing',
+ 'core',
+ 'graphicalEvent',
+ 'presentation',
+ 'xlink'
+ ],
+ attrs: [
+ 'class',
+ 'style',
+ 'externalResourcesRequired',
+ 'x',
+ 'y',
+ 'dx',
+ 'dy',
+ 'glyphRef',
+ 'format',
+ 'rotate'
+ ]
+ },
+ altGlyphDef: {
+ attrsGroups: [
+ 'core'
+ ],
+ content: [
+ 'glyphRef'
+ ]
+ },
+ altGlyphItem: {
+ attrsGroups: [
+ 'core'
+ ],
+ content: [
+ 'glyphRef',
+ 'altGlyphItem'
+ ]
+ },
+ animate: {
+ attrsGroups: [
+ 'conditionalProcessing',
+ 'core',
+ 'animationAddition',
+ 'animationAttributeTarget',
+ 'animationEvent',
+ 'animationTiming',
+ 'animationValue',
+ 'presentation',
+ 'xlink'
+ ],
+ attrs: [
+ 'externalResourcesRequired'
+ ],
+ contentGroups: [
+ 'descriptive'
+ ]
+ },
+ animateColor: {
+ attrsGroups: [
+ 'conditionalProcessing',
+ 'core',
+ 'animationEvent',
+ 'xlink',
+ 'animationAttributeTarget',
+ 'animationTiming',
+ 'animationValue',
+ 'animationAddition',
+ 'presentation'
+ ],
+ attrs: [
+ 'externalResourcesRequired'
+ ],
+ contentGroups: [
+ 'descriptive'
+ ]
+ },
+ animateMotion: {
+ attrsGroups: [
+ 'conditionalProcessing',
+ 'core',
+ 'animationEvent',
+ 'xlink',
+ 'animationTiming',
+ 'animationValue',
+ 'animationAddition'
+ ],
+ attrs: [
+ 'externalResourcesRequired',
+ 'path',
+ 'keyPoints',
+ 'rotate',
+ 'origin'
+ ],
+ defaults: {
+ 'rotate': '0'
+ },
+ contentGroups: [
+ 'descriptive'
+ ],
+ content: [
+ 'mpath'
+ ]
+ },
+ animateTransform: {
+ attrsGroups: [
+ 'conditionalProcessing',
+ 'core',
+ 'animationEvent',
+ 'xlink',
+ 'animationAttributeTarget',
+ 'animationTiming',
+ 'animationValue',
+ 'animationAddition'
+ ],
+ attrs: [
+ 'externalResourcesRequired',
+ 'type'
+ ],
+ contentGroups: [
+ 'descriptive'
+ ]
+ },
+ circle: {
+ attrsGroups: [
+ 'conditionalProcessing',
+ 'core',
+ 'graphicalEvent',
+ 'presentation'
+ ],
+ attrs: [
+ 'class',
+ 'style',
+ 'externalResourcesRequired',
+ 'transform',
+ 'cx',
+ 'cy',
+ 'r'
+ ],
+ defaults: {
+ cx: '0',
+ cy: '0'
+ },
+ contentGroups: [
+ 'animation',
+ 'descriptive'
+ ]
+ },
+ clipPath: {
+ attrsGroups: [
+ 'conditionalProcessing',
+ 'core',
+ 'presentation'
+ ],
+ attrs: [
+ 'class',
+ 'style',
+ 'externalResourcesRequired',
+ 'transform',
+ 'clipPathUnits'
+ ],
+ defaults: {
+ clipPathUnits: 'userSpaceOnUse'
+ },
+ contentGroups: [
+ 'animation',
+ 'descriptive',
+ 'shape'
+ ],
+ content: [
+ 'text',
+ 'use'
+ ]
+ },
+ 'color-profile': {
+ attrsGroups: [
+ 'core',
+ 'xlink'
+ ],
+ attrs: [
+ 'local',
+ 'name',
+ 'rendering-intent'
+ ],
+ defaults: {
+ name: 'sRGB',
+ 'rendering-intent': 'auto'
+ },
+ contentGroups: [
+ 'descriptive'
+ ]
+ },
+ cursor: {
+ attrsGroups: [
+ 'core',
+ 'conditionalProcessing',
+ 'xlink'
+ ],
+ attrs: [
+ 'externalResourcesRequired',
+ 'x',
+ 'y'
+ ],
+ defaults: {
+ x: '0',
+ y: '0'
+ },
+ contentGroups: [
+ 'descriptive'
+ ]
+ },
+ defs: {
+ attrsGroups: [
+ 'conditionalProcessing',
+ 'core',
+ 'graphicalEvent',
+ 'presentation'
+ ],
+ attrs: [
+ 'class',
+ 'style',
+ 'externalResourcesRequired',
+ 'transform'
+ ],
+ contentGroups: [
+ 'animation',
+ 'descriptive',
+ 'shape',
+ 'structural',
+ 'paintServer'
+ ],
+ content: [
+ 'a',
+ 'altGlyphDef',
+ 'clipPath',
+ 'color-profile',
+ 'cursor',
+ 'filter',
+ 'font',
+ 'font-face',
+ 'foreignObject',
+ 'image',
+ 'marker',
+ 'mask',
+ 'pattern',
+ 'script',
+ 'style',
+ 'switch',
+ 'text',
+ 'view'
+ ]
+ },
+ desc: {
+ attrsGroups: [
+ 'core'
+ ],
+ attrs: [
+ 'class',
+ 'style'
+ ]
+ },
+ ellipse: {
+ attrsGroups: [
+ 'conditionalProcessing',
+ 'core',
+ 'graphicalEvent',
+ 'presentation'
+ ],
+ attrs: [
+ 'class',
+ 'style',
+ 'externalResourcesRequired',
+ 'transform',
+ 'cx',
+ 'cy',
+ 'rx',
+ 'ry'
+ ],
+ defaults: {
+ cx: '0',
+ cy: '0'
+ },
+ contentGroups: [
+ 'animation',
+ 'descriptive'
+ ]
+ },
+ feBlend: {
+ attrsGroups: [
+ 'core',
+ 'presentation',
+ 'filterPrimitive'
+ ],
+ attrs: [
+ 'class',
+ 'style',
+ // TODO: in - 'If no value is provided and this is the first filter primitive,
+ // then this filter primitive will use SourceGraphic as its input'
+ 'in',
+ 'in2',
+ 'mode'
+ ],
+ defaults: {
+ mode: 'normal'
+ },
+ content: [
+ 'animate',
+ 'set'
+ ]
+ },
+ feColorMatrix: {
+ attrsGroups: [
+ 'core',
+ 'presentation',
+ 'filterPrimitive'
+ ],
+ attrs: [
+ 'class',
+ 'style',
+ 'in',
+ 'type',
+ 'values'
+ ],
+ defaults: {
+ type: 'matrix'
+ },
+ content: [
+ 'animate',
+ 'set'
+ ]
+ },
+ feComponentTransfer: {
+ attrsGroups: [
+ 'core',
+ 'presentation',
+ 'filterPrimitive'
+ ],
+ attrs: [
+ 'class',
+ 'style',
+ 'in'
+ ],
+ content: [
+ 'feFuncA',
+ 'feFuncB',
+ 'feFuncG',
+ 'feFuncR'
+ ]
+ },
+ feComposite: {
+ attrsGroups: [
+ 'core',
+ 'presentation',
+ 'filterPrimitive'
+ ],
+ attrs: [
+ 'class',
+ 'style',
+ 'in',
+ 'in2',
+ 'operator',
+ 'k1',
+ 'k2',
+ 'k3',
+ 'k4'
+ ],
+ defaults: {
+ operator: 'over',
+ k1: '0',
+ k2: '0',
+ k3: '0',
+ k4: '0'
+ },
+ content: [
+ 'animate',
+ 'set'
+ ]
+ },
+ feConvolveMatrix: {
+ attrsGroups: [
+ 'core',
+ 'presentation',
+ 'filterPrimitive'
+ ],
+ attrs: [
+ 'class',
+ 'style',
+ 'in',
+ 'order',
+ 'kernelMatrix',
+ // TODO: divisor - 'The default value is the sum of all values in kernelMatrix,
+ // with the exception that if the sum is zero, then the divisor is set to 1'
+ 'divisor',
+ 'bias',
+ // TODO: targetX - 'By default, the convolution matrix is centered in X over each
+ // pixel of the input image (i.e., targetX = floor ( orderX / 2 ))'
+ 'targetX',
+ 'targetY',
+ 'edgeMode',
+ // TODO: kernelUnitLength - 'The first number is the <dx> value. The second number
+ // is the <dy> value. If the <dy> value is not specified, it defaults to the same value as <dx>'
+ 'kernelUnitLength',
+ 'preserveAlpha'
+ ],
+ defaults: {
+ order: '3',
+ bias: '0',
+ edgeMode: 'duplicate',
+ preserveAlpha: 'false'
+ },
+ content: [
+ 'animate',
+ 'set'
+ ]
+ },
+ feDiffuseLighting: {
+ attrsGroups: [
+ 'core',
+ 'presentation',
+ 'filterPrimitive'
+ ],
+ attrs: [
+ 'class',
+ 'style',
+ 'in',
+ 'surfaceScale',
+ 'diffuseConstant',
+ 'kernelUnitLength'
+ ],
+ defaults: {
+ surfaceScale: '1',
+ diffuseConstant: '1'
+ },
+ contentGroups: [
+ 'descriptive'
+ ],
+ content: [
+ // TODO: 'exactly one light source element, in any order'
+ 'feDistantLight',
+ 'fePointLight',
+ 'feSpotLight'
+ ]
+ },
+ feDisplacementMap: {
+ attrsGroups: [
+ 'core',
+ 'presentation',
+ 'filterPrimitive'
+ ],
+ attrs: [
+ 'class',
+ 'style',
+ 'in',
+ 'in2',
+ 'scale',
+ 'xChannelSelector',
+ 'yChannelSelector'
+ ],
+ defaults: {
+ scale: '0',
+ xChannelSelector: 'A',
+ yChannelSelector: 'A'
+ },
+ content: [
+ 'animate',
+ 'set'
+ ]
+ },
+ feDistantLight: {
+ attrsGroups: [
+ 'core'
+ ],
+ attrs: [
+ 'azimuth',
+ 'elevation'
+ ],
+ defaults: {
+ azimuth: '0',
+ elevation: '0'
+ },
+ content: [
+ 'animate',
+ 'set'
+ ]
+ },
+ feFlood: {
+ attrsGroups: [
+ 'core',
+ 'presentation',
+ 'filterPrimitive'
+ ],
+ attrs: [
+ 'class',
+ 'style'
+ ],
+ content: [
+ 'animate',
+ 'animateColor',
+ 'set'
+ ]
+ },
+ feFuncA: {
+ attrsGroups: [
+ 'core',
+ 'transferFunction'
+ ],
+ content: [
+ 'set',
+ 'animate'
+ ]
+ },
+ feFuncB: {
+ attrsGroups: [
+ 'core',
+ 'transferFunction'
+ ],
+ content: [
+ 'set',
+ 'animate'
+ ]
+ },
+ feFuncG: {
+ attrsGroups: [
+ 'core',
+ 'transferFunction'
+ ],
+ content: [
+ 'set',
+ 'animate'
+ ]
+ },
+ feFuncR: {
+ attrsGroups: [
+ 'core',
+ 'transferFunction'
+ ],
+ content: [
+ 'set',
+ 'animate'
+ ]
+ },
+ feGaussianBlur: {
+ attrsGroups: [
+ 'core',
+ 'presentation',
+ 'filterPrimitive'
+ ],
+ attrs: [
+ 'class',
+ 'style',
+ 'in',
+ 'stdDeviation'
+ ],
+ defaults: {
+ stdDeviation: '0'
+ },
+ content: [
+ 'set',
+ 'animate'
+ ]
+ },
+ feImage: {
+ attrsGroups: [
+ 'core',
+ 'presentation',
+ 'filterPrimitive',
+ 'xlink'
+ ],
+ attrs: [
+ 'class',
+ 'style',
+ 'externalResourcesRequired',
+ 'preserveAspectRatio',
+ 'xlink:href'
+ ],
+ defaults: {
+ preserveAspectRatio: 'xMidYMid meet'
+ },
+ content: [
+ 'animate',
+ 'animateTransform',
+ 'set'
+ ]
+ },
+ feMerge: {
+ attrsGroups: [
+ 'core',
+ 'presentation',
+ 'filterPrimitive'
+ ],
+ attrs: [
+ 'class',
+ 'style'
+ ],
+ content: [
+ 'feMergeNode'
+ ]
+ },
+ feMergeNode: {
+ attrsGroups: [
+ 'core'
+ ],
+ attrs: [
+ 'in'
+ ],
+ content: [
+ 'animate',
+ 'set'
+ ]
+ },
+ feMorphology: {
+ attrsGroups: [
+ 'core',
+ 'presentation',
+ 'filterPrimitive'
+ ],
+ attrs: [
+ 'class',
+ 'style',
+ 'in',
+ 'operator',
+ 'radius'
+ ],
+ defaults: {
+ operator: 'erode',
+ radius: '0'
+ },
+ content: [
+ 'animate',
+ 'set'
+ ]
+ },
+ feOffset: {
+ attrsGroups: [
+ 'core',
+ 'presentation',
+ 'filterPrimitive'
+ ],
+ attrs: [
+ 'class',
+ 'style',
+ 'in',
+ 'dx',
+ 'dy'
+ ],
+ defaults: {
+ dx: '0',
+ dy: '0'
+ },
+ content: [
+ 'animate',
+ 'set'
+ ]
+ },
+ fePointLight: {
+ attrsGroups: [
+ 'core'
+ ],
+ attrs: [
+ 'x',
+ 'y',
+ 'z'
+ ],
+ defaults: {
+ x: '0',
+ y: '0',
+ z: '0'
+ },
+ content: [
+ 'animate',
+ 'set'
+ ]
+ },
+ feSpecularLighting: {
+ attrsGroups: [
+ 'core',
+ 'presentation',
+ 'filterPrimitive'
+ ],
+ attrs: [
+ 'class',
+ 'style',
+ 'in',
+ 'surfaceScale',
+ 'specularConstant',
+ 'specularExponent',
+ 'kernelUnitLength'
+ ],
+ defaults: {
+ surfaceScale: '1',
+ specularConstant: '1',
+ specularExponent: '1'
+ },
+ contentGroups: [
+ 'descriptive',
+ // TODO: exactly one 'light source element'
+ 'lightSource'
+ ]
+ },
+ feSpotLight: {
+ attrsGroups: [
+ 'core'
+ ],
+ attrs: [
+ 'x',
+ 'y',
+ 'z',
+ 'pointsAtX',
+ 'pointsAtY',
+ 'pointsAtZ',
+ 'specularExponent',
+ 'limitingConeAngle'
+ ],
+ defaults: {
+ x: '0',
+ y: '0',
+ z: '0',
+ pointsAtX: '0',
+ pointsAtY: '0',
+ pointsAtZ: '0',
+ specularExponent: '1'
+ },
+ content: [
+ 'animate',
+ 'set'
+ ]
+ },
+ feTile: {
+ attrsGroups: [
+ 'core',
+ 'presentation',
+ 'filterPrimitive'
+ ],
+ attrs: [
+ 'class',
+ 'style',
+ 'in'
+ ],
+ content: [
+ 'animate',
+ 'set'
+ ]
+ },
+ feTurbulence: {
+ attrsGroups: [
+ 'core',
+ 'presentation',
+ 'filterPrimitive'
+ ],
+ attrs: [
+ 'class',
+ 'style',
+ 'baseFrequency',
+ 'numOctaves',
+ 'seed',
+ 'stitchTiles',
+ 'type'
+ ],
+ defaults: {
+ baseFrequency: '0',
+ numOctaves: '1',
+ seed: '0',
+ stitchTiles: 'noStitch',
+ type: 'turbulence'
+ },
+ content: [
+ 'animate',
+ 'set'
+ ]
+ },
+ filter: {
+ attrsGroups: [
+ 'core',
+ 'presentation',
+ 'xlink'
+ ],
+ attrs: [
+ 'class',
+ 'style',
+ 'externalResourcesRequired',
+ 'x',
+ 'y',
+ 'width',
+ 'height',
+ 'filterRes',
+ 'filterUnits',
+ 'primitiveUnits',
+ 'xlink:href'
+ ],
+ defaults: {
+ primitiveUnits: 'userSpaceOnUse',
+ x: '-10%',
+ y: '-10%',
+ width: '120%',
+ height: '120%'
+ },
+ contentGroups: [
+ 'descriptive',
+ 'filterPrimitive'
+ ],
+ content: [
+ 'animate',
+ 'set'
+ ]
+ },
+ font: {
+ attrsGroups: [
+ 'core',
+ 'presentation'
+ ],
+ attrs: [
+ 'class',
+ 'style',
+ 'externalResourcesRequired',
+ 'horiz-origin-x',
+ 'horiz-origin-y',
+ 'horiz-adv-x',
+ 'vert-origin-x',
+ 'vert-origin-y',
+ 'vert-adv-y'
+ ],
+ defaults: {
+ 'horiz-origin-x': '0',
+ 'horiz-origin-y': '0'
+ },
+ contentGroups: [
+ 'descriptive'
+ ],
+ content: [
+ 'font-face',
+ 'glyph',
+ 'hkern',
+ 'missing-glyph',
+ 'vkern'
+ ]
+ },
+ 'font-face': {
+ attrsGroups: [
+ 'core'
+ ],
+ attrs: [
+ 'font-family',
+ 'font-style',
+ 'font-variant',
+ 'font-weight',
+ 'font-stretch',
+ 'font-size',
+ 'unicode-range',
+ 'units-per-em',
+ 'panose-1',
+ 'stemv',
+ 'stemh',
+ 'slope',
+ 'cap-height',
+ 'x-height',
+ 'accent-height',
+ 'ascent',
+ 'descent',
+ 'widths',
+ 'bbox',
+ 'ideographic',
+ 'alphabetic',
+ 'mathematical',
+ 'hanging',
+ 'v-ideographic',
+ 'v-alphabetic',
+ 'v-mathematical',
+ 'v-hanging',
+ 'underline-position',
+ 'underline-thickness',
+ 'strikethrough-position',
+ 'strikethrough-thickness',
+ 'overline-position',
+ 'overline-thickness'
+ ],
+ defaults: {
+ 'font-style': 'all',
+ 'font-variant': 'normal',
+ 'font-weight': 'all',
+ 'font-stretch': 'normal',
+ 'unicode-range': 'U+0-10FFFF',
+ 'units-per-em': '1000',
+ 'panose-1': '0 0 0 0 0 0 0 0 0 0',
+ 'slope': '0'
+ },
+ contentGroups: [
+ 'descriptive'
+ ],
+ content: [
+ // TODO: "at most one 'font-face-src' element"
+ 'font-face-src'
+ ]
+ },
+ // TODO: empty content
+ 'font-face-format': {
+ attrsGroups: [
+ 'core'
+ ],
+ attrs: [
+ 'string'
+ ]
+ },
+ 'font-face-name': {
+ attrsGroups: [
+ 'core'
+ ],
+ attrs: [
+ 'name'
+ ]
+ },
+ 'font-face-src': {
+ attrsGroups: [
+ 'core'
+ ],
+ content: [
+ 'font-face-name',
+ 'font-face-uri'
+ ]
+ },
+ 'font-face-uri': {
+ attrsGroups: [
+ 'core',
+ 'xlink'
+ ],
+ attrs: [
+ 'xlink:href'
+ ],
+ content: [
+ 'font-face-format'
+ ]
+ },
+ foreignObject: {
+ attrsGroups: [
+ 'core',
+ 'conditionalProcessing',
+ 'graphicalEvent',
+ 'presentation'
+ ],
+ attrs: [
+ 'class',
+ 'style',
+ 'externalResourcesRequired',
+ 'transform',
+ 'x',
+ 'y',
+ 'width',
+ 'height'
+ ],
+ defaults: {
+ x: 0,
+ y: 0
+ }
+ },
+ g: {
+ attrsGroups: [
+ 'conditionalProcessing',
+ 'core',
+ 'graphicalEvent',
+ 'presentation'
+ ],
+ attrs: [
+ 'class',
+ 'style',
+ 'externalResourcesRequired',
+ 'transform'
+ ],
+ contentGroups: [
+ 'animation',
+ 'descriptive',
+ 'shape',
+ 'structural',
+ 'paintServer'
+ ],
+ content: [
+ 'a',
+ 'altGlyphDef',
+ 'clipPath',
+ 'color-profile',
+ 'cursor',
+ 'filter',
+ 'font',
+ 'font-face',
+ 'foreignObject',
+ 'image',
+ 'marker',
+ 'mask',
+ 'pattern',
+ 'script',
+ 'style',
+ 'switch',
+ 'text',
+ 'view'
+ ]
+ },
+ glyph: {
+ attrsGroups: [
+ 'core',
+ 'presentation'
+ ],
+ attrs: [
+ 'class',
+ 'style',
+ 'd',
+ 'horiz-adv-x',
+ 'vert-origin-x',
+ 'vert-origin-y',
+ 'vert-adv-y',
+ 'unicode',
+ 'glyph-name',
+ 'orientation',
+ 'arabic-form',
+ 'lang'
+ ],
+ defaults: {
+ 'arabic-form': 'initial'
+ },
+ contentGroups: [
+ 'animation',
+ 'descriptive',
+ 'shape',
+ 'structural',
+ 'paintServer'
+ ],
+ content: [
+ 'a',
+ 'altGlyphDef',
+ 'clipPath',
+ 'color-profile',
+ 'cursor',
+ 'filter',
+ 'font',
+ 'font-face',
+ 'foreignObject',
+ 'image',
+ 'marker',
+ 'mask',
+ 'pattern',
+ 'script',
+ 'style',
+ 'switch',
+ 'text',
+ 'view'
+ ],
+ },
+ glyphRef: {
+ attrsGroups: [
+ 'core',
+ 'presentation'
+ ],
+ attrs: [
+ 'class',
+ 'style',
+ 'd',
+ 'horiz-adv-x',
+ 'vert-origin-x',
+ 'vert-origin-y',
+ 'vert-adv-y'
+ ],
+ contentGroups: [
+ 'animation',
+ 'descriptive',
+ 'shape',
+ 'structural',
+ 'paintServer'
+ ],
+ content: [
+ 'a',
+ 'altGlyphDef',
+ 'clipPath',
+ 'color-profile',
+ 'cursor',
+ 'filter',
+ 'font',
+ 'font-face',
+ 'foreignObject',
+ 'image',
+ 'marker',
+ 'mask',
+ 'pattern',
+ 'script',
+ 'style',
+ 'switch',
+ 'text',
+ 'view'
+ ]
+ },
+ hatch: {
+ attrsGroups: [
+ 'core',
+ 'presentation',
+ 'xlink'
+ ],
+ attrs: [
+ 'class',
+ 'style',
+ 'x',
+ 'y',
+ 'pitch',
+ 'rotate',
+ 'hatchUnits',
+ 'hatchContentUnits',
+ 'transform'
+ ],
+ defaults: {
+ hatchUnits: 'objectBoundingBox',
+ hatchContentUnits: 'userSpaceOnUse',
+ x: '0',
+ y: '0',
+ pitch: '0',
+ rotate: '0'
+ },
+ contentGroups: [
+ 'animation',
+ 'descriptive'
+ ],
+ content: [
+ 'hatchPath'
+ ]
+ },
+ hatchPath: {
+ attrsGroups: [
+ 'core',
+ 'presentation',
+ 'xlink'
+ ],
+ attrs: [
+ 'class',
+ 'style',
+ 'd',
+ 'offset'
+ ],
+ defaults: {
+ offset: '0'
+ },
+ contentGroups: [
+ 'animation',
+ 'descriptive'
+ ]
+ },
+ hkern: {
+ attrsGroups: [
+ 'core'
+ ],
+ attrs: [
+ 'u1',
+ 'g1',
+ 'u2',
+ 'g2',
+ 'k'
+ ]
+ },
+ image: {
+ attrsGroups: [
+ 'core',
+ 'conditionalProcessing',
+ 'graphicalEvent',
+ 'xlink',
+ 'presentation'
+ ],
+ attrs: [
+ 'class',
+ 'style',
+ 'externalResourcesRequired',
+ 'preserveAspectRatio',
+ 'transform',
+ 'x',
+ 'y',
+ 'width',
+ 'height',
+ 'xlink:href'
+ ],
+ defaults: {
+ x: '0',
+ y: '0',
+ preserveAspectRatio: 'xMidYMid meet'
+ },
+ contentGroups: [
+ 'animation',
+ 'descriptive'
+ ]
+ },
+ line: {
+ attrsGroups: [
+ 'conditionalProcessing',
+ 'core',
+ 'graphicalEvent',
+ 'presentation'
+ ],
+ attrs: [
+ 'class',
+ 'style',
+ 'externalResourcesRequired',
+ 'transform',
+ 'x1',
+ 'y1',
+ 'x2',
+ 'y2'
+ ],
+ defaults: {
+ x1: '0',
+ y1: '0',
+ x2: '0',
+ y2: '0'
+ },
+ contentGroups: [
+ 'animation',
+ 'descriptive'
+ ]
+ },
+ linearGradient: {
+ attrsGroups: [
+ 'core',
+ 'presentation',
+ 'xlink'
+ ],
+ attrs: [
+ 'class',
+ 'style',
+ 'externalResourcesRequired',
+ 'x1',
+ 'y1',
+ 'x2',
+ 'y2',
+ 'gradientUnits',
+ 'gradientTransform',
+ 'spreadMethod',
+ 'xlink:href'
+ ],
+ defaults: {
+ x1: '0',
+ y1: '0',
+ x2: '100%',
+ y2: '0',
+ spreadMethod: 'pad'
+ },
+ contentGroups: [
+ 'descriptive'
+ ],
+ content: [
+ 'animate',
+ 'animateTransform',
+ 'set',
+ 'stop'
+ ]
+ },
+ marker: {
+ attrsGroups: [
+ 'core',
+ 'presentation'
+ ],
+ attrs: [
+ 'class',
+ 'style',
+ 'externalResourcesRequired',
+ 'viewBox',
+ 'preserveAspectRatio',
+ 'refX',
+ 'refY',
+ 'markerUnits',
+ 'markerWidth',
+ 'markerHeight',
+ 'orient'
+ ],
+ defaults: {
+ markerUnits: 'strokeWidth',
+ refX: '0',
+ refY: '0',
+ markerWidth: '3',
+ markerHeight: '3'
+ },
+ contentGroups: [
+ 'animation',
+ 'descriptive',
+ 'shape',
+ 'structural',
+ 'paintServer'
+ ],
+ content: [
+ 'a',
+ 'altGlyphDef',
+ 'clipPath',
+ 'color-profile',
+ 'cursor',
+ 'filter',
+ 'font',
+ 'font-face',
+ 'foreignObject',
+ 'image',
+ 'marker',
+ 'mask',
+ 'pattern',
+ 'script',
+ 'style',
+ 'switch',
+ 'text',
+ 'view'
+ ]
+ },
+ mask: {
+ attrsGroups: [
+ 'conditionalProcessing',
+ 'core',
+ 'presentation'
+ ],
+ attrs: [
+ 'class',
+ 'style',
+ 'externalResourcesRequired',
+ 'x',
+ 'y',
+ 'width',
+ 'height',
+ 'maskUnits',
+ 'maskContentUnits'
+ ],
+ defaults: {
+ maskUnits: 'objectBoundingBox',
+ maskContentUnits: 'userSpaceOnUse',
+ x: '-10%',
+ y: '-10%',
+ width: '120%',
+ height: '120%'
+ },
+ contentGroups: [
+ 'animation',
+ 'descriptive',
+ 'shape',
+ 'structural',
+ 'paintServer'
+ ],
+ content: [
+ 'a',
+ 'altGlyphDef',
+ 'clipPath',
+ 'color-profile',
+ 'cursor',
+ 'filter',
+ 'font',
+ 'font-face',
+ 'foreignObject',
+ 'image',
+ 'marker',
+ 'mask',
+ 'pattern',
+ 'script',
+ 'style',
+ 'switch',
+ 'text',
+ 'view'
+ ]
+ },
+ metadata: {
+ attrsGroups: [
+ 'core'
+ ]
+ },
+ 'missing-glyph': {
+ attrsGroups: [
+ 'core',
+ 'presentation'
+ ],
+ attrs: [
+ 'class',
+ 'style',
+ 'd',
+ 'horiz-adv-x',
+ 'vert-origin-x',
+ 'vert-origin-y',
+ 'vert-adv-y'
+ ],
+ contentGroups: [
+ 'animation',
+ 'descriptive',
+ 'shape',
+ 'structural',
+ 'paintServer'
+ ],
+ content: [
+ 'a',
+ 'altGlyphDef',
+ 'clipPath',
+ 'color-profile',
+ 'cursor',
+ 'filter',
+ 'font',
+ 'font-face',
+ 'foreignObject',
+ 'image',
+ 'marker',
+ 'mask',
+ 'pattern',
+ 'script',
+ 'style',
+ 'switch',
+ 'text',
+ 'view'
+ ]
+ },
+ mpath: {
+ attrsGroups: [
+ 'core',
+ 'xlink'
+ ],
+ attrs: [
+ 'externalResourcesRequired',
+ 'xlink:href'
+ ],
+ contentGroups: [
+ 'descriptive'
+ ]
+ },
+ path: {
+ attrsGroups: [
+ 'conditionalProcessing',
+ 'core',
+ 'graphicalEvent',
+ 'presentation'
+ ],
+ attrs: [
+ 'class',
+ 'style',
+ 'externalResourcesRequired',
+ 'transform',
+ 'd',
+ 'pathLength'
+ ],
+ contentGroups: [
+ 'animation',
+ 'descriptive'
+ ]
+ },
+ pattern: {
+ attrsGroups: [
+ 'conditionalProcessing',
+ 'core',
+ 'presentation',
+ 'xlink'
+ ],
+ attrs: [
+ 'class',
+ 'style',
+ 'externalResourcesRequired',
+ 'viewBox',
+ 'preserveAspectRatio',
+ 'x',
+ 'y',
+ 'width',
+ 'height',
+ 'patternUnits',
+ 'patternContentUnits',
+ 'patternTransform',
+ 'xlink:href'
+ ],
+ defaults: {
+ patternUnits: 'objectBoundingBox',
+ patternContentUnits: 'userSpaceOnUse',
+ x: '0',
+ y: '0',
+ width: '0',
+ height: '0',
+ preserveAspectRatio: 'xMidYMid meet'
+ },
+ contentGroups: [
+ 'animation',
+ 'descriptive',
+ 'paintServer',
+ 'shape',
+ 'structural'
+ ],
+ content: [
+ 'a',
+ 'altGlyphDef',
+ 'clipPath',
+ 'color-profile',
+ 'cursor',
+ 'filter',
+ 'font',
+ 'font-face',
+ 'foreignObject',
+ 'image',
+ 'marker',
+ 'mask',
+ 'pattern',
+ 'script',
+ 'style',
+ 'switch',
+ 'text',
+ 'view'
+ ]
+ },
+ polygon: {
+ attrsGroups: [
+ 'conditionalProcessing',
+ 'core',
+ 'graphicalEvent',
+ 'presentation'
+ ],
+ attrs: [
+ 'class',
+ 'style',
+ 'externalResourcesRequired',
+ 'transform',
+ 'points'
+ ],
+ contentGroups: [
+ 'animation',
+ 'descriptive'
+ ]
+ },
+ polyline: {
+ attrsGroups: [
+ 'conditionalProcessing',
+ 'core',
+ 'graphicalEvent',
+ 'presentation'
+ ],
+ attrs: [
+ 'class',
+ 'style',
+ 'externalResourcesRequired',
+ 'transform',
+ 'points'
+ ],
+ contentGroups: [
+ 'animation',
+ 'descriptive'
+ ]
+ },
+ radialGradient: {
+ attrsGroups: [
+ 'core',
+ 'presentation',
+ 'xlink'
+ ],
+ attrs: [
+ 'class',
+ 'style',
+ 'externalResourcesRequired',
+ 'cx',
+ 'cy',
+ 'r',
+ 'fx',
+ 'fy',
+ 'fr',
+ 'gradientUnits',
+ 'gradientTransform',
+ 'spreadMethod',
+ 'xlink:href'
+ ],
+ defaults: {
+ gradientUnits: 'objectBoundingBox',
+ cx: '50%',
+ cy: '50%',
+ r: '50%'
+ },
+ contentGroups: [
+ 'descriptive'
+ ],
+ content: [
+ 'animate',
+ 'animateTransform',
+ 'set',
+ 'stop'
+ ]
+ },
+ meshGradient: {
+ attrsGroups: [
+ 'core',
+ 'presentation',
+ 'xlink'
+ ],
+ attrs: [
+ 'class',
+ 'style',
+ 'x',
+ 'y',
+ 'gradientUnits',
+ 'transform'
+ ],
+ contentGroups: [
+ 'descriptive',
+ 'paintServer',
+ 'animation',
+ ],
+ content: [
+ 'meshRow'
+ ]
+ },
+ meshRow: {
+ attrsGroups: [
+ 'core',
+ 'presentation'
+ ],
+ attrs: [
+ 'class',
+ 'style'
+ ],
+ contentGroups: [
+ 'descriptive'
+ ],
+ content: [
+ 'meshPatch'
+ ]
+ },
+ meshPatch: {
+ attrsGroups: [
+ 'core',
+ 'presentation'
+ ],
+ attrs: [
+ 'class',
+ 'style'
+ ],
+ contentGroups: [
+ 'descriptive'
+ ],
+ content: [
+ 'stop'
+ ]
+ },
+ rect: {
+ attrsGroups: [
+ 'conditionalProcessing',
+ 'core',
+ 'graphicalEvent',
+ 'presentation'
+ ],
+ attrs: [
+ 'class',
+ 'style',
+ 'externalResourcesRequired',
+ 'transform',
+ 'x',
+ 'y',
+ 'width',
+ 'height',
+ 'rx',
+ 'ry'
+ ],
+ defaults: {
+ x: '0',
+ y: '0'
+ },
+ contentGroups: [
+ 'animation',
+ 'descriptive'
+ ]
+ },
+ script: {
+ attrsGroups: [
+ 'core',
+ 'xlink'
+ ],
+ attrs: [
+ 'externalResourcesRequired',
+ 'type',
+ 'xlink:href'
+ ]
+ },
+ set: {
+ attrsGroups: [
+ 'conditionalProcessing',
+ 'core',
+ 'animation',
+ 'xlink',
+ 'animationAttributeTarget',
+ 'animationTiming',
+ ],
+ attrs: [
+ 'externalResourcesRequired',
+ 'to'
+ ],
+ contentGroups: [
+ 'descriptive'
+ ]
+ },
+ solidColor: {
+ attrsGroups: [
+ 'core',
+ 'presentation'
+ ],
+ attrs: [
+ 'class',
+ 'style'
+ ],
+ contentGroups: [
+ 'paintServer'
+ ]
+ },
+ stop: {
+ attrsGroups: [
+ 'core',
+ 'presentation'
+ ],
+ attrs: [
+ 'class',
+ 'style',
+ 'offset',
+ 'path'
+ ],
+ content: [
+ 'animate',
+ 'animateColor',
+ 'set'
+ ]
+ },
+ style: {
+ attrsGroups: [
+ 'core'
+ ],
+ attrs: [
+ 'type',
+ 'media',
+ 'title'
+ ],
+ defaults: {
+ type: 'text/css'
+ }
+ },
+ svg: {
+ attrsGroups: [
+ 'conditionalProcessing',
+ 'core',
+ 'documentEvent',
+ 'graphicalEvent',
+ 'presentation'
+ ],
+ attrs: [
+ 'class',
+ 'style',
+ 'x',
+ 'y',
+ 'width',
+ 'height',
+ 'viewBox',
+ 'preserveAspectRatio',
+ 'zoomAndPan',
+ 'version',
+ 'baseProfile',
+ 'contentScriptType',
+ 'contentStyleType'
+ ],
+ defaults: {
+ x: '0',
+ y: '0',
+ width: '100%',
+ height: '100%',
+ preserveAspectRatio: 'xMidYMid meet',
+ zoomAndPan: 'magnify',
+ version: '1.1',
+ baseProfile: 'none',
+ contentScriptType: 'application/ecmascript',
+ contentStyleType: 'text/css'
+ },
+ contentGroups: [
+ 'animation',
+ 'descriptive',
+ 'shape',
+ 'structural',
+ 'paintServer'
+ ],
+ content: [
+ 'a',
+ 'altGlyphDef',
+ 'clipPath',
+ 'color-profile',
+ 'cursor',
+ 'filter',
+ 'font',
+ 'font-face',
+ 'foreignObject',
+ 'image',
+ 'marker',
+ 'mask',
+ 'pattern',
+ 'script',
+ 'style',
+ 'switch',
+ 'text',
+ 'view'
+ ]
+ },
+ switch: {
+ attrsGroups: [
+ 'conditionalProcessing',
+ 'core',
+ 'graphicalEvent',
+ 'presentation'
+ ],
+ attrs: [
+ 'class',
+ 'style',
+ 'externalResourcesRequired',
+ 'transform'
+ ],
+ contentGroups: [
+ 'animation',
+ 'descriptive',
+ 'shape'
+ ],
+ content: [
+ 'a',
+ 'foreignObject',
+ 'g',
+ 'image',
+ 'svg',
+ 'switch',
+ 'text',
+ 'use'
+ ]
+ },
+ symbol: {
+ attrsGroups: [
+ 'core',
+ 'graphicalEvent',
+ 'presentation'
+ ],
+ attrs: [
+ 'class',
+ 'style',
+ 'externalResourcesRequired',
+ 'preserveAspectRatio',
+ 'viewBox',
+ 'refX',
+ 'refY'
+ ],
+ defaults: {
+ refX: 0,
+ refY: 0
+ },
+ contentGroups: [
+ 'animation',
+ 'descriptive',
+ 'shape',
+ 'structural',
+ 'paintServer'
+ ],
+ content: [
+ 'a',
+ 'altGlyphDef',
+ 'clipPath',
+ 'color-profile',
+ 'cursor',
+ 'filter',
+ 'font',
+ 'font-face',
+ 'foreignObject',
+ 'image',
+ 'marker',
+ 'mask',
+ 'pattern',
+ 'script',
+ 'style',
+ 'switch',
+ 'text',
+ 'view'
+ ]
+ },
+ text: {
+ attrsGroups: [
+ 'conditionalProcessing',
+ 'core',
+ 'graphicalEvent',
+ 'presentation'
+ ],
+ attrs: [
+ 'class',
+ 'style',
+ 'externalResourcesRequired',
+ 'transform',
+ 'lengthAdjust',
+ 'x',
+ 'y',
+ 'dx',
+ 'dy',
+ 'rotate',
+ 'textLength'
+ ],
+ defaults: {
+ x: '0',
+ y: '0',
+ lengthAdjust: 'spacing'
+ },
+ contentGroups: [
+ 'animation',
+ 'descriptive',
+ 'textContentChild'
+ ],
+ content: [
+ 'a'
+ ]
+ },
+ textPath: {
+ attrsGroups: [
+ 'conditionalProcessing',
+ 'core',
+ 'graphicalEvent',
+ 'presentation',
+ 'xlink'
+ ],
+ attrs: [
+ 'class',
+ 'style',
+ 'externalResourcesRequired',
+ 'xlink:href',
+ 'startOffset',
+ 'method',
+ 'spacing',
+ 'd'
+ ],
+ defaults: {
+ startOffset: '0',
+ method: 'align',
+ spacing: 'exact'
+ },
+ contentGroups: [
+ 'descriptive'
+ ],
+ content: [
+ 'a',
+ 'altGlyph',
+ 'animate',
+ 'animateColor',
+ 'set',
+ 'tref',
+ 'tspan'
+ ]
+ },
+ title: {
+ attrsGroups: [
+ 'core'
+ ],
+ attrs: [
+ 'class',
+ 'style'
+ ]
+ },
+ tref: {
+ attrsGroups: [
+ 'conditionalProcessing',
+ 'core',
+ 'graphicalEvent',
+ 'presentation',
+ 'xlink'
+ ],
+ attrs: [
+ 'class',
+ 'style',
+ 'externalResourcesRequired',
+ 'xlink:href'
+ ],
+ contentGroups: [
+ 'descriptive'
+ ],
+ content: [
+ 'animate',
+ 'animateColor',
+ 'set'
+ ]
+ },
+ tspan: {
+ attrsGroups: [
+ 'conditionalProcessing',
+ 'core',
+ 'graphicalEvent',
+ 'presentation'
+ ],
+ attrs: [
+ 'class',
+ 'style',
+ 'externalResourcesRequired',
+ 'x',
+ 'y',
+ 'dx',
+ 'dy',
+ 'rotate',
+ 'textLength',
+ 'lengthAdjust'
+ ],
+ contentGroups: [
+ 'descriptive'
+ ],
+ content: [
+ 'a',
+ 'altGlyph',
+ 'animate',
+ 'animateColor',
+ 'set',
+ 'tref',
+ 'tspan'
+ ]
+ },
+ use: {
+ attrsGroups: [
+ 'core',
+ 'conditionalProcessing',
+ 'graphicalEvent',
+ 'presentation',
+ 'xlink'
+ ],
+ attrs: [
+ 'class',
+ 'style',
+ 'externalResourcesRequired',
+ 'transform',
+ 'x',
+ 'y',
+ 'width',
+ 'height',
+ 'xlink:href'
+ ],
+ defaults: {
+ x: '0',
+ y: '0'
+ },
+ contentGroups: [
+ 'animation',
+ 'descriptive'
+ ]
+ },
+ view: {
+ attrsGroups: [
+ 'core'
+ ],
+ attrs: [
+ 'externalResourcesRequired',
+ 'viewBox',
+ 'preserveAspectRatio',
+ 'zoomAndPan',
+ 'viewTarget'
+ ],
+ contentGroups: [
+ 'descriptive'
+ ]
+ },
+ vkern: {
+ attrsGroups: [
+ 'core'
+ ],
+ attrs: [
+ 'u1',
+ 'g1',
+ 'u2',
+ 'g2',
+ 'k'
+ ]
+ }
+};
+
+// http://wiki.inkscape.org/wiki/index.php/Inkscape-specific_XML_attributes
+exports.editorNamespaces = [
+ 'http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd',
+ 'http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd',
+ 'http://www.inkscape.org/namespaces/inkscape',
+ 'http://www.bohemiancoding.com/sketch/ns',
+ 'http://ns.adobe.com/AdobeIllustrator/10.0/',
+ 'http://ns.adobe.com/Graphs/1.0/',
+ 'http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/',
+ 'http://ns.adobe.com/Variables/1.0/',
+ 'http://ns.adobe.com/SaveForWeb/1.0/',
+ 'http://ns.adobe.com/Extensibility/1.0/',
+ 'http://ns.adobe.com/Flows/1.0/',
+ 'http://ns.adobe.com/ImageReplacement/1.0/',
+ 'http://ns.adobe.com/GenericCustomNamespace/1.0/',
+ 'http://ns.adobe.com/XPath/1.0/'
+];
+
+// http://www.w3.org/TR/SVG/linking.html#processingIRI
+exports.referencesProps = [
+ 'clip-path',
+ 'color-profile',
+ 'fill',
+ 'filter',
+ 'marker-start',
+ 'marker-mid',
+ 'marker-end',
+ 'mask',
+ 'stroke',
+ 'style'
+];
+
+// http://www.w3.org/TR/SVG/propidx.html
+exports.inheritableAttrs = [
+ 'clip-rule',
+ 'color',
+ 'color-interpolation',
+ 'color-interpolation-filters',
+ 'color-profile',
+ 'color-rendering',
+ 'cursor',
+ 'direction',
+ 'fill',
+ 'fill-opacity',
+ 'fill-rule',
+ 'font',
+ 'font-family',
+ 'font-size',
+ 'font-size-adjust',
+ 'font-stretch',
+ 'font-style',
+ 'font-variant',
+ 'font-weight',
+ 'glyph-orientation-horizontal',
+ 'glyph-orientation-vertical',
+ 'image-rendering',
+ 'kerning',
+ 'letter-spacing',
+ 'marker',
+ 'marker-end',
+ 'marker-mid',
+ 'marker-start',
+ 'pointer-events',
+ 'shape-rendering',
+ 'stroke',
+ 'stroke-dasharray',
+ 'stroke-dashoffset',
+ 'stroke-linecap',
+ 'stroke-linejoin',
+ 'stroke-miterlimit',
+ 'stroke-opacity',
+ 'stroke-width',
+ 'text-anchor',
+ 'text-rendering',
+ 'transform',
+ 'visibility',
+ 'white-space',
+ 'word-spacing',
+ 'writing-mode'
+];
+
+// http://www.w3.org/TR/SVG/single-page.html#types-ColorKeywords
+exports.colorsNames = {
+ 'aliceblue': '#f0f8ff',
+ 'antiquewhite': '#faebd7',
+ 'aqua': '#0ff',
+ 'aquamarine': '#7fffd4',
+ 'azure': '#f0ffff',
+ 'beige': '#f5f5dc',
+ 'bisque': '#ffe4c4',
+ 'black': '#000',
+ 'blanchedalmond': '#ffebcd',
+ 'blue': '#00f',
+ 'blueviolet': '#8a2be2',
+ 'brown': '#a52a2a',
+ 'burlywood': '#deb887',
+ 'cadetblue': '#5f9ea0',
+ 'chartreuse': '#7fff00',
+ 'chocolate': '#d2691e',
+ 'coral': '#ff7f50',
+ 'cornflowerblue': '#6495ed',
+ 'cornsilk': '#fff8dc',
+ 'crimson': '#dc143c',
+ 'cyan': '#0ff',
+ 'darkblue': '#00008b',
+ 'darkcyan': '#008b8b',
+ 'darkgoldenrod': '#b8860b',
+ 'darkgray': '#a9a9a9',
+ 'darkgreen': '#006400',
+ 'darkkhaki': '#bdb76b',
+ 'darkmagenta': '#8b008b',
+ 'darkolivegreen': '#556b2f',
+ 'darkorange': '#ff8c00',
+ 'darkorchid': '#9932cc',
+ 'darkred': '#8b0000',
+ 'darksalmon': '#e9967a',
+ 'darkseagreen': '#8fbc8f',
+ 'darkslateblue': '#483d8b',
+ 'darkslategray': '#2f4f4f',
+ 'darkturquoise': '#00ced1',
+ 'darkviolet': '#9400d3',
+ 'deeppink': '#ff1493',
+ 'deepskyblue': '#00bfff',
+ 'dimgray': '#696969',
+ 'dodgerblue': '#1e90ff',
+ 'firebrick': '#b22222',
+ 'floralwhite': '#fffaf0',
+ 'forestgreen': '#228b22',
+ 'fuchsia': '#f0f',
+ 'gainsboro': '#dcdcdc',
+ 'ghostwhite': '#f8f8ff',
+ 'gold': '#ffd700',
+ 'goldenrod': '#daa520',
+ 'gray': '#808080',
+ 'green': '#008000',
+ 'greenyellow': '#adff2f',
+ 'honeydew': '#f0fff0',
+ 'hotpink': '#ff69b4',
+ 'indianred': '#cd5c5c',
+ 'indigo': '#4b0082',
+ 'ivory': '#fffff0',
+ 'khaki': '#f0e68c',
+ 'lavender': '#e6e6fa',
+ 'lavenderblush': '#fff0f5',
+ 'lawngreen': '#7cfc00',
+ 'lemonchiffon': '#fffacd',
+ 'lightblue': '#add8e6',
+ 'lightcoral': '#f08080',
+ 'lightcyan': '#e0ffff',
+ 'lightgoldenrodyellow': '#fafad2',
+ 'lightgreen': '#90ee90',
+ 'lightgrey': '#d3d3d3',
+ 'lightpink': '#ffb6c1',
+ 'lightsalmon': '#ffa07a',
+ 'lightseagreen': '#20b2aa',
+ 'lightskyblue': '#87cefa',
+ 'lightslategray': '#789',
+ 'lightsteelblue': '#b0c4de',
+ 'lightyellow': '#ffffe0',
+ 'lime': '#0f0',
+ 'limegreen': '#32cd32',
+ 'linen': '#faf0e6',
+ 'magenta': '#f0f',
+ 'maroon': '#800000',
+ 'mediumaquamarine': '#66cdaa',
+ 'mediumblue': '#0000cd',
+ 'mediumorchid': '#ba55d3',
+ 'mediumpurple': '#9370db',
+ 'mediumseagreen': '#3cb371',
+ 'mediumslateblue': '#7b68ee',
+ 'mediumspringgreen': '#00fa9a',
+ 'mediumturquoise': '#48d1cc',
+ 'mediumvioletred': '#c71585',
+ 'midnightblue': '#191970',
+ 'mintcream': '#f5fffa',
+ 'mistyrose': '#ffe4e1',
+ 'moccasin': '#ffe4b5',
+ 'navajowhite': '#ffdead',
+ 'navy': '#000080',
+ 'oldlace': '#fdf5e6',
+ 'olive': '#808000',
+ 'olivedrab': '#6b8e23',
+ 'orange': '#ffa500',
+ 'orangered': '#ff4500',
+ 'orchid': '#da70d6',
+ 'palegoldenrod': '#eee8aa',
+ 'palegreen': '#98fb98',
+ 'paleturquoise': '#afeeee',
+ 'palevioletred': '#db7093',
+ 'papayawhip': '#ffefd5',
+ 'peachpuff': '#ffdab9',
+ 'peru': '#cd853f',
+ 'pink': '#ffc0cb',
+ 'plum': '#dda0dd',
+ 'powderblue': '#b0e0e6',
+ 'purple': '#800080',
+ 'red': '#f00',
+ 'rosybrown': '#bc8f8f',
+ 'royalblue': '#4169e1',
+ 'saddlebrown': '#8b4513',
+ 'salmon': '#fa8072',
+ 'sandybrown': '#f4a460',
+ 'seagreen': '#2e8b57',
+ 'seashell': '#fff5ee',
+ 'sienna': '#a0522d',
+ 'silver': '#c0c0c0',
+ 'skyblue': '#87ceeb',
+ 'slateblue': '#6a5acd',
+ 'slategray': '#708090',
+ 'snow': '#fffafa',
+ 'springgreen': '#00ff7f',
+ 'steelblue': '#4682b4',
+ 'tan': '#d2b48c',
+ 'teal': '#008080',
+ 'thistle': '#d8bfd8',
+ 'tomato': '#ff6347',
+ 'turquoise': '#40e0d0',
+ 'violet': '#ee82ee',
+ 'wheat': '#f5deb3',
+ 'white': '#fff',
+ 'whitesmoke': '#f5f5f5',
+ 'yellow': '#ff0',
+ 'yellowgreen': '#9acd32'
+};
+
+exports.colorsShortNames = {
+ '#f0ffff': 'azure',
+ '#f5f5dc': 'beige',
+ '#ffe4c4': 'bisque',
+ '#a52a2a': 'brown',
+ '#ff7f50': 'coral',
+ '#ffd700': 'gold',
+ '#808080': 'gray',
+ '#008000': 'green',
+ '#4b0082': 'indigo',
+ '#fffff0': 'ivory',
+ '#f0e68c': 'khaki',
+ '#faf0e6': 'linen',
+ '#800000': 'maroon',
+ '#000080': 'navy',
+ '#808000': 'olive',
+ '#ffa500': 'orange',
+ '#da70d6': 'orchid',
+ '#cd853f': 'peru',
+ '#ffc0cb': 'pink',
+ '#dda0dd': 'plum',
+ '#800080': 'purple',
+ '#f00': 'red',
+ '#fa8072': 'salmon',
+ '#a0522d': 'sienna',
+ '#c0c0c0': 'silver',
+ '#fffafa': 'snow',
+ '#d2b48c': 'tan',
+ '#008080': 'teal',
+ '#ff6347': 'tomato',
+ '#ee82ee': 'violet',
+ '#f5deb3': 'wheat'
+};
+
+// http://www.w3.org/TR/SVG/single-page.html#types-DataTypeColor
+exports.colorsProps = [
+ 'color', 'fill', 'stroke', 'stop-color', 'flood-color', 'lighting-color'
+];
diff --git a/node_modules/svgo/plugins/_path.js b/node_modules/svgo/plugins/_path.js
new file mode 100644
index 00000000..2aa567a0
--- /dev/null
+++ b/node_modules/svgo/plugins/_path.js
@@ -0,0 +1,962 @@
+/* global a2c */
+'use strict';
+
+var regPathInstructions = /([MmLlHhVvCcSsQqTtAaZz])\s*/,
+ regPathData = /[-+]?(?:\d*\.\d+|\d+\.?)([eE][-+]?\d+)?/g,
+ regNumericValues = /[-+]?(\d*\.\d+|\d+\.?)(?:[eE][-+]?\d+)?/,
+ transform2js = require('./_transforms').transform2js,
+ transformsMultiply = require('./_transforms').transformsMultiply,
+ transformArc = require('./_transforms').transformArc,
+ collections = require('./_collections.js'),
+ referencesProps = collections.referencesProps,
+ defaultStrokeWidth = collections.attrsGroupsDefaults.presentation['stroke-width'],
+ cleanupOutData = require('../lib/svgo/tools').cleanupOutData,
+ removeLeadingZero = require('../lib/svgo/tools').removeLeadingZero,
+ prevCtrlPoint;
+
+/**
+ * Convert path string to JS representation.
+ *
+ * @param {String} pathString input string
+ * @param {Object} params plugin params
+ * @return {Array} output array
+ */
+exports.path2js = function(path) {
+ if (path.pathJS) return path.pathJS;
+
+ var paramsLength = { // Number of parameters of every path command
+ H: 1, V: 1, M: 2, L: 2, T: 2, Q: 4, S: 4, C: 6, A: 7,
+ h: 1, v: 1, m: 2, l: 2, t: 2, q: 4, s: 4, c: 6, a: 7
+ },
+ pathData = [], // JS representation of the path data
+ instruction, // current instruction context
+ startMoveto = false;
+
+ // splitting path string into array like ['M', '10 50', 'L', '20 30']
+ path.attr('d').value.split(regPathInstructions).forEach(function(data) {
+ if (!data) return;
+ if (!startMoveto) {
+ if (data == 'M' || data == 'm') {
+ startMoveto = true;
+ } else return;
+ }
+
+ // instruction item
+ if (regPathInstructions.test(data)) {
+ instruction = data;
+
+ // z - instruction w/o data
+ if (instruction == 'Z' || instruction == 'z') {
+ pathData.push({
+ instruction: 'z'
+ });
+ }
+ // data item
+ } else {
+ data = data.match(regPathData);
+ if (!data) return;
+
+ data = data.map(Number);
+
+ // Subsequent moveto pairs of coordinates are threated as implicit lineto commands
+ // http://www.w3.org/TR/SVG/paths.html#PathDataMovetoCommands
+ if (instruction == 'M' || instruction == 'm') {
+ pathData.push({
+ instruction: pathData.length == 0 ? 'M' : instruction,
+ data: data.splice(0, 2)
+ });
+ instruction = instruction == 'M' ? 'L' : 'l';
+ }
+
+ for (var pair = paramsLength[instruction]; data.length;) {
+ pathData.push({
+ instruction: instruction,
+ data: data.splice(0, pair)
+ });
+ }
+ }
+ });
+
+ // First moveto is actually absolute. Subsequent coordinates were separated above.
+ if (pathData.length && pathData[0].instruction == 'm') {
+ pathData[0].instruction = 'M';
+ }
+ path.pathJS = pathData;
+
+ return pathData;
+};
+
+/**
+ * Convert relative Path data to absolute.
+ *
+ * @param {Array} data input data
+ * @return {Array} output data
+ */
+var relative2absolute = exports.relative2absolute = function(data) {
+ var currentPoint = [0, 0],
+ subpathPoint = [0, 0],
+ i;
+
+ data = data.map(function(item) {
+
+ var instruction = item.instruction,
+ itemData = item.data && item.data.slice();
+
+ if (instruction == 'M') {
+
+ set(currentPoint, itemData);
+ set(subpathPoint, itemData);
+
+ } else if ('mlcsqt'.indexOf(instruction) > -1) {
+
+ for (i = 0; i < itemData.length; i++) {
+ itemData[i] += currentPoint[i % 2];
+ }
+ set(currentPoint, itemData);
+
+ if (instruction == 'm') {
+ set(subpathPoint, itemData);
+ }
+
+ } else if (instruction == 'a') {
+
+ itemData[5] += currentPoint[0];
+ itemData[6] += currentPoint[1];
+ set(currentPoint, itemData);
+
+ } else if (instruction == 'h') {
+
+ itemData[0] += currentPoint[0];
+ currentPoint[0] = itemData[0];
+
+ } else if (instruction == 'v') {
+
+ itemData[0] += currentPoint[1];
+ currentPoint[1] = itemData[0];
+
+ } else if ('MZLCSQTA'.indexOf(instruction) > -1) {
+
+ set(currentPoint, itemData);
+
+ } else if (instruction == 'H') {
+
+ currentPoint[0] = itemData[0];
+
+ } else if (instruction == 'V') {
+
+ currentPoint[1] = itemData[0];
+
+ } else if (instruction == 'z') {
+
+ set(currentPoint, subpathPoint);
+
+ }
+
+ return instruction == 'z' ?
+ { instruction: 'z' } :
+ {
+ instruction: instruction.toUpperCase(),
+ data: itemData
+ };
+
+ });
+
+ return data;
+};
+
+/**
+ * Apply transformation(s) to the Path data.
+ *
+ * @param {Object} elem current element
+ * @param {Array} path input path data
+ * @param {Object} params whether to apply transforms to stroked lines and transform precision (used for stroke width)
+ * @return {Array} output path data
+ */
+exports.applyTransforms = function(elem, path, params) {
+ // if there are no 'stroke' attr and references to other objects such as
+ // gradiends or clip-path which are also subjects to transform.
+ if (!elem.hasAttr('transform') || !elem.attr('transform').value ||
+ elem.someAttr(function(attr) {
+ return ~referencesProps.indexOf(attr.name) && ~attr.value.indexOf('url(');
+ }))
+ return path;
+
+ var matrix = transformsMultiply(transform2js(elem.attr('transform').value)),
+ stroke = elem.computedAttr('stroke'),
+ id = elem.computedAttr('id'),
+ transformPrecision = params.transformPrecision,
+ newPoint, scale;
+
+ if (stroke && stroke != 'none') {
+ if (!params.applyTransformsStroked ||
+ (matrix.data[0] != matrix.data[3] || matrix.data[1] != -matrix.data[2]) &&
+ (matrix.data[0] != -matrix.data[3] || matrix.data[1] != matrix.data[2]))
+ return path;
+
+ // "stroke-width" should be inside the part with ID, otherwise it can be overrided in <use>
+ if (id) {
+ var idElem = elem,
+ hasStrokeWidth = false;
+
+ do {
+ if (idElem.hasAttr('stroke-width')) hasStrokeWidth = true;
+ } while (!idElem.hasAttr('id', id) && !hasStrokeWidth && (idElem = idElem.parentNode));
+
+ if (!hasStrokeWidth) return path;
+ }
+
+ scale = +Math.sqrt(matrix.data[0] * matrix.data[0] + matrix.data[1] * matrix.data[1]).toFixed(transformPrecision);
+
+ if (scale !== 1) {
+ var strokeWidth = elem.computedAttr('stroke-width') || defaultStrokeWidth;
+
+ if (elem.hasAttr('stroke-width')) {
+ elem.attrs['stroke-width'].value = elem.attrs['stroke-width'].value.trim()
+ .replace(regNumericValues, function(num) { return removeLeadingZero(num * scale) });
+ } else {
+ elem.addAttr({
+ name: 'stroke-width',
+ prefix: '',
+ local: 'stroke-width',
+ value: strokeWidth.replace(regNumericValues, function(num) { return removeLeadingZero(num * scale) })
+ });
+ }
+ }
+ } else if (id) { // Stroke and stroke-width can be redefined with <use>
+ return path;
+ }
+
+ path.forEach(function(pathItem) {
+
+ if (pathItem.data) {
+
+ // h -> l
+ if (pathItem.instruction === 'h') {
+
+ pathItem.instruction = 'l';
+ pathItem.data[1] = 0;
+
+ // v -> l
+ } else if (pathItem.instruction === 'v') {
+
+ pathItem.instruction = 'l';
+ pathItem.data[1] = pathItem.data[0];
+ pathItem.data[0] = 0;
+
+ }
+
+ // if there is a translate() transform
+ if (pathItem.instruction === 'M' &&
+ (matrix.data[4] !== 0 ||
+ matrix.data[5] !== 0)
+ ) {
+
+ // then apply it only to the first absoluted M
+ newPoint = transformPoint(matrix.data, pathItem.data[0], pathItem.data[1]);
+ set(pathItem.data, newPoint);
+ set(pathItem.coords, newPoint);
+
+ // clear translate() data from transform matrix
+ matrix.data[4] = 0;
+ matrix.data[5] = 0;
+
+ } else {
+
+ if (pathItem.instruction == 'a') {
+
+ transformArc(pathItem.data, matrix.data);
+
+ // reduce number of digits in rotation angle
+ if (Math.abs(pathItem.data[2]) > 80) {
+ var a = pathItem.data[0],
+ rotation = pathItem.data[2];
+ pathItem.data[0] = pathItem.data[1];
+ pathItem.data[1] = a;
+ pathItem.data[2] = rotation + (rotation > 0 ? -90 : 90);
+ }
+
+ newPoint = transformPoint(matrix.data, pathItem.data[5], pathItem.data[6]);
+ pathItem.data[5] = newPoint[0];
+ pathItem.data[6] = newPoint[1];
+
+ } else {
+
+ for (var i = 0; i < pathItem.data.length; i += 2) {
+ newPoint = transformPoint(matrix.data, pathItem.data[i], pathItem.data[i + 1]);
+ pathItem.data[i] = newPoint[0];
+ pathItem.data[i + 1] = newPoint[1];
+ }
+ }
+
+ pathItem.coords[0] = pathItem.base[0] + pathItem.data[pathItem.data.length - 2];
+ pathItem.coords[1] = pathItem.base[1] + pathItem.data[pathItem.data.length - 1];
+
+ }
+
+ }
+
+ });
+
+ // remove transform attr
+ elem.removeAttr('transform');
+
+ return path;
+};
+
+/**
+ * Apply transform 3x3 matrix to x-y point.
+ *
+ * @param {Array} matrix transform 3x3 matrix
+ * @param {Array} point x-y point
+ * @return {Array} point with new coordinates
+ */
+function transformPoint(matrix, x, y) {
+
+ return [
+ matrix[0] * x + matrix[2] * y + matrix[4],
+ matrix[1] * x + matrix[3] * y + matrix[5]
+ ];
+
+}
+
+/**
+ * Compute Cubic Bézie bounding box.
+ *
+ * @see http://processingjs.nihongoresources.com/bezierinfo/
+ *
+ * @param {Float} xa
+ * @param {Float} ya
+ * @param {Float} xb
+ * @param {Float} yb
+ * @param {Float} xc
+ * @param {Float} yc
+ * @param {Float} xd
+ * @param {Float} yd
+ *
+ * @return {Object}
+ */
+exports.computeCubicBoundingBox = function(xa, ya, xb, yb, xc, yc, xd, yd) {
+
+ var minx = Number.POSITIVE_INFINITY,
+ miny = Number.POSITIVE_INFINITY,
+ maxx = Number.NEGATIVE_INFINITY,
+ maxy = Number.NEGATIVE_INFINITY,
+ ts,
+ t,
+ x,
+ y,
+ i;
+
+ // X
+ if (xa < minx) { minx = xa; }
+ if (xa > maxx) { maxx = xa; }
+ if (xd < minx) { minx= xd; }
+ if (xd > maxx) { maxx = xd; }
+
+ ts = computeCubicFirstDerivativeRoots(xa, xb, xc, xd);
+
+ for (i = 0; i < ts.length; i++) {
+
+ t = ts[i];
+
+ if (t >= 0 && t <= 1) {
+ x = computeCubicBaseValue(t, xa, xb, xc, xd);
+ // y = computeCubicBaseValue(t, ya, yb, yc, yd);
+
+ if (x < minx) { minx = x; }
+ if (x > maxx) { maxx = x; }
+ }
+
+ }
+
+ // Y
+ if (ya < miny) { miny = ya; }
+ if (ya > maxy) { maxy = ya; }
+ if (yd < miny) { miny = yd; }
+ if (yd > maxy) { maxy = yd; }
+
+ ts = computeCubicFirstDerivativeRoots(ya, yb, yc, yd);
+
+ for (i = 0; i < ts.length; i++) {
+
+ t = ts[i];
+
+ if (t >= 0 && t <= 1) {
+ // x = computeCubicBaseValue(t, xa, xb, xc, xd);
+ y = computeCubicBaseValue(t, ya, yb, yc, yd);
+
+ if (y < miny) { miny = y; }
+ if (y > maxy) { maxy = y; }
+ }
+
+ }
+
+ return {
+ minx: minx,
+ miny: miny,
+ maxx: maxx,
+ maxy: maxy
+ };
+
+};
+
+// compute the value for the cubic bezier function at time=t
+function computeCubicBaseValue(t, a, b, c, d) {
+
+ var mt = 1 - t;
+
+ return mt * mt * mt * a + 3 * mt * mt * t * b + 3 * mt * t * t * c + t * t * t * d;
+
+}
+
+// compute the value for the first derivative of the cubic bezier function at time=t
+function computeCubicFirstDerivativeRoots(a, b, c, d) {
+
+ var result = [-1, -1],
+ tl = -a + 2 * b - c,
+ tr = -Math.sqrt(-a * (c - d) + b * b - b * (c + d) + c * c),
+ dn = -a + 3 * b - 3 * c + d;
+
+ if (dn !== 0) {
+ result[0] = (tl + tr) / dn;
+ result[1] = (tl - tr) / dn;
+ }
+
+ return result;
+
+}
+
+/**
+ * Compute Quadratic Bézier bounding box.
+ *
+ * @see http://processingjs.nihongoresources.com/bezierinfo/
+ *
+ * @param {Float} xa
+ * @param {Float} ya
+ * @param {Float} xb
+ * @param {Float} yb
+ * @param {Float} xc
+ * @param {Float} yc
+ *
+ * @return {Object}
+ */
+exports.computeQuadraticBoundingBox = function(xa, ya, xb, yb, xc, yc) {
+
+ var minx = Number.POSITIVE_INFINITY,
+ miny = Number.POSITIVE_INFINITY,
+ maxx = Number.NEGATIVE_INFINITY,
+ maxy = Number.NEGATIVE_INFINITY,
+ t,
+ x,
+ y;
+
+ // X
+ if (xa < minx) { minx = xa; }
+ if (xa > maxx) { maxx = xa; }
+ if (xc < minx) { minx = xc; }
+ if (xc > maxx) { maxx = xc; }
+
+ t = computeQuadraticFirstDerivativeRoot(xa, xb, xc);
+
+ if (t >= 0 && t <= 1) {
+ x = computeQuadraticBaseValue(t, xa, xb, xc);
+ // y = computeQuadraticBaseValue(t, ya, yb, yc);
+
+ if (x < minx) { minx = x; }
+ if (x > maxx) { maxx = x; }
+ }
+
+ // Y
+ if (ya < miny) { miny = ya; }
+ if (ya > maxy) { maxy = ya; }
+ if (yc < miny) { miny = yc; }
+ if (yc > maxy) { maxy = yc; }
+
+ t = computeQuadraticFirstDerivativeRoot(ya, yb, yc);
+
+ if (t >= 0 && t <=1 ) {
+ // x = computeQuadraticBaseValue(t, xa, xb, xc);
+ y = computeQuadraticBaseValue(t, ya, yb, yc);
+
+ if (y < miny) { miny = y; }
+ if (y > maxy) { maxy = y ; }
+
+ }
+
+ return {
+ minx: minx,
+ miny: miny,
+ maxx: maxx,
+ maxy: maxy
+ };
+
+};
+
+// compute the value for the quadratic bezier function at time=t
+function computeQuadraticBaseValue(t, a, b, c) {
+
+ var mt = 1 - t;
+
+ return mt * mt * a + 2 * mt * t * b + t * t * c;
+
+}
+
+// compute the value for the first derivative of the quadratic bezier function at time=t
+function computeQuadraticFirstDerivativeRoot(a, b, c) {
+
+ var t = -1,
+ denominator = a - 2 * b + c;
+
+ if (denominator !== 0) {
+ t = (a - b) / denominator;
+ }
+
+ return t;
+
+}
+
+/**
+ * Convert path array to string.
+ *
+ * @param {Array} path input path data
+ * @param {Object} params plugin params
+ * @return {String} output path string
+ */
+exports.js2path = function(path, data, params) {
+
+ path.pathJS = data;
+
+ if (params.collapseRepeated) {
+ data = collapseRepeated(data);
+ }
+
+ path.attr('d').value = data.reduce(function(pathString, item) {
+ return pathString += item.instruction + (item.data ? cleanupOutData(item.data, params) : '');
+ }, '');
+
+};
+
+/**
+ * Collapse repeated instructions data
+ *
+ * @param {Array} path input path data
+ * @return {Array} output path data
+ */
+function collapseRepeated(data) {
+
+ var prev,
+ prevIndex;
+
+ // copy an array and modifieds item to keep original data untouched
+ data = data.reduce(function(newPath, item) {
+ if (
+ prev && item.data &&
+ item.instruction == prev.instruction
+ ) {
+ // concat previous data with current
+ if (item.instruction != 'M') {
+ prev = newPath[prevIndex] = {
+ instruction: prev.instruction,
+ data: prev.data.concat(item.data),
+ coords: item.coords,
+ base: prev.base
+ };
+ } else {
+ prev.data = item.data;
+ prev.coords = item.coords;
+ }
+ } else {
+ newPath.push(item);
+ prev = item;
+ prevIndex = newPath.length - 1;
+ }
+
+ return newPath;
+ }, []);
+
+ return data;
+
+}
+
+function set(dest, source) {
+ dest[0] = source[source.length - 2];
+ dest[1] = source[source.length - 1];
+ return dest;
+}
+
+/**
+ * Checks if two paths have an intersection by checking convex hulls
+ * collision using Gilbert-Johnson-Keerthi distance algorithm
+ * http://entropyinteractive.com/2011/04/gjk-algorithm/
+ *
+ * @param {Array} path1 JS path representation
+ * @param {Array} path2 JS path representation
+ * @return {Boolean}
+ */
+exports.intersects = function(path1, path2) {
+ if (path1.length < 3 || path2.length < 3) return false; // nothing to fill
+
+ // Collect points of every subpath.
+ var points1 = relative2absolute(path1).reduce(gatherPoints, []),
+ points2 = relative2absolute(path2).reduce(gatherPoints, []);
+
+ // Axis-aligned bounding box check.
+ if (points1.maxX <= points2.minX || points2.maxX <= points1.minX ||
+ points1.maxY <= points2.minY || points2.maxY <= points1.minY ||
+ points1.every(function (set1) {
+ return points2.every(function (set2) {
+ return set1[set1.maxX][0] <= set2[set2.minX][0] ||
+ set2[set2.maxX][0] <= set1[set1.minX][0] ||
+ set1[set1.maxY][1] <= set2[set2.minY][1] ||
+ set2[set2.maxY][1] <= set1[set1.minY][1];
+ });
+ })
+ ) return false;
+
+ // Get a convex hull from points of each subpath. Has the most complexity O(n·log n).
+ var hullNest1 = points1.map(convexHull),
+ hullNest2 = points2.map(convexHull);
+
+ // Check intersection of every subpath of the first path with every subpath of the second.
+ return hullNest1.some(function(hull1) {
+ if (hull1.length < 3) return false;
+
+ return hullNest2.some(function(hull2) {
+ if (hull2.length < 3) return false;
+
+ var simplex = [getSupport(hull1, hull2, [1, 0])], // create the initial simplex
+ direction = minus(simplex[0]); // set the direction to point towards the origin
+
+ var iterations = 1e4; // infinite loop protection, 10 000 iterations is more than enough
+ while (true) {
+ if (iterations-- == 0) {
+ console.error('Error: infinite loop while processing mergePaths plugin.');
+ return true; // true is the safe value that means “do nothing with paths”
+ }
+ // add a new point
+ simplex.push(getSupport(hull1, hull2, direction));
+ // see if the new point was on the correct side of the origin
+ if (dot(direction, simplex[simplex.length - 1]) <= 0) return false;
+ // process the simplex
+ if (processSimplex(simplex, direction)) return true;
+ }
+ });
+ });
+
+ function getSupport(a, b, direction) {
+ return sub(supportPoint(a, direction), supportPoint(b, minus(direction)));
+ }
+
+ // Computes farthest polygon point in particular direction.
+ // Thanks to knowledge of min/max x and y coordinates we can choose a quadrant to search in.
+ // Since we're working on convex hull, the dot product is increasing until we find the farthest point.
+ function supportPoint(polygon, direction) {
+ var index = direction[1] >= 0 ?
+ direction[0] < 0 ? polygon.maxY : polygon.maxX :
+ direction[0] < 0 ? polygon.minX : polygon.minY,
+ max = -Infinity,
+ value;
+ while ((value = dot(polygon[index], direction)) > max) {
+ max = value;
+ index = ++index % polygon.length;
+ }
+ return polygon[(index || polygon.length) - 1];
+ }
+};
+
+function processSimplex(simplex, direction) {
+ /* jshint -W004 */
+
+ // we only need to handle to 1-simplex and 2-simplex
+ if (simplex.length == 2) { // 1-simplex
+ var a = simplex[1],
+ b = simplex[0],
+ AO = minus(simplex[1]),
+ AB = sub(b, a);
+ // AO is in the same direction as AB
+ if (dot(AO, AB) > 0) {
+ // get the vector perpendicular to AB facing O
+ set(direction, orth(AB, a));
+ } else {
+ set(direction, AO);
+ // only A remains in the simplex
+ simplex.shift();
+ }
+ } else { // 2-simplex
+ var a = simplex[2], // [a, b, c] = simplex
+ b = simplex[1],
+ c = simplex[0],
+ AB = sub(b, a),
+ AC = sub(c, a),
+ AO = minus(a),
+ ACB = orth(AB, AC), // the vector perpendicular to AB facing away from C
+ ABC = orth(AC, AB); // the vector perpendicular to AC facing away from B
+
+ if (dot(ACB, AO) > 0) {
+ if (dot(AB, AO) > 0) { // region 4
+ set(direction, ACB);
+ simplex.shift(); // simplex = [b, a]
+ } else { // region 5
+ set(direction, AO);
+ simplex.splice(0, 2); // simplex = [a]
+ }
+ } else if (dot(ABC, AO) > 0) {
+ if (dot(AC, AO) > 0) { // region 6
+ set(direction, ABC);
+ simplex.splice(1, 1); // simplex = [c, a]
+ } else { // region 5 (again)
+ set(direction, AO);
+ simplex.splice(0, 2); // simplex = [a]
+ }
+ } else // region 7
+ return true;
+ }
+ return false;
+}
+
+function minus(v) {
+ return [-v[0], -v[1]];
+}
+
+function sub(v1, v2) {
+ return [v1[0] - v2[0], v1[1] - v2[1]];
+}
+
+function dot(v1, v2) {
+ return v1[0] * v2[0] + v1[1] * v2[1];
+}
+
+function orth(v, from) {
+ var o = [-v[1], v[0]];
+ return dot(o, minus(from)) < 0 ? minus(o) : o;
+}
+
+function gatherPoints(points, item, index, path) {
+
+ var subPath = points.length && points[points.length - 1],
+ prev = index && path[index - 1],
+ basePoint = subPath.length && subPath[subPath.length - 1],
+ data = item.data,
+ ctrlPoint = basePoint;
+
+ switch (item.instruction) {
+ case 'M':
+ points.push(subPath = []);
+ break;
+ case 'H':
+ addPoint(subPath, [data[0], basePoint[1]]);
+ break;
+ case 'V':
+ addPoint(subPath, [basePoint[0], data[0]]);
+ break;
+ case 'Q':
+ addPoint(subPath, data.slice(0, 2));
+ prevCtrlPoint = [data[2] - data[0], data[3] - data[1]]; // Save control point for shorthand
+ break;
+ case 'T':
+ if (prev.instruction == 'Q' && prev.instruction == 'T') {
+ ctrlPoint = [basePoint[0] + prevCtrlPoint[0], basePoint[1] + prevCtrlPoint[1]];
+ addPoint(subPath, ctrlPoint);
+ prevCtrlPoint = [data[0] - ctrlPoint[0], data[1] - ctrlPoint[1]];
+ }
+ break;
+ case 'C':
+ // Approximate quibic Bezier curve with middle points between control points
+ addPoint(subPath, [.5 * (basePoint[0] + data[0]), .5 * (basePoint[1] + data[1])]);
+ addPoint(subPath, [.5 * (data[0] + data[2]), .5 * (data[1] + data[3])]);
+ addPoint(subPath, [.5 * (data[2] + data[4]), .5 * (data[3] + data[5])]);
+ prevCtrlPoint = [data[4] - data[2], data[5] - data[3]]; // Save control point for shorthand
+ break;
+ case 'S':
+ if (prev.instruction == 'C' && prev.instruction == 'S') {
+ addPoint(subPath, [basePoint[0] + .5 * prevCtrlPoint[0], basePoint[1] + .5 * prevCtrlPoint[1]]);
+ ctrlPoint = [basePoint[0] + prevCtrlPoint[0], basePoint[1] + prevCtrlPoint[1]];
+ }
+ addPoint(subPath, [.5 * (ctrlPoint[0] + data[0]), .5 * (ctrlPoint[1]+ data[1])]);
+ addPoint(subPath, [.5 * (data[0] + data[2]), .5 * (data[1] + data[3])]);
+ prevCtrlPoint = [data[2] - data[0], data[3] - data[1]];
+ break;
+ case 'A':
+ // Convert the arc to bezier curves and use the same approximation
+ var curves = a2c.apply(0, basePoint.concat(data));
+ for (var cData; (cData = curves.splice(0,6).map(toAbsolute)).length;) {
+ addPoint(subPath, [.5 * (basePoint[0] + cData[0]), .5 * (basePoint[1] + cData[1])]);
+ addPoint(subPath, [.5 * (cData[0] + cData[2]), .5 * (cData[1] + cData[3])]);
+ addPoint(subPath, [.5 * (cData[2] + cData[4]), .5 * (cData[3] + cData[5])]);
+ if (curves.length) addPoint(subPath, basePoint = cData.slice(-2));
+ }
+ break;
+ }
+ // Save final command coordinates
+ if (data && data.length >= 2) addPoint(subPath, data.slice(-2));
+ return points;
+
+ function toAbsolute(n, i) { return n + basePoint[i % 2] }
+
+ // Writes data about the extreme points on each axle
+ function addPoint(path, point) {
+ if (!path.length || point[1] > path[path.maxY][1]) {
+ path.maxY = path.length;
+ points.maxY = points.length ? Math.max(point[1], points.maxY) : point[1];
+ }
+ if (!path.length || point[0] > path[path.maxX][0]) {
+ path.maxX = path.length;
+ points.maxX = points.length ? Math.max(point[0], points.maxX) : point[0];
+ }
+ if (!path.length || point[1] < path[path.minY][1]) {
+ path.minY = path.length;
+ points.minY = points.length ? Math.min(point[1], points.minY) : point[1];
+ }
+ if (!path.length || point[0] < path[path.minX][0]) {
+ path.minX = path.length;
+ points.minX = points.length ? Math.min(point[0], points.minX) : point[0];
+ }
+ path.push(point);
+ }
+}
+
+/**
+ * Forms a convex hull from set of points of every subpath using monotone chain convex hull algorithm.
+ * http://en.wikibooks.org/wiki/Algorithm_Implementation/Geometry/Convex_hull/Monotone_chain
+ *
+ * @param points An array of [X, Y] coordinates
+ */
+function convexHull(points) {
+ /* jshint -W004 */
+
+ points.sort(function(a, b) {
+ return a[0] == b[0] ? a[1] - b[1] : a[0] - b[0];
+ });
+
+ var lower = [],
+ minY = 0,
+ bottom = 0;
+ for (var i = 0; i < points.length; i++) {
+ while (lower.length >= 2 && cross(lower[lower.length - 2], lower[lower.length - 1], points[i]) <= 0) {
+ lower.pop();
+ }
+ if (points[i][1] < points[minY][1]) {
+ minY = i;
+ bottom = lower.length;
+ }
+ lower.push(points[i]);
+ }
+
+ var upper = [],
+ maxY = points.length - 1,
+ top = 0;
+ for (var i = points.length; i--;) {
+ while (upper.length >= 2 && cross(upper[upper.length - 2], upper[upper.length - 1], points[i]) <= 0) {
+ upper.pop();
+ }
+ if (points[i][1] > points[maxY][1]) {
+ maxY = i;
+ top = upper.length;
+ }
+ upper.push(points[i]);
+ }
+
+ // last points are equal to starting points of the other part
+ upper.pop();
+ lower.pop();
+
+ var hull = lower.concat(upper);
+
+ hull.minX = 0; // by sorting
+ hull.maxX = lower.length;
+ hull.minY = bottom;
+ hull.maxY = (lower.length + top) % hull.length;
+
+ return hull;
+}
+
+function cross(o, a, b) {
+ return (a[0] - o[0]) * (b[1] - o[1]) - (a[1] - o[1]) * (b[0] - o[0]);
+}
+
+/* Based on code from Snap.svg (Apache 2 license). http://snapsvg.io/
+ * Thanks to Dmitry Baranovskiy for his great work!
+ */
+
+// jshint ignore: start
+function a2c(x1, y1, rx, ry, angle, large_arc_flag, sweep_flag, x2, y2, recursive) {
+ // for more information of where this Math came from visit:
+ // http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes
+ var _120 = Math.PI * 120 / 180,
+ rad = Math.PI / 180 * (+angle || 0),
+ res = [],
+ rotateX = function(x, y, rad) { return x * Math.cos(rad) - y * Math.sin(rad) },
+ rotateY = function(x, y, rad) { return x * Math.sin(rad) + y * Math.cos(rad) };
+ if (!recursive) {
+ x1 = rotateX(x1, y1, -rad);
+ y1 = rotateY(x1, y1, -rad);
+ x2 = rotateX(x2, y2, -rad);
+ y2 = rotateY(x2, y2, -rad);
+ var x = (x1 - x2) / 2,
+ y = (y1 - y2) / 2;
+ var h = (x * x) / (rx * rx) + (y * y) / (ry * ry);
+ if (h > 1) {
+ h = Math.sqrt(h);
+ rx = h * rx;
+ ry = h * ry;
+ }
+ var rx2 = rx * rx,
+ ry2 = ry * ry,
+ k = (large_arc_flag == sweep_flag ? -1 : 1) *
+ Math.sqrt(Math.abs((rx2 * ry2 - rx2 * y * y - ry2 * x * x) / (rx2 * y * y + ry2 * x * x))),
+ cx = k * rx * y / ry + (x1 + x2) / 2,
+ cy = k * -ry * x / rx + (y1 + y2) / 2,
+ f1 = Math.asin(((y1 - cy) / ry).toFixed(9)),
+ f2 = Math.asin(((y2 - cy) / ry).toFixed(9));
+
+ f1 = x1 < cx ? Math.PI - f1 : f1;
+ f2 = x2 < cx ? Math.PI - f2 : f2;
+ f1 < 0 && (f1 = Math.PI * 2 + f1);
+ f2 < 0 && (f2 = Math.PI * 2 + f2);
+ if (sweep_flag && f1 > f2) {
+ f1 = f1 - Math.PI * 2;
+ }
+ if (!sweep_flag && f2 > f1) {
+ f2 = f2 - Math.PI * 2;
+ }
+ } else {
+ f1 = recursive[0];
+ f2 = recursive[1];
+ cx = recursive[2];
+ cy = recursive[3];
+ }
+ var df = f2 - f1;
+ if (Math.abs(df) > _120) {
+ var f2old = f2,
+ x2old = x2,
+ y2old = y2;
+ f2 = f1 + _120 * (sweep_flag && f2 > f1 ? 1 : -1);
+ x2 = cx + rx * Math.cos(f2);
+ y2 = cy + ry * Math.sin(f2);
+ res = a2c(x2, y2, rx, ry, angle, 0, sweep_flag, x2old, y2old, [f2, f2old, cx, cy]);
+ }
+ df = f2 - f1;
+ var c1 = Math.cos(f1),
+ s1 = Math.sin(f1),
+ c2 = Math.cos(f2),
+ s2 = Math.sin(f2),
+ t = Math.tan(df / 4),
+ hx = 4 / 3 * rx * t,
+ hy = 4 / 3 * ry * t,
+ m = [
+ - hx * s1, hy * c1,
+ x2 + hx * s2 - x1, y2 - hy * c2 - y1,
+ x2 - x1, y2 - y1
+ ];
+ if (recursive) {
+ return m.concat(res);
+ } else {
+ res = m.concat(res);
+ var newres = [];
+ for (var i = 0, n = res.length; i < n; i++) {
+ newres[i] = i % 2 ? rotateY(res[i - 1], res[i], rad) : rotateX(res[i], res[i + 1], rad);
+ }
+ return newres;
+ }
+}
+// jshint ignore: end
diff --git a/node_modules/svgo/plugins/_transforms.js b/node_modules/svgo/plugins/_transforms.js
new file mode 100644
index 00000000..796ca259
--- /dev/null
+++ b/node_modules/svgo/plugins/_transforms.js
@@ -0,0 +1,308 @@
+'use strict';
+
+var regTransformTypes = /matrix|translate|scale|rotate|skewX|skewY/,
+ regTransformSplit = /\s*(matrix|translate|scale|rotate|skewX|skewY)\s*\(\s*(.+?)\s*\)[\s,]*/,
+ regNumericValues = /[-+]?(?:\d*\.\d+|\d+\.?)(?:[eE][-+]?\d+)?/g;
+
+/**
+ * Convert transform string to JS representation.
+ *
+ * @param {String} transformString input string
+ * @param {Object} params plugin params
+ * @return {Array} output array
+ */
+exports.transform2js = function(transformString) {
+
+ // JS representation of the transform data
+ var transforms = [],
+ // current transform context
+ current;
+
+ // split value into ['', 'translate', '10 50', '', 'scale', '2', '', 'rotate', '-45', '']
+ transformString.split(regTransformSplit).forEach(function(item) {
+ /*jshint -W084 */
+ var num;
+
+ if (item) {
+ // if item is a translate function
+ if (regTransformTypes.test(item)) {
+ // then collect it and change current context
+ transforms.push(current = { name: item });
+ // else if item is data
+ } else {
+ // then split it into [10, 50] and collect as context.data
+ while (num = regNumericValues.exec(item)) {
+ num = Number(num);
+ if (current.data)
+ current.data.push(num);
+ else
+ current.data = [num];
+ }
+ }
+ }
+ });
+
+ return transforms;
+
+};
+
+/**
+ * Multiply transforms into one.
+ *
+ * @param {Array} input transforms array
+ * @return {Array} output matrix array
+ */
+exports.transformsMultiply = function(transforms) {
+
+ // convert transforms objects to the matrices
+ transforms = transforms.map(function(transform) {
+ if (transform.name === 'matrix') {
+ return transform.data;
+ }
+ return transformToMatrix(transform);
+ });
+
+ // multiply all matrices into one
+ transforms = {
+ name: 'matrix',
+ data: transforms.reduce(function(a, b) {
+ return multiplyTransformMatrices(a, b);
+ })
+ };
+
+ return transforms;
+
+};
+
+/**
+ * Do math like a schoolgirl.
+ *
+ * @type {Object}
+ */
+var mth = exports.mth = {
+
+ rad: function(deg) {
+ return deg * Math.PI / 180;
+ },
+
+ deg: function(rad) {
+ return rad * 180 / Math.PI;
+ },
+
+ cos: function(deg) {
+ return Math.cos(this.rad(deg));
+ },
+
+ acos: function(val, floatPrecision) {
+ return +(this.deg(Math.acos(val)).toFixed(floatPrecision));
+ },
+
+ sin: function(deg) {
+ return Math.sin(this.rad(deg));
+ },
+
+ asin: function(val, floatPrecision) {
+ return +(this.deg(Math.asin(val)).toFixed(floatPrecision));
+ },
+
+ tan: function(deg) {
+ return Math.tan(this.rad(deg));
+ },
+
+ atan: function(val, floatPrecision) {
+ return +(this.deg(Math.atan(val)).toFixed(floatPrecision));
+ }
+
+};
+
+/**
+ * Decompose matrix into simple transforms. See
+ * http://www.maths-informatique-jeux.com/blog/frederic/?post/2013/12/01/Decomposition-of-2D-transform-matrices
+ *
+ * @param {Object} data matrix transform object
+ * @return {Object|Array} transforms array or original transform object
+ */
+exports.matrixToTransform = function(transform, params) {
+ var floatPrecision = params.floatPrecision,
+ data = transform.data,
+ transforms = [],
+ sx = +Math.sqrt(data[0] * data[0] + data[1] * data[1]).toFixed(params.transformPrecision),
+ sy = +((data[0] * data[3] - data[1] * data[2]) / sx).toFixed(params.transformPrecision),
+ colsSum = data[0] * data[2] + data[1] * data[3],
+ rowsSum = data[0] * data[1] + data[2] * data[3],
+ scaleBefore = rowsSum || +(sx == sy);
+
+ // [..., ..., ..., ..., tx, ty] → translate(tx, ty)
+ if (data[4] || data[5]) {
+ transforms.push({ name: 'translate', data: data.slice(4, data[5] ? 6 : 5) });
+ }
+
+ // [sx, 0, tan(a)·sy, sy, 0, 0] → skewX(a)·scale(sx, sy)
+ if (!data[1] && data[2]) {
+ transforms.push({ name: 'skewX', data: [mth.atan(data[2] / sy, floatPrecision)] });
+
+ // [sx, sx·tan(a), 0, sy, 0, 0] → skewY(a)·scale(sx, sy)
+ } else if (data[1] && !data[2]) {
+ transforms.push({ name: 'skewY', data: [mth.atan(data[1] / data[0], floatPrecision)] });
+ sx = data[0];
+ sy = data[3];
+
+ // [sx·cos(a), sx·sin(a), sy·-sin(a), sy·cos(a), x, y] → rotate(a[, cx, cy])·(scale or skewX) or
+ // [sx·cos(a), sy·sin(a), sx·-sin(a), sy·cos(a), x, y] → scale(sx, sy)·rotate(a[, cx, cy]) (if !scaleBefore)
+ } else if (!colsSum || (sx == 1 && sy == 1) || !scaleBefore) {
+ if (!scaleBefore) {
+ sx = (data[0] < 0 ? -1 : 1) * Math.sqrt(data[0] * data[0] + data[2] * data[2]);
+ sy = (data[3] < 0 ? -1 : 1) * Math.sqrt(data[1] * data[1] + data[3] * data[3]);
+ transforms.push({ name: 'scale', data: [sx, sy] });
+ }
+ var rotate = [mth.acos(data[0] / sx, floatPrecision) * (data[1] * sy < 0 ? -1 : 1)];
+
+ if (rotate[0]) transforms.push({ name: 'rotate', data: rotate });
+
+ if (rowsSum && colsSum) transforms.push({
+ name: 'skewX',
+ data: [mth.atan(colsSum / (sx * sx), floatPrecision)]
+ });
+
+ // rotate(a, cx, cy) can consume translate() within optional arguments cx, cy (rotation point)
+ if (rotate[0] && (data[4] || data[5])) {
+ transforms.shift();
+ var cos = data[0] / sx,
+ sin = data[1] / (scaleBefore ? sx : sy),
+ x = data[4] * (scaleBefore || sy),
+ y = data[5] * (scaleBefore || sx),
+ denom = (Math.pow(1 - cos, 2) + Math.pow(sin, 2)) * (scaleBefore || sx * sy);
+ rotate.push(((1 - cos) * x - sin * y) / denom);
+ rotate.push(((1 - cos) * y + sin * x) / denom);
+ }
+
+ // Too many transformations, return original matrix if it isn't just a scale/translate
+ } else if (data[1] || data[2]) {
+ return transform;
+ }
+
+ if (scaleBefore && (sx != 1 || sy != 1) || !transforms.length) transforms.push({
+ name: 'scale',
+ data: sx == sy ? [sx] : [sx, sy]
+ });
+
+ return transforms;
+};
+
+/**
+ * Convert transform to the matrix data.
+ *
+ * @param {Object} transform transform object
+ * @return {Array} matrix data
+ */
+function transformToMatrix(transform) {
+
+ if (transform.name === 'matrix') return transform.data;
+
+ var matrix;
+
+ switch (transform.name) {
+ case 'translate':
+ // [1, 0, 0, 1, tx, ty]
+ matrix = [1, 0, 0, 1, transform.data[0], transform.data[1] || 0];
+ break;
+ case 'scale':
+ // [sx, 0, 0, sy, 0, 0]
+ matrix = [transform.data[0], 0, 0, transform.data[1] || transform.data[0], 0, 0];
+ break;
+ case 'rotate':
+ // [cos(a), sin(a), -sin(a), cos(a), x, y]
+ var cos = mth.cos(transform.data[0]),
+ sin = mth.sin(transform.data[0]),
+ cx = transform.data[1] || 0,
+ cy = transform.data[2] || 0;
+
+ matrix = [cos, sin, -sin, cos, (1 - cos) * cx + sin * cy, (1 - cos) * cy - sin * cx];
+ break;
+ case 'skewX':
+ // [1, 0, tan(a), 1, 0, 0]
+ matrix = [1, 0, mth.tan(transform.data[0]), 1, 0, 0];
+ break;
+ case 'skewY':
+ // [1, tan(a), 0, 1, 0, 0]
+ matrix = [1, mth.tan(transform.data[0]), 0, 1, 0, 0];
+ break;
+ }
+
+ return matrix;
+
+}
+
+/**
+ * Applies transformation to an arc. To do so, we represent ellipse as a matrix, multiply it
+ * by the transformation matrix and use a singular value decomposition to represent in a form
+ * rotate(θ)·scale(a b)·rotate(φ). This gives us new ellipse params a, b and θ.
+ * SVD is being done with the formulae provided by Wolffram|Alpha (svd {{m0, m2}, {m1, m3}})
+ *
+ * @param {Array} arc [a, b, rotation in deg]
+ * @param {Array} transform transformation matrix
+ * @return {Array} arc transformed input arc
+ */
+exports.transformArc = function(arc, transform) {
+
+ var a = arc[0],
+ b = arc[1],
+ rot = arc[2] * Math.PI / 180,
+ cos = Math.cos(rot),
+ sin = Math.sin(rot),
+ h = Math.pow(arc[5] * cos + arc[6] * sin, 2) / (4 * a * a) +
+ Math.pow(arc[6] * cos - arc[5] * sin, 2) / (4 * b * b);
+ if (h > 1) {
+ h = Math.sqrt(h);
+ a *= h;
+ b *= h;
+ }
+ var ellipse = [a * cos, a * sin, -b * sin, b * cos, 0, 0],
+ m = multiplyTransformMatrices(transform, ellipse),
+ // Decompose the new ellipse matrix
+ lastCol = m[2] * m[2] + m[3] * m[3],
+ squareSum = m[0] * m[0] + m[1] * m[1] + lastCol,
+ root = Math.sqrt(
+ (Math.pow(m[0] - m[3], 2) + Math.pow(m[1] + m[2], 2)) *
+ (Math.pow(m[0] + m[3], 2) + Math.pow(m[1] - m[2], 2))
+ );
+
+ if (!root) { // circle
+ arc[0] = arc[1] = Math.sqrt(squareSum / 2);
+ arc[2] = 0;
+ } else {
+ var majorAxisSqr = (squareSum + root) / 2,
+ minorAxisSqr = (squareSum - root) / 2,
+ major = Math.abs(majorAxisSqr - lastCol) > 1e-6,
+ sub = (major ? majorAxisSqr : minorAxisSqr) - lastCol,
+ rowsSum = m[0] * m[2] + m[1] * m[3],
+ term1 = m[0] * sub + m[2] * rowsSum,
+ term2 = m[1] * sub + m[3] * rowsSum;
+ arc[0] = Math.sqrt(majorAxisSqr);
+ arc[1] = Math.sqrt(minorAxisSqr);
+ arc[2] = ((major ? term2 < 0 : term1 > 0) ? -1 : 1) *
+ Math.acos((major ? term1 : term2) / Math.sqrt(term1 * term1 + term2 * term2)) * 180 / Math.PI;
+ }
+ return arc;
+
+};
+
+/**
+ * Multiply transformation matrices.
+ *
+ * @param {Array} a matrix A data
+ * @param {Array} b matrix B data
+ * @return {Array} result
+ */
+function multiplyTransformMatrices(a, b) {
+
+ return [
+ a[0] * b[0] + a[2] * b[1],
+ a[1] * b[0] + a[3] * b[1],
+ a[0] * b[2] + a[2] * b[3],
+ a[1] * b[2] + a[3] * b[3],
+ a[0] * b[4] + a[2] * b[5] + a[4],
+ a[1] * b[4] + a[3] * b[5] + a[5]
+ ];
+
+}
diff --git a/node_modules/svgo/plugins/addAttributesToSVGElement.js b/node_modules/svgo/plugins/addAttributesToSVGElement.js
new file mode 100644
index 00000000..9b97c95c
--- /dev/null
+++ b/node_modules/svgo/plugins/addAttributesToSVGElement.js
@@ -0,0 +1,57 @@
+'use strict';
+
+exports.type = 'full';
+
+exports.active = false;
+
+exports.description = 'adds attributes to an outer <svg> element';
+
+var ENOCLS = 'Error in plugin "addAttributesToSVGElement": absent parameters.\n\
+It should have a list of classes in "attributes" or one "attribute".\n\
+Config example:\n\n\
+\
+plugins:\n\
+- addAttributesToSVGElement:\n\
+ attribute: "mySvg"\n\n\
+\
+plugins:\n\
+- addAttributesToSVGElement:\n\
+ attributes: ["mySvg", "size-big"]\n';
+
+/**
+ * Add attributes to an outer <svg> element. Example config:
+ *
+ * plugins:
+ * - addAttributesToSVGElement:
+ * attribute: 'data-icon'
+ *
+ * plugins:
+ * - addAttributesToSVGElement:
+ * attributes: ['data-icon', 'data-disabled']
+ *
+ * @author April Arcus
+ */
+exports.fn = function(data, params) {
+ if (!params || !(Array.isArray(params.attributes) && params.attributes.some(String) || params.attribute)) {
+ console.error(ENOCLS);
+ return data;
+ }
+
+ var attributes = params.attributes || [ params.attribute ],
+ svg = data.content[0];
+
+ if (svg.isElem('svg')) {
+ attributes.forEach(function (attribute) {
+ if (!svg.hasAttr(attribute)) {
+ svg.addAttr({
+ name: attribute,
+ prefix: '',
+ local: attribute
+ });
+ }
+ });
+ }
+
+ return data;
+
+};
diff --git a/node_modules/svgo/plugins/addClassesToSVGElement.js b/node_modules/svgo/plugins/addClassesToSVGElement.js
new file mode 100644
index 00000000..3f9596aa
--- /dev/null
+++ b/node_modules/svgo/plugins/addClassesToSVGElement.js
@@ -0,0 +1,64 @@
+'use strict';
+
+exports.type = 'full';
+
+exports.active = false;
+
+exports.description = 'adds classnames to an outer <svg> element';
+
+var ENOCLS = 'Error in plugin "addClassesToSVGElement": absent parameters.\n\
+It should have a list of classes in "classNames" or one "className".\n\
+Config example:\n\n\
+\
+plugins:\n\
+- addClassesToSVGElement:\n\
+ className: "mySvg"\n\n\
+\
+plugins:\n\
+- addClassesToSVGElement:\n\
+ classNames: ["mySvg", "size-big"]\n';
+
+/**
+ * Add classnames to an outer <svg> element. Example config:
+ *
+ * plugins:
+ * - addClassesToSVGElement:
+ * className: 'mySvg'
+ *
+ * plugins:
+ * - addClassesToSVGElement:
+ * classNames: ['mySvg', 'size-big']
+ *
+ * @author April Arcus
+ */
+exports.fn = function(data, params) {
+ if (!params || !(Array.isArray(params.classNames) && params.classNames.some(String) || params.className)) {
+ console.error(ENOCLS);
+ return data;
+ }
+
+ var classNames = params.classNames || [ params.className ],
+ svg = data.content[0];
+
+ if (svg.isElem('svg')) {
+ if (svg.hasAttr('class')) {
+ var classes = svg.attr('class').value.split(' ');
+ classNames.forEach(function(className){
+ if (classes.indexOf(className) < 0) {
+ classes.push(className);
+ }
+ });
+ svg.attr('class').value = classes.join(' ');
+ } else {
+ svg.addAttr({
+ name: 'class',
+ value: classNames.join(' '),
+ prefix: '',
+ local: 'class'
+ });
+ }
+ }
+
+ return data;
+
+};
diff --git a/node_modules/svgo/plugins/cleanupAttrs.js b/node_modules/svgo/plugins/cleanupAttrs.js
new file mode 100644
index 00000000..47e77ac7
--- /dev/null
+++ b/node_modules/svgo/plugins/cleanupAttrs.js
@@ -0,0 +1,56 @@
+'use strict';
+
+exports.type = 'perItem';
+
+exports.active = true;
+
+exports.description = 'cleanups attributes from newlines, trailing and repeating spaces';
+
+exports.params = {
+ newlines: true,
+ trim: true,
+ spaces: true
+};
+
+var regNewlinesNeedSpace = /(\S)\r?\n(\S)/g,
+ regNewlines = /\r?\n/g,
+ regSpaces = /\s{2,}/g;
+
+/**
+ * Cleanup attributes values from newlines, trailing and repeating spaces.
+ *
+ * @param {Object} item current iteration item
+ * @param {Object} params plugin params
+ * @return {Boolean} if false, item will be filtered out
+ *
+ * @author Kir Belevich
+ */
+exports.fn = function(item, params) {
+
+ if (item.isElem()) {
+
+ item.eachAttr(function(attr) {
+
+ if (params.newlines) {
+ // new line which requires a space instead of themselve
+ attr.value = attr.value.replace(regNewlinesNeedSpace, function(match, p1, p2) {
+ return p1 + ' ' + p2;
+ });
+
+ // simple new line
+ attr.value = attr.value.replace(regNewlines, '');
+ }
+
+ if (params.trim) {
+ attr.value = attr.value.trim();
+ }
+
+ if (params.spaces) {
+ attr.value = attr.value.replace(regSpaces, ' ');
+ }
+
+ });
+
+ }
+
+};
diff --git a/node_modules/svgo/plugins/cleanupEnableBackground.js b/node_modules/svgo/plugins/cleanupEnableBackground.js
new file mode 100644
index 00000000..e6384ab5
--- /dev/null
+++ b/node_modules/svgo/plugins/cleanupEnableBackground.js
@@ -0,0 +1,84 @@
+'use strict';
+
+exports.type = 'full';
+
+exports.active = true;
+
+exports.description = 'remove or cleanup enable-background attribute when possible';
+
+/**
+ * Remove or cleanup enable-background attr which coincides with a width/height box.
+ *
+ * @see http://www.w3.org/TR/SVG/filters.html#EnableBackgroundProperty
+ *
+ * @example
+ * <svg width="100" height="50" enable-background="new 0 0 100 50">
+ * ⬇
+ * <svg width="100" height="50">
+ *
+ * @param {Object} item current iteration item
+ * @return {Boolean} if false, item will be filtered out
+ *
+ * @author Kir Belevich
+ */
+exports.fn = function(data) {
+
+ var regEnableBackground = /^new\s0\s0\s([\-+]?\d*\.?\d+([eE][\-+]?\d+)?)\s([\-+]?\d*\.?\d+([eE][\-+]?\d+)?)$/,
+ hasFilter = false,
+ elems = ['svg', 'mask', 'pattern'];
+
+ function checkEnableBackground(item) {
+ if (
+ item.isElem(elems) &&
+ item.hasAttr('enable-background') &&
+ item.hasAttr('width') &&
+ item.hasAttr('height')
+ ) {
+
+ var match = item.attr('enable-background').value.match(regEnableBackground);
+
+ if (match) {
+ if (
+ item.attr('width').value === match[1] &&
+ item.attr('height').value === match[3]
+ ) {
+ if (item.isElem('svg')) {
+ item.removeAttr('enable-background');
+ } else {
+ item.attr('enable-background').value = 'new';
+ }
+ }
+ }
+
+ }
+ }
+
+ function checkForFilter(item) {
+ if (item.isElem('filter')) {
+ hasFilter = true;
+ }
+ }
+
+ function monkeys(items, fn) {
+ items.content.forEach(function(item) {
+ fn(item);
+
+ if (item.content) {
+ monkeys(item, fn);
+ }
+ });
+ return items;
+ }
+
+ var firstStep = monkeys(data, function(item) {
+ checkEnableBackground(item);
+ if (!hasFilter) {
+ checkForFilter(item);
+ }
+ });
+
+ return hasFilter ? firstStep : monkeys(firstStep, function(item) {
+ //we don't need 'enable-background' if we have no filters
+ item.removeAttr('enable-background');
+ });
+};
diff --git a/node_modules/svgo/plugins/cleanupIDs.js b/node_modules/svgo/plugins/cleanupIDs.js
new file mode 100644
index 00000000..38b5cfb4
--- /dev/null
+++ b/node_modules/svgo/plugins/cleanupIDs.js
@@ -0,0 +1,208 @@
+'use strict';
+
+exports.type = 'full';
+
+exports.active = true;
+
+exports.description = 'removes unused IDs and minifies used';
+
+exports.params = {
+ remove: true,
+ minify: true,
+ prefix: ''
+};
+
+var referencesProps = require('./_collections').referencesProps,
+ regReferencesUrl = /\burl\(("|')?#(.+?)\1\)/,
+ regReferencesHref = /^#(.+?)$/,
+ regReferencesBegin = /^(\w+?)\./,
+ styleOrScript = ['style', 'script'],
+ generateIDchars = [
+ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'
+ ],
+ maxIDindex = generateIDchars.length - 1;
+
+/**
+ * Remove unused and minify used IDs
+ * (only if there are no any <style> or <script>).
+ *
+ * @param {Object} item current iteration item
+ * @param {Object} params plugin params
+ *
+ * @author Kir Belevich
+ */
+exports.fn = function(data, params) {
+
+ var currentID,
+ currentIDstring,
+ IDs = Object.create(null),
+ referencesIDs = Object.create(null),
+ idPrefix = 'id-', // prefix IDs so that values like '__proto__' don't break the work
+ hasStyleOrScript = false;
+
+ /**
+ * Bananas!
+ *
+ * @param {Array} items input items
+ * @return {Array} output items
+ */
+ function monkeys(items) {
+
+ for (var i = 0; i < items.content.length && !hasStyleOrScript; i++) {
+
+ var item = items.content[i],
+ match;
+
+ // check if <style> of <script> presents
+ if (item.isElem(styleOrScript)) {
+ hasStyleOrScript = true;
+ continue;
+ }
+
+ // …and don't remove any ID if yes
+ if (item.isElem()) {
+
+ item.eachAttr(function(attr) {
+ var key;
+ // save IDs
+ if (attr.name === 'id') {
+ key = idPrefix + attr.value;
+ if (key in IDs) {
+ item.removeAttr('id');
+ } else {
+ IDs[key] = item;
+ }
+ }
+
+ // save IDs url() references
+ else if (referencesProps.indexOf(attr.name) > -1) {
+ match = attr.value.match(regReferencesUrl);
+
+ if (match) {
+ key = idPrefix + match[2];
+ if (referencesIDs[key]) {
+ referencesIDs[key].push(attr);
+ } else {
+ referencesIDs[key] = [attr];
+ }
+ }
+ }
+
+ // save IDs href references
+ else if (
+ attr.local === 'href' && (match = attr.value.match(regReferencesHref)) ||
+ attr.name === 'begin' && (match = attr.value.match(regReferencesBegin))
+ ) {
+ key = idPrefix + match[1];
+ if (referencesIDs[key]) {
+ referencesIDs[key].push(attr);
+ } else {
+ referencesIDs[key] = [attr];
+ }
+ }
+ });
+
+ }
+
+ // go deeper
+ if (item.content) {
+ monkeys(item);
+ }
+ }
+
+ return items;
+
+ }
+
+ data = monkeys(data);
+
+ if (hasStyleOrScript) {
+ return data;
+ }
+
+ var idKey;
+ for (var k in referencesIDs) {
+ if (IDs[k]) {
+ idKey = k;
+ k = k.replace(idPrefix, '');
+ // replace referenced IDs with the minified ones
+ if (params.minify) {
+ currentIDstring = getIDstring(currentID = generateID(currentID), params);
+ IDs[idKey].attr('id').value = currentIDstring;
+
+ referencesIDs[idKey].forEach(function(attr) {
+ attr.value = attr.value
+ .replace('#' + k, '#' + currentIDstring)
+ .replace(k + '.', currentIDstring + '.');
+ });
+
+ idKey = idPrefix + k;
+ }
+
+ // don't remove referenced IDs
+ delete IDs[idKey];
+ }
+ }
+
+ // remove non-referenced IDs attributes from elements
+ if (params.remove) {
+
+ for(var ID in IDs) {
+ IDs[ID].removeAttr('id');
+ }
+
+ }
+
+ return data;
+
+};
+
+/**
+ * Generate unique minimal ID.
+ *
+ * @param {Array} [currentID] current ID
+ * @return {Array} generated ID array
+ */
+function generateID(currentID) {
+
+ if (!currentID) return [0];
+
+ currentID[currentID.length - 1]++;
+
+ for(var i = currentID.length - 1; i > 0; i--) {
+ if (currentID[i] > maxIDindex) {
+ currentID[i] = 0;
+
+ if (currentID[i - 1] !== undefined) {
+ currentID[i - 1]++;
+ }
+ }
+ }
+
+ if (currentID[0] > maxIDindex) {
+ currentID[0] = 0;
+ currentID.unshift(0);
+ }
+
+ return currentID;
+
+}
+
+/**
+ * Get string from generated ID array.
+ *
+ * @param {Array} arr input ID array
+ * @return {String} output ID string
+ */
+function getIDstring(arr, params) {
+
+ var str = params.prefix;
+
+ arr.forEach(function(i) {
+ str += generateIDchars[i];
+ });
+
+ return str;
+
+}
diff --git a/node_modules/svgo/plugins/cleanupListOfValues.js b/node_modules/svgo/plugins/cleanupListOfValues.js
new file mode 100644
index 00000000..e75944da
--- /dev/null
+++ b/node_modules/svgo/plugins/cleanupListOfValues.js
@@ -0,0 +1,141 @@
+'use strict';
+
+exports.type = 'perItem';
+
+exports.active = false;
+
+exports.description = 'rounds list of values to the fixed precision';
+
+exports.params = {
+ floatPrecision: 3,
+ leadingZero: true,
+ defaultPx: true,
+ convertToPx: true
+};
+
+var regNumericValues = /^([\-+]?\d*\.?\d+([eE][\-+]?\d+)?)(px|pt|pc|mm|cm|m|in|ft|em|ex|%)?$/,
+ regSeparator = /\s+,?\s*|,\s*/,
+ removeLeadingZero = require('../lib/svgo/tools').removeLeadingZero,
+ absoluteLengths = { // relative to px
+ cm: 96/2.54,
+ mm: 96/25.4,
+ in: 96,
+ pt: 4/3,
+ pc: 16
+ };
+
+/**
+ * Round list of values to the fixed precision.
+ *
+ * @example
+ * <svg viewBox="0 0 200.28423 200.28423" enable-background="new 0 0 200.28423 200.28423">
+ * ⬇
+ * <svg viewBox="0 0 200.284 200.284" enable-background="new 0 0 200.284 200.284">
+ *
+ *
+ * <polygon points="208.250977 77.1308594 223.069336 ... "/>
+ * ⬇
+ * <polygon points="208.251 77.131 223.069 ... "/>
+ *
+ *
+ * @param {Object} item current iteration item
+ * @param {Object} params plugin params
+ * @return {Boolean} if false, item will be filtered out
+ *
+ * @author kiyopikko
+ */
+exports.fn = function(item, params) {
+
+
+ if ( item.hasAttr('points') ) {
+ roundValues(item.attrs.points);
+ }
+
+ if ( item.hasAttr('enable-background') ) {
+ roundValues(item.attrs['enable-background']);
+ }
+
+ if ( item.hasAttr('viewBox') ) {
+ roundValues(item.attrs.viewBox);
+ }
+
+ if ( item.hasAttr('stroke-dasharray') ) {
+ roundValues(item.attrs['stroke-dasharray']);
+ }
+
+ if ( item.hasAttr('dx') ) {
+ roundValues(item.attrs.dx);
+ }
+
+ if ( item.hasAttr('dy') ) {
+ roundValues(item.attrs.dy);
+ }
+
+ if ( item.hasAttr('x') ) {
+ roundValues(item.attrs.x);
+ }
+
+ if ( item.hasAttr('y') ) {
+ roundValues(item.attrs.y);
+ }
+
+
+ function roundValues($prop){
+
+ var num, units,
+ match,
+ matchNew,
+ lists = $prop.value,
+ listsArr = lists.split(regSeparator),
+ roundedListArr = [],
+ roundedList;
+
+ listsArr.forEach(function(elem){
+
+ match = elem.match(regNumericValues);
+ matchNew = elem.match(/new/);
+
+ // if attribute value matches regNumericValues
+ if(match){
+
+ // round it to the fixed precision
+ num = +(+match[1]).toFixed(params.floatPrecision),
+ units = match[3] || '';
+
+ // convert absolute values to pixels
+ if (params.convertToPx && units && (units in absoluteLengths)) {
+ var pxNum = +(absoluteLengths[units] * match[1]).toFixed(params.floatPrecision);
+
+ if (String(pxNum).length < match[0].length)
+ num = pxNum,
+ units = 'px';
+ }
+
+ // and remove leading zero
+ if (params.leadingZero) {
+ num = removeLeadingZero(num);
+ }
+
+ // remove default 'px' units
+ if (params.defaultPx && units === 'px') {
+ units = '';
+ }
+
+ roundedListArr.push(num+units);
+
+ }
+ // if attribute value is "new"(only enable-background).
+ else if(matchNew){
+
+ roundedListArr.push('new');
+
+ }
+
+ });
+
+ roundedList = roundedListArr.join(' ');
+ $prop.value = roundedList;
+
+ }
+
+};
diff --git a/node_modules/svgo/plugins/cleanupNumericValues.js b/node_modules/svgo/plugins/cleanupNumericValues.js
new file mode 100644
index 00000000..487443a5
--- /dev/null
+++ b/node_modules/svgo/plugins/cleanupNumericValues.js
@@ -0,0 +1,76 @@
+'use strict';
+
+exports.type = 'perItem';
+
+exports.active = true;
+
+exports.description = 'rounds numeric values to the fixed precision, removes default ‘px’ units';
+
+exports.params = {
+ floatPrecision: 3,
+ leadingZero: true,
+ defaultPx: true,
+ convertToPx: true
+};
+
+var regNumericValues = /^([\-+]?\d*\.?\d+([eE][\-+]?\d+)?)(px|pt|pc|mm|cm|m|in|ft|em|ex|%)?$/,
+ removeLeadingZero = require('../lib/svgo/tools').removeLeadingZero,
+ absoluteLengths = { // relative to px
+ cm: 96/2.54,
+ mm: 96/25.4,
+ in: 96,
+ pt: 4/3,
+ pc: 16
+ };
+
+/**
+ * Round numeric values to the fixed precision,
+ * remove default 'px' units.
+ *
+ * @param {Object} item current iteration item
+ * @param {Object} params plugin params
+ * @return {Boolean} if false, item will be filtered out
+ *
+ * @author Kir Belevich
+ */
+exports.fn = function(item, params) {
+
+ if (item.isElem()) {
+
+ var match;
+
+ item.eachAttr(function(attr) {
+ match = attr.value.match(regNumericValues);
+
+ // if attribute value matches regNumericValues
+ if (match) {
+ // round it to the fixed precision
+ var num = +(+match[1]).toFixed(params.floatPrecision),
+ units = match[3] || '';
+
+ // convert absolute values to pixels
+ if (params.convertToPx && units && (units in absoluteLengths)) {
+ var pxNum = +(absoluteLengths[units] * match[1]).toFixed(params.floatPrecision);
+
+ if (String(pxNum).length < match[0].length)
+ num = pxNum,
+ units = 'px';
+ }
+
+ // and remove leading zero
+ if (params.leadingZero) {
+ num = removeLeadingZero(num);
+ }
+
+ // remove default 'px' units
+ if (params.defaultPx && units === 'px') {
+ units = '';
+ }
+
+ attr.value = num + units;
+ }
+ });
+
+ }
+
+};
diff --git a/node_modules/svgo/plugins/collapseGroups.js b/node_modules/svgo/plugins/collapseGroups.js
new file mode 100644
index 00000000..adc97638
--- /dev/null
+++ b/node_modules/svgo/plugins/collapseGroups.js
@@ -0,0 +1,91 @@
+'use strict';
+
+exports.type = 'perItemReverse';
+
+exports.active = true;
+
+exports.description = 'collapses useless groups';
+
+var collections = require('./_collections'),
+ attrsInheritable = collections.inheritableAttrs,
+ animationElems = collections.elemsGroups.animation;
+
+function hasAnimatedAttr(item) {
+ /* jshint validthis:true */
+ return item.isElem(animationElems) && item.hasAttr('attributeName', this) ||
+ !item.isEmpty() && item.content.some(hasAnimatedAttr, this);
+}
+
+/*
+ * Collapse useless groups.
+ *
+ * @example
+ * <g>
+ * <g attr1="val1">
+ * <path d="..."/>
+ * </g>
+ * </g>
+ * ⬇
+ * <g>
+ * <g>
+ * <path attr1="val1" d="..."/>
+ * </g>
+ * </g>
+ * ⬇
+ * <path attr1="val1" d="..."/>
+ *
+ * @param {Object} item current iteration item
+ * @return {Boolean} if false, item will be filtered out
+ *
+ * @author Kir Belevich
+ */
+exports.fn = function(item) {
+
+ // non-empty elements
+ if (item.isElem() && !item.isElem('switch') && !item.isEmpty()) {
+
+ item.content.forEach(function(g, i) {
+
+ // non-empty groups
+ if (g.isElem('g') && !g.isEmpty()) {
+
+ // move group attibutes to the single content element
+ if (g.hasAttr() && g.content.length === 1) {
+ var inner = g.content[0];
+
+ if (inner.isElem() && !inner.hasAttr('id') &&
+ !(g.hasAttr('class') && inner.hasAttr('class')) && (
+ !g.hasAttr('clip-path') && !g.hasAttr('mask') ||
+ inner.isElem('g') && !g.hasAttr('transform') && !inner.hasAttr('transform')
+ )
+ ) {
+ g.eachAttr(function(attr) {
+ if (g.content.some(hasAnimatedAttr, attr.name)) return;
+
+ if (!inner.hasAttr(attr.name)) {
+ inner.addAttr(attr);
+ } else if (attr.name == 'transform') {
+ inner.attr(attr.name).value = attr.value + ' ' + inner.attr(attr.name).value;
+ } else if (
+ attrsInheritable.indexOf(attr.name) < 0 &&
+ !inner.hasAttr(attr.name, attr.value)
+ ) {
+ return;
+ }
+
+ g.removeAttr(attr.name);
+ });
+ }
+ }
+
+ // collapse groups without attributes
+ if (!g.hasAttr() && !g.content.some(function(item) { return item.isElem(animationElems) })) {
+ item.spliceContent(i, 1, g.content);
+ }
+ }
+
+ });
+
+ }
+
+};
diff --git a/node_modules/svgo/plugins/convertColors.js b/node_modules/svgo/plugins/convertColors.js
new file mode 100644
index 00000000..b856e130
--- /dev/null
+++ b/node_modules/svgo/plugins/convertColors.js
@@ -0,0 +1,127 @@
+'use strict';
+
+exports.type = 'perItem';
+
+exports.active = true;
+
+exports.description = 'converts colors: rgb() to #rrggbb and #rrggbb to #rgb';
+
+exports.params = {
+ currentColor: false,
+ names2hex: true,
+ rgb2hex: true,
+ shorthex: true,
+ shortname: true
+};
+
+var collections = require('./_collections'),
+ rNumber = '([+-]?(?:\\d*\\.\\d+|\\d+\\.?)%?)',
+ rComma = '\\s*,\\s*',
+ regRGB = new RegExp('^rgb\\(\\s*' + rNumber + rComma + rNumber + rComma + rNumber + '\\s*\\)$'),
+ regHEX = /^\#(([a-fA-F0-9])\2){3}$/,
+ none = /\bnone\b/i;
+
+/**
+ * Convert different colors formats in element attributes to hex.
+ *
+ * @see http://www.w3.org/TR/SVG/types.html#DataTypeColor
+ * @see http://www.w3.org/TR/SVG/single-page.html#types-ColorKeywords
+ *
+ * @example
+ * Convert color name keyword to long hex:
+ * fuchsia ➡ #ff00ff
+ *
+ * Convert rgb() to long hex:
+ * rgb(255, 0, 255) ➡ #ff00ff
+ * rgb(50%, 100, 100%) ➡ #7f64ff
+ *
+ * Convert long hex to short hex:
+ * #aabbcc ➡ #abc
+ *
+ * Convert hex to short name
+ * #000080 ➡ navy
+ *
+ * @param {Object} item current iteration item
+ * @param {Object} params plugin params
+ * @return {Boolean} if false, item will be filtered out
+ *
+ * @author Kir Belevich
+ */
+exports.fn = function(item, params) {
+
+ if (item.elem) {
+
+ item.eachAttr(function(attr) {
+
+ if (collections.colorsProps.indexOf(attr.name) > -1) {
+
+ var val = attr.value,
+ match;
+
+ // Convert colors to currentColor
+ if (params.currentColor) {
+ if (typeof params.currentColor === 'string') {
+ match = val === params.currentColor;
+ } else if (params.currentColor.exec) {
+ match = params.currentColor.exec(val);
+ } else {
+ match = !val.match(none);
+ }
+ if (match) {
+ val = 'currentColor';
+ }
+ }
+
+ // Convert color name keyword to long hex
+ if (params.names2hex && val.toLowerCase() in collections.colorsNames) {
+ val = collections.colorsNames[val.toLowerCase()];
+ }
+
+ // Convert rgb() to long hex
+ if (params.rgb2hex && (match = val.match(regRGB))) {
+ match = match.slice(1, 4).map(function(m) {
+ if (m.indexOf('%') > -1)
+ m = Math.round(parseFloat(m) * 2.55);
+
+ return Math.max(0, Math.min(m, 255));
+ });
+
+ val = rgb2hex(match);
+ }
+
+ // Convert long hex to short hex
+ if (params.shorthex && (match = val.match(regHEX))) {
+ val = '#' + match[0][1] + match[0][3] + match[0][5];
+ }
+
+ // Convert hex to short name
+ if (params.shortname && val in collections.colorsShortNames) {
+ val = collections.colorsShortNames[val];
+ }
+
+ attr.value = val;
+
+ }
+
+ });
+
+ }
+
+};
+
+/**
+ * Convert [r, g, b] to #rrggbb.
+ *
+ * @see https://gist.github.com/983535
+ *
+ * @example
+ * rgb2hex([255, 255, 255]) // '#ffffff'
+ *
+ * @param {Array} rgb [r, g, b]
+ * @return {String} #rrggbb
+ *
+ * @author Jed Schmidt
+ */
+function rgb2hex(rgb) {
+ return '#' + ('00000' + (rgb[0] << 16 | rgb[1] << 8 | rgb[2]).toString(16)).slice(-6).toUpperCase();
+}
diff --git a/node_modules/svgo/plugins/convertPathData.js b/node_modules/svgo/plugins/convertPathData.js
new file mode 100644
index 00000000..c76a52c2
--- /dev/null
+++ b/node_modules/svgo/plugins/convertPathData.js
@@ -0,0 +1,957 @@
+'use strict';
+
+exports.type = 'perItem';
+
+exports.active = true;
+
+exports.description = 'optimizes path data: writes in shorter form, applies transformations';
+
+exports.params = {
+ applyTransforms: true,
+ applyTransformsStroked: true,
+ makeArcs: {
+ threshold: 2.5, // coefficient of rounding error
+ tolerance: 0.5 // percentage of radius
+ },
+ straightCurves: true,
+ lineShorthands: true,
+ curveSmoothShorthands: true,
+ floatPrecision: 3,
+ transformPrecision: 5,
+ removeUseless: true,
+ collapseRepeated: true,
+ utilizeAbsolute: true,
+ leadingZero: true,
+ negativeExtraSpace: true
+};
+
+var pathElems = require('./_collections.js').pathElems,
+ path2js = require('./_path.js').path2js,
+ js2path = require('./_path.js').js2path,
+ applyTransforms = require('./_path.js').applyTransforms,
+ cleanupOutData = require('../lib/svgo/tools').cleanupOutData,
+ roundData,
+ precision,
+ error,
+ arcThreshold,
+ arcTolerance,
+ hasMarkerMid;
+
+/**
+ * Convert absolute Path to relative,
+ * collapse repeated instructions,
+ * detect and convert Lineto shorthands,
+ * remove useless instructions like "l0,0",
+ * trim useless delimiters and leading zeros,
+ * decrease accuracy of floating-point numbers.
+ *
+ * @see http://www.w3.org/TR/SVG/paths.html#PathData
+ *
+ * @param {Object} item current iteration item
+ * @param {Object} params plugin params
+ * @return {Boolean} if false, item will be filtered out
+ *
+ * @author Kir Belevich
+ */
+exports.fn = function(item, params) {
+
+ if (item.isElem(pathElems) && item.hasAttr('d')) {
+
+ precision = params.floatPrecision;
+ error = precision !== false ? +Math.pow(.1, precision).toFixed(precision) : 1e-2;
+ roundData = precision > 0 && precision < 20 ? strongRound : round;
+ if (params.makeArcs) {
+ arcThreshold = params.makeArcs.threshold;
+ arcTolerance = params.makeArcs.tolerance;
+ }
+ hasMarkerMid = item.hasAttr('marker-mid');
+
+ var data = path2js(item);
+
+ // TODO: get rid of functions returns
+ if (data.length) {
+ convertToRelative(data);
+
+ if (params.applyTransforms) {
+ data = applyTransforms(item, data, params);
+ }
+
+ data = filters(data, params);
+
+ if (params.utilizeAbsolute) {
+ data = convertToMixed(data, params);
+ }
+
+ js2path(item, data, params);
+ }
+
+ }
+
+};
+
+/**
+ * Convert absolute path data coordinates to relative.
+ *
+ * @param {Array} path input path data
+ * @param {Object} params plugin params
+ * @return {Array} output path data
+ */
+function convertToRelative(path) {
+
+ var point = [0, 0],
+ subpathPoint = [0, 0],
+ baseItem;
+
+ path.forEach(function(item, index) {
+
+ var instruction = item.instruction,
+ data = item.data;
+
+ // data !== !z
+ if (data) {
+
+ // already relative
+ // recalculate current point
+ if ('mcslqta'.indexOf(instruction) > -1) {
+
+ point[0] += data[data.length - 2];
+ point[1] += data[data.length - 1];
+
+ if (instruction === 'm') {
+ subpathPoint[0] = point[0];
+ subpathPoint[1] = point[1];
+ baseItem = item;
+ }
+
+ } else if (instruction === 'h') {
+
+ point[0] += data[0];
+
+ } else if (instruction === 'v') {
+
+ point[1] += data[0];
+
+ }
+
+ // convert absolute path data coordinates to relative
+ // if "M" was not transformed from "m"
+ // M → m
+ if (instruction === 'M') {
+
+ if (index > 0) instruction = 'm';
+
+ data[0] -= point[0];
+ data[1] -= point[1];
+
+ subpathPoint[0] = point[0] += data[0];
+ subpathPoint[1] = point[1] += data[1];
+
+ baseItem = item;
+
+ }
+
+ // L → l
+ // T → t
+ else if ('LT'.indexOf(instruction) > -1) {
+
+ instruction = instruction.toLowerCase();
+
+ // x y
+ // 0 1
+ data[0] -= point[0];
+ data[1] -= point[1];
+
+ point[0] += data[0];
+ point[1] += data[1];
+
+ // C → c
+ } else if (instruction === 'C') {
+
+ instruction = 'c';
+
+ // x1 y1 x2 y2 x y
+ // 0 1 2 3 4 5
+ data[0] -= point[0];
+ data[1] -= point[1];
+ data[2] -= point[0];
+ data[3] -= point[1];
+ data[4] -= point[0];
+ data[5] -= point[1];
+
+ point[0] += data[4];
+ point[1] += data[5];
+
+ // S → s
+ // Q → q
+ } else if ('SQ'.indexOf(instruction) > -1) {
+
+ instruction = instruction.toLowerCase();
+
+ // x1 y1 x y
+ // 0 1 2 3
+ data[0] -= point[0];
+ data[1] -= point[1];
+ data[2] -= point[0];
+ data[3] -= point[1];
+
+ point[0] += data[2];
+ point[1] += data[3];
+
+ // A → a
+ } else if (instruction === 'A') {
+
+ instruction = 'a';
+
+ // rx ry x-axis-rotation large-arc-flag sweep-flag x y
+ // 0 1 2 3 4 5 6
+ data[5] -= point[0];
+ data[6] -= point[1];
+
+ point[0] += data[5];
+ point[1] += data[6];
+
+ // H → h
+ } else if (instruction === 'H') {
+
+ instruction = 'h';
+
+ data[0] -= point[0];
+
+ point[0] += data[0];
+
+ // V → v
+ } else if (instruction === 'V') {
+
+ instruction = 'v';
+
+ data[0] -= point[1];
+
+ point[1] += data[0];
+
+ }
+
+ item.instruction = instruction;
+ item.data = data;
+
+ // store absolute coordinates for later use
+ item.coords = point.slice(-2);
+
+ }
+
+ // !data === z, reset current point
+ else if (instruction == 'z') {
+ if (baseItem) {
+ item.coords = baseItem.coords;
+ }
+ point[0] = subpathPoint[0];
+ point[1] = subpathPoint[1];
+ }
+
+ item.base = index > 0 ? path[index - 1].coords : [0, 0];
+
+ });
+
+ return path;
+
+}
+
+/**
+ * Main filters loop.
+ *
+ * @param {Array} path input path data
+ * @param {Object} params plugin params
+ * @return {Array} output path data
+ */
+function filters(path, params) {
+
+ var stringify = data2Path.bind(null, params),
+ relSubpoint = [0, 0],
+ pathBase = [0, 0],
+ prev = {};
+
+ path = path.filter(function(item, index, path) {
+
+ var instruction = item.instruction,
+ data = item.data,
+ next = path[index + 1];
+
+ if (data) {
+
+ var sdata = data,
+ circle;
+
+ if (instruction === 's') {
+ sdata = [0, 0].concat(data);
+
+ if ('cs'.indexOf(prev.instruction) > -1) {
+ var pdata = prev.data,
+ n = pdata.length;
+
+ // (-x, -y) of the prev tangent point relative to the current point
+ sdata[0] = pdata[n - 2] - pdata[n - 4];
+ sdata[1] = pdata[n - 1] - pdata[n - 3];
+ }
+
+ }
+
+ // convert curves to arcs if possible
+ if (
+ params.makeArcs &&
+ (instruction == 'c' || instruction == 's') &&
+ isConvex(sdata) &&
+ (circle = findCircle(sdata))
+ ) {
+ var r = roundData([circle.radius])[0],
+ angle = findArcAngle(sdata, circle),
+ sweep = sdata[5] * sdata[0] - sdata[4] * sdata[1] > 0 ? 1 : 0,
+ arc = {
+ instruction: 'a',
+ data: [r, r, 0, 0, sweep, sdata[4], sdata[5]],
+ coords: item.coords.slice(),
+ base: item.base
+ },
+ output = [arc],
+ // relative coordinates to adjust the found circle
+ relCenter = [circle.center[0] - sdata[4], circle.center[1] - sdata[5]],
+ relCircle = { center: relCenter, radius: circle.radius },
+ arcCurves = [item],
+ hasPrev = 0,
+ suffix = '',
+ nextLonghand;
+
+ if (
+ prev.instruction == 'c' && isConvex(prev.data) && isArcPrev(prev.data, circle) ||
+ prev.instruction == 'a' && prev.sdata && isArcPrev(prev.sdata, circle)
+ ) {
+ arcCurves.unshift(prev);
+ arc.base = prev.base;
+ arc.data[5] = arc.coords[0] - arc.base[0];
+ arc.data[6] = arc.coords[1] - arc.base[1];
+ var prevData = prev.instruction == 'a' ? prev.sdata : prev.data;
+ angle += findArcAngle(prevData,
+ {
+ center: [prevData[4] + relCenter[0], prevData[5] + relCenter[1]],
+ radius: circle.radius
+ }
+ );
+ if (angle > Math.PI) arc.data[3] = 1;
+ hasPrev = 1;
+ }
+
+ // check if next curves are fitting the arc
+ for (var j = index; (next = path[++j]) && ~'cs'.indexOf(next.instruction);) {
+ var nextData = next.data;
+ if (next.instruction == 's') {
+ nextLonghand = makeLonghand({instruction: 's', data: next.data.slice() },
+ path[j - 1].data);
+ nextData = nextLonghand.data;
+ nextLonghand.data = nextData.slice(0, 2);
+ suffix = stringify([nextLonghand]);
+ }
+ if (isConvex(nextData) && isArc(nextData, relCircle)) {
+ angle += findArcAngle(nextData, relCircle);
+ if (angle - 2 * Math.PI > 1e-3) break; // more than 360°
+ if (angle > Math.PI) arc.data[3] = 1;
+ arcCurves.push(next);
+ if (2 * Math.PI - angle > 1e-3) { // less than 360°
+ arc.coords = next.coords;
+ arc.data[5] = arc.coords[0] - arc.base[0];
+ arc.data[6] = arc.coords[1] - arc.base[1];
+ } else {
+ // full circle, make a half-circle arc and add a second one
+ arc.data[5] = 2 * (relCircle.center[0] - nextData[4]);
+ arc.data[6] = 2 * (relCircle.center[1] - nextData[5]);
+ arc.coords = [arc.base[0] + arc.data[5], arc.base[1] + arc.data[6]];
+ arc = {
+ instruction: 'a',
+ data: [r, r, 0, 0, sweep,
+ next.coords[0] - arc.coords[0], next.coords[1] - arc.coords[1]],
+ coords: next.coords,
+ base: arc.coords
+ };
+ output.push(arc);
+ j++;
+ break;
+ }
+ relCenter[0] -= nextData[4];
+ relCenter[1] -= nextData[5];
+ } else break;
+ }
+
+ if ((stringify(output) + suffix).length < stringify(arcCurves).length) {
+ if (path[j] && path[j].instruction == 's') {
+ makeLonghand(path[j], path[j - 1].data);
+ }
+ if (hasPrev) {
+ var prevArc = output.shift();
+ roundData(prevArc.data);
+ relSubpoint[0] += prevArc.data[5] - prev.data[prev.data.length - 2];
+ relSubpoint[1] += prevArc.data[6] - prev.data[prev.data.length - 1];
+ prev.instruction = 'a';
+ prev.data = prevArc.data;
+ item.base = prev.coords = prevArc.coords;
+ }
+ arc = output.shift();
+ if (arcCurves.length == 1) {
+ item.sdata = sdata.slice(); // preserve curve data for future checks
+ } else if (arcCurves.length - 1 - hasPrev > 0) {
+ // filter out consumed next items
+ path.splice.apply(path, [index + 1, arcCurves.length - 1 - hasPrev].concat(output));
+ }
+ if (!arc) return false;
+ instruction = 'a';
+ data = arc.data;
+ item.coords = arc.coords;
+ }
+ }
+
+ // Rounding relative coordinates, taking in account accummulating error
+ // to get closer to absolute coordinates. Sum of rounded value remains same:
+ // l .25 3 .25 2 .25 3 .25 2 -> l .3 3 .2 2 .3 3 .2 2
+ if (precision !== false) {
+ if ('mltqsc'.indexOf(instruction) > -1) {
+ for (var i = data.length; i--;) {
+ data[i] += item.base[i % 2] - relSubpoint[i % 2];
+ }
+ } else if (instruction == 'h') {
+ data[0] += item.base[0] - relSubpoint[0];
+ } else if (instruction == 'v') {
+ data[0] += item.base[1] - relSubpoint[1];
+ } else if (instruction == 'a') {
+ data[5] += item.base[0] - relSubpoint[0];
+ data[6] += item.base[1] - relSubpoint[1];
+ }
+ roundData(data);
+
+ if (instruction == 'h') relSubpoint[0] += data[0];
+ else if (instruction == 'v') relSubpoint[1] += data[0];
+ else {
+ relSubpoint[0] += data[data.length - 2];
+ relSubpoint[1] += data[data.length - 1];
+ }
+ roundData(relSubpoint);
+
+ if (instruction.toLowerCase() == 'm') {
+ pathBase[0] = relSubpoint[0];
+ pathBase[1] = relSubpoint[1];
+ }
+ }
+
+ // convert straight curves into lines segments
+ if (params.straightCurves) {
+
+ if (
+ instruction === 'c' &&
+ isCurveStraightLine(data) ||
+ instruction === 's' &&
+ isCurveStraightLine(sdata)
+ ) {
+ if (next && next.instruction == 's')
+ makeLonghand(next, data); // fix up next curve
+ instruction = 'l';
+ data = data.slice(-2);
+ }
+
+ else if (
+ instruction === 'q' &&
+ isCurveStraightLine(data)
+ ) {
+ if (next && next.instruction == 't')
+ makeLonghand(next, data); // fix up next curve
+ instruction = 'l';
+ data = data.slice(-2);
+ }
+
+ else if (
+ instruction === 't' &&
+ prev.instruction !== 'q' &&
+ prev.instruction !== 't'
+ ) {
+ instruction = 'l';
+ data = data.slice(-2);
+ }
+
+ else if (
+ instruction === 'a' &&
+ (data[0] === 0 || data[1] === 0)
+ ) {
+ instruction = 'l';
+ data = data.slice(-2);
+ }
+ }
+
+ // horizontal and vertical line shorthands
+ // l 50 0 → h 50
+ // l 0 50 → v 50
+ if (
+ params.lineShorthands &&
+ instruction === 'l'
+ ) {
+ if (data[1] === 0) {
+ instruction = 'h';
+ data.pop();
+ } else if (data[0] === 0) {
+ instruction = 'v';
+ data.shift();
+ }
+ }
+
+ // collapse repeated commands
+ // h 20 h 30 -> h 50
+ if (
+ params.collapseRepeated &&
+ !hasMarkerMid &&
+ ('mhv'.indexOf(instruction) > -1) &&
+ prev.instruction &&
+ instruction == prev.instruction.toLowerCase() &&
+ (
+ (instruction != 'h' && instruction != 'v') ||
+ (prev.data[0] >= 0) == (item.data[0] >= 0)
+ )) {
+ prev.data[0] += data[0];
+ if (instruction != 'h' && instruction != 'v') {
+ prev.data[1] += data[1];
+ }
+ prev.coords = item.coords;
+ path[index] = prev;
+ return false;
+ }
+
+ // convert curves into smooth shorthands
+ if (params.curveSmoothShorthands && prev.instruction) {
+
+ // curveto
+ if (instruction === 'c') {
+
+ // c + c → c + s
+ if (
+ prev.instruction === 'c' &&
+ data[0] === -(prev.data[2] - prev.data[4]) &&
+ data[1] === -(prev.data[3] - prev.data[5])
+ ) {
+ instruction = 's';
+ data = data.slice(2);
+ }
+
+ // s + c → s + s
+ else if (
+ prev.instruction === 's' &&
+ data[0] === -(prev.data[0] - prev.data[2]) &&
+ data[1] === -(prev.data[1] - prev.data[3])
+ ) {
+ instruction = 's';
+ data = data.slice(2);
+ }
+
+ // [^cs] + c → [^cs] + s
+ else if (
+ 'cs'.indexOf(prev.instruction) === -1 &&
+ data[0] === 0 &&
+ data[1] === 0
+ ) {
+ instruction = 's';
+ data = data.slice(2);
+ }
+
+ }
+
+ // quadratic Bézier curveto
+ else if (instruction === 'q') {
+
+ // q + q → q + t
+ if (
+ prev.instruction === 'q' &&
+ data[0] === (prev.data[2] - prev.data[0]) &&
+ data[1] === (prev.data[3] - prev.data[1])
+ ) {
+ instruction = 't';
+ data = data.slice(2);
+ }
+
+ // t + q → t + t
+ else if (
+ prev.instruction === 't' &&
+ data[2] === prev.data[0] &&
+ data[3] === prev.data[1]
+ ) {
+ instruction = 't';
+ data = data.slice(2);
+ }
+
+ }
+
+ }
+
+ // remove useless non-first path segments
+ if (params.removeUseless) {
+
+ // l 0,0 / h 0 / v 0 / q 0,0 0,0 / t 0,0 / c 0,0 0,0 0,0 / s 0,0 0,0
+ if (
+ (
+ 'lhvqtcs'.indexOf(instruction) > -1
+ ) &&
+ data.every(function(i) { return i === 0; })
+ ) {
+ path[index] = prev;
+ return false;
+ }
+
+ // a 25,25 -30 0,1 0,0
+ if (
+ instruction === 'a' &&
+ data[5] === 0 &&
+ data[6] === 0
+ ) {
+ path[index] = prev;
+ return false;
+ }
+
+ }
+
+ item.instruction = instruction;
+ item.data = data;
+
+ prev = item;
+
+ } else {
+
+ // z resets coordinates
+ relSubpoint[0] = pathBase[0];
+ relSubpoint[1] = pathBase[1];
+ if (prev.instruction == 'z') return false;
+ prev = item;
+
+ }
+
+ return true;
+
+ });
+
+ return path;
+
+}
+
+/**
+ * Writes data in shortest form using absolute or relative coordinates.
+ *
+ * @param {Array} data input path data
+ * @return {Boolean} output
+ */
+function convertToMixed(path, params) {
+
+ var prev = path[0];
+
+ path = path.filter(function(item, index) {
+
+ if (index == 0) return true;
+ if (!item.data) {
+ prev = item;
+ return true;
+ }
+
+ var instruction = item.instruction,
+ data = item.data,
+ adata = data && data.slice(0);
+
+ if ('mltqsc'.indexOf(instruction) > -1) {
+ for (var i = adata.length; i--;) {
+ adata[i] += item.base[i % 2];
+ }
+ } else if (instruction == 'h') {
+ adata[0] += item.base[0];
+ } else if (instruction == 'v') {
+ adata[0] += item.base[1];
+ } else if (instruction == 'a') {
+ adata[5] += item.base[0];
+ adata[6] += item.base[1];
+ }
+
+ roundData(adata);
+
+ var absoluteDataStr = cleanupOutData(adata, params),
+ relativeDataStr = cleanupOutData(data, params);
+
+ // Convert to absolute coordinates if it's shorter.
+ // v-20 -> V0
+ // Don't convert if it fits following previous instruction.
+ // l20 30-10-50 instead of l20 30L20 30
+ if (
+ absoluteDataStr.length < relativeDataStr.length &&
+ !(
+ params.negativeExtraSpace &&
+ instruction == prev.instruction &&
+ prev.instruction.charCodeAt(0) > 96 &&
+ absoluteDataStr.length == relativeDataStr.length - 1 &&
+ (data[0] < 0 || /^0\./.test(data[0]) && prev.data[prev.data.length - 1] % 1)
+ )
+ ) {
+ item.instruction = instruction.toUpperCase();
+ item.data = adata;
+ }
+
+ prev = item;
+
+ return true;
+
+ });
+
+ return path;
+
+}
+
+/**
+ * Checks if curve is convex. Control points of such a curve must form
+ * a convex quadrilateral with diagonals crosspoint inside of it.
+ *
+ * @param {Array} data input path data
+ * @return {Boolean} output
+ */
+function isConvex(data) {
+
+ var center = getIntersection([0, 0, data[2], data[3], data[0], data[1], data[4], data[5]]);
+
+ return center &&
+ (data[2] < center[0] == center[0] < 0) &&
+ (data[3] < center[1] == center[1] < 0) &&
+ (data[4] < center[0] == center[0] < data[0]) &&
+ (data[5] < center[1] == center[1] < data[1]);
+
+}
+
+/**
+ * Computes lines equations by two points and returns their intersection point.
+ *
+ * @param {Array} coords 8 numbers for 4 pairs of coordinates (x,y)
+ * @return {Array|undefined} output coordinate of lines' crosspoint
+ */
+function getIntersection(coords) {
+
+ // Prev line equation parameters.
+ var a1 = coords[1] - coords[3], // y1 - y2
+ b1 = coords[2] - coords[0], // x2 - x1
+ c1 = coords[0] * coords[3] - coords[2] * coords[1], // x1 * y2 - x2 * y1
+
+ // Next line equation parameters
+ a2 = coords[5] - coords[7], // y1 - y2
+ b2 = coords[6] - coords[4], // x2 - x1
+ c2 = coords[4] * coords[7] - coords[5] * coords[6], // x1 * y2 - x2 * y1
+ denom = (a1 * b2 - a2 * b1);
+
+ if (!denom) return; // parallel lines havn't an intersection
+
+ var cross = [
+ (b1 * c2 - b2 * c1) / denom,
+ (a1 * c2 - a2 * c1) / -denom
+ ];
+ if (
+ !isNaN(cross[0]) && !isNaN(cross[1]) &&
+ isFinite(cross[0]) && isFinite(cross[1])
+ ) {
+ return cross;
+ }
+
+}
+
+/**
+ * Decrease accuracy of floating-point numbers
+ * in path data keeping a specified number of decimals.
+ * Smart rounds values like 2.3491 to 2.35 instead of 2.349.
+ * Doesn't apply "smartness" if the number precision fits already.
+ *
+ * @param {Array} data input data array
+ * @return {Array} output data array
+ */
+function strongRound(data) {
+ for (var i = data.length; i-- > 0;) {
+ if (data[i].toFixed(precision) != data[i]) {
+ var rounded = +data[i].toFixed(precision - 1);
+ data[i] = +Math.abs(rounded - data[i]).toFixed(precision + 1) >= error ?
+ +data[i].toFixed(precision) :
+ rounded;
+ }
+ }
+ return data;
+}
+
+/**
+ * Simple rounding function if precision is 0.
+ *
+ * @param {Array} data input data array
+ * @return {Array} output data array
+ */
+function round(data) {
+ for (var i = data.length; i-- > 0;) {
+ data[i] = Math.round(data[i]);
+ }
+ return data;
+}
+
+/**
+ * Checks if a curve is a straight line by measuring distance
+ * from middle points to the line formed by end points.
+ *
+ * @param {Array} xs array of curve points x-coordinates
+ * @param {Array} ys array of curve points y-coordinates
+ * @return {Boolean}
+ */
+
+function isCurveStraightLine(data) {
+
+ // Get line equation a·x + b·y + c = 0 coefficients a, b (c = 0) by start and end points.
+ var i = data.length - 2,
+ a = -data[i + 1], // y1 − y2 (y1 = 0)
+ b = data[i], // x2 − x1 (x1 = 0)
+ d = 1 / (a * a + b * b); // same part for all points
+
+ if (i <= 1 || !isFinite(d)) return false; // curve that ends at start point isn't the case
+
+ // Distance from point (x0, y0) to the line is sqrt((c − a·x0 − b·y0)² / (a² + b²))
+ while ((i -= 2) >= 0) {
+ if (Math.sqrt(Math.pow(a * data[i] + b * data[i + 1], 2) * d) > error)
+ return false;
+ }
+
+ return true;
+
+}
+
+/**
+ * Converts next curve from shorthand to full form using the current curve data.
+ *
+ * @param {Object} item curve to convert
+ * @param {Array} data current curve data
+ */
+
+function makeLonghand(item, data) {
+ switch (item.instruction) {
+ case 's': item.instruction = 'c'; break;
+ case 't': item.instruction = 'q'; break;
+ }
+ item.data.unshift(data[data.length - 2] - data[data.length - 4], data[data.length - 1] - data[data.length - 3]);
+ return item;
+}
+
+/**
+ * Returns distance between two points
+ *
+ * @param {Array} point1 first point coordinates
+ * @param {Array} point2 second point coordinates
+ * @return {Number} distance
+ */
+
+function getDistance(point1, point2) {
+ return Math.sqrt(Math.pow(point1[0] - point2[0], 2) + Math.pow(point1[1] - point2[1], 2));
+}
+
+/**
+ * Returns coordinates of the curve point corresponding to the certain t
+ * a·(1 - t)³·p1 + b·(1 - t)²·t·p2 + c·(1 - t)·t²·p3 + d·t³·p4,
+ * where pN are control points and p1 is zero due to relative coordinates.
+ *
+ * @param {Array} curve array of curve points coordinates
+ * @param {Number} t parametric position from 0 to 1
+ * @return {Array} Point coordinates
+ */
+
+function getCubicBezierPoint(curve, t) {
+ var sqrT = t * t,
+ cubT = sqrT * t,
+ mt = 1 - t,
+ sqrMt = mt * mt;
+
+ return [
+ 3 * sqrMt * t * curve[0] + 3 * mt * sqrT * curve[2] + cubT * curve[4],
+ 3 * sqrMt * t * curve[1] + 3 * mt * sqrT * curve[3] + cubT * curve[5]
+ ];
+}
+
+/**
+ * Finds circle by 3 points of the curve and checks if the curve fits the found circle.
+ *
+ * @param {Array} curve
+ * @return {Object|undefined} circle
+ */
+
+function findCircle(curve) {
+ var midPoint = getCubicBezierPoint(curve, 1/2),
+ m1 = [midPoint[0] / 2, midPoint[1] / 2],
+ m2 = [(midPoint[0] + curve[4]) / 2, (midPoint[1] + curve[5]) / 2],
+ center = getIntersection([
+ m1[0], m1[1],
+ m1[0] + m1[1], m1[1] - m1[0],
+ m2[0], m2[1],
+ m2[0] + (m2[1] - midPoint[1]), m2[1] - (m2[0] - midPoint[0])
+ ]),
+ radius = center && getDistance([0, 0], center),
+ tolerance = Math.min(arcThreshold * error, arcTolerance * radius / 100);
+
+ if (center && [1/4, 3/4].every(function(point) {
+ return Math.abs(getDistance(getCubicBezierPoint(curve, point), center) - radius) <= tolerance;
+ }))
+ return { center: center, radius: radius};
+}
+
+/**
+ * Checks if a curve fits the given circe.
+ *
+ * @param {Object} circle
+ * @param {Array} curve
+ * @return {Boolean}
+ */
+
+function isArc(curve, circle) {
+ var tolerance = Math.min(arcThreshold * error, arcTolerance * circle.radius / 100);
+
+ return [0, 1/4, 1/2, 3/4, 1].every(function(point) {
+ return Math.abs(getDistance(getCubicBezierPoint(curve, point), circle.center) - circle.radius) <= tolerance;
+ });
+}
+
+/**
+ * Checks if a previos curve fits the given circe.
+ *
+ * @param {Object} circle
+ * @param {Array} curve
+ * @return {Boolean}
+ */
+
+function isArcPrev(curve, circle) {
+ return isArc(curve, {
+ center: [circle.center[0] + curve[4], circle.center[1] + curve[5]],
+ radius: circle.radius
+ });
+}
+
+/**
+ * Finds angle of a curve fitting the given arc.
+
+ * @param {Array} curve
+ * @param {Object} relCircle
+ * @return {Number} angle
+ */
+
+function findArcAngle(curve, relCircle) {
+ var x1 = -relCircle.center[0],
+ y1 = -relCircle.center[1],
+ x2 = curve[4] - relCircle.center[0],
+ y2 = curve[5] - relCircle.center[1];
+
+ return Math.acos(
+ (x1 * x2 + y1 * y2) /
+ Math.sqrt((x1 * x1 + y1 * y1) * (x2 * x2 + y2 * y2))
+ );
+}
+
+/**
+ * Converts given path data to string.
+ *
+ * @param {Object} params
+ * @param {Array} pathData
+ * @return {String}
+ */
+
+function data2Path(params, pathData) {
+ return pathData.reduce(function(pathString, item) {
+ return pathString += item.instruction + (item.data ? cleanupOutData(roundData(item.data.slice()), params) : '');
+ }, '');
+}
diff --git a/node_modules/svgo/plugins/convertShapeToPath.js b/node_modules/svgo/plugins/convertShapeToPath.js
new file mode 100644
index 00000000..6d328049
--- /dev/null
+++ b/node_modules/svgo/plugins/convertShapeToPath.js
@@ -0,0 +1,103 @@
+'use strict';
+
+exports.type = 'perItem';
+
+exports.active = true;
+
+exports.description = 'converts basic shapes to more compact path form';
+
+var none = { value: 0 },
+ regNumber = /[-+]?(?:\d*\.\d+|\d+\.?)(?:[eE][-+]?\d+)?/g;
+
+/**
+ * Converts basic shape to more compact path.
+ * It also allows further optimizations like
+ * combining paths with similar attributes.
+ *
+ * @see http://www.w3.org/TR/SVG/shapes.html
+ *
+ * @param {Object} item current iteration item
+ * @param {Object} params plugin params
+ * @return {Boolean} if false, item will be filtered out
+ *
+ * @author Lev Solntsev
+ */
+exports.fn = function(item) {
+
+ if (
+ item.isElem('rect') &&
+ item.hasAttr('width') &&
+ item.hasAttr('height') &&
+ !item.hasAttr('rx') &&
+ !item.hasAttr('ry')
+ ) {
+
+ var x = +(item.attr('x') || none).value,
+ y = +(item.attr('y') || none).value,
+ width = +item.attr('width').value,
+ height = +item.attr('height').value;
+
+ // Values like '100%' compute to NaN, thus running after
+ // cleanupNumericValues when 'px' units has already been removed.
+ // TODO: Calculate sizes from % and non-px units if possible.
+ if (isNaN(x - y + width - height)) return;
+
+ var pathData =
+ 'M' + x + ' ' + y +
+ 'H' + (x + width) +
+ 'V' + (y + height) +
+ 'H' + x +
+ 'z';
+
+ item.addAttr({
+ name: 'd',
+ value: pathData,
+ prefix: '',
+ local: 'd'
+ });
+
+ item.renameElem('path')
+ .removeAttr(['x', 'y', 'width', 'height']);
+
+ } else if (item.isElem('line')) {
+
+ var x1 = +(item.attr('x1') || none).value,
+ y1 = +(item.attr('y1') || none).value,
+ x2 = +(item.attr('x2') || none).value,
+ y2 = +(item.attr('y2') || none).value;
+ if (isNaN(x1 - y1 + x2 - y2)) return;
+
+ item.addAttr({
+ name: 'd',
+ value: 'M' + x1 + ' ' + y1 + 'L' + x2 + ' ' + y2,
+ prefix: '',
+ local: 'd'
+ });
+
+ item.renameElem('path')
+ .removeAttr(['x1', 'y1', 'x2', 'y2']);
+
+ } else if ((
+ item.isElem('polyline') ||
+ item.isElem('polygon')
+ ) &&
+ item.hasAttr('points')
+ ) {
+
+ var coords = (item.attr('points').value.match(regNumber) || []).map(Number);
+ if (coords.length < 4) return false;
+
+ item.addAttr({
+ name: 'd',
+ value: 'M' + coords.slice(0,2).join(' ') +
+ 'L' + coords.slice(2).join(' ') +
+ (item.isElem('polygon') ? 'z' : ''),
+ prefix: '',
+ local: 'd'
+ });
+
+ item.renameElem('path')
+ .removeAttr('points');
+ }
+
+};
diff --git a/node_modules/svgo/plugins/convertStyleToAttrs.js b/node_modules/svgo/plugins/convertStyleToAttrs.js
new file mode 100644
index 00000000..02bbc550
--- /dev/null
+++ b/node_modules/svgo/plugins/convertStyleToAttrs.js
@@ -0,0 +1,117 @@
+/* jshint quotmark: false */
+'use strict';
+
+exports.type = 'perItem';
+
+exports.active = true;
+
+exports.description = 'converts style to attributes';
+
+var EXTEND = require('whet.extend'),
+ stylingProps = require('./_collections').attrsGroups.presentation,
+ rEscape = '\\\\(?:[0-9a-f]{1,6}\\s?|\\r\\n|.)', // Like \" or \2051. Code points consume one space.
+ rAttr = '\\s*(' + g('[^:;\\\\]', rEscape) + '*?)\\s*', // attribute name like ‘fill’
+ rSingleQuotes = "'(?:[^'\\n\\r\\\\]|" + rEscape + ")*?(?:'|$)", // string in single quotes: 'smth'
+ rQuotes = '"(?:[^"\\n\\r\\\\]|' + rEscape + ')*?(?:"|$)', // string in double quotes: "smth"
+ rQuotedString = new RegExp('^' + g(rSingleQuotes, rQuotes) + '$'),
+
+ // Parentheses, E.g.: url(data:image/png;base64,iVBO...).
+ // ':' and ';' inside of it should be threated as is. (Just like in strings.)
+ rParenthesis = '\\(' + g('[^\'"()\\\\]+', rEscape, rSingleQuotes, rQuotes) + '*?' + '\\)',
+
+ // The value. It can have strings and parentheses (see above). Fallbacks to anything in case of unexpected input.
+ rValue = '\\s*(' + g('[^\'"();\\\\]+?', rEscape, rSingleQuotes, rQuotes, rParenthesis, '[^;]*?') + '*?' + ')',
+
+ // End of declaration. Spaces outside of capturing groups help to do natural trimming.
+ rDeclEnd = '\\s*(?:;\\s*|$)',
+
+ // Final RegExp to parse CSS declarations.
+ regDeclarationBlock = new RegExp(rAttr + ':' + rValue + rDeclEnd, 'ig'),
+
+ // Comments expression. Honors escape sequences and strings.
+ regStripComments = new RegExp(g(rEscape, rSingleQuotes, rQuotes, '/\\*[^]*?\\*/'), 'ig');
+
+/**
+ * Convert style in attributes. Cleanups comments and illegal declarations (without colon) as a side effect.
+ *
+ * @example
+ * <g style="fill:#000; color: #fff;">
+ * ⬇
+ * <g fill="#000" color="#fff">
+ *
+ * @example
+ * <g style="fill:#000; color: #fff; -webkit-blah: blah">
+ * ⬇
+ * <g fill="#000" color="#fff" style="-webkit-blah: blah">
+ *
+ * @param {Object} item current iteration item
+ * @return {Boolean} if false, item will be filtered out
+ *
+ * @author Kir Belevich
+ */
+exports.fn = function(item) {
+ /* jshint boss: true */
+
+ if (item.elem && item.hasAttr('style')) {
+ // ['opacity: 1', 'color: #000']
+ var styleValue = item.attr('style').value,
+ styles = [],
+ attrs = {};
+
+ // Strip CSS comments preserving escape sequences and strings.
+ styleValue = styleValue.replace(regStripComments, function(match) {
+ return match[0] == '/' ? '' :
+ match[0] == '\\' && /[-g-z]/i.test(match[1]) ? match[1] : match;
+ });
+
+ regDeclarationBlock.lastIndex = 0;
+ for (var rule; rule = regDeclarationBlock.exec(styleValue);) {
+ styles.push([rule[1], rule[2]]);
+ }
+
+ if (styles.length) {
+
+ styles = styles.filter(function(style) {
+ if (style[0]) {
+ var prop = style[0].toLowerCase(),
+ val = style[1];
+
+ if (rQuotedString.test(val)) {
+ val = val.slice(1, -1);
+ }
+
+ if (stylingProps.indexOf(prop) > -1) {
+
+ attrs[prop] = {
+ name: prop,
+ value: val,
+ local: prop,
+ prefix: ''
+ };
+
+ return false;
+ }
+ }
+
+ return true;
+ });
+
+ EXTEND(item.attrs, attrs);
+
+ if (styles.length) {
+ item.attr('style').value = styles
+ .map(function(declaration) { return declaration.join(':') })
+ .join(';');
+ } else {
+ item.removeAttr('style');
+ }
+
+ }
+
+ }
+
+};
+
+function g() {
+ return '(?:' + Array.prototype.join.call(arguments, '|') + ')';
+}
diff --git a/node_modules/svgo/plugins/convertTransform.js b/node_modules/svgo/plugins/convertTransform.js
new file mode 100644
index 00000000..c2085892
--- /dev/null
+++ b/node_modules/svgo/plugins/convertTransform.js
@@ -0,0 +1,364 @@
+'use strict';
+
+exports.type = 'perItem';
+
+exports.active = true;
+
+exports.description = 'collapses multiple transformations and optimizes it';
+
+exports.params = {
+ convertToShorts: true,
+ // degPrecision: 3, // transformPrecision (or matrix precision) - 2 by default
+ floatPrecision: 3,
+ transformPrecision: 5,
+ matrixToTransform: true,
+ shortTranslate: true,
+ shortScale: true,
+ shortRotate: true,
+ removeUseless: true,
+ collapseIntoOne: true,
+ leadingZero: true,
+ negativeExtraSpace: false
+};
+
+var cleanupOutData = require('../lib/svgo/tools').cleanupOutData,
+ EXTEND = require('whet.extend'),
+ transform2js = require('./_transforms.js').transform2js,
+ transformsMultiply = require('./_transforms.js').transformsMultiply,
+ matrixToTransform = require('./_transforms.js').matrixToTransform,
+ degRound,
+ floatRound,
+ transformRound;
+
+/**
+ * Convert matrices to the short aliases,
+ * convert long translate, scale or rotate transform notations to the shorts ones,
+ * convert transforms to the matrices and multiply them all into one,
+ * remove useless transforms.
+ *
+ * @see http://www.w3.org/TR/SVG/coords.html#TransformMatrixDefined
+ *
+ * @param {Object} item current iteration item
+ * @param {Object} params plugin params
+ * @return {Boolean} if false, item will be filtered out
+ *
+ * @author Kir Belevich
+ */
+exports.fn = function(item, params) {
+
+ if (item.elem) {
+
+ // transform
+ if (item.hasAttr('transform')) {
+ convertTransform(item, 'transform', params);
+ }
+
+ // gradientTransform
+ if (item.hasAttr('gradientTransform')) {
+ convertTransform(item, 'gradientTransform', params);
+ }
+
+ // patternTransform
+ if (item.hasAttr('patternTransform')) {
+ convertTransform(item, 'patternTransform', params);
+ }
+
+ }
+
+};
+
+/**
+ * Main function.
+ *
+ * @param {Object} item input item
+ * @param {String} attrName attribute name
+ * @param {Object} params plugin params
+ */
+function convertTransform(item, attrName, params) {
+ var data = transform2js(item.attr(attrName).value);
+ params = definePrecision(data, params);
+
+ if (params.collapseIntoOne && data.length > 1) {
+ data = [transformsMultiply(data)];
+ }
+
+ if (params.convertToShorts) {
+ data = convertToShorts(data, params);
+ } else {
+ data.forEach(roundTransform);
+ }
+
+ if (params.removeUseless) {
+ data = removeUseless(data);
+ }
+
+ if (data.length) {
+ item.attr(attrName).value = js2transform(data, params);
+ } else {
+ item.removeAttr(attrName);
+ }
+}
+
+/**
+ * Defines precision to work with certain parts.
+ * transformPrecision - for scale and four first matrix parameters (needs a better precision due to multiplying),
+ * floatPrecision - for translate including two last matrix and rotate parameters,
+ * degPrecision - for rotate and skew. By default it's equal to (rougly)
+ * transformPrecision - 2 or floatPrecision whichever is lower. Can be set in params.
+ *
+ * @param {Array} transforms input array
+ * @param {Object} params plugin params
+ * @return {Array} output array
+ */
+function definePrecision(data, params) {
+ /* jshint validthis: true */
+ var matrixData = data.reduce(getMatrixData, []),
+ significantDigits = params.transformPrecision;
+
+ // Clone params so it don't affect other elements transformations.
+ params = EXTEND({}, params);
+
+ // Limit transform precision with matrix one. Calculating with larger precision doesn't add any value.
+ if (matrixData.length) {
+ params.transformPrecision = Math.min(params.transformPrecision,
+ Math.max.apply(Math, matrixData.map(floatDigits)) || params.transformPrecision);
+
+ significantDigits = Math.max.apply(Math, matrixData.map(function(n) {
+ return String(n).replace(/\D+/g, '').length; // Number of digits in a number. 123.45 → 5
+ }));
+ }
+ // No sense in angle precision more then number of significant digits in matrix.
+ if (!('degPrecision' in params)) {
+ params.degPrecision = Math.max(0, Math.min(params.floatPrecision, significantDigits - 2));
+ }
+
+ floatRound = params.floatPrecision >= 1 && params.floatPrecision < 20 ?
+ smartRound.bind(this, params.floatPrecision) :
+ round;
+ degRound = params.degPrecision >= 1 && params.floatPrecision < 20 ?
+ smartRound.bind(this, params.degPrecision) :
+ round;
+ transformRound = params.transformPrecision >= 1 && params.floatPrecision < 20 ?
+ smartRound.bind(this, params.transformPrecision) :
+ round;
+
+ return params;
+}
+
+/**
+ * Gathers four first matrix parameters.
+ *
+ * @param {Array} a array of data
+ * @param {Object} transform
+ * @return {Array} output array
+ */
+function getMatrixData(a, b) {
+ return b.name == 'matrix' ? a.concat(b.data.slice(0, 4)) : a;
+}
+
+/**
+ * Returns number of digits after the point. 0.125 → 3
+ */
+function floatDigits(n) {
+ return (n = String(n)).slice(n.indexOf('.')).length - 1;
+}
+
+/**
+ * Convert transforms to the shorthand alternatives.
+ *
+ * @param {Array} transforms input array
+ * @param {Object} params plugin params
+ * @return {Array} output array
+ */
+function convertToShorts(transforms, params) {
+
+ for(var i = 0; i < transforms.length; i++) {
+
+ var transform = transforms[i];
+
+ // convert matrix to the short aliases
+ if (
+ params.matrixToTransform &&
+ transform.name === 'matrix'
+ ) {
+ var decomposed = matrixToTransform(transform, params);
+ if (decomposed != transform &&
+ js2transform(decomposed, params).length <= js2transform([transform], params).length) {
+
+ transforms.splice.apply(transforms, [i, 1].concat(decomposed));
+ }
+ transform = transforms[i];
+ }
+
+ // fixed-point numbers
+ // 12.754997 → 12.755
+ roundTransform(transform);
+
+ // convert long translate transform notation to the shorts one
+ // translate(10 0) → translate(10)
+ if (
+ params.shortTranslate &&
+ transform.name === 'translate' &&
+ transform.data.length === 2 &&
+ !transform.data[1]
+ ) {
+ transform.data.pop();
+ }
+
+ // convert long scale transform notation to the shorts one
+ // scale(2 2) → scale(2)
+ if (
+ params.shortScale &&
+ transform.name === 'scale' &&
+ transform.data.length === 2 &&
+ transform.data[0] === transform.data[1]
+ ) {
+ transform.data.pop();
+ }
+
+ // convert long rotate transform notation to the short one
+ // translate(cx cy) rotate(a) translate(-cx -cy) → rotate(a cx cy)
+ if (
+ params.shortRotate &&
+ transforms[i - 2] &&
+ transforms[i - 2].name === 'translate' &&
+ transforms[i - 1].name === 'rotate' &&
+ transforms[i].name === 'translate' &&
+ transforms[i - 2].data[0] === -transforms[i].data[0] &&
+ transforms[i - 2].data[1] === -transforms[i].data[1]
+ ) {
+ transforms.splice(i - 2, 3, {
+ name: 'rotate',
+ data: [
+ transforms[i - 1].data[0],
+ transforms[i - 2].data[0],
+ transforms[i - 2].data[1]
+ ]
+ });
+
+ // splice compensation
+ i -= 2;
+
+ transform = transforms[i];
+ }
+
+ }
+
+ return transforms;
+
+}
+
+/**
+ * Remove useless transforms.
+ *
+ * @param {Array} transforms input array
+ * @return {Array} output array
+ */
+function removeUseless(transforms) {
+
+ return transforms.filter(function(transform) {
+
+ // translate(0), rotate(0[, cx, cy]), skewX(0), skewY(0)
+ if (
+ ['translate', 'rotate', 'skewX', 'skewY'].indexOf(transform.name) > -1 &&
+ (transform.data.length == 1 || transform.name == 'rotate') &&
+ !transform.data[0] ||
+
+ // translate(0, 0)
+ transform.name == 'translate' &&
+ !transform.data[0] &&
+ !transform.data[1] ||
+
+ // scale(1)
+ transform.name == 'scale' &&
+ transform.data[0] == 1 &&
+ (transform.data.length < 2 || transform.data[1] == 1) ||
+
+ // matrix(1 0 0 1 0 0)
+ transform.name == 'matrix' &&
+ transform.data[0] == 1 &&
+ transform.data[3] == 1 &&
+ !(transform.data[1] || transform.data[2] || transform.data[4] || transform.data[5])
+ ) {
+ return false;
+ }
+
+ return true;
+
+ });
+
+}
+
+/**
+ * Convert transforms JS representation to string.
+ *
+ * @param {Array} transformJS JS representation array
+ * @param {Object} params plugin params
+ * @return {String} output string
+ */
+function js2transform(transformJS, params) {
+
+ var transformString = '';
+
+ // collect output value string
+ transformJS.forEach(function(transform) {
+ roundTransform(transform);
+ transformString += (transformString && ' ') + transform.name + '(' + cleanupOutData(transform.data, params) + ')';
+ });
+
+ return transformString;
+
+}
+
+function roundTransform(transform) {
+ switch (transform.name) {
+ case 'translate':
+ transform.data = floatRound(transform.data);
+ break;
+ case 'rotate':
+ transform.data = degRound(transform.data.slice(0, 1)).concat(floatRound(transform.data.slice(1)));
+ break;
+ case 'skewX':
+ case 'skewY':
+ transform.data = degRound(transform.data);
+ break;
+ case 'scale':
+ transform.data = transformRound(transform.data);
+ break;
+ case 'matrix':
+ transform.data = transformRound(transform.data.slice(0, 4)).concat(floatRound(transform.data.slice(4)));
+ break;
+ }
+ return transform;
+}
+
+/**
+ * Rounds numbers in array.
+ *
+ * @param {Array} data input data array
+ * @return {Array} output data array
+ */
+function round(data) {
+ return data.map(Math.round);
+}
+
+/**
+ * Decrease accuracy of floating-point numbers
+ * in transforms keeping a specified number of decimals.
+ * Smart rounds values like 2.349 to 2.35.
+ *
+ * @param {Number} fixed number of decimals
+ * @param {Array} data input data array
+ * @return {Array} output data array
+ */
+function smartRound(precision, data) {
+ for (var i = data.length, tolerance = +Math.pow(.1, precision).toFixed(precision); i--;) {
+ if (data[i].toFixed(precision) != data[i]) {
+ var rounded = +data[i].toFixed(precision - 1);
+ data[i] = +Math.abs(rounded - data[i]).toFixed(precision + 1) >= tolerance ?
+ +data[i].toFixed(precision) :
+ rounded;
+ }
+ }
+ return data;
+}
diff --git a/node_modules/svgo/plugins/mergePaths.js b/node_modules/svgo/plugins/mergePaths.js
new file mode 100644
index 00000000..63cf56e8
--- /dev/null
+++ b/node_modules/svgo/plugins/mergePaths.js
@@ -0,0 +1,71 @@
+'use strict';
+
+exports.type = 'perItem';
+
+exports.active = true;
+
+exports.description = 'merges multiple paths in one if possible';
+
+exports.params = {
+ collapseRepeated: true,
+ leadingZero: true,
+ negativeExtraSpace: true
+};
+
+var path2js = require('./_path.js').path2js,
+ js2path = require('./_path.js').js2path,
+ intersects = require('./_path.js').intersects;
+
+/**
+ * Merge multiple Paths into one.
+ *
+ * @param {Object} item current iteration item
+ * @return {Boolean} if false, item will be filtered out
+ *
+ * @author Kir Belevich, Lev Solntsev
+ */
+exports.fn = function(item, params) {
+
+ if (!item.isElem() || item.isEmpty()) return;
+
+ var prevContentItem = null,
+ prevContentItemKeys = null;
+
+ item.content = item.content.filter(function(contentItem) {
+
+ if (prevContentItem &&
+ prevContentItem.isElem('path') &&
+ prevContentItem.isEmpty() &&
+ prevContentItem.hasAttr('d') &&
+ contentItem.isElem('path') &&
+ contentItem.isEmpty() &&
+ contentItem.hasAttr('d')
+ ) {
+
+ if (!prevContentItemKeys) {
+ prevContentItemKeys = Object.keys(prevContentItem.attrs);
+ }
+
+ var contentItemAttrs = Object.keys(contentItem.attrs),
+ equalData = prevContentItemKeys.length == contentItemAttrs.length &&
+ contentItemAttrs.every(function(key) {
+ return key == 'd' ||
+ prevContentItem.hasAttr(key) &&
+ prevContentItem.attr(key).value == contentItem.attr(key).value;
+ }),
+ prevPathJS = path2js(prevContentItem),
+ curPathJS = path2js(contentItem);
+
+ if (equalData && !intersects(prevPathJS, curPathJS)) {
+ js2path(prevContentItem, prevPathJS.concat(curPathJS), params);
+ return false;
+ }
+ }
+
+ prevContentItem = contentItem;
+ prevContentItemKeys = null;
+ return true;
+
+ });
+
+};
diff --git a/node_modules/svgo/plugins/minifyStyles.js b/node_modules/svgo/plugins/minifyStyles.js
new file mode 100644
index 00000000..3977b367
--- /dev/null
+++ b/node_modules/svgo/plugins/minifyStyles.js
@@ -0,0 +1,45 @@
+'use strict';
+
+exports.type = 'perItem';
+
+exports.active = true;
+
+exports.params = {
+ svgo: {}
+};
+
+exports.description = 'minifies existing styles in svg';
+
+var csso = require('csso');
+
+/**
+ * Minifies styles (<style> element + style attribute) using svgo
+ *
+ * @param {Object} item current iteration item
+ * @return {Boolean} if false, item will be filtered out
+ *
+ * @author strarsis <strarsis@gmail.com>
+ */
+exports.fn = function(item, svgoOptions) {
+
+ if(item.elem) {
+ if(item.isElem('style') && !item.isEmpty()) {
+ var styleCss = item.content[0].text || item.content[0].cdata || [],
+ DATA = styleCss.indexOf('>') >= 0 || styleCss.indexOf('<') >= 0 ? 'cdata' : 'text';
+ if(styleCss.length > 0) {
+ var styleCssMinified = csso.minify(styleCss, svgoOptions);
+ item.content[0][DATA] = styleCssMinified.css;
+ }
+ }
+
+ if(item.hasAttr('style')) {
+ var itemCss = item.attr('style').value;
+ if(itemCss.length > 0) {
+ var itemCssMinified = csso.minifyBlock(itemCss, svgoOptions);
+ item.attr('style').value = itemCssMinified.css;
+ }
+ }
+ }
+
+ return item;
+};
diff --git a/node_modules/svgo/plugins/moveElemsAttrsToGroup.js b/node_modules/svgo/plugins/moveElemsAttrsToGroup.js
new file mode 100644
index 00000000..0f3b65c7
--- /dev/null
+++ b/node_modules/svgo/plugins/moveElemsAttrsToGroup.js
@@ -0,0 +1,126 @@
+'use strict';
+
+exports.type = 'perItemReverse';
+
+exports.active = true;
+
+exports.description = 'moves elements attributes to the existing group wrapper';
+
+var inheritableAttrs = require('./_collections').inheritableAttrs,
+ pathElems = require('./_collections.js').pathElems;
+
+/**
+ * Collapse content's intersected and inheritable
+ * attributes to the existing group wrapper.
+ *
+ * @example
+ * <g attr1="val1">
+ * <g attr2="val2">
+ * text
+ * </g>
+ * <circle attr2="val2" attr3="val3"/>
+ * </g>
+ * ⬇
+ * <g attr1="val1" attr2="val2">
+ * <g>
+ * text
+ * </g>
+ * <circle attr3="val3"/>
+ * </g>
+ *
+ * @param {Object} item current iteration item
+ * @return {Boolean} if false, item will be filtered out
+ *
+ * @author Kir Belevich
+ */
+exports.fn = function(item) {
+
+ if (item.isElem('g') && !item.isEmpty() && item.content.length > 1) {
+
+ var intersection = {},
+ hasTransform = false,
+ hasClip = item.hasAttr('clip-path') || item.hasAttr('mask'),
+ intersected = item.content.every(function(inner) {
+ if (inner.isElem() && inner.hasAttr()) {
+ // don't mess with possible styles (hack until CSS parsing is implemented)
+ if (inner.hasAttr('class')) return false;
+ if (!Object.keys(intersection).length) {
+ intersection = inner.attrs;
+ } else {
+ intersection = intersectInheritableAttrs(intersection, inner.attrs);
+
+ if (!intersection) return false;
+ }
+
+ return true;
+ }
+ }),
+ allPath = item.content.every(function(inner) {
+ return inner.isElem(pathElems);
+ });
+
+ if (intersected) {
+
+ item.content.forEach(function(g) {
+
+ for (var name in intersection) {
+
+ if (!allPath && !hasClip || name !== 'transform') {
+
+ g.removeAttr(name);
+
+ if (name === 'transform') {
+ if (!hasTransform) {
+ if (item.hasAttr('transform')) {
+ item.attr('transform').value += ' ' + intersection[name].value;
+ } else {
+ item.addAttr(intersection[name]);
+ }
+
+ hasTransform = true;
+ }
+ } else {
+ item.addAttr(intersection[name]);
+ }
+
+ }
+ }
+
+ });
+
+ }
+
+ }
+
+};
+
+/**
+ * Intersect inheritable attributes.
+ *
+ * @param {Object} a first attrs object
+ * @param {Object} b second attrs object
+ *
+ * @return {Object} intersected attrs object
+ */
+function intersectInheritableAttrs(a, b) {
+
+ var c = {};
+
+ for (var n in a) {
+ if (
+ b.hasOwnProperty(n) &&
+ inheritableAttrs.indexOf(n) > -1 &&
+ a[n].name === b[n].name &&
+ a[n].value === b[n].value &&
+ a[n].prefix === b[n].prefix &&
+ a[n].local === b[n].local
+ ) {
+ c[n] = a[n];
+ }
+ }
+
+ if (!Object.keys(c).length) return false;
+
+ return c;
+
+}
diff --git a/node_modules/svgo/plugins/moveGroupAttrsToElems.js b/node_modules/svgo/plugins/moveGroupAttrsToElems.js
new file mode 100644
index 00000000..a966f882
--- /dev/null
+++ b/node_modules/svgo/plugins/moveGroupAttrsToElems.js
@@ -0,0 +1,63 @@
+'use strict';
+
+exports.type = 'perItem';
+
+exports.active = true;
+
+exports.description = 'moves some group attributes to the content elements';
+
+var collections = require('./_collections.js'),
+ pathElems = collections.pathElems.concat(['g', 'text']),
+ referencesProps = collections.referencesProps;
+
+/**
+ * Move group attrs to the content elements.
+ *
+ * @example
+ * <g transform="scale(2)">
+ * <path transform="rotate(45)" d="M0,0 L10,20"/>
+ * <path transform="translate(10, 20)" d="M0,10 L20,30"/>
+ * </g>
+ * ⬇
+ * <g>
+ * <path transform="scale(2) rotate(45)" d="M0,0 L10,20"/>
+ * <path transform="scale(2) translate(10, 20)" d="M0,10 L20,30"/>
+ * </g>
+ *
+ * @param {Object} item current iteration item
+ * @return {Boolean} if false, item will be filtered out
+ *
+ * @author Kir Belevich
+ */
+exports.fn = function(item) {
+
+ // move group transform attr to content's pathElems
+ if (
+ item.isElem('g') &&
+ item.hasAttr('transform') &&
+ !item.isEmpty() &&
+ !item.someAttr(function(attr) {
+ return ~referencesProps.indexOf(attr.name) && ~attr.value.indexOf('url(');
+ }) &&
+ item.content.every(function(inner) {
+ return inner.isElem(pathElems) && !inner.hasAttr('id');
+ })
+ ) {
+ item.content.forEach(function(inner) {
+ var attr = item.attr('transform');
+ if (inner.hasAttr('transform')) {
+ inner.attr('transform').value = attr.value + ' ' + inner.attr('transform').value;
+ } else {
+ inner.addAttr({
+ 'name': attr.name,
+ 'local': attr.local,
+ 'prefix': attr.prefix,
+ 'value': attr.value
+ });
+ }
+ });
+
+ item.removeAttr('transform');
+ }
+
+};
diff --git a/node_modules/svgo/plugins/removeAttrs.js b/node_modules/svgo/plugins/removeAttrs.js
new file mode 100644
index 00000000..bd2fca62
--- /dev/null
+++ b/node_modules/svgo/plugins/removeAttrs.js
@@ -0,0 +1,119 @@
+'use strict';
+
+var ELEM_SEP = ':';
+
+exports.type = 'perItem';
+
+exports.active = false;
+
+exports.description = 'removes specified attributes';
+
+exports.params = {
+ attrs: []
+};
+
+/**
+ * Remove attributes
+ *
+ * @param attrs:
+ *
+ * format: [ element* : attribute* ]
+ *
+ * element : regexp (wrapped into ^...$), single * or omitted > all elements
+ * attribute : regexp (wrapped into ^...$)
+ *
+ * examples:
+ *
+ * > basic: remove fill attribute
+ * ---
+ * removeAttrs:
+ * attrs: 'fill'
+ *
+ * > remove fill attribute on path element
+ * ---
+ * attrs: 'path:fill'
+ *
+ *
+ * > remove all fill and stroke attribute
+ * ---
+ * attrs:
+ * - 'fill'
+ * - 'stroke'
+ *
+ * [is same as]
+ *
+ * attrs: '(fill|stroke)'
+ *
+ * [is same as]
+ *
+ * attrs: '*:(fill|stroke)'
+ *
+ * [is same as]
+ *
+ * attrs: '.*:(fill|stroke)'
+ *
+ *
+ * > remove all stroke related attributes
+ * ----
+ * attrs: 'stroke.*'
+ *
+ *
+ * @param {Object} item current iteration item
+ * @param {Object} params plugin params
+ * @return {Boolean} if false, item will be filtered out
+ *
+ * @author Benny Schudel
+ */
+exports.fn = function(item, params) {
+
+ // wrap into an array if params is not
+ if (!Array.isArray(params.attrs)) {
+ params.attrs = [params.attrs];
+ }
+
+ if (item.isElem()) {
+
+ // prepare patterns
+ var patterns = params.attrs.map(function(pattern) {
+
+ // apply to all elements if specifc element is omitted
+ if (pattern.indexOf(ELEM_SEP) === -1) {
+ pattern = ['.*', ELEM_SEP, pattern].join('');
+ }
+
+ // create regexps for element and attribute name
+ return pattern.split(ELEM_SEP)
+ .map(function(value) {
+
+ // adjust single * to match anything
+ if (value === '*') { value = '.*'; }
+
+ return new RegExp(['^', value, '$'].join(''), 'i');
+ });
+
+ });
+
+ // loop patterns
+ patterns.forEach(function(pattern) {
+
+ // matches element
+ if (pattern[0].test(item.elem)) {
+
+ // loop attributes
+ item.eachAttr(function(attr) {
+ var name = attr.name;
+
+ // matches attribute name
+ if (pattern[1].test(name)) {
+ item.removeAttr(name);
+ }
+
+ });
+
+ }
+
+ });
+
+ }
+
+};
diff --git a/node_modules/svgo/plugins/removeComments.js b/node_modules/svgo/plugins/removeComments.js
new file mode 100644
index 00000000..8bfd21b0
--- /dev/null
+++ b/node_modules/svgo/plugins/removeComments.js
@@ -0,0 +1,27 @@
+'use strict';
+
+exports.type = 'perItem';
+
+exports.active = true;
+
+exports.description = 'removes comments';
+
+/**
+ * Remove comments.
+ *
+ * @example
+ * <!-- Generator: Adobe Illustrator 15.0.0, SVG Export
+ * Plug-In . SVG Version: 6.00 Build 0) -->
+ *
+ * @param {Object} item current iteration item
+ * @return {Boolean} if false, item will be filtered out
+ *
+ * @author Kir Belevich
+ */
+exports.fn = function(item) {
+
+ if (item.comment && item.comment.charAt(0) !== '!') {
+ return false;
+ }
+
+};
diff --git a/node_modules/svgo/plugins/removeDesc.js b/node_modules/svgo/plugins/removeDesc.js
new file mode 100644
index 00000000..e2848c6c
--- /dev/null
+++ b/node_modules/svgo/plugins/removeDesc.js
@@ -0,0 +1,32 @@
+'use strict';
+
+exports.type = 'perItem';
+
+exports.active = true;
+
+exports.params = {
+ removeAny: false
+};
+
+exports.description = 'removes <desc> (only non-meaningful by default)';
+
+var standardDescs = /^Created with/;
+
+/**
+ * Removes <desc>.
+ * Removes only standard editors content or empty elements 'cause it can be used for accessibility.
+ * Enable parameter 'removeAny' to remove any description.
+ *
+ * https://developer.mozilla.org/en-US/docs/Web/SVG/Element/desc
+ *
+ * @param {Object} item current iteration item
+ * @return {Boolean} if false, item will be filtered out
+ *
+ * @author Daniel Wabyick
+ */
+exports.fn = function(item, params) {
+
+ return !item.isElem('desc') || !(params.removeAny || item.isEmpty() ||
+ standardDescs.test(item.content[0].text));
+
+};
diff --git a/node_modules/svgo/plugins/removeDimensions.js b/node_modules/svgo/plugins/removeDimensions.js
new file mode 100644
index 00000000..b25ff8f7
--- /dev/null
+++ b/node_modules/svgo/plugins/removeDimensions.js
@@ -0,0 +1,32 @@
+'use strict';
+
+exports.type = 'perItem';
+
+exports.active = false;
+
+exports.description = 'removes width and height in presence of viewBox';
+
+/**
+ * Remove width/height attributes when a viewBox attribute is present.
+ *
+ * @example
+ * <svg width="100" height="50" viewBox="0 0 100 50">
+ * ↓
+ * <svg viewBox="0 0 100 50">
+ *
+ * @param {Object} item current iteration item
+ * @return {Boolean} if true, with and height will be filtered out
+ *
+ * @author Benny Schudel
+ */
+exports.fn = function(item) {
+
+ if (
+ item.isElem('svg') &&
+ item.hasAttr('viewBox')
+ ) {
+ item.removeAttr('width');
+ item.removeAttr('height');
+ }
+
+};
diff --git a/node_modules/svgo/plugins/removeDoctype.js b/node_modules/svgo/plugins/removeDoctype.js
new file mode 100644
index 00000000..32ee4f46
--- /dev/null
+++ b/node_modules/svgo/plugins/removeDoctype.js
@@ -0,0 +1,40 @@
+'use strict';
+
+exports.type = 'perItem';
+
+exports.active = true;
+
+exports.description = 'removes doctype declaration';
+
+/**
+ * Remove DOCTYPE declaration.
+ *
+ * "Unfortunately the SVG DTDs are a source of so many
+ * issues that the SVG WG has decided not to write one
+ * for the upcoming SVG 1.2 standard. In fact SVG WG
+ * members are even telling people not to use a DOCTYPE
+ * declaration in SVG 1.0 and 1.1 documents"
+ * https://jwatt.org/svg/authoring/#doctype-declaration
+ *
+ * @example
+ * <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+ * q"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+ *
+ * @example
+ * <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ * "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" [
+ * <!-- an internal subset can be embedded here -->
+ * ]>
+ *
+ * @param {Object} item current iteration item
+ * @return {Boolean} if false, item will be filtered out
+ *
+ * @author Kir Belevich
+ */
+exports.fn = function(item) {
+
+ if (item.doctype) {
+ return false;
+ }
+
+};
diff --git a/node_modules/svgo/plugins/removeEditorsNSData.js b/node_modules/svgo/plugins/removeEditorsNSData.js
new file mode 100644
index 00000000..9e5c8cd8
--- /dev/null
+++ b/node_modules/svgo/plugins/removeEditorsNSData.js
@@ -0,0 +1,65 @@
+'use strict';
+
+exports.type = 'perItem';
+
+exports.active = true;
+
+exports.description = 'removes editors namespaces, elements and attributes';
+
+var editorNamespaces = require('./_collections').editorNamespaces,
+ prefixes = [];
+
+exports.params = {
+ additionalNamespaces: []
+};
+
+/**
+ * Remove editors namespaces, elements and attributes.
+ *
+ * @example
+ * <svg xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd">
+ * <sodipodi:namedview/>
+ * <path sodipodi:nodetypes="cccc"/>
+ *
+ * @param {Object} item current iteration item
+ * @param {Object} params plugin params
+ * @return {Boolean} if false, item will be filtered out
+ *
+ * @author Kir Belevich
+ */
+exports.fn = function(item, params) {
+
+ if (Array.isArray(params.additionalNamespaces)) {
+ editorNamespaces = editorNamespaces.concat(params.additionalNamespaces);
+ }
+
+ if (item.elem) {
+
+ if (item.isElem('svg')) {
+
+ item.eachAttr(function(attr) {
+ if (attr.prefix === 'xmlns' && editorNamespaces.indexOf(attr.value) > -1) {
+ prefixes.push(attr.local);
+
+ // <svg xmlns:sodipodi="">
+ item.removeAttr(attr.name);
+ }
+ });
+
+ }
+
+ // <* sodipodi:*="">
+ item.eachAttr(function(attr) {
+ if (prefixes.indexOf(attr.prefix) > -1) {
+ item.removeAttr(attr.name);
+ }
+ });
+
+ // <sodipodi:*>
+ if (prefixes.indexOf(item.prefix) > -1) {
+ return false;
+ }
+
+ }
+
+};
diff --git a/node_modules/svgo/plugins/removeElementsByAttr.js b/node_modules/svgo/plugins/removeElementsByAttr.js
new file mode 100644
index 00000000..c726f708
--- /dev/null
+++ b/node_modules/svgo/plugins/removeElementsByAttr.js
@@ -0,0 +1,80 @@
+'use strict';
+
+exports.type = 'perItem';
+
+exports.active = false;
+
+exports.description = 'removes arbitrary elements by ID or className (disabled by default)';
+
+exports.params = {
+ id: [],
+ class: []
+};
+
+/**
+ * Remove arbitrary SVG elements by ID or className.
+ *
+ * @param id
+ * examples:
+ *
+ * > single: remove element with ID of `elementID`
+ * ---
+ * removeElementsByAttr:
+ * id: 'elementID'
+ *
+ * > list: remove multiple elements by ID
+ * ---
+ * removeElementsByAttr:
+ * id:
+ * - 'elementID'
+ * - 'anotherID'
+ *
+ * @param class
+ * examples:
+ *
+ * > single: remove all elements with class of `elementClass`
+ * ---
+ * removeElementsByAttr:
+ * class: 'elementClass'
+ *
+ * > list: remove all elements with class of `elementClass` or `anotherClass`
+ * ---
+ * removeElementsByAttr:
+ * class:
+ * - 'elementClass'
+ * - 'anotherClass'
+ *
+ * @param {Object} item current iteration item
+ * @param {Object} params plugin params
+ * @return {Boolean} if false, item will be filtered out
+ *
+ * @author Eli Dupuis (@elidupuis)
+ */
+exports.fn = function(item, params) {
+ var elemId, elemClass;
+
+ // wrap params in an array if not already
+ ['id', 'class'].forEach(function(key) {
+ if (!Array.isArray(params[key])) {
+ params[key] = [ params[key] ];
+ }
+ });
+
+ // abort if current item is no an element
+ if (!item.isElem()) {
+ return;
+ }
+
+ // remove element if it's `id` matches configured `id` params
+ elemId = item.attr('id');
+ if (elemId) {
+ return params.id.indexOf(elemId.value) === -1;
+ }
+
+ // remove element if it's `class` contains any of the configured `class` params
+ elemClass = item.attr('class');
+ if (elemClass) {
+ var hasClassRegex = new RegExp(params.class.join('|'));
+ return !hasClassRegex.test(elemClass.value);
+ }
+};
diff --git a/node_modules/svgo/plugins/removeEmptyAttrs.js b/node_modules/svgo/plugins/removeEmptyAttrs.js
new file mode 100644
index 00000000..ae73e6c9
--- /dev/null
+++ b/node_modules/svgo/plugins/removeEmptyAttrs.js
@@ -0,0 +1,29 @@
+'use strict';
+
+exports.type = 'perItem';
+
+exports.active = true;
+
+exports.description = 'removes empty attributes';
+
+/**
+ * Remove attributes with empty values.
+ *
+ * @param {Object} item current iteration item
+ * @return {Boolean} if false, item will be filtered out
+ *
+ * @author Kir Belevich
+ */
+exports.fn = function(item) {
+
+ if (item.elem) {
+
+ item.eachAttr(function(attr) {
+ if (attr.value === '') {
+ item.removeAttr(attr.name);
+ }
+ });
+
+ }
+
+};
diff --git a/node_modules/svgo/plugins/removeEmptyContainers.js b/node_modules/svgo/plugins/removeEmptyContainers.js
new file mode 100644
index 00000000..356a5835
--- /dev/null
+++ b/node_modules/svgo/plugins/removeEmptyContainers.js
@@ -0,0 +1,32 @@
+'use strict';
+
+exports.type = 'perItemReverse';
+
+exports.active = true;
+
+exports.description = 'removes empty container elements';
+
+var container = require('./_collections').elemsGroups.container;
+
+/**
+ * Remove empty containers.
+ *
+ * @see http://www.w3.org/TR/SVG/intro.html#TermContainerElement
+ *
+ * @example
+ * <defs/>
+ *
+ * @example
+ * <g><marker><a/></marker></g>
+ *
+ * @param {Object} item current iteration item
+ * @return {Boolean} if false, item will be filtered out
+ *
+ * @author Kir Belevich
+ */
+exports.fn = function(item) {
+
+ return !(item.isElem(container) && !item.isElem('svg') && item.isEmpty() &&
+ (!item.isElem('pattern') || !item.hasAttrLocal('href')));
+
+};
diff --git a/node_modules/svgo/plugins/removeEmptyText.js b/node_modules/svgo/plugins/removeEmptyText.js
new file mode 100644
index 00000000..049b1819
--- /dev/null
+++ b/node_modules/svgo/plugins/removeEmptyText.js
@@ -0,0 +1,59 @@
+'use strict';
+
+exports.type = 'perItem';
+
+exports.active = true;
+
+exports.description = 'removes empty <text> elements';
+
+exports.params = {
+ text: true,
+ tspan: true,
+ tref: true
+};
+
+/**
+ * Remove empty Text elements.
+ *
+ * @see http://www.w3.org/TR/SVG/text.html
+ *
+ * @example
+ * Remove empty text element:
+ * <text/>
+ *
+ * Remove empty tspan element:
+ * <tspan/>
+ *
+ * Remove tref with empty xlink:href attribute:
+ * <tref xlink:href=""/>
+ *
+ * @param {Object} item current iteration item
+ * @param {Object} params plugin params
+ * @return {Boolean} if false, item will be filtered out
+ *
+ * @author Kir Belevich
+ */
+exports.fn = function(item, params) {
+
+ // Remove empty text element
+ if (
+ params.text &&
+ item.isElem('text') &&
+ item.isEmpty()
+ ) return false;
+
+ // Remove empty tspan element
+ if (
+ params.tspan &&
+ item.isElem('tspan') &&
+ item.isEmpty()
+ ) return false;
+
+ // Remove tref with empty xlink:href attribute
+ if (
+ params.tref &&
+ item.isElem('tref') &&
+ !item.hasAttrLocal('href')
+ ) return false;
+
+};
diff --git a/node_modules/svgo/plugins/removeHiddenElems.js b/node_modules/svgo/plugins/removeHiddenElems.js
new file mode 100644
index 00000000..231a2bdf
--- /dev/null
+++ b/node_modules/svgo/plugins/removeHiddenElems.js
@@ -0,0 +1,218 @@
+'use strict';
+
+exports.type = 'perItem';
+
+exports.active = true;
+
+exports.description = 'removes hidden elements (zero sized, with absent attributes)';
+
+exports.params = {
+ displayNone: true,
+ opacity0: true,
+ circleR0: true,
+ ellipseRX0: true,
+ ellipseRY0: true,
+ rectWidth0: true,
+ rectHeight0: true,
+ patternWidth0: true,
+ patternHeight0: true,
+ imageWidth0: true,
+ imageHeight0: true,
+ pathEmptyD: true,
+ polylineEmptyPoints: true,
+ polygonEmptyPoints: true
+};
+
+var regValidPath = /M\s*(?:[-+]?(?:\d*\.\d+|\d+(?:\.|(?!\.)))([eE][-+]?\d+)?(?!\d)\s*,?\s*){2}\D*\d/i;
+
+/**
+ * Remove hidden elements with disabled rendering:
+ * - display="none"
+ * - opacity="0"
+ * - circle with zero radius
+ * - ellipse with zero x-axis or y-axis radius
+ * - rectangle with zero width or height
+ * - pattern with zero width or height
+ * - image with zero width or height
+ * - path with empty data
+ * - polyline with empty points
+ * - polygon with empty points
+ *
+ * @param {Object} item current iteration item
+ * @param {Object} params plugin params
+ * @return {Boolean} if false, item will be filtered out
+ *
+ * @author Kir Belevich
+ */
+exports.fn = function(item, params) {
+
+ if (item.elem) {
+
+ // display="none"
+ //
+ // http://www.w3.org/TR/SVG/painting.html#DisplayProperty
+ // "A value of display: none indicates that the given element
+ // and its children shall not be rendered directly"
+ if (
+ params.displayNone &&
+ item.hasAttr('display', 'none')
+ ) return false;
+
+ // opacity="0"
+ //
+ // http://www.w3.org/TR/SVG/masking.html#ObjectAndGroupOpacityProperties
+ if (
+ params.opacity0 &&
+ item.hasAttr('opacity', '0')
+ ) return false;
+
+ // Circles with zero radius
+ //
+ // http://www.w3.org/TR/SVG/shapes.html#CircleElementRAttribute
+ // "A value of zero disables rendering of the element"
+ //
+ // <circle r="0">
+ if (
+ params.circleR0 &&
+ item.isElem('circle') &&
+ item.isEmpty() &&
+ item.hasAttr('r', '0')
+ ) return false;
+
+ // Ellipse with zero x-axis radius
+ //
+ // http://www.w3.org/TR/SVG/shapes.html#EllipseElementRXAttribute
+ // "A value of zero disables rendering of the element"
+ //
+ // <ellipse rx="0">
+ if (
+ params.ellipseRX0 &&
+ item.isElem('ellipse') &&
+ item.isEmpty() &&
+ item.hasAttr('rx', '0')
+ ) return false;
+
+ // Ellipse with zero y-axis radius
+ //
+ // http://www.w3.org/TR/SVG/shapes.html#EllipseElementRYAttribute
+ // "A value of zero disables rendering of the element"
+ //
+ // <ellipse ry="0">
+ if (
+ params.ellipseRY0 &&
+ item.isElem('ellipse') &&
+ item.isEmpty() &&
+ item.hasAttr('ry', '0')
+ ) return false;
+
+ // Rectangle with zero width
+ //
+ // http://www.w3.org/TR/SVG/shapes.html#RectElementWidthAttribute
+ // "A value of zero disables rendering of the element"
+ //
+ // <rect width="0">
+ if (
+ params.rectWidth0 &&
+ item.isElem('rect') &&
+ item.isEmpty() &&
+ item.hasAttr('width', '0')
+ ) return false;
+
+ // Rectangle with zero height
+ //
+ // http://www.w3.org/TR/SVG/shapes.html#RectElementHeightAttribute
+ // "A value of zero disables rendering of the element"
+ //
+ // <rect height="0">
+ if (
+ params.rectHeight0 &&
+ params.rectWidth0 &&
+ item.isElem('rect') &&
+ item.isEmpty() &&
+ item.hasAttr('height', '0')
+ ) return false;
+
+ // Pattern with zero width
+ //
+ // http://www.w3.org/TR/SVG/pservers.html#PatternElementWidthAttribute
+ // "A value of zero disables rendering of the element (i.e., no paint is applied)"
+ //
+ // <pattern width="0">
+ if (
+ params.patternWidth0 &&
+ item.isElem('pattern') &&
+ item.hasAttr('width', '0')
+ ) return false;
+
+ // Pattern with zero height
+ //
+ // http://www.w3.org/TR/SVG/pservers.html#PatternElementHeightAttribute
+ // "A value of zero disables rendering of the element (i.e., no paint is applied)"
+ //
+ // <pattern height="0">
+ if (
+ params.patternHeight0 &&
+ item.isElem('pattern') &&
+ item.hasAttr('height', '0')
+ ) return false;
+
+ // Image with zero width
+ //
+ // http://www.w3.org/TR/SVG/struct.html#ImageElementWidthAttribute
+ // "A value of zero disables rendering of the element"
+ //
+ // <image width="0">
+ if (
+ params.imageWidth0 &&
+ item.isElem('image') &&
+ item.hasAttr('width', '0')
+ ) return false;
+
+ // Image with zero height
+ //
+ // http://www.w3.org/TR/SVG/struct.html#ImageElementHeightAttribute
+ // "A value of zero disables rendering of the element"
+ //
+ // <image height="0">
+ if (
+ params.imageHeight0 &&
+ item.isElem('image') &&
+ item.hasAttr('height', '0')
+ ) return false;
+
+ // Path with empty data
+ //
+ // http://www.w3.org/TR/SVG/paths.html#DAttribute
+ //
+ // <path d=""/>
+ if (
+ params.pathEmptyD &&
+ item.isElem('path') &&
+ (!item.hasAttr('d') || !regValidPath.test(item.attr('d').value))
+ ) return false;
+
+ // Polyline with empty points
+ //
+ // http://www.w3.org/TR/SVG/shapes.html#PolylineElementPointsAttribute
+ //
+ // <polyline points="">
+ if (
+ params.polylineEmptyPoints &&
+ item.isElem('polyline') &&
+ !item.hasAttr('points')
+ ) return false;
+
+ // Polygon with empty points
+ //
+ // http://www.w3.org/TR/SVG/shapes.html#PolygonElementPointsAttribute
+ //
+ // <polygon points="">
+ if (
+ params.polygonEmptyPoints &&
+ item.isElem('polygon') &&
+ !item.hasAttr('points')
+ ) return false;
+
+ }
+
+};
diff --git a/node_modules/svgo/plugins/removeMetadata.js b/node_modules/svgo/plugins/removeMetadata.js
new file mode 100644
index 00000000..fa7a5795
--- /dev/null
+++ b/node_modules/svgo/plugins/removeMetadata.js
@@ -0,0 +1,23 @@
+'use strict';
+
+exports.type = 'perItem';
+
+exports.active = true;
+
+exports.description = 'removes <metadata>';
+
+/**
+ * Remove <metadata>.
+ *
+ * http://www.w3.org/TR/SVG/metadata.html
+ *
+ * @param {Object} item current iteration item
+ * @return {Boolean} if false, item will be filtered out
+ *
+ * @author Kir Belevich
+ */
+exports.fn = function(item) {
+
+ return !item.isElem('metadata');
+
+};
diff --git a/node_modules/svgo/plugins/removeNonInheritableGroupAttrs.js b/node_modules/svgo/plugins/removeNonInheritableGroupAttrs.js
new file mode 100644
index 00000000..f999d568
--- /dev/null
+++ b/node_modules/svgo/plugins/removeNonInheritableGroupAttrs.js
@@ -0,0 +1,40 @@
+'use strict';
+
+exports.type = 'perItem';
+
+exports.active = true;
+
+exports.description = 'removes non-inheritable group’s presentational attributes';
+
+var inheritableAttrs = require('./_collections').inheritableAttrs,
+ attrsGroups = require('./_collections').attrsGroups,
+ excludedAttrs = ['display', 'opacity'];
+
+/**
+ * Remove non-inheritable group's "presentation" attributes.
+ *
+ * @param {Object} item current iteration item
+ * @return {Boolean} if false, item will be filtered out
+ *
+ * @author Kir Belevich
+ */
+exports.fn = function(item) {
+
+ if (item.isElem('g')) {
+
+ item.eachAttr(function(attr) {
+ if (
+ ~attrsGroups.presentation.indexOf(attr.name) &&
+ ~attrsGroups.graphicalEvent.indexOf(attr.name) &&
+ ~attrsGroups.core.indexOf(attr.name) &&
+ ~attrsGroups.conditionalProcessing.indexOf(attr.name) &&
+ !~excludedAttrs.indexOf(attr.name) &&
+ !~inheritableAttrs.indexOf(attr.name)
+ ) {
+ item.removeAttr(attr.name);
+ }
+ });
+
+ }
+
+};
diff --git a/node_modules/svgo/plugins/removeRasterImages.js b/node_modules/svgo/plugins/removeRasterImages.js
new file mode 100644
index 00000000..cbddebe3
--- /dev/null
+++ b/node_modules/svgo/plugins/removeRasterImages.js
@@ -0,0 +1,28 @@
+'use strict';
+
+exports.type = 'perItem';
+
+exports.active = false;
+
+exports.description = 'removes raster images (disabled by default)';
+
+/**
+ * Remove raster images references in <image>.
+ *
+ * @see https://bugs.webkit.org/show_bug.cgi?id=63548
+ *
+ * @param {Object} item current iteration item
+ * @return {Boolean} if false, item will be filtered out
+ *
+ * @author Kir Belevich
+ */
+exports.fn = function(item) {
+
+ if (
+ item.isElem('image') &&
+ item.hasAttrLocal('href', /(\.|image\/)(jpg|png|gif)/)
+ ) {
+ return false;
+ }
+
+};
diff --git a/node_modules/svgo/plugins/removeStyleElement.js b/node_modules/svgo/plugins/removeStyleElement.js
new file mode 100644
index 00000000..964ce45c
--- /dev/null
+++ b/node_modules/svgo/plugins/removeStyleElement.js
@@ -0,0 +1,23 @@
+'use strict';
+
+exports.type = 'perItem';
+
+exports.active = false;
+
+exports.description = 'removes <style> element (disabled by default)';
+
+/**
+ * Remove <style>.
+ *
+ * http://www.w3.org/TR/SVG/styling.html#StyleElement
+ *
+ * @param {Object} item current iteration item
+ * @return {Boolean} if false, item will be filtered out
+ *
+ * @author Betsy Dupuis
+ */
+exports.fn = function(item) {
+
+ return !item.isElem('style');
+
+};
diff --git a/node_modules/svgo/plugins/removeTitle.js b/node_modules/svgo/plugins/removeTitle.js
new file mode 100644
index 00000000..3d077e45
--- /dev/null
+++ b/node_modules/svgo/plugins/removeTitle.js
@@ -0,0 +1,24 @@
+'use strict';
+
+exports.type = 'perItem';
+
+exports.active = false;
+
+exports.description = 'removes <title> (disabled by default)';
+
+/**
+ * Remove <title>.
+ * Disabled by default cause it may be used for accessibility.
+ *
+ * https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title
+ *
+ * @param {Object} item current iteration item
+ * @return {Boolean} if false, item will be filtered out
+ *
+ * @author Igor Kalashnikov
+ */
+exports.fn = function(item) {
+
+ return !item.isElem('title');
+
+};
diff --git a/node_modules/svgo/plugins/removeUnknownsAndDefaults.js b/node_modules/svgo/plugins/removeUnknownsAndDefaults.js
new file mode 100644
index 00000000..341b1fd7
--- /dev/null
+++ b/node_modules/svgo/plugins/removeUnknownsAndDefaults.js
@@ -0,0 +1,143 @@
+'use strict';
+
+exports.type = 'perItem';
+
+exports.active = true;
+
+exports.description = 'removes unknown elements content and attributes, removes attrs with default values';
+
+exports.params = {
+ unknownContent: true,
+ unknownAttrs: true,
+ defaultAttrs: true,
+ uselessOverrides: true,
+ keepDataAttrs: true
+};
+
+var collections = require('./_collections'),
+ elems = collections.elems,
+ attrsGroups = collections.attrsGroups,
+ elemsGroups = collections.elemsGroups,
+ attrsGroupsDefaults = collections.attrsGroupsDefaults,
+ attrsInheritable = collections.inheritableAttrs;
+
+// collect and extend all references
+for (var elem in elems) {
+ elem = elems[elem];
+
+ if (elem.attrsGroups) {
+ elem.attrs = elem.attrs || [];
+
+ elem.attrsGroups.forEach(function(attrsGroupName) {
+ elem.attrs = elem.attrs.concat(attrsGroups[attrsGroupName]);
+
+ var groupDefaults = attrsGroupsDefaults[attrsGroupName];
+
+ if (groupDefaults) {
+ elem.defaults = elem.defaults || {};
+
+ for (var attrName in groupDefaults) {
+ elem.defaults[attrName] = groupDefaults[attrName];
+ }
+ }
+ });
+
+ }
+
+ if (elem.contentGroups) {
+ elem.content = elem.content || [];
+
+ elem.contentGroups.forEach(function(contentGroupName) {
+ elem.content = elem.content.concat(elemsGroups[contentGroupName]);
+ });
+ }
+}
+
+/**
+ * Remove unknown elements content and attributes,
+ * remove attributes with default values.
+ *
+ * @param {Object} item current iteration item
+ * @param {Object} params plugin params
+ * @return {Boolean} if false, item will be filtered out
+ *
+ * @author Kir Belevich
+ */
+exports.fn = function(item, params) {
+
+ // elems w/o namespace prefix
+ if (item.isElem() && !item.prefix) {
+
+ var elem = item.elem;
+
+ // remove unknown element's content
+ if (
+ params.unknownContent &&
+ !item.isEmpty() &&
+ elems[elem] && // make sure we know of this element before checking its children
+ elem !== 'foreignObject' // Don't check foreignObject
+ ) {
+ item.content.forEach(function(content, i) {
+ if (
+ content.isElem() &&
+ !content.prefix &&
+ (
+ (
+ elems[elem].content && // Do we have a record of its permitted content?
+ elems[elem].content.indexOf(content.elem) === -1
+ ) ||
+ (
+ !elems[elem].content && // we dont know about its permitted content
+ !elems[content.elem] // check that we know about the element at all
+ )
+ )
+ ) {
+ item.content.splice(i, 1);
+ }
+ });
+ }
+
+ // remove element's unknown attrs and attrs with default values
+ if (elems[elem] && elems[elem].attrs) {
+
+ item.eachAttr(function(attr) {
+
+ if (
+ attr.name !== 'xmlns' &&
+ (attr.prefix === 'xml' || !attr.prefix) &&
+ (!params.keepDataAttrs || attr.name.indexOf('data-') != 0)
+ ) {
+ if (
+ // unknown attrs
+ (
+ params.unknownAttrs &&
+ elems[elem].attrs.indexOf(attr.name) === -1
+ ) ||
+ // attrs with default values
+ (
+ params.defaultAttrs &&
+ elems[elem].defaults &&
+ elems[elem].defaults[attr.name] === attr.value && (
+ attrsInheritable.indexOf(attr.name) < 0 ||
+ !item.parentNode.computedAttr(attr.name)
+ )
+ ) ||
+ // useless overrides
+ (
+ params.uselessOverrides &&
+ attr.name !== 'transform' &&
+ attrsInheritable.indexOf(attr.name) > -1 &&
+ item.parentNode.computedAttr(attr.name, attr.value)
+ )
+ ) {
+ item.removeAttr(attr.name);
+ }
+ }
+
+ });
+
+ }
+
+ }
+
+};
diff --git a/node_modules/svgo/plugins/removeUnusedNS.js b/node_modules/svgo/plugins/removeUnusedNS.js
new file mode 100644
index 00000000..c4787915
--- /dev/null
+++ b/node_modules/svgo/plugins/removeUnusedNS.js
@@ -0,0 +1,107 @@
+'use strict';
+
+exports.type = 'full';
+
+exports.active = true;
+
+exports.description = 'removes unused namespaces declaration';
+
+/**
+ * Remove unused namespaces declaration.
+ *
+ * @param {Object} item current iteration item
+ * @return {Boolean} if false, item will be filtered out
+ *
+ * @author Kir Belevich
+ */
+exports.fn = function(data) {
+
+ var svgElem,
+ xmlnsCollection = [];
+
+ /**
+ * Remove namespace from collection.
+ *
+ * @param {String} ns namescape name
+ */
+ function removeNSfromCollection(ns) {
+
+ var pos = xmlnsCollection.indexOf(ns);
+
+ // if found - remove ns from the namespaces collection
+ if (pos > -1) {
+ xmlnsCollection.splice(pos, 1);
+ }
+
+ }
+
+ /**
+ * Bananas!
+ *
+ * @param {Array} items input items
+ *
+ * @return {Array} output items
+ */
+ function monkeys(items) {
+
+ var i = 0,
+ length = items.content.length;
+
+ while(i < length) {
+
+ var item = items.content[i];
+
+ if (item.isElem('svg')) {
+
+ item.eachAttr(function(attr) {
+ // collect namespaces
+ if (attr.prefix === 'xmlns' && attr.local) {
+ xmlnsCollection.push(attr.local);
+ }
+ });
+
+ // if svg element has ns-attr
+ if (xmlnsCollection.length) {
+ // save svg element
+ svgElem = item;
+ }
+
+ } else if (xmlnsCollection.length) {
+
+ // check item for the ns-attrs
+ if (item.prefix) {
+ removeNSfromCollection(item.prefix);
+ }
+
+ // check each attr for the ns-attrs
+ item.eachAttr(function(attr) {
+ removeNSfromCollection(attr.prefix);
+ });
+
+ }
+
+ // if nothing is found - go deeper
+ if (xmlnsCollection.length && item.content) {
+ monkeys(item);
+ }
+
+ i++;
+
+ }
+
+ return items;
+
+ }
+
+ data = monkeys(data);
+
+ // remove svg element ns-attributes if they are not used even once
+ if (xmlnsCollection.length) {
+ xmlnsCollection.forEach(function(name) {
+ svgElem.removeAttr('xmlns:' + name);
+ });
+ }
+
+ return data;
+
+};
diff --git a/node_modules/svgo/plugins/removeUselessDefs.js b/node_modules/svgo/plugins/removeUselessDefs.js
new file mode 100644
index 00000000..b8c97a52
--- /dev/null
+++ b/node_modules/svgo/plugins/removeUselessDefs.js
@@ -0,0 +1,51 @@
+'use strict';
+
+exports.type = 'perItem';
+
+exports.active = true;
+
+exports.description = 'removes elements in <defs> without id';
+
+var nonRendering = require('./_collections').elemsGroups.nonRendering,
+ defs;
+
+/**
+ * Removes content of defs and properties that aren't rendered directly without ids.
+ *
+ * @param {Object} item current iteration item
+ * @return {Boolean} if false, item will be filtered out
+ *
+ * @author Lev Solntsev
+ */
+exports.fn = function(item) {
+
+ if (item.isElem('defs')) {
+
+ defs = item;
+ item.content = (item.content || []).reduce(getUsefulItems, []);
+
+ if (item.isEmpty()) return false;
+
+ } else if (item.isElem(nonRendering) && !item.hasAttr('id')) {
+
+ return false;
+
+ }
+
+};
+
+function getUsefulItems(usefulItems, item) {
+
+ if (item.hasAttr('id') || item.isElem('style')) {
+
+ usefulItems.push(item);
+ item.parentNode = defs;
+
+ } else if (!item.isEmpty()) {
+
+ item.content.reduce(getUsefulItems, usefulItems);
+
+ }
+
+ return usefulItems;
+}
diff --git a/node_modules/svgo/plugins/removeUselessStrokeAndFill.js b/node_modules/svgo/plugins/removeUselessStrokeAndFill.js
new file mode 100644
index 00000000..47090eb8
--- /dev/null
+++ b/node_modules/svgo/plugins/removeUselessStrokeAndFill.js
@@ -0,0 +1,92 @@
+'use strict';
+
+exports.type = 'perItem';
+
+exports.active = true;
+
+exports.description = 'removes useless stroke and fill attributes';
+
+exports.params = {
+ stroke: true,
+ fill: true
+};
+
+var shape = require('./_collections').elemsGroups.shape,
+ regStrokeProps = /^stroke/,
+ regFillProps = /^fill-/,
+ styleOrScript = ['style', 'script'],
+ hasStyleOrScript = false;
+
+/**
+ * Remove useless stroke and fill attrs.
+ *
+ * @param {Object} item current iteration item
+ * @param {Object} params plugin params
+ * @return {Boolean} if false, item will be filtered out
+ *
+ * @author Kir Belevich
+ */
+exports.fn = function(item, params) {
+
+ if (item.isElem(styleOrScript)) {
+ hasStyleOrScript = true;
+ }
+
+ if (!hasStyleOrScript && item.isElem(shape) && !item.computedAttr('id')) {
+
+ var stroke = params.stroke && item.computedAttr('stroke'),
+ fill = params.fill && !item.computedAttr('fill', 'none');
+
+ // remove stroke*
+ if (
+ params.stroke &&
+ (!stroke ||
+ stroke == 'none' ||
+ item.computedAttr('stroke-opacity', '0') ||
+ item.computedAttr('stroke-width', '0')
+ )
+ ) {
+ var parentStroke = item.parentNode.computedAttr('stroke'),
+ declineStroke = parentStroke && parentStroke != 'none';
+
+ item.eachAttr(function(attr) {
+ if (regStrokeProps.test(attr.name)) {
+ item.removeAttr(attr.name);
+ }
+ });
+
+ if (declineStroke) item.addAttr({
+ name: 'stroke',
+ value: 'none',
+ prefix: '',
+ local: 'stroke'
+ });
+ }
+
+ // remove fill*
+ if (
+ params.fill &&
+ (!fill || item.computedAttr('fill-opacity', '0'))
+ ) {
+ item.eachAttr(function(attr) {
+ if (regFillProps.test(attr.name)) {
+ item.removeAttr(attr.name);
+ }
+ });
+
+ if (fill) {
+ if (item.hasAttr('fill'))
+ item.attr('fill').value = 'none';
+ else
+ item.addAttr({
+ name: 'fill',
+ value: 'none',
+ prefix: '',
+ local: 'fill'
+ });
+ }
+ }
+
+ }
+
+};
diff --git a/node_modules/svgo/plugins/removeViewBox.js b/node_modules/svgo/plugins/removeViewBox.js
new file mode 100644
index 00000000..33595656
--- /dev/null
+++ b/node_modules/svgo/plugins/removeViewBox.js
@@ -0,0 +1,49 @@
+'use strict';
+
+exports.type = 'perItem';
+
+exports.active = false;
+
+exports.description = 'removes viewBox attribute when possible (disabled by default)';
+
+var regViewBox = /^0\s0\s([\-+]?\d*\.?\d+([eE][\-+]?\d+)?)\s([\-+]?\d*\.?\d+([eE][\-+]?\d+)?)$/,
+ viewBoxElems = ['svg', 'pattern'];
+
+/**
+ * Remove viewBox attr which coincides with a width/height box.
+ *
+ * @see http://www.w3.org/TR/SVG/coords.html#ViewBoxAttribute
+ *
+ * @example
+ * <svg width="100" height="50" viewBox="0 0 100 50">
+ * ⬇
+ * <svg width="100" height="50">
+ *
+ * @param {Object} item current iteration item
+ * @return {Boolean} if false, item will be filtered out
+ *
+ * @author Kir Belevich
+ */
+exports.fn = function(item) {
+
+ if (
+ item.isElem(viewBoxElems) &&
+ item.hasAttr('viewBox') &&
+ item.hasAttr('width') &&
+ item.hasAttr('height')
+ ) {
+
+ var match = item.attr('viewBox').value.match(regViewBox);
+
+ if (match) {
+ if (
+ item.attr('width').value === match[1] &&
+ item.attr('height').value === match[3]
+ ) {
+ item.removeAttr('viewBox');
+ }
+ }
+
+ }
+
+};
diff --git a/node_modules/svgo/plugins/removeXMLNS.js b/node_modules/svgo/plugins/removeXMLNS.js
new file mode 100644
index 00000000..afda99d3
--- /dev/null
+++ b/node_modules/svgo/plugins/removeXMLNS.js
@@ -0,0 +1,28 @@
+'use strict';
+
+exports.type = 'perItem';
+
+exports.active = false;
+
+exports.description = 'removes xmlns attribute (for inline svg, disabled by default)';
+
+/**
+ * Remove the xmlns attribute when present.
+ *
+ * @example
+ * <svg viewBox="0 0 100 50" xmlns="http://www.w3.org/2000/svg">
+ * ↓
+ * <svg viewBox="0 0 100 50">
+ *
+ * @param {Object} item current iteration item
+ * @return {Boolean} if true, xmlns will be filtered out
+ *
+ * @author Ricardo Tomasi
+ */
+exports.fn = function(item) {
+
+ if (item.isElem('svg') && item.hasAttr('xmlns')) {
+ item.removeAttr('xmlns');
+ }
+
+}; \ No newline at end of file
diff --git a/node_modules/svgo/plugins/removeXMLProcInst.js b/node_modules/svgo/plugins/removeXMLProcInst.js
new file mode 100644
index 00000000..afd425d5
--- /dev/null
+++ b/node_modules/svgo/plugins/removeXMLProcInst.js
@@ -0,0 +1,24 @@
+'use strict';
+
+exports.type = 'perItem';
+
+exports.active = true;
+
+exports.description = 'removes XML processing instructions';
+
+/**
+ * Remove XML Processing Instruction.
+ *
+ * @example
+ * <?xml version="1.0" encoding="utf-8"?>
+ *
+ * @param {Object} item current iteration item
+ * @return {Boolean} if false, item will be filtered out
+ *
+ * @author Kir Belevich
+ */
+exports.fn = function(item) {
+
+ return !(item.processinginstruction && item.processinginstruction.name === 'xml');
+
+};
diff --git a/node_modules/svgo/plugins/sortAttrs.js b/node_modules/svgo/plugins/sortAttrs.js
new file mode 100644
index 00000000..221a4bf5
--- /dev/null
+++ b/node_modules/svgo/plugins/sortAttrs.js
@@ -0,0 +1,81 @@
+'use strict';
+
+exports.type = 'perItem';
+
+exports.active = false;
+
+exports.description = 'sorts element attributes (disabled by default)';
+
+exports.params = {
+ order: [
+ 'id',
+ 'width', 'height',
+ 'x', 'x1', 'x2',
+ 'y', 'y1', 'y2',
+ 'cx', 'cy', 'r',
+ 'fill', 'stroke', 'marker',
+ 'd', 'points'
+ ]
+};
+
+/**
+ * Sort element attributes for epic readability.
+ *
+ * @param {Object} item current iteration item
+ * @param {Object} params plugin params
+ *
+ * @author Nikolay Frantsev
+ */
+exports.fn = function(item, params) {
+
+ var attrs = [],
+ sorted = {},
+ orderlen = params.order.length + 1;
+
+ if (item.elem) {
+
+ item.eachAttr(function(attr) {
+ attrs.push(attr);
+ });
+
+ attrs.sort(function(a, b) {
+ if (a.prefix != b.prefix) {
+ // xmlns attributes implicitly have the prefix xmlns
+ if (a.prefix == 'xmlns')
+ return -1;
+ if (b.prefix == 'xmlns')
+ return 1;
+ return a.prefix < b.prefix ? -1 : 1;
+ }
+
+ var aindex = orderlen;
+ var bindex = orderlen;
+
+ for (var i = 0; i < params.order.length; i++) {
+ if (a.name == params.order[i]) {
+ aindex = i;
+ } else if (a.name.indexOf(params.order[i] + '-') === 0) {
+ aindex = i + .5;
+ }
+ if (b.name == params.order[i]) {
+ bindex = i;
+ } else if (b.name.indexOf(params.order[i] + '-') === 0) {
+ bindex = i + .5;
+ }
+ }
+
+ if (aindex != bindex) {
+ return aindex - bindex;
+ }
+ return a.name < b.name ? -1 : 1;
+ });
+
+ attrs.forEach(function (attr) {
+ sorted[attr.name] = attr;
+ });
+
+ item.attrs = sorted;
+
+ }
+
+};
diff --git a/node_modules/svgo/plugins/transformsWithOnePath.js b/node_modules/svgo/plugins/transformsWithOnePath.js
new file mode 100644
index 00000000..f4dec7e6
--- /dev/null
+++ b/node_modules/svgo/plugins/transformsWithOnePath.js
@@ -0,0 +1,327 @@
+'use strict';
+
+/*
+ * Thanks to http://fontello.com project for sponsoring this plugin
+ */
+
+exports.type = 'full';
+
+exports.active = false;
+
+exports.description = 'performs a set of operations on SVG with one path inside (disabled by default)';
+
+exports.params = {
+ // width and height to resize SVG and rescale inner Path
+ width: false,
+ height: false,
+
+ // scale inner Path without resizing SVG
+ scale: false,
+
+ // shiftX/Y inner Path
+ shiftX: false,
+ shiftY: false,
+
+ // crop SVG width along the real width of inner Path
+ hcrop: false,
+
+ // vertical center inner Path inside SVG height
+ vcenter: false,
+
+ // stringify params
+ floatPrecision: 3,
+ leadingZero: true,
+ negativeExtraSpace: true
+};
+
+var _path = require('./_path.js'),
+ relative2absolute = _path.relative2absolute,
+ computeCubicBoundingBox = _path.computeCubicBoundingBox,
+ computeQuadraticBoundingBox = _path.computeQuadraticBoundingBox,
+ applyTransforms = _path.applyTransforms,
+ js2path = _path.js2path,
+ path2js = _path.path2js,
+ EXTEND = require('whet.extend');
+
+exports.fn = function(data, params) {
+
+ data.content.forEach(function(item) {
+
+ // only for SVG with one Path inside
+ if (item.isElem('svg') &&
+ item.content.length === 1 &&
+ item.content[0].isElem('path')
+ ) {
+
+ var svgElem = item,
+ pathElem = svgElem.content[0],
+ // get absoluted Path data
+ path = relative2absolute(EXTEND(true, [], path2js(pathElem))),
+ xs = [],
+ ys = [],
+ cubicСontrolPoint = [0, 0],
+ quadraticСontrolPoint = [0, 0],
+ lastPoint = [0, 0],
+ cubicBoundingBox,
+ quadraticBoundingBox,
+ i,
+ segment;
+
+ path.forEach(function(pathItem) {
+
+ // ML
+ if ('ML'.indexOf(pathItem.instruction) > -1) {
+
+ for (i = 0; i < pathItem.data.length; i++) {
+ if (i % 2 === 0) {
+ xs.push(pathItem.data[i]);
+ } else {
+ ys.push(pathItem.data[i]);
+ }
+ }
+
+ lastPoint = cubicСontrolPoint = quadraticСontrolPoint = pathItem.data.slice(-2);
+
+ // H
+ } else if (pathItem.instruction === 'H') {
+
+ pathItem.data.forEach(function(d) {
+ xs.push(d);
+ });
+
+ lastPoint[0] = cubicСontrolPoint[0] = quadraticСontrolPoint[0] = pathItem.data[pathItem.data.length - 2];
+
+ // V
+ } else if (pathItem.instruction === 'V') {
+
+ pathItem.data.forEach(function(d) {
+ ys.push(d);
+ });
+
+ lastPoint[1] = cubicСontrolPoint[1] = quadraticСontrolPoint[1] = pathItem.data[pathItem.data.length - 1];
+
+ // C
+ } else if (pathItem.instruction === 'C') {
+
+ for (i = 0; i < pathItem.data.length; i += 6) {
+
+ segment = pathItem.data.slice(i, i + 6);
+
+ cubicBoundingBox = computeCubicBoundingBox.apply(this, lastPoint.concat(segment));
+
+ xs.push(cubicBoundingBox.minx);
+ xs.push(cubicBoundingBox.maxx);
+
+ ys.push(cubicBoundingBox.miny);
+ ys.push(cubicBoundingBox.maxy);
+
+ // reflected control point for the next possible S
+ cubicСontrolPoint = [
+ 2 * segment[4] - segment[2],
+ 2 * segment[5] - segment[3]
+ ];
+
+ lastPoint = segment.slice(-2);
+
+ }
+
+ // S
+ } else if (pathItem.instruction === 'S') {
+
+ for (i = 0; i < pathItem.data.length; i += 4) {
+
+ segment = pathItem.data.slice(i, i + 4);
+
+ cubicBoundingBox = computeCubicBoundingBox.apply(this, lastPoint.concat(cubicСontrolPoint).concat(segment));
+
+ xs.push(cubicBoundingBox.minx);
+ xs.push(cubicBoundingBox.maxx);
+
+ ys.push(cubicBoundingBox.miny);
+ ys.push(cubicBoundingBox.maxy);
+
+ // reflected control point for the next possible S
+ cubicСontrolPoint = [
+ 2 * segment[2] - cubicСontrolPoint[0],
+ 2 * segment[3] - cubicСontrolPoint[1],
+ ];
+
+ lastPoint = segment.slice(-2);
+
+ }
+
+ // Q
+ } else if (pathItem.instruction === 'Q') {
+
+ for (i = 0; i < pathItem.data.length; i += 4) {
+
+ segment = pathItem.data.slice(i, i + 4);
+
+ quadraticBoundingBox = computeQuadraticBoundingBox.apply(this, lastPoint.concat(segment));
+
+ xs.push(quadraticBoundingBox.minx);
+ xs.push(quadraticBoundingBox.maxx);
+
+ ys.push(quadraticBoundingBox.miny);
+ ys.push(quadraticBoundingBox.maxy);
+
+ // reflected control point for the next possible T
+ quadraticСontrolPoint = [
+ 2 * segment[2] - segment[0],
+ 2 * segment[3] - segment[1]
+ ];
+
+ lastPoint = segment.slice(-2);
+
+ }
+
+ // S
+ } else if (pathItem.instruction === 'T') {
+
+ for (i = 0; i < pathItem.data.length; i += 2) {
+
+ segment = pathItem.data.slice(i, i + 2);
+
+ quadraticBoundingBox = computeQuadraticBoundingBox.apply(this, lastPoint.concat(quadraticСontrolPoint).concat(segment));
+
+ xs.push(quadraticBoundingBox.minx);
+ xs.push(quadraticBoundingBox.maxx);
+
+ ys.push(quadraticBoundingBox.miny);
+ ys.push(quadraticBoundingBox.maxy);
+
+ // reflected control point for the next possible T
+ quadraticСontrolPoint = [
+ 2 * segment[0] - quadraticСontrolPoint[0],
+ 2 * segment[1] - quadraticСontrolPoint[1]
+ ];
+
+ lastPoint = segment.slice(-2);
+
+ }
+
+ }
+
+ });
+
+ var xmin = Math.min.apply(this, xs).toFixed(params.floatPrecision),
+ xmax = Math.max.apply(this, xs).toFixed(params.floatPrecision),
+ ymin = Math.min.apply(this, ys).toFixed(params.floatPrecision),
+ ymax = Math.max.apply(this, ys).toFixed(params.floatPrecision),
+ svgWidth = +svgElem.attr('width').value,
+ svgHeight = +svgElem.attr('height').value,
+ realWidth = Math.round(xmax - xmin),
+ realHeight = Math.round(ymax - ymin),
+ transform = '',
+ scale;
+
+ // width & height
+ if (params.width && params.height) {
+
+ scale = Math.min(params.width / svgWidth, params.height / svgHeight);
+
+ realWidth = realWidth * scale;
+ realHeight = realHeight * scale;
+
+ svgWidth = svgElem.attr('width').value = params.width;
+ svgHeight = svgElem.attr('height').value = params.height;
+
+ transform += ' scale(' + scale + ')';
+
+ // width
+ } else if (params.width && !params.height) {
+
+ scale = params.width / svgWidth;
+
+ realWidth = realWidth * scale;
+ realHeight = realHeight * scale;
+
+ svgWidth = svgElem.attr('width').value = params.width;
+ svgHeight = svgElem.attr('height').value = svgHeight * scale;
+
+ transform += ' scale(' + scale + ')';
+
+ // height
+ } else if (params.height && !params.width) {
+
+ scale = params.height / svgHeight;
+
+ realWidth = realWidth * scale;
+ realHeight = realHeight * scale;
+
+ svgWidth = svgElem.attr('width').value = svgWidth * scale;
+ svgHeight = svgElem.attr('height').value = params.height;
+
+ transform += ' scale(' + scale + ')';
+
+ }
+
+ // shiftX
+ if (params.shiftX) {
+ transform += ' translate(' + realWidth * params.shiftX + ', 0)';
+ }
+
+ // shiftY
+ if (params.shiftY) {
+ transform += ' translate(0, ' + realHeight * params.shiftY + ')';
+ }
+
+ // scale
+ if (params.scale) {
+ scale = params.scale;
+
+ var shiftX = svgWidth / 2,
+ shiftY = svgHeight / 2;
+
+ realWidth = realWidth * scale;
+ realHeight = realHeight * scale;
+
+ if (params.shiftX || params.shiftY) {
+ transform += ' scale(' + scale + ')';
+ } else {
+ transform += ' translate(' + shiftX + ' ' + shiftY + ') scale(' + scale + ') translate(-' + shiftX + ' -' + shiftY + ')';
+ }
+ }
+
+ // hcrop
+ if (params.hcrop) {
+ transform += ' translate(' + (-xmin) + ' 0)';
+
+ svgElem.attr('width').value = realWidth;
+ }
+
+ // vcenter
+ if (params.vcenter) {
+ transform += ' translate(0 ' + (((svgHeight - realHeight) / 2) - ymin) + ')';
+ }
+
+ if (transform) {
+ pathElem.addAttr({
+ name: 'transform',
+ prefix: '',
+ local: 'transform',
+ value: transform
+ });
+
+ path = applyTransforms(pathElem, pathElem.pathJS, true, params.floatPrecision);
+
+ // transformed data rounding
+ path.forEach(function(pathItem) {
+ if (pathItem.data) {
+ pathItem.data = pathItem.data.map(function(num) {
+ return +num.toFixed(params.floatPrecision);
+ });
+ }
+ });
+
+ // save new
+ js2path(pathElem, path, params);
+ }
+
+ }
+
+ });
+
+ return data;
+
+};