progress on migrating to heex templates and font-icons

This commit is contained in:
Adam Piontek 2022-08-13 07:32:36 -04:00
parent d43daafdb7
commit 3eff955672
21793 changed files with 2161968 additions and 16895 deletions

75
assets_old/node_modules/svgo/.svgo.yml generated vendored Normal file
View file

@ -0,0 +1,75 @@
# 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
- inlineStyles
- minifyStyles
- convertStyleToAttrs
- cleanupIDs
- prefixIds
- removeRasterImages
- removeUselessDefs
- cleanupNumericValues
- cleanupListOfValues
- convertColors
- removeUnknownsAndDefaults
- removeNonInheritableGroupAttrs
- removeUselessStrokeAndFill
- removeViewBox
- cleanupEnableBackground
- removeHiddenElems
- removeEmptyText
- convertShapeToPath
- convertEllipseToCircle
- moveElemsAttrsToGroup
- moveGroupAttrsToElems
- collapseGroups
- convertPathData
- convertTransform
- removeEmptyAttrs
- removeEmptyContainers
- mergePaths
- removeUnusedNS
- sortAttrs
- sortDefsChildren
- removeTitle
- removeDesc
- removeDimensions
- removeAttrs
- removeAttributesBySelector
- removeElementsByAttr
- addClassesToSVGElement
- removeStyleElement
- removeScriptElement
- addAttributesToSVGElement
- removeOffCanvasPaths
- reusePaths
# 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: ' '

533
assets_old/node_modules/svgo/CHANGELOG.md generated vendored Normal file
View file

@ -0,0 +1,533 @@
### [ [>](https://github.com/svg/svgo/tree/v1.3.2) ] 1.3.2 / 30.10.2019
* Fixed TypeError: Cannot set property 'multipassCount' of undefined
### [ [>](https://github.com/svg/svgo/tree/v1.3.1) ] 1.3.1 / 29.10.2019
* Updated CSSO version to 4.0.2 fixing the issue with empty semicolons ";;" in styles (thanks to @strarsis and @lahmatiy).
* `prefixIds` plugin now runs only once with `--multipass` option (by @strarsis).
* `cleanupIDs` plugin is prevented from producing a preserved ID, including one which matches a preserved prefix, when minifying (by @thomsj).
### [ [>](https://github.com/svg/svgo/tree/v1.3.0) ] 1.3.0 / 14.07.2019
* Custom plugins now can be loaded from external js through `path` plugin param.
* New plugin `convertEllipseToCircle` to convert ellipse with equal radius measures to circle (by @tigt).
* New plugin `sortDefsChildren` for improved compression (by @davidleston).
* SVGO now removes unnecessary spaces after `arcto` path command flags.
* `removeDimensions` plugin now adds `viewBox` if it's missing (by @adipascu).
* Fixed `removeUnusedNS` not counting attributes in `<svg>` tag itself.
* Fixed an issue with incorrect processing multiple images (by @cyberalien).
* Fixed an error with incorrect converting multiple segmented curve to an arc.
* Fixed an error with matrix decomposition in `convertTransform` due to rounding error leading to illegal value.
* Added `force` option for `mergePaths` plugin (by @goyney).
* Added options to `prefixIds` plugin for selectively prefixing IDs and/or classes (by @strarsis).
* Exported config function (by @1000ch).
### [ [>](https://github.com/svg/svgo/tree/v1.2.2) ] 1.2.2 / 16.04.2019
* Update js-yaml for Code Injection warning (by @kaungst).
### [ [>](https://github.com/svg/svgo/tree/v1.2.1) ] 1.2.1 / 04.04.2019
Some goodness from pull-requests.
* Bump up js-yaml version to fix DoS vulnerability (by @eugestarr).
### [ [>](https://github.com/svg/svgo/tree/v1.2.0) ] 1.2.0 / 24.02.2019
Some goodness from pull-requests.
* Fixed extra blank lines when processing many files (by @panczarny).
* Added `--recursive` option to process folders recursevely with option `-f` (by @dartess).
* Added `removeAttributesBySelector` plugin to remove elements matching a css selector (by @bmease).
* Added `removeOffCanvasPaths` plugin to remove elements outside of the viewbox (by @JoshyPHP).
* `removeAttrs` plugin: added `preserveCurrentColor` color (by @roblevintennis) and 3rd optional filter for a value (by @Herman-Freund).
* Added `reusePaths` plugin to replace duplicated elements with link (by @jhowcrof).
* Added support of comma-separated plugins list in `--disable` and `--enable` options (by @jmwebservices).
* Added option to preserve IDs based on prefix in `cleanupIDs` plugin (by @bkotzz).
* Replaced `colors` dependency with `chalk` (by @xPaw).
### [ [>](https://github.com/svg/svgo/tree/v1.1.1) ] 1.1.1 / 17.09.2018
* Fixed crash in `SVGO.optimize()` when info is absent.
* Removed extra space after `cleanupListOfValues` plugin.
### [ [>](https://github.com/svg/svgo/tree/v1.1.0) ] 1.1.0 / 16.09.2018
* Fixed `collapseGroups` plugin removing property with a child having `inherit` value.
* `version` attribute value is not more being rounded.
* Fixed jsAPI `clone` method with respect to the introduced CSS classes.
* Fixed scaling strokes with `vector-effect="non-scaling-stroke"` (by @alexjlockwood).
* Fixed passing properties from groups in `collapseGroups` plugin if child have a filter (by @stristr).
* Fixed arc path commands parsing without separators after flags, effectively producing a JS error.
* Fixed `viewBox` separators parsing.
* Fixed `removeNonInheritableGroupAttrs` plugin to work as intended.
* Fixed removing path segments without length in presence of `stroke-linecap`.
* Fixed `removeUnknownsAndDefaults` plugin removing attributes from elements with `id`.
* Fixed converting to large arcs from nearly straight lines curves.
* Fixed `collapseGroups` plugin affecting `<switch>` and its subgroups.
* Fixed `convertTransform` plugin converting to `rotate()` with wrong sign in some case.
* Fixed `cleanupListOfValues` plugin not preserving non-numeric values.
* Fixed `!important` being passed to attributes in `convertStyleToAttrs` plugin.
* Added option `keepImportant` to `convertStyleToAttrs` plugin to preserve styles with `!important`.
* `removeHiddenElems` plugin now also removes elements with `visibility="hidden"` attribute (by @mikolaj92).
* Added `forceAbsolutePath` option to `convertPathData` plugin to always use absolute coordinates (by @cool).
* Added `keepRoleAttr` for `removeUnknownsAndDefaults` plugin to preserve `role-` attributes (by @himedlooff).
* Added `xmlns` order option in `sortAttrs` plugin (by @hellatan).
* Added an option to `prefixIds` plugin to pass prefix as false or as a function that returns false (by @vzaidman).
* `prefixIds` plugin now adds prefix to every class (by @vzaidman).
* Updated and improved docs a bit (multiple authors).
### [ [>](https://github.com/svg/svgo/tree/v1.0.5) ] 1.0.5 / 26.02.2018
* Fixed issue with prefixIDs plugin not replacing url() values correctly (by @harrisjose).
### [ [>](https://github.com/svg/svgo/tree/v1.0.4) ] 1.0.4 / 30.01.2018
* Fixed bug with removing groups that are direct child of "<switch>".
* Fixed bug with shorthand path points counting (thanks @alexjlockwood for noticing).
* Fixed crash on parsing invalid transform, e.g. without close parenthesis.
### [ [>](https://github.com/svg/svgo/tree/v1.0.3) ] 1.0.3 / 08.11.2017
* Fixed `removeViewBox` plugin to check for zero start coordinates.
* Removed extra info from STDOUT when it set to output.
### [ [>](https://github.com/svg/svgo/tree/v1.0.2) ] 1.0.2 / 03.11.2017
* Fixed a couple of errors related to `inlineStyles` plugin.
* Updated some lost details in documentation to reflect v1.0 changes.
### [ [>](https://github.com/svg/svgo/tree/v1.0.1) ] 1.0.1 / 31.10.2017
* Fixed error “Object.defineProperty called on non-object” in images with `<foreignObject/>`.
### [ [>](https://github.com/svg/svgo/tree/v1.0.0) ] 1.0.0 / 30.10.2017
* SVGO now requires Node 4 or higher.
* Changed CLI syntax to treat filenames as input, thus allowing `svgo *.svg` syntax.
* `SVGO.optimize()` now returns `Promise`.
* Added `datauri` option to JS API.
* Added support for SVG 2 `href` attribute.
* `cleanupIDs` now don't removes IDs if an image consists only of `defs`.
* New plugin `inlineStyles` for converting styles from `<style>` element to attributes if possible (by @strarsis).
* `cleanupNumericValues` now rounds values in `viewBox` (by @caub).
* New plugin: `removeScriptElement` (disabled by default) to align with `removeStyleElement` (by @pklingem).
* `minifyStyles` now removes styles based on usage with controlling options (by @lahmatiy).
* New option `except` in `cleanupIDs` to keep IDs (by @Velenir).
* New option `force` in `cleanupIDs` to work even if SVG contains `style` or `script` elements (by @Velenir).
* Fixed arcs transforming with different signed `scale` parameters (by @JoshyPHP).
* Fixed `removeUselessStrokeAndFill` to check for `style` or `script` elements per file (by @caub).
* New option `keepAriaAttrs` in `removeUnknownsAndDefaults` (by @davidtheclark).
* Corrected parsing in `cleanupIDs` to account animation syntax (by @caub).
* `#ff0000` now converts to `red` as well as `#f00` (by @davidleston).
* Added “gray” variation to colors list per CSS Color Module Level 4 (by @ydaniv).
* Fixed error on empty files.
* A separator character in `removeAttrs` now can be changed per `elemSeparator` option (by @mikestreety).
* `addAttributesToSVGElement` now can add values to attributes.
### [ [>](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 attribute.
* 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 declaration 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)
* Transformations 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 transformed 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 with parsing numbers with exponent fraction (could happen with high precision >= 7).
* Fixed rounding error due to incorrect preserving of precision in transformations.
* Fixed shorthand 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

55
assets_old/node_modules/svgo/LICENSE generated vendored Normal file
View file

@ -0,0 +1,55 @@
The MIT License
Copyright © 20122016 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 © 20122016 Кир Белевич
Данная лицензия разрешает лицам, получившим копию данного
программного обеспечения и сопутствующей документации
(в дальнейшем именуемыми «Программное Обеспечение»), безвозмездно
использовать Программное Обеспечение без ограничений, включая
неограниченное право на использование, копирование, изменение,
добавление, публикацию, распространение, сублицензирование
и/или продажу копий Программного Обеспечения, также как и лицам,
которым предоставляется данное Программное Обеспечение,
при соблюдении следующих условий:
Указанное выше уведомление об авторском праве и данные условия
должны быть включены во все копии или значимые части данного
Программного Обеспечения.
ДАННОЕ ПРОГРАММНОЕ ОБЕСПЕЧЕНИЕ ПРЕДОСТАВЛЯЕТСЯ «КАК ЕСТЬ»,
БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ, ЯВНО ВЫРАЖЕННЫХ ИЛИ ПОДРАЗУМЕВАЕМЫХ,
ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИВАЯСЬ ГАРАНТИЯМИ ТОВАРНОЙ ПРИГОДНОСТИ,
СООТВЕТСТВИЯ ПО ЕГО КОНКРЕТНОМУ НАЗНАЧЕНИЮ И ОТСУТСТВИЯ НАРУШЕНИЙ
ПРАВ. НИ В КАКОМ СЛУЧАЕ АВТОРЫ ИЛИ ПРАВООБЛАДАТЕЛИ НЕ НЕСУТ
ОТВЕТСТВЕННОСТИ ПО ИСКАМ О ВОЗМЕЩЕНИИ УЩЕРБА, УБЫТКОВ ИЛИ ДРУГИХ
ТРЕБОВАНИЙ ПО ДЕЙСТВУЮЩИМ КОНТРАКТАМ, ДЕЛИКТАМ ИЛИ ИНОМУ,
ВОЗНИКШИМ ИЗ, ИМЕЮЩИМ ПРИЧИНОЙ ИЛИ СВЯЗАННЫМ С ПРОГРАММНЫМ
ОБЕСПЕЧЕНИЕМ ИЛИ ИСПОЛЬЗОВАНИЕМ ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ
ИЛИ ИНЫМИ ДЕЙСТВИЯМИ С ПРОГРАММНЫМ ОБЕСПЕЧЕНИЕМ.

21
assets_old/node_modules/svgo/Makefile generated vendored Normal file
View file

@ -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: lint test coveralls
lint:
@npm run lint
.PHONY: test

215
assets_old/node_modules/svgo/README.md generated vendored Normal file
View file

@ -0,0 +1,215 @@
**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) [![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 those exported from various editors, usually contain a lot of redundant and useless information. This can include editor metadata, comments, hidden elements, default or non-optimal values and other stuff that can be safely removed or converted without affecting the 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 | Default |
| ------ | ----------- | ------- |
| [cleanupAttrs](https://github.com/svg/svgo/blob/master/plugins/cleanupAttrs.js) | cleanup attributes from newlines, trailing, and repeating spaces | `enabled` |
| [inlineStyles](https://github.com/svg/svgo/blob/master/plugins/inlineStyles.js) | move and merge styles from `<style>` elements to element `style` attributes | `enabled` |
| [removeDoctype](https://github.com/svg/svgo/blob/master/plugins/removeDoctype.js) | remove doctype declaration | `enabled` |
| [removeXMLProcInst](https://github.com/svg/svgo/blob/master/plugins/removeXMLProcInst.js) | remove XML processing instructions | `enabled` |
| [removeComments](https://github.com/svg/svgo/blob/master/plugins/removeComments.js) | remove comments | `enabled` |
| [removeMetadata](https://github.com/svg/svgo/blob/master/plugins/removeMetadata.js) | remove `<metadata>` | `enabled` |
| [removeTitle](https://github.com/svg/svgo/blob/master/plugins/removeTitle.js) | remove `<title>` | `enabled` |
| [removeDesc](https://github.com/svg/svgo/blob/master/plugins/removeDesc.js) | remove `<desc>` | `enabled` |
| [removeUselessDefs](https://github.com/svg/svgo/blob/master/plugins/removeUselessDefs.js) | remove elements of `<defs>` without `id` | `enabled` |
| [removeXMLNS](https://github.com/svg/svgo/blob/master/plugins/removeXMLNS.js) | removes `xmlns` attribute (for inline svg) | `disabled` |
| [removeEditorsNSData](https://github.com/svg/svgo/blob/master/plugins/removeEditorsNSData.js) | remove editors namespaces, elements, and attributes | `enabled` |
| [removeEmptyAttrs](https://github.com/svg/svgo/blob/master/plugins/removeEmptyAttrs.js) | remove empty attributes | `enabled` |
| [removeHiddenElems](https://github.com/svg/svgo/blob/master/plugins/removeHiddenElems.js) | remove hidden elements | `enabled` |
| [removeEmptyText](https://github.com/svg/svgo/blob/master/plugins/removeEmptyText.js) | remove empty Text elements | `enabled` |
| [removeEmptyContainers](https://github.com/svg/svgo/blob/master/plugins/removeEmptyContainers.js) | remove empty Container elements | `enabled` |
| [removeViewBox](https://github.com/svg/svgo/blob/master/plugins/removeViewBox.js) | remove `viewBox` attribute when possible | `enabled` |
| [cleanupEnableBackground](https://github.com/svg/svgo/blob/master/plugins/cleanupEnableBackground.js) | remove or cleanup `enable-background` attribute when possible | `enabled` |
| [minifyStyles](https://github.com/svg/svgo/blob/master/plugins/minifyStyles.js) | minify `<style>` elements content with [CSSO](https://github.com/css/csso) | `enabled` |
| [convertStyleToAttrs](https://github.com/svg/svgo/blob/master/plugins/convertStyleToAttrs.js) | convert styles into attributes | `enabled` |
| [convertColors](https://github.com/svg/svgo/blob/master/plugins/convertColors.js) | convert colors (from `rgb()` to `#rrggbb`, from `#rrggbb` to `#rgb`) | `enabled` |
| [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 | `enabled` |
| [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 | `enabled` |
| [removeUnknownsAndDefaults](https://github.com/svg/svgo/blob/master/plugins/removeUnknownsAndDefaults.js) | remove unknown elements content and attributes, remove attrs with default values | `enabled` |
| [removeNonInheritableGroupAttrs](https://github.com/svg/svgo/blob/master/plugins/removeNonInheritableGroupAttrs.js) | remove non-inheritable group's "presentation" attributes | `enabled` |
| [removeUselessStrokeAndFill](https://github.com/svg/svgo/blob/master/plugins/removeUselessStrokeAndFill.js) | remove useless `stroke` and `fill` attrs | `enabled` |
| [removeUnusedNS](https://github.com/svg/svgo/blob/master/plugins/removeUnusedNS.js) | remove unused namespaces declaration | `enabled` |
| [prefixIds](https://github.com/svg/svgo/blob/master/plugins/prefixIds.js) | prefix IDs and classes with the SVG filename or an arbitrary string | `disabled` |
| [cleanupIDs](https://github.com/svg/svgo/blob/master/plugins/cleanupIDs.js) | remove unused and minify used IDs | `enabled` |
| [cleanupNumericValues](https://github.com/svg/svgo/blob/master/plugins/cleanupNumericValues.js) | round numeric values to the fixed precision, remove default `px` units | `enabled` |
| [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 `enable-background`) | `disabled` |
| [moveElemsAttrsToGroup](https://github.com/svg/svgo/blob/master/plugins/moveElemsAttrsToGroup.js) | move elements' attributes to their enclosing group | `enabled` |
| [moveGroupAttrsToElems](https://github.com/svg/svgo/blob/master/plugins/moveGroupAttrsToElems.js) | move some group attributes to the contained elements | `enabled` |
| [collapseGroups](https://github.com/svg/svgo/blob/master/plugins/collapseGroups.js) | collapse useless groups | `enabled` |
| [removeRasterImages](https://github.com/svg/svgo/blob/master/plugins/removeRasterImages.js) | remove raster images | `disabled` |
| [mergePaths](https://github.com/svg/svgo/blob/master/plugins/mergePaths.js) | merge multiple Paths into one | `enabled` |
| [convertShapeToPath](https://github.com/svg/svgo/blob/master/plugins/convertShapeToPath.js) | convert some basic shapes to `<path>` | `enabled` |
| [convertEllipseToCircle](https://github.com/svg/svgo/blob/master/plugins/convertEllipseToCircle.js) | convert non-eccentric `<ellipse>` to `<circle>` | `enabled` |
| [sortAttrs](https://github.com/svg/svgo/blob/master/plugins/sortAttrs.js) | sort element attributes for epic readability | `disabled` |
| [sortDefsChildren](https://github.com/svg/svgo/blob/master/plugins/sortDefsChildren.js) | sort children of `<defs>` in order to improve compression | `enabled` |
| [removeDimensions](https://github.com/svg/svgo/blob/master/plugins/removeDimensions.js) | remove `width`/`height` and add `viewBox` if it's missing (opposite to removeViewBox, disable it first) | `disabled` |
| [removeAttrs](https://github.com/svg/svgo/blob/master/plugins/removeAttrs.js) | remove attributes by pattern | `disabled` |
| [removeAttributesBySelector](https://github.com/svg/svgo/blob/master/plugins/removeAttributesBySelector.js) | removes attributes of elements that match a css selector | `disabled` |
| [removeElementsByAttr](https://github.com/svg/svgo/blob/master/plugins/removeElementsByAttr.js) | remove arbitrary elements by ID or className | `disabled` |
| [addClassesToSVGElement](https://github.com/svg/svgo/blob/master/plugins/addClassesToSVGElement.js) | add classnames to an outer `<svg>` element | `disabled` |
| [addAttributesToSVGElement](https://github.com/svg/svgo/blob/master/plugins/addAttributesToSVGElement.js) | adds attributes to an outer `<svg>` element | `disabled` |
| [removeOffCanvasPaths](https://github.com/svg/svgo/blob/master/plugins/removeOffCanvasPaths.js) | removes elements that are drawn outside of the viewbox | `disabled` |
| [removeStyleElement](https://github.com/svg/svgo/blob/master/plugins/removeStyleElement.js) | remove `<style>` elements | `disabled` |
| [removeScriptElement](https://github.com/svg/svgo/blob/master/plugins/removeScriptElement.js) | remove `<script>` elements | `disabled` |
| [reusePaths](https://github.com/svg/svgo/blob/master/plugins/reusePaths.js) | Find duplicated <path> elements and replace them with <use> links | `disabled` |
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))
## Installation
```sh
$ [sudo] npm install -g svgo
```
## Usage
### <abbr title="Command Line Interface">CLI</abbr>
```
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=PLUGIN : Disable plugin by name, "--disable=PLUGIN1,PLUGIN2" for multiple plugins
--enable=PLUGIN : Enable plugin by name, "--enable=PLUGIN3,PLUGIN4" for multiple plugins
--datauri=DATAURI : Output as Data URI string (base64, URI encoded or unencoded)
--multipass : Pass over SVGs multiple times to ensure all optimizations are applied
--pretty : Make SVG pretty printed
--indent=INDENT : Indent number when pretty printing SVGs
-r, --recursive : Use with '-f'. Optimizes *.svg files in folders recursively.
-q, --quiet : Only output error messages, not regular status messages
--show-plugins : Show available plugins and exit
Arguments:
INPUT : Alias to --input
```
* with files:
```sh
$ svgo test.svg
```
or:
```sh
$ svgo *.svg
```
```sh
$ svgo test.svg -o test.min.svg
```
```sh
$ svgo test.svg other.svg third.svg
```
```sh
$ svgo test.svg other.svg third.svg -o test.min.svg -o other.min.svg -o third.min.svg
```
* with STDIN / STDOUT:
```sh
$ cat test.svg | svgo -i - -o - > test.min.svg
```
* with folder
```sh
$ svgo -f ../path/to/folder/with/svg/files
```
or:
```sh
$ svgo -f ../path/to/folder/with/svg/files -o ../path/to/folder/with/svg/output
```
```sh
$ svgo *.svg -o ../path/to/folder/with/svg/output
```
* with strings:
```sh
$ svgo -s '<svg version="1.1">test</svg>' -o test.min.svg
```
or even with Data URI base64:
```sh
$ svgo -s 'data:image/svg+xml;base64,...' -o test.min.svg
```
* with SVGZ:
from `.svgz` to `.svg`:
```sh
$ gunzip -c test.svgz | svgo -i - -o test.min.svg
```
from `.svg` to `.svgz`:
```sh
$ svgo test.svg -o - | gzip -cfq9 > test.svgz
```
### Other Ways to Use SVGO
* 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)
* as an Inkscape plugin [inkscape-svgo](https://github.com/konsumer/inkscape-svgo)
* as a Sketch plugin - [svgo-compressor](https://github.com/BohemianCoding/svgo-compressor)
* as macOS app - [Image Shrinker](https://image-shrinker.com)
* as a Rollup plugin - [rollup-plugin-svgo](https://github.com/porsager/rollup-plugin-svgo)
## Backers
| [<img src="https://sheetjs.com/sketch128.png" width="80">](https://sheetjs.com/) | [<img src="https://rawgithub.com/fontello/fontello/master/fontello-image.svg" width="80">](http://fontello.com/) |
|:-:|:-:|
| [SheetJS LLC](https://sheetjs.com/) | [Fontello](http://fontello.com/) |
## Donations
- PayPal: https://www.paypal.me/deepsweet
## License and Copyright
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/).

205
assets_old/node_modules/svgo/README.ru.md generated vendored Normal file
View file

@ -0,0 +1,205 @@
[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) [![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 | Default |
| ------ | ----------- | ------- |
| [cleanupAttrs](https://github.com/svg/svgo/blob/master/plugins/cleanupAttrs.js) | удаление переносов строк и лишних пробелов | `включен` |
| [inlineStyles](https://github.com/svg/svgo/blob/master/plugins/inlineStyles.js) | перенос стилей из элементов `<style>` в атрибуты `style` | `включен` |
| [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) | удаление деклараций неиспользуемых пространств имён | `включен` |
| [prefixIds](https://github.com/svg/svgo/blob/master/plugins/prefixIds.js) | добавляет префикс в ID или классы в виде имени файла или произвольной строки | `выключено` |
| [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>` | `включен` |
| [removeRasterImages](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 | `включен` |
| [convertEllipseToCircle](https://github.com/svg/svgo/blob/master/plugins/convertEllipseToCircle.js) | конвертирование вырожденного эллипса `<ellipse>` в круг `<circle>` | `включен` |
| [sortAttrs](https://github.com/svg/svgo/blob/master/plugins/sortAttrs.js) | сортировка атрибутов элементов для удобочитаемости | `выключено` |
| [sortDefsChildren](https://github.com/svg/svgo/blob/master/plugins/sortDefsChildren.js) | сортировка детей `<defs>` для лучшей компрессии | `включен` |
| [removeDimensions](https://github.com/svg/svgo/blob/master/plugins/removeDimensions.js) | удаляет атрибуты width/height при наличии viewBox (противоречит removeViewBox  плагин должен быть выключен) | `выключено` |
| [removeAttrs](https://github.com/svg/svgo/blob/master/plugins/removeAttrs.js) | удаляет атрибуты по указанному паттерну | `выключено` |
| [removeAttributesBySelector](https://github.com/svg/svgo/blob/master/plugins/removeAttributesBySelector.js) | удаляет атрибуты по CSS-селектору | `выключено` |
| [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>` | `выключено` |
| [removeOffCanvasPaths](https://github.com/svg/svgo/blob/master/plugins/removeOffCanvasPaths.js) | удаляет элементы вне отрисовываемой области | `выключено` |
| [removeStyleElement](https://github.com/svg/svgo/blob/master/plugins/removeStyleElement.js) | удаляет элементы `<style>` | `выключено` |
| [removeScriptElement](https://github.com/svg/svgo/blob/master/plugins/removeScriptElement.js) | удаляет элементы `<script>` | `выключено` |
| [reusePaths](https://github.com/svg/svgo/blob/master/plugins/reusePaths.js) | Заменяет дублирующиеся элементы <path> ссылками <use> | `выключено` |
Хотите узнать принципы работы и как написать свой плагин? [Конечно же, да!](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=PLUGIN : Выключение плагина по имени, "--disable=PLUGIN1,PLUGIN2" для отключения нескольких плагинов
--enable=PLUGIN : Включение плагина по имени, "--enable=PLUGIN3,PLUGIN4" для отключения нескольких плагинов
--datauri=DATAURI : Результат в виде строки Data URI (base64, URI encoded или unencoded)
--multipass : Оптимизация в несколько проходов для применения всех возможных оптимизаций
--pretty : Удобочитаемое форматирование SVG
--indent=INDENT : Размер отступа для удобочитаемого форматирования
-r, --recursive : Совместно с '-f'. Рекурсивно обрабатывать *.svg файлы в папках.
-q, --quiet : Подавляет вывод информации, выводятся только сообщения об ошибках
--show-plugins : Доступные плагины
Аргументы:
INPUT : Аналогично --input
```
* с файлами:
```sh
$ svgo test.svg
```
или:
```sh
$ svgo *.svg
```
```sh
$ svgo test.svg -o test.min.svg
```
```sh
$ svgo test.svg other.svg third.svg
```
```sh
$ svgo test.svg other.svg third.svg -o test.min.svg -o other.min.svg -o third.min.svg
```
* со STDIN / STDOUT:
```sh
$ cat test.svg | svgo -i - -o - > test.min.svg
```
* с папками
```sh
$ svgo -f ../path/to/folder/with/svg/files
```
или:
```sh
$ svgo -f ../path/to/folder/with/svg/files -o ../path/to/folder/with/svg/output
```
```sh
$ svgo *.svg -o ../path/to/folder/with/svg/output
```
* со строками:
```sh
$ svgo -s '<svg version="1.1">test</svg>' -o test.min.svg
```
или даже с Data URI base64:
```sh
$ svgo -s 'data:image/svg+xml;base64,…' -o test.min.svg
```
* с SVGZ:
из `.svgz` в `.svg`:
```sh
$ gunzip -c test.svgz | svgo -i - -o test.min.svg
```
из `.svg` в `.svgz`:
```sh
$ svgo test.svg -o - | gzip -cfq9 > test.svgz
```
### Другие способы использования SVGO
* в виде веб-приложения - [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)
* как плагин для Inkscape [inkscape-svgo](https://github.com/konsumer/inkscape-svgo)
* как плагин для Sketch - [svgo-compressor](https://github.com/BohemianCoding/svgo-compressor)
* в виде приложения macOS - [Image Shrinker](https://image-shrinker.com)
* как плагин для Rollup - [rollup-plugin-svgo](https://github.com/porsager/rollup-plugin-svgo)
## Лицензия и копирайты
Данное программное обеспечение выпускается под [лицензией MIT](https://github.com/svg/svgo/blob/master/LICENSE).
Логотип [Егор Большаков](http://xizzzy.ru/).

3
assets_old/node_modules/svgo/bin/svgo generated vendored Executable file
View file

@ -0,0 +1,3 @@
#!/usr/bin/env node
require('../lib/svgo/coa').run();

222
assets_old/node_modules/svgo/lib/css-tools.js generated vendored Normal file
View file

@ -0,0 +1,222 @@
'use strict';
var csstree = require('css-tree'),
List = csstree.List,
stable = require('stable'),
specificity = require('csso/lib/restructure/prepare/specificity');
/**
* Flatten a CSS AST to a selectors list.
*
* @param {Object} cssAst css-tree AST to flatten
* @return {Array} selectors
*/
function flattenToSelectors(cssAst) {
var selectors = [];
csstree.walk(cssAst, {visit: 'Rule', enter: function(node) {
if (node.type !== 'Rule') {
return;
}
var atrule = this.atrule;
var rule = node;
node.prelude.children.each(function(selectorNode, selectorItem) {
var selector = {
item: selectorItem,
atrule: atrule,
rule: rule,
pseudos: []
};
selectorNode.children.each(function(selectorChildNode, selectorChildItem, selectorChildList) {
if (selectorChildNode.type === 'PseudoClassSelector' ||
selectorChildNode.type === 'PseudoElementSelector') {
selector.pseudos.push({
item: selectorChildItem,
list: selectorChildList
});
}
});
selectors.push(selector);
});
}});
return selectors;
}
/**
* Filter selectors by Media Query.
*
* @param {Array} selectors to filter
* @param {Array} useMqs Array with strings of media queries that should pass (<name> <expression>)
* @return {Array} Filtered selectors that match the passed media queries
*/
function filterByMqs(selectors, useMqs) {
return selectors.filter(function(selector) {
if (selector.atrule === null) {
return ~useMqs.indexOf('');
}
var mqName = selector.atrule.name;
var mqStr = mqName;
if (selector.atrule.expression &&
selector.atrule.expression.children.first().type === 'MediaQueryList') {
var mqExpr = csstree.generate(selector.atrule.expression);
mqStr = [mqName, mqExpr].join(' ');
}
return ~useMqs.indexOf(mqStr);
});
}
/**
* Filter selectors by the pseudo-elements and/or -classes they contain.
*
* @param {Array} selectors to filter
* @param {Array} usePseudos Array with strings of single or sequence of pseudo-elements and/or -classes that should pass
* @return {Array} Filtered selectors that match the passed pseudo-elements and/or -classes
*/
function filterByPseudos(selectors, usePseudos) {
return selectors.filter(function(selector) {
var pseudoSelectorsStr = csstree.generate({
type: 'Selector',
children: new List().fromArray(selector.pseudos.map(function(pseudo) {
return pseudo.item.data;
}))
});
return ~usePseudos.indexOf(pseudoSelectorsStr);
});
}
/**
* Remove pseudo-elements and/or -classes from the selectors for proper matching.
*
* @param {Array} selectors to clean
* @return {Array} Selectors without pseudo-elements and/or -classes
*/
function cleanPseudos(selectors) {
selectors.forEach(function(selector) {
selector.pseudos.forEach(function(pseudo) {
pseudo.list.remove(pseudo.item);
});
});
}
/**
* Compares two selector specificities.
* extracted from https://github.com/keeganstreet/specificity/blob/master/specificity.js#L211
*
* @param {Array} aSpecificity Specificity of selector A
* @param {Array} bSpecificity Specificity of selector B
* @return {Number} Score of selector specificity A compared to selector specificity B
*/
function compareSpecificity(aSpecificity, bSpecificity) {
for (var i = 0; i < 4; i += 1) {
if (aSpecificity[i] < bSpecificity[i]) {
return -1;
} else if (aSpecificity[i] > bSpecificity[i]) {
return 1;
}
}
return 0;
}
/**
* Compare two simple selectors.
*
* @param {Object} aSimpleSelectorNode Simple selector A
* @param {Object} bSimpleSelectorNode Simple selector B
* @return {Number} Score of selector A compared to selector B
*/
function compareSimpleSelectorNode(aSimpleSelectorNode, bSimpleSelectorNode) {
var aSpecificity = specificity(aSimpleSelectorNode),
bSpecificity = specificity(bSimpleSelectorNode);
return compareSpecificity(aSpecificity, bSpecificity);
}
function _bySelectorSpecificity(selectorA, selectorB) {
return compareSimpleSelectorNode(selectorA.item.data, selectorB.item.data);
}
/**
* Sort selectors stably by their specificity.
*
* @param {Array} selectors to be sorted
* @return {Array} Stable sorted selectors
*/
function sortSelectors(selectors) {
return stable(selectors, _bySelectorSpecificity);
}
/**
* Convert a css-tree AST style declaration to CSSStyleDeclaration property.
*
* @param {Object} declaration css-tree style declaration
* @return {Object} CSSStyleDeclaration property
*/
function csstreeToStyleDeclaration(declaration) {
var propertyName = declaration.property,
propertyValue = csstree.generate(declaration.value),
propertyPriority = (declaration.important ? 'important' : '');
return {
name: propertyName,
value: propertyValue,
priority: propertyPriority
};
}
/**
* Gets the CSS string of a style element
*
* @param {Object} element style element
* @return {String|Array} CSS string or empty array if no styles are set
*/
function getCssStr(elem) {
return elem.content[0].text || elem.content[0].cdata || [];
}
/**
* Sets the CSS string of a style element
*
* @param {Object} element style element
* @param {String} CSS string to be set
* @return {Object} reference to field with CSS
*/
function setCssStr(elem, css) {
// in case of cdata field
if(elem.content[0].cdata) {
elem.content[0].cdata = css;
return elem.content[0].cdata;
}
// in case of text field + if nothing was set yet
elem.content[0].text = css;
return elem.content[0].text;
}
module.exports.flattenToSelectors = flattenToSelectors;
module.exports.filterByMqs = filterByMqs;
module.exports.filterByPseudos = filterByPseudos;
module.exports.cleanPseudos = cleanPseudos;
module.exports.compareSpecificity = compareSpecificity;
module.exports.compareSimpleSelectorNode = compareSimpleSelectorNode;
module.exports.sortSelectors = sortSelectors;
module.exports.csstreeToStyleDeclaration = csstreeToStyleDeclaration;
module.exports.getCssStr = getCssStr;
module.exports.setCssStr = setCssStr;

90
assets_old/node_modules/svgo/lib/svgo.js generated vendored Executable file
View file

@ -0,0 +1,90 @@
'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'),
encodeSVGDatauri = require('./svgo/tools.js').encodeSVGDatauri,
JS2SVG = require('./svgo/js2svg.js');
var SVGO = function(config) {
this.config = CONFIG(config);
};
SVGO.prototype.optimize = function(svgstr, info) {
info = info || {};
return new Promise((resolve, reject) => {
if (this.config.error) {
reject(this.config.error);
return;
}
var config = this.config,
maxPassCount = config.multipass ? 10 : 1,
counter = 0,
prevResultSize = Number.POSITIVE_INFINITY,
optimizeOnceCallback = (svgjs) => {
if (svgjs.error) {
reject(svgjs.error);
return;
}
info.multipassCount = counter;
if (++counter < maxPassCount && svgjs.data.length < prevResultSize) {
prevResultSize = svgjs.data.length;
this._optimizeOnce(svgjs.data, info, optimizeOnceCallback);
} else {
if (config.datauri) {
svgjs.data = encodeSVGDatauri(svgjs.data, config.datauri);
}
if (info && info.path) {
svgjs.path = info.path;
}
resolve(svgjs);
}
};
this._optimizeOnce(svgstr, info, optimizeOnceCallback);
});
};
SVGO.prototype._optimizeOnce = function(svgstr, info, callback) {
var config = this.config;
SVG2JS(svgstr, function(svgjs) {
if (svgjs.error) {
callback(svgjs);
return;
}
svgjs = PLUGINS(svgjs, info, 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);
};
SVGO.Config = CONFIG;
module.exports = SVGO;
// Offer ES module interop compatibility.
module.exports.default = SVGO;

579
assets_old/node_modules/svgo/lib/svgo/coa.js generated vendored Normal file
View file

@ -0,0 +1,579 @@
/* jshint quotmark: false */
'use strict';
var FS = require('fs'),
PATH = require('path'),
chalk = require('chalk'),
mkdirp = require('mkdirp'),
promisify = require('util.promisify'),
readdir = promisify(FS.readdir),
readFile = promisify(FS.readFile),
writeFile = promisify(FS.writeFile),
SVGO = require('../svgo.js'),
YAML = require('js-yaml'),
PKG = require('../../package.json'),
encodeSVGDatauri = require('./tools.js').encodeSVGDatauri,
decodeSVGDatauri = require('./tools.js').decodeSVGDatauri,
checkIsDir = require('./tools.js').checkIsDir,
regSVGFile = /\.svg$/,
noop = () => {},
svgo;
/**
* 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')
.arr()
.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')
.arr()
.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, "--disable={PLUGIN1,PLUGIN2}" for multiple plugins (*nix)')
.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, "--enable={PLUGIN3,PLUGIN4}" for multiple plugins (*nix)')
.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('Pass over SVGs multiple times to ensure all optimizations are applied')
.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('recursive').title('Use with \'-f\'. Optimizes *.svg files in folders recursively.')
.short('r').long('recursive')
.flag()
.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')
.arr()
.end()
.act(function(opts, args) {
var input = opts.input || args.input,
output = opts.output,
config = {};
// --show-plugins
if (opts['show-plugins']) {
showAvailablePlugins();
return;
}
// w/o anything
if (
(!input || input[0] === '-') &&
!opts.string &&
!opts.stdin &&
!opts.folder &&
process.stdin.isTTY === true
) return this.usage();
if (typeof process == 'object' && process.versions && process.versions.node && PKG && PKG.engines.node) {
var nodeVersion = String(PKG.engines.node).match(/\d*(\.\d+)*/)[0];
if (parseFloat(process.versions.node) < parseFloat(nodeVersion)) {
return printErrorAndExit(`Error: ${PKG.name} requires Node.js version ${nodeVersion} or higher.`);
}
}
// --config
if (opts.config) {
// string
if (opts.config.charAt(0) === '{') {
try {
config = JSON.parse(opts.config);
} catch (e) {
return printErrorAndExit(`Error: Couldn't parse config JSON.\n${String(e)}`);
}
// external file
} else {
var configPath = PATH.resolve(opts.config),
configData;
try {
// require() adds some weird output on YML files
configData = FS.readFileSync(configPath, 'utf8');
config = JSON.parse(configData);
} catch (err) {
if (err.code === 'ENOENT') {
return printErrorAndExit(`Error: couldn't find config file '${opts.config}'.`);
} else if (err.code === 'EISDIR') {
return printErrorAndExit(`Error: directory '${opts.config}' is not a config file.`);
}
config = YAML.safeLoad(configData);
config.__DIR = PATH.dirname(configPath); // will use it to resolve custom plugins defined via path
if (!config || Array.isArray(config)) {
return printErrorAndExit(`Error: invalid config file '${opts.config}'.`);
}
}
}
}
// --quiet
if (opts.quiet) {
config.quiet = opts.quiet;
}
// --recursive
if (opts.recursive) {
config.recursive = opts.recursive;
}
// --precision
if (opts.precision) {
var precision = Math.min(Math.max(0, parseInt(opts.precision)), 20);
if (!isNaN(precision)) {
config.floatPrecision = 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;
var indent;
if (opts.indent && !isNaN(indent = parseInt(opts.indent))) {
config.js2svg.indent = indent;
}
}
svgo = new SVGO(config);
// --output
if (output) {
if (input && input[0] != '-') {
if (output.length == 1 && checkIsDir(output[0])) {
var dir = output[0];
for (var i = 0; i < input.length; i++) {
output[i] = checkIsDir(input[i]) ? input[i] : PATH.resolve(dir, PATH.basename(input[i]));
}
} else if (output.length < input.length) {
output = output.concat(input.slice(output.length));
}
}
} else if (input) {
output = input;
} else if (opts.string) {
output = '-';
}
if (opts.datauri) {
config.datauri = opts.datauri;
}
// --folder
if (opts.folder) {
var ouputFolder = output && output[0] || opts.folder;
return optimizeFolder(config, opts.folder, ouputFolder).then(noop, printErrorAndExit);
}
// --input
if (input) {
// STDIN
if (input[0] === '-') {
return new Promise((resolve, reject) => {
var data = '',
file = output[0];
process.stdin
.on('data', chunk => data += chunk)
.once('end', () => processSVGData(config, {input: 'string'}, data, file).then(resolve, reject));
});
// file
} else {
return Promise.all(input.map((file, n) => optimizeFile(config, file, output[n])))
.then(noop, printErrorAndExit);
}
// --string
} else if (opts.string) {
var data = decodeSVGDatauri(opts.string);
return processSVGData(config, {input: 'string'}, data, output[0]);
}
});
/**
* 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) {
names.forEach(flattenPluginsCbk);
// extend config
if (config.plugins) {
for (var name of names) {
var matched = false,
key;
for (var plugin of config.plugins) {
// 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) {
// push new plugin Object
config.plugins.push({ [name]: state });
matched = true;
}
}
// just push
} else {
config.plugins = names.map(name => ({ [name]: state }));
}
return config;
}
/**
* Flatten an array of plugins by invoking this callback on each element
* whose value may be a comma separated list of plugins.
*
* @param {String} name Plugin name
* @param {Number} index Plugin index
* @param {Array} names Plugins being traversed
*/
function flattenPluginsCbk(name, index, names)
{
var split = name.split(',');
if(split.length > 1) {
names[index] = split.shift();
names.push.apply(names, split);
}
}
/**
* Optimize SVG files in a directory.
* @param {Object} config options
* @param {string} dir input directory
* @param {string} output output directory
* @return {Promise}
*/
function optimizeFolder(config, dir, output) {
if (!config.quiet) {
console.log(`Processing directory '${dir}':\n`);
}
return readdir(dir).then(files => processDirectory(config, dir, files, output));
}
/**
* Process given files, take only SVG.
* @param {Object} config options
* @param {string} dir input directory
* @param {Array} files list of file names in the directory
* @param {string} output output directory
* @return {Promise}
*/
function processDirectory(config, dir, files, output) {
// take only *.svg files, recursively if necessary
var svgFilesDescriptions = getFilesDescriptions(config, dir, files, output);
return svgFilesDescriptions.length ?
Promise.all(svgFilesDescriptions.map(fileDescription => optimizeFile(config, fileDescription.inputPath, fileDescription.outputPath))) :
Promise.reject(new Error(`No SVG files have been found in '${dir}' directory.`));
}
/**
* Get svg files descriptions
* @param {Object} config options
* @param {string} dir input directory
* @param {Array} files list of file names in the directory
* @param {string} output output directory
* @return {Array}
*/
function getFilesDescriptions(config, dir, files, output) {
const filesInThisFolder = files
.filter(name => regSVGFile.test(name))
.map(name => ({
inputPath: PATH.resolve(dir, name),
outputPath: PATH.resolve(output, name),
}));
return config.recursive ?
[].concat(
filesInThisFolder,
files
.filter(name => checkIsDir(PATH.resolve(dir, name)))
.map(subFolderName => {
const subFolderPath = PATH.resolve(dir, subFolderName);
const subFolderFiles = FS.readdirSync(subFolderPath);
const subFolderOutput = PATH.resolve(output, subFolderName);
return getFilesDescriptions(config, subFolderPath, subFolderFiles, subFolderOutput);
})
.reduce((a, b) => [].concat(a, b), [])
) :
filesInThisFolder;
}
/**
* Read SVG file and pass to processing.
* @param {Object} config options
* @param {string} file
* @param {string} output
* @return {Promise}
*/
function optimizeFile(config, file, output) {
return readFile(file, 'utf8').then(
data => processSVGData(config, {input: 'file', path: file}, data, output, file),
error => checkOptimizeFileError(config, file, output, error)
);
}
/**
* Optimize SVG data.
* @param {Object} config options
* @param {string} data SVG content to optimize
* @param {string} output where to write optimized file
* @param {string} [input] input file name (being used if output is a directory)
* @return {Promise}
*/
function processSVGData(config, info, data, output, input) {
var startTime = Date.now(),
prevFileSize = Buffer.byteLength(data, 'utf8');
return svgo.optimize(data, info).then(function(result) {
if (config.datauri) {
result.data = encodeSVGDatauri(result.data, config.datauri);
}
var resultFileSize = Buffer.byteLength(result.data, 'utf8'),
processingTime = Date.now() - startTime;
return writeOutput(input, output, result.data).then(function() {
if (!config.quiet && output != '-') {
if (input) {
console.log(`\n${PATH.basename(input)}:`);
}
printTimeInfo(processingTime);
printProfitInfo(prevFileSize, resultFileSize);
}
},
error => Promise.reject(new Error(error.code === 'ENOTDIR' ? `Error: output '${output}' is not a directory.` : error)));
});
}
/**
* Write result of an optimization.
* @param {string} input
* @param {string} output output file name. '-' for stdout
* @param {string} data data to write
* @return {Promise}
*/
function writeOutput(input, output, data) {
if (output == '-') {
console.log(data);
return Promise.resolve();
}
mkdirp.sync(PATH.dirname(output));
return writeFile(output, data, 'utf8').catch(error => checkWriteFileError(input, output, data, error));
}
/**
* Write a time taken by optimization.
* @param {number} time time in milliseconds.
*/
function printTimeInfo(time) {
console.log(`Done in ${time} ms!`);
}
/**
* Write optimizing information in human readable format.
* @param {number} inBytes size before optimization.
* @param {number} outBytes size after optimization.
*/
function printProfitInfo(inBytes, outBytes) {
var profitPercents = 100 - outBytes * 100 / inBytes;
console.log(
(Math.round((inBytes / 1024) * 1000) / 1000) + ' KiB' +
(profitPercents < 0 ? ' + ' : ' - ') +
chalk.green(Math.abs((Math.round(profitPercents * 10) / 10)) + '%') + ' = ' +
(Math.round((outBytes / 1024) * 1000) / 1000) + ' KiB'
);
}
/**
* Check for errors, if it's a dir optimize the dir.
* @param {Object} config
* @param {string} input
* @param {string} output
* @param {Error} error
* @return {Promise}
*/
function checkOptimizeFileError(config, input, output, error) {
if (error.code == 'EISDIR') {
return optimizeFolder(config, input, output);
} else if (error.code == 'ENOENT') {
return Promise.reject(new Error(`Error: no such file or directory '${error.path}'.`));
}
return Promise.reject(error);
}
/**
* Check for saving file error. If the output is a dir, then write file there.
* @param {string} input
* @param {string} output
* @param {string} data
* @param {Error} error
* @return {Promise}
*/
function checkWriteFileError(input, output, data, error) {
if (error.code == 'EISDIR' && input) {
return writeFile(PATH.resolve(output, PATH.basename(input)), data, 'utf8');
} else {
return Promise.reject(error);
}
}
/**
* Show list of available plugins with short description.
*/
function showAvailablePlugins() {
console.log('Currently available plugins:');
// Flatten an array of plugins grouped per type, sort and write output
var list = [].concat.apply([], new SVGO().config.plugins)
.sort((a, b) => a.name.localeCompare(b.name))
.map(plugin => ` [ ${chalk.green(plugin.name)} ] ${plugin.description}`)
.join('\n');
console.log(list);
}
/**
* Write an error and exit.
* @param {Error} error
* @return {Promise} a promise for running tests
*/
function printErrorAndExit(error) {
console.error(chalk.red(error));
process.exit(1);
return Promise.reject(error); // for tests
}

250
assets_old/node_modules/svgo/lib/svgo/config.js generated vendored Normal file
View file

@ -0,0 +1,250 @@
'use strict';
var FS = require('fs');
var PATH = require('path');
var yaml = require('js-yaml');
/**
* 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(config, defaults.plugins);
}
} else {
defaults = Object.assign({}, yaml.safeLoad(FS.readFileSync(__dirname + '/../../.svgo.yml', 'utf8')));
defaults.plugins = preparePluginsArray(config, 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 = Object.assign({}, plugin.params, { floatPrecision: config.floatPrecision });
}
});
}
if ('datauri' in config) {
defaults.datauri = config.datauri;
}
if (Array.isArray(defaults.plugins)) {
defaults.plugins = optimizePluginsArray(defaults.plugins);
}
return defaults;
};
/**
* Require() all plugins in array.
*
* @param {Object} config
* @param {Array} plugins input plugins array
* @return {Array} input plugins array of arrays
*/
function preparePluginsArray(config, 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 = setPluginActiveState(
loadPlugin(config, key, item[key].path),
item,
key
);
plugin.name = key;
}
// name
} else {
plugin = loadPlugin(config, item);
plugin.name = item;
if (typeof plugin.params === 'object') {
plugin.params = Object.assign({}, plugin.params);
}
}
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];
if (item[key] == null) {
console.error(`Error: '${key}' plugin is misconfigured! Have you padded its content in YML properly?\n`);
}
// custom
if (typeof item[key] === 'object' && item[key].fn && typeof item[key].fn === 'function') {
defaults.plugins.push(setupCustomPlugin(key, item[key]));
// plugin defined via path
} else if (typeof item[key] === 'object' && item[key].path) {
defaults.plugins.push(setPluginActiveState(loadPlugin(config, undefined, item[key].path), item, key));
} else {
defaults.plugins.forEach(function(plugin) {
if (plugin.name === key) {
plugin = setPluginActiveState(plugin, item, key);
}
});
}
}
});
}
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 = Object.assign({}, 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;
}, []);
}
/**
* Sets plugin to active or inactive state.
*
* @param {Object} plugin
* @param {Object} item
* @param {Object} key
* @return {Object} plugin
*/
function setPluginActiveState(plugin, item, key) {
// name: {}
if (typeof item[key] === 'object') {
plugin.params = Object.assign({}, 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;
}
return plugin;
}
/**
* Loads default plugin using name or custom plugin defined via path in config.
*
* @param {Object} config
* @param {Object} name
* @param {Object} path
* @return {Object} plugin
*/
function loadPlugin(config, name, path) {
var plugin;
if (!path) {
plugin = require('../../plugins/' + name);
} else {
plugin = require(PATH.resolve(config.__DIR, path));
}
return Object.assign({}, plugin);
}

138
assets_old/node_modules/svgo/lib/svgo/css-class-list.js generated vendored Normal file
View file

@ -0,0 +1,138 @@
'use strict';
var values = require('object.values');
if (!Object.values) {
values.shim();
}
var CSSClassList = function(node) {
this.parentNode = node;
this.classNames = new Set();
this.classAttr = null;
//this.classValue = null;
};
/**
* Performs a deep clone of this object.
*
* @param parentNode the parentNode to assign to the cloned result
*/
CSSClassList.prototype.clone = function(parentNode) {
var node = this;
var nodeData = {};
Object.keys(node).forEach(function(key) {
if (key !== 'parentNode') {
nodeData[key] = node[key];
}
});
// Deep-clone node data.
nodeData = JSON.parse(JSON.stringify(nodeData));
var clone = new CSSClassList(parentNode);
Object.assign(clone, nodeData);
return clone;
};
CSSClassList.prototype.hasClass = function() {
this.classAttr = { // empty class attr
'name': 'class',
'value': null
};
this.addClassHandler();
};
// attr.class
CSSClassList.prototype.addClassHandler = function() {
Object.defineProperty(this.parentNode.attrs, 'class', {
get: this.getClassAttr.bind(this),
set: this.setClassAttr.bind(this),
enumerable: true,
configurable: true
});
this.addClassValueHandler();
};
// attr.class.value
CSSClassList.prototype.addClassValueHandler = function() {
Object.defineProperty(this.classAttr, 'value', {
get: this.getClassValue.bind(this),
set: this.setClassValue.bind(this),
enumerable: true,
configurable: true
});
};
CSSClassList.prototype.getClassAttr = function() {
return this.classAttr;
};
CSSClassList.prototype.setClassAttr = function(newClassAttr) {
this.setClassValue(newClassAttr.value); // must before applying value handler!
this.classAttr = newClassAttr;
this.addClassValueHandler();
};
CSSClassList.prototype.getClassValue = function() {
var arrClassNames = Array.from(this.classNames);
return arrClassNames.join(' ');
};
CSSClassList.prototype.setClassValue = function(newValue) {
if(typeof newValue === 'undefined') {
this.classNames.clear();
return;
}
var arrClassNames = newValue.split(' ');
this.classNames = new Set(arrClassNames);
};
CSSClassList.prototype.add = function(/* variadic */) {
this.hasClass();
Object.values(arguments).forEach(this._addSingle.bind(this));
};
CSSClassList.prototype._addSingle = function(className) {
this.classNames.add(className);
};
CSSClassList.prototype.remove = function(/* variadic */) {
this.hasClass();
Object.values(arguments).forEach(this._removeSingle.bind(this));
};
CSSClassList.prototype._removeSingle = function(className) {
this.classNames.delete(className);
};
CSSClassList.prototype.item = function(index) {
var arrClassNames = Array.from(this.classNames);
return arrClassNames[index];
};
CSSClassList.prototype.toggle = function(className, force) {
if(this.contains(className) || force === false) {
this.classNames.delete(className);
}
this.classNames.add(className);
};
CSSClassList.prototype.contains = function(className) {
return this.classNames.has(className);
};
module.exports = CSSClassList;

View file

@ -0,0 +1,53 @@
'use strict';
var baseCssAdapter = require('css-select-base-adapter');
/**
* DOMUtils API for SVGO AST (used by css-select)
*/
var svgoCssSelectAdapterMin = {
// is the node a tag?
// isTag: ( node:Node ) => isTag:Boolean
isTag: function(node) {
return node.isElem();
},
// get the parent of the node
// getParent: ( node:Node ) => parentNode:Node
// returns null when no parent exists
getParent: function(node) {
return node.parentNode || null;
},
// get the node's children
// getChildren: ( node:Node ) => children:[Node]
getChildren: function(node) {
return node.content || [];
},
// get the name of the tag
// getName: ( elem:ElementNode ) => tagName:String
getName: function(elemAst) {
return elemAst.elem;
},
// get the text content of the node, and its children if it has any
// getText: ( node:Node ) => text:String
// returns empty string when there is no text
getText: function(node) {
return node.content[0].text || node.content[0].cdata || '';
},
// get the attribute value
// getAttributeValue: ( elem:ElementNode, name:String ) => value:String
// returns null when attribute doesn't exist
getAttributeValue: function(elem, name) {
return elem.hasAttr(name) ? elem.attr(name).value : null;
}
};
// use base adapter for default implementation
var svgoCssSelectAdapter = baseCssAdapter(svgoCssSelectAdapterMin);
module.exports = svgoCssSelectAdapter;

View file

@ -0,0 +1,285 @@
'use strict';
var csstree = require('css-tree'),
csstools = require('../css-tools');
var CSSStyleDeclaration = function(node) {
this.parentNode = node;
this.properties = new Map();
this.hasSynced = false;
this.styleAttr = null;
this.styleValue = null;
this.parseError = false;
};
/**
* Performs a deep clone of this object.
*
* @param parentNode the parentNode to assign to the cloned result
*/
CSSStyleDeclaration.prototype.clone = function(parentNode) {
var node = this;
var nodeData = {};
Object.keys(node).forEach(function(key) {
if (key !== 'parentNode') {
nodeData[key] = node[key];
}
});
// Deep-clone node data.
nodeData = JSON.parse(JSON.stringify(nodeData));
var clone = new CSSStyleDeclaration(parentNode);
Object.assign(clone, nodeData);
return clone;
};
CSSStyleDeclaration.prototype.hasStyle = function() {
this.addStyleHandler();
};
// attr.style
CSSStyleDeclaration.prototype.addStyleHandler = function() {
this.styleAttr = { // empty style attr
'name': 'style',
'value': null
};
Object.defineProperty(this.parentNode.attrs, 'style', {
get: this.getStyleAttr.bind(this),
set: this.setStyleAttr.bind(this),
enumerable: true,
configurable: true
});
this.addStyleValueHandler();
};
// attr.style.value
CSSStyleDeclaration.prototype.addStyleValueHandler = function() {
Object.defineProperty(this.styleAttr, 'value', {
get: this.getStyleValue.bind(this),
set: this.setStyleValue.bind(this),
enumerable: true,
configurable: true
});
};
CSSStyleDeclaration.prototype.getStyleAttr = function() {
return this.styleAttr;
};
CSSStyleDeclaration.prototype.setStyleAttr = function(newStyleAttr) {
this.setStyleValue(newStyleAttr.value); // must before applying value handler!
this.styleAttr = newStyleAttr;
this.addStyleValueHandler();
this.hasSynced = false; // raw css changed
};
CSSStyleDeclaration.prototype.getStyleValue = function() {
return this.getCssText();
};
CSSStyleDeclaration.prototype.setStyleValue = function(newValue) {
this.properties.clear(); // reset all existing properties
this.styleValue = newValue;
this.hasSynced = false; // raw css changed
};
CSSStyleDeclaration.prototype._loadCssText = function() {
if (this.hasSynced) {
return;
}
this.hasSynced = true; // must be set here to prevent loop in setProperty(...)
if (!this.styleValue || this.styleValue.length === 0) {
return;
}
var inlineCssStr = this.styleValue;
var declarations = {};
try {
declarations = csstree.parse(inlineCssStr, {
context: 'declarationList',
parseValue: false
});
} catch (parseError) {
this.parseError = parseError;
return;
}
this.parseError = false;
var self = this;
declarations.children.each(function(declaration) {
try {
var styleDeclaration = csstools.csstreeToStyleDeclaration(declaration);
self.setProperty(styleDeclaration.name, styleDeclaration.value, styleDeclaration.priority);
} catch(styleError) {
if(styleError.message !== 'Unknown node type: undefined') {
self.parseError = styleError;
}
}
});
};
// only reads from properties
/**
* Get the textual representation of the declaration block (equivalent to .cssText attribute).
*
* @return {String} Textual representation of the declaration block (empty string for no properties)
*/
CSSStyleDeclaration.prototype.getCssText = function() {
var properties = this.getProperties();
if (this.parseError) {
// in case of a parse error, pass through original styles
return this.styleValue;
}
var cssText = [];
properties.forEach(function(property, propertyName) {
var strImportant = property.priority === 'important' ? '!important' : '';
cssText.push(propertyName.trim() + ':' + property.value.trim() + strImportant);
});
return cssText.join(';');
};
CSSStyleDeclaration.prototype._handleParseError = function() {
if (this.parseError) {
console.warn('Warning: Parse error when parsing inline styles, style properties of this element cannot be used. The raw styles can still be get/set using .attr(\'style\').value. Error details: ' + this.parseError);
}
};
CSSStyleDeclaration.prototype._getProperty = function(propertyName) {
if(typeof propertyName === 'undefined') {
throw Error('1 argument required, but only 0 present.');
}
var properties = this.getProperties();
this._handleParseError();
var property = properties.get(propertyName.trim());
return property;
};
/**
* Return the optional priority, "important".
*
* @param {String} propertyName representing the property name to be checked.
* @return {String} priority that represents the priority (e.g. "important") if one exists. If none exists, returns the empty string.
*/
CSSStyleDeclaration.prototype.getPropertyPriority = function(propertyName) {
var property = this._getProperty(propertyName);
return property ? property.priority : '';
};
/**
* Return the property value given a property name.
*
* @param {String} propertyName representing the property name to be checked.
* @return {String} value containing the value of the property. If not set, returns the empty string.
*/
CSSStyleDeclaration.prototype.getPropertyValue = function(propertyName) {
var property = this._getProperty(propertyName);
return property ? property.value : null;
};
/**
* Return a property name.
*
* @param {Number} index of the node to be fetched. The index is zero-based.
* @return {String} propertyName that is the name of the CSS property at the specified index.
*/
CSSStyleDeclaration.prototype.item = function(index) {
if(typeof index === 'undefined') {
throw Error('1 argument required, but only 0 present.');
}
var properties = this.getProperties();
this._handleParseError();
return Array.from(properties.keys())[index];
};
/**
* Return all properties of the node.
*
* @return {Map} properties that is a Map with propertyName as key and property (propertyValue + propertyPriority) as value.
*/
CSSStyleDeclaration.prototype.getProperties = function() {
this._loadCssText();
return this.properties;
};
// writes to properties
/**
* Remove a property from the CSS declaration block.
*
* @param {String} propertyName representing the property name to be removed.
* @return {String} oldValue equal to the value of the CSS property before it was removed.
*/
CSSStyleDeclaration.prototype.removeProperty = function(propertyName) {
if(typeof propertyName === 'undefined') {
throw Error('1 argument required, but only 0 present.');
}
this.hasStyle();
var properties = this.getProperties();
this._handleParseError();
var oldValue = this.getPropertyValue(propertyName);
properties.delete(propertyName.trim());
return oldValue;
};
/**
* Modify an existing CSS property or creates a new CSS property in the declaration block.
*
* @param {String} propertyName representing the CSS property name to be modified.
* @param {String} [value] containing the new property value. If not specified, treated as the empty string. value must not contain "!important" -- that should be set using the priority parameter.
* @param {String} [priority] allowing the "important" CSS priority to be set. If not specified, treated as the empty string.
* @return {undefined}
*/
CSSStyleDeclaration.prototype.setProperty = function(propertyName, value, priority) {
if(typeof propertyName === 'undefined') {
throw Error('propertyName argument required, but only not present.');
}
this.hasStyle();
var properties = this.getProperties();
this._handleParseError();
var property = {
value: value.trim(),
priority: priority.trim()
};
properties.set(propertyName.trim(), property);
return property;
};
module.exports = CSSStyleDeclaration;

348
assets_old/node_modules/svgo/lib/svgo/js2svg.js generated vendored Normal file
View file

@ -0,0 +1,348 @@
'use strict';
var EOL = require('os').EOL,
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 = Object.assign({}, defaults, config);
} else {
this.config = Object.assign({}, defaults);
}
var indent = this.config.indent;
if (typeof indent == 'number' && !isNaN(indent)) {
this.config.indent = (indent < 0) ? '\t' : ' '.repeat(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) {
indent = this.config.indent.repeat(this.indentLevel - 1);
}
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);
};

372
assets_old/node_modules/svgo/lib/svgo/jsAPI.js generated vendored Normal file
View file

@ -0,0 +1,372 @@
'use strict';
var cssSelect = require('css-select');
var svgoCssSelectAdapter = require('./css-select-adapter');
var cssSelectOpts = {
xmlMode: true,
adapter: svgoCssSelectAdapter
};
var JSAPI = module.exports = function(data, parentNode) {
Object.assign(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 !== 'class' && key !== 'style' && key !== 'content') {
nodeData[key] = node[key];
}
});
// Deep-clone node data.
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.class) {
clonedNode.class = node.class.clone(clonedNode);
}
if (node.style) {
clonedNode.style = node.style.clone(clonedNode);
}
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;
};
/**
* Find the closest ancestor of the current element.
* @param elemName
*
* @return {?Object}
*/
JSAPI.prototype.closestElem = function(elemName) {
var elem = this;
while ((elem = elem.parentNode) && !elem.isElem(elemName));
return elem;
};
/**
* 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);
return false;
}
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;
if(attr.name === 'class') { // newly added class attribute
this.class.hasClass();
}
if(attr.name === 'style') { // newly added style attribute
this.style.hasStyle();
}
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;
};
/**
* Evaluate a string of CSS selectors against the element and returns matched elements.
*
* @param {String} selectors CSS selector(s) string
* @return {Array} null if no elements matched
*/
JSAPI.prototype.querySelectorAll = function(selectors) {
var matchedEls = cssSelect(selectors, this, cssSelectOpts);
return matchedEls.length > 0 ? matchedEls : null;
};
/**
* Evaluate a string of CSS selectors against the element and returns only the first matched element.
*
* @param {String} selectors CSS selector(s) string
* @return {Array} null if no element matched
*/
JSAPI.prototype.querySelector = function(selectors) {
return cssSelect.selectOne(selectors, this, cssSelectOpts);
};
/**
* Test if a selector matches a given element.
*
* @param {String} selector CSS selector string
* @return {Boolean} true if element would be selected by selector string, false if it does not
*/
JSAPI.prototype.matches = function(selector) {
return cssSelect.is(this, selector, cssSelectOpts);
};

101
assets_old/node_modules/svgo/lib/svgo/plugins.js generated vendored Normal file
View file

@ -0,0 +1,101 @@
'use strict';
/**
* Plugins engine.
*
* @module plugins
*
* @param {Object} data input data
* @param {Object} info extra information
* @param {Object} plugins plugins object from config
* @return {Object} output data
*/
module.exports = function(data, info, plugins) {
plugins.forEach(function(group) {
switch(group[0].type) {
case 'perItem':
data = perItem(data, info, group);
break;
case 'perItemReverse':
data = perItem(data, info, group, true);
break;
case 'full':
data = full(data, info, group);
break;
}
});
return data;
};
/**
* Direct or reverse per-item loop.
*
* @param {Object} data input data
* @param {Object} info extra information
* @param {Array} plugins plugins list to process
* @param {Boolean} [reverse] reverse pass?
* @return {Object} output data
*/
function perItem(data, info, 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, info) === 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 {Object} info extra information
* @param {Array} plugins plugins list to process
* @return {Object} output data
*/
function full(data, info, plugins) {
plugins.forEach(function(plugin) {
if (plugin.active) {
data = plugin.fn(data, plugin.params, info);
}
});
return data;
}

200
assets_old/node_modules/svgo/lib/svgo/svg2js.js generated vendored Normal file
View file

@ -0,0 +1,200 @@
'use strict';
var SAX = require('sax'),
JSAPI = require('./jsAPI.js'),
CSSClassList = require('./css-class-list'),
CSSStyleDeclaration = require('./css-style-declaration'),
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', content: [] }),
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,
attrs: {}
};
elem.class = new CSSClassList(elem);
elem.style = new CSSStyleDeclaration(elem);
if (Object.keys(data.attributes).length) {
for (var name in data.attributes) {
if (name === 'class') { // has class attribute
elem.class.hasClass();
}
if (name === 'style') { // has style attribute
elem.style.hasStyle();
}
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;
}
};

155
assets_old/node_modules/svgo/lib/svgo/tools.js generated vendored Normal file
View file

@ -0,0 +1,155 @@
'use strict';
var FS = require('fs');
/**
* 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';
if (!type || type === 'base64') {
// base64
prefix += ';base64,';
if (Buffer.from) {
str = prefix + Buffer.from(str).toString('base64');
} else {
str = prefix + new Buffer(str).toString('base64');
}
} else if (type === 'enc') {
// URI encoded
str = prefix + ',' + encodeURIComponent(str);
} else if (type === 'unenc') {
// unencoded
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];
if (match[2]) {
// base64
str = new Buffer(data, 'base64').toString('utf8');
} else if (data.charAt(0) === '%') {
// URI encoded
str = decodeURIComponent(data);
} else if (data.charAt(0) === '<') {
// unencoded
str = data;
}
return str;
};
exports.intersectArrays = function(a, b) {
return a.filter(function(n) {
return b.indexOf(n) > -1;
});
};
/**
* Convert a row of numbers to an optimized string view.
*
* @example
* [0, -1, .5, .5] "0-1 .5.5"
*
* @param {number[]} data
* @param {Object} params
* @param {string?} command path data instruction
* @return {string}
*/
exports.cleanupOutData = function(data, params, command) {
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 = '';
// no extra space after 'arcto' command flags
if (params.noSpaceAfterFlags && (command == 'A' || command == 'a')) {
var pos = i % 7;
if (pos == 4 || pos == 5) 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 &&
delimiter != '' &&
(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;
};
/**
* Synchronously check if path is a directory. Tolerant to errors like ENOENT.
* @param {string} path
*/
exports.checkIsDir = function(path) {
try {
return FS.lstatSync(path).isDirectory();
} catch(e) {
return false;
}
};

1
assets_old/node_modules/svgo/node_modules/.bin/mkdirp generated vendored Symbolic link
View file

@ -0,0 +1 @@
../mkdirp/bin/cmd.js

View file

@ -0,0 +1,21 @@
Copyright 2010 James Halliday (mail@substack.net)
This project is free software released under the MIT/X11 license:
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.

33
assets_old/node_modules/svgo/node_modules/mkdirp/bin/cmd.js generated vendored Executable file
View file

@ -0,0 +1,33 @@
#!/usr/bin/env node
var mkdirp = require('../');
var minimist = require('minimist');
var fs = require('fs');
var argv = minimist(process.argv.slice(2), {
alias: { m: 'mode', h: 'help' },
string: [ 'mode' ]
});
if (argv.help) {
fs.createReadStream(__dirname + '/usage.txt').pipe(process.stdout);
return;
}
var paths = argv._.slice();
var mode = argv.mode ? parseInt(argv.mode, 8) : undefined;
(function next () {
if (paths.length === 0) return;
var p = paths.shift();
if (mode === undefined) mkdirp(p, cb)
else mkdirp(p, mode, cb)
function cb (err) {
if (err) {
console.error(err.message);
process.exit(1);
}
else next();
}
})();

View file

@ -0,0 +1,12 @@
usage: mkdirp [DIR1,DIR2..] {OPTIONS}
Create each supplied directory including any necessary parent directories that
don't yet exist.
If the directory already exists, do nothing.
OPTIONS are:
-m, --mode If a directory needs to be created, set the mode as an octal
permission string.

View file

@ -0,0 +1,99 @@
var path = require('path');
var fs = require('fs');
var _0777 = parseInt('0777', 8);
module.exports = mkdirP.mkdirp = mkdirP.mkdirP = mkdirP;
function mkdirP (p, opts, f, made) {
if (typeof opts === 'function') {
f = opts;
opts = {};
}
else if (!opts || typeof opts !== 'object') {
opts = { mode: opts };
}
var mode = opts.mode;
var xfs = opts.fs || fs;
if (mode === undefined) {
mode = _0777
}
if (!made) made = null;
var cb = f || function () {};
p = path.resolve(p);
xfs.mkdir(p, mode, function (er) {
if (!er) {
made = made || p;
return cb(null, made);
}
switch (er.code) {
case 'ENOENT':
if (path.dirname(p) === p) return cb(er);
mkdirP(path.dirname(p), opts, function (er, made) {
if (er) cb(er, made);
else mkdirP(p, opts, cb, made);
});
break;
// In the case of any other error, just see if there's a dir
// there already. If so, then hooray! If not, then something
// is borked.
default:
xfs.stat(p, function (er2, stat) {
// if the stat fails, then that's super weird.
// let the original error be the failure reason.
if (er2 || !stat.isDirectory()) cb(er, made)
else cb(null, made);
});
break;
}
});
}
mkdirP.sync = function sync (p, opts, made) {
if (!opts || typeof opts !== 'object') {
opts = { mode: opts };
}
var mode = opts.mode;
var xfs = opts.fs || fs;
if (mode === undefined) {
mode = _0777
}
if (!made) made = null;
p = path.resolve(p);
try {
xfs.mkdirSync(p, mode);
made = made || p;
}
catch (err0) {
switch (err0.code) {
case 'ENOENT' :
made = sync(path.dirname(p), opts, made);
sync(p, opts, made);
break;
// In the case of any other error, just see if there's a dir
// there already. If so, then hooray! If not, then something
// is borked.
default:
var stat;
try {
stat = xfs.statSync(p);
}
catch (err1) {
throw err0;
}
if (!stat.isDirectory()) throw err0;
break;
}
}
return made;
};

View file

@ -0,0 +1,34 @@
{
"name": "mkdirp",
"description": "Recursively mkdir, like `mkdir -p`",
"version": "0.5.5",
"publishConfig": {
"tag": "legacy"
},
"author": "James Halliday <mail@substack.net> (http://substack.net)",
"main": "index.js",
"keywords": [
"mkdir",
"directory"
],
"repository": {
"type": "git",
"url": "https://github.com/substack/node-mkdirp.git"
},
"scripts": {
"test": "tap test/*.js"
},
"dependencies": {
"minimist": "^1.2.5"
},
"devDependencies": {
"mock-fs": "^3.7.0",
"tap": "^5.4.2"
},
"bin": "bin/cmd.js",
"license": "MIT",
"files": [
"bin",
"index.js"
]
}

View file

@ -0,0 +1,100 @@
# mkdirp
Like `mkdir -p`, but in node.js!
[![build status](https://secure.travis-ci.org/substack/node-mkdirp.png)](http://travis-ci.org/substack/node-mkdirp)
# example
## pow.js
```js
var mkdirp = require('mkdirp');
mkdirp('/tmp/foo/bar/baz', function (err) {
if (err) console.error(err)
else console.log('pow!')
});
```
Output
```
pow!
```
And now /tmp/foo/bar/baz exists, huzzah!
# methods
```js
var mkdirp = require('mkdirp');
```
## mkdirp(dir, opts, cb)
Create a new directory and any necessary subdirectories at `dir` with octal
permission string `opts.mode`. If `opts` is a non-object, it will be treated as
the `opts.mode`.
If `opts.mode` isn't specified, it defaults to `0777`.
`cb(err, made)` fires with the error or the first directory `made`
that had to be created, if any.
You can optionally pass in an alternate `fs` implementation by passing in
`opts.fs`. Your implementation should have `opts.fs.mkdir(path, mode, cb)` and
`opts.fs.stat(path, cb)`.
## mkdirp.sync(dir, opts)
Synchronously create a new directory and any necessary subdirectories at `dir`
with octal permission string `opts.mode`. If `opts` is a non-object, it will be
treated as the `opts.mode`.
If `opts.mode` isn't specified, it defaults to `0777`.
Returns the first directory that had to be created, if any.
You can optionally pass in an alternate `fs` implementation by passing in
`opts.fs`. Your implementation should have `opts.fs.mkdirSync(path, mode)` and
`opts.fs.statSync(path)`.
# usage
This package also ships with a `mkdirp` command.
```
usage: mkdirp [DIR1,DIR2..] {OPTIONS}
Create each supplied directory including any necessary parent directories that
don't yet exist.
If the directory already exists, do nothing.
OPTIONS are:
-m, --mode If a directory needs to be created, set the mode as an octal
permission string.
```
# install
With [npm](http://npmjs.org) do:
```
npm install mkdirp
```
to get the library, or
```
npm install -g mkdirp
```
to get the command.
# license
MIT

79
assets_old/node_modules/svgo/package.json generated vendored Normal file
View file

@ -0,0 +1,79 @@
{
"name": "svgo",
"version": "1.3.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"
},
"author": {
"name": "Kir Belevich",
"email": "kir@belevi.ch",
"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",
"lint": "jshint --show-non-errors .",
"jshint": "npm run lint"
},
"dependencies": {
"chalk": "^2.4.1",
"coa": "^2.0.2",
"css-select": "^2.0.0",
"css-select-base-adapter": "^0.1.1",
"css-tree": "1.0.0-alpha.37",
"csso": "^4.0.2",
"js-yaml": "^3.13.1",
"mkdirp": "~0.5.1",
"object.values": "^1.1.0",
"sax": "~1.2.4",
"stable": "^0.1.8",
"unquote": "~1.1.1",
"util.promisify": "~1.0.0"
},
"devDependencies": {
"coveralls": "^3.0.7",
"fs-extra": "~8.1.0",
"istanbul": "~0.4.5",
"jshint": "~2.10.2",
"mocha": "~6.2.2",
"mocha-istanbul": "~0.3.0",
"mock-stdin": "~0.3.1",
"should": "~13.2.3"
},
"engines": {
"node": ">=4.0.0"
},
"license": "MIT"
}

2558
assets_old/node_modules/svgo/plugins/_collections.js generated vendored Normal file

File diff suppressed because it is too large Load diff

988
assets_old/node_modules/svgo/plugins/_path.js generated vendored Normal file
View file

@ -0,0 +1,988 @@
/* global a2c */
'use strict';
var rNumber = String.raw`[-+]?(?:\d*\.\d+|\d+\.?)(?:[eE][-+]?\d+)?\s*`,
rCommaWsp = String.raw`(?:\s,?\s*|,\s*)`,
rNumberCommaWsp = `(${rNumber})` + rCommaWsp,
rFlagCommaWsp = `([01])${rCommaWsp}?`,
rCoordinatePair = String.raw`(${rNumber})${rCommaWsp}?(${rNumber})`,
rArcSeq = (rNumberCommaWsp + '?').repeat(2) + rNumberCommaWsp + rFlagCommaWsp.repeat(2) + rCoordinatePair;
var regPathInstructions = /([MmLlHhVvCcSsQqTtAaZz])\s*/,
regCoordinateSequence = new RegExp(rNumber, 'g'),
regArcArgumentSequence = new RegExp(rArcSeq, '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 {
/* jshint boss: true */
if (instruction == 'A' || instruction == 'a') {
var newData = [];
for (var args; (args = regArcArgumentSequence.exec(data));) {
for (var i = 1; i < args.length; i++) {
newData.push(args[i]);
}
}
data = newData;
} else {
data = data.match(regCoordinateSequence);
}
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;
return 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
};
});
};
/**
* 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('vector-effect') || elem.attr('vector-effect').value !== 'non-scaling-stroke') {
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) {
var strData = '';
if (item.data) {
strData = cleanupOutData(item.data, params, item.instruction);
}
return pathString += item.instruction + strData;
}, '');
};
/**
* 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

310
assets_old/node_modules/svgo/plugins/_transforms.js generated vendored Normal file
View file

@ -0,0 +1,310 @@
'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 empty array if broken transform (no data)
return current && current.data ? 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.length > 0 ? transforms.reduce(multiplyTransformMatrices) : []
};
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://frederic-wang.fr/decomposition-of-2d-transform-matrices.html
*
* @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.hypot(data[0], 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 != 0 || 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.hypot(data[0], data[2]);
sy = (data[3] < 0 ? -1 : 1) * Math.hypot(data[1], data[3]);
transforms.push({ name: 'scale', data: [sx, sy] });
}
var angle = Math.min(Math.max(-1, data[0] / sx), 1),
rotate = [mth.acos(angle, floatPrecision) * ((scaleBefore ? 1 : sy) * data[1] < 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.hypot(m[0] - m[3], m[1] + m[2]) * Math.hypot(m[0] + m[3], m[1] - m[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.hypot(term1, term2)) * 180 / Math.PI;
}
if ((transform[0] < 0) !== (transform[3] < 0)) {
// Flip the sweep flag if coordinates are being flipped horizontally XOR vertically
arc[4] = 1 - arc[4];
}
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]
];
}

View file

@ -0,0 +1,82 @@
'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.
It should have a list of "attributes" or one "attribute".
Config example:
plugins:
- addAttributesToSVGElement:
attribute: "mySvg"
plugins:
- addAttributesToSVGElement:
attributes: ["mySvg", "size-big"]
plugins:
- addAttributesToSVGElement:
attributes:
- focusable: false
- data-image: icon`;
/**
* Add attributes to an outer <svg> element. Example config:
*
* plugins:
* - addAttributesToSVGElement:
* attribute: 'data-icon'
*
* plugins:
* - addAttributesToSVGElement:
* attributes: ['data-icon', 'data-disabled']
*
* plugins:
* - addAttributesToSVGElement:
* attributes:
* - focusable: false
* - data-image: icon
*
* @author April Arcus
*/
exports.fn = function(data, params) {
if (!params || !(Array.isArray(params.attributes) || 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 (typeof attribute === 'string') {
if (!svg.hasAttr(attribute)) {
svg.addAttr({
name: attribute,
prefix: '',
local: attribute
});
}
} else if (typeof attribute === 'object') {
Object.keys(attribute).forEach(function (key) {
if (!svg.hasAttr(key)) {
svg.addAttr({
name: key,
value: attribute[key],
prefix: '',
local: key
});
}
});
}
});
}
return data;
};

View file

@ -0,0 +1,50 @@
'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.
It should have a list of classes in "classNames" or one "className".
Config example:
plugins:
- addClassesToSVGElement:
className: "mySvg"
plugins:
- addClassesToSVGElement:
classNames: ["mySvg", "size-big"]
`;
/**
* 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')) {
svg.class.add.apply(svg.class, classNames);
}
return data;
};

56
assets_old/node_modules/svgo/plugins/cleanupAttrs.js generated vendored Normal file
View file

@ -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, ' ');
}
});
}
};

View file

@ -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');
});
};

209
assets_old/node_modules/svgo/plugins/cleanupIDs.js generated vendored Normal file
View file

@ -0,0 +1,209 @@
'use strict';
exports.type = 'full';
exports.active = true;
exports.description = 'removes unused IDs and minifies used';
exports.params = {
remove: true,
minify: true,
prefix: '',
preserve: [],
preservePrefixes: [],
force: false
};
var referencesProps = new Set(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 = new Map(),
referencesIDs = new Map(),
hasStyleOrScript = false,
preserveIDs = new Set(Array.isArray(params.preserve) ? params.preserve : params.preserve ? [params.preserve] : []),
preserveIDPrefixes = new Set(Array.isArray(params.preservePrefixes) ? params.preservePrefixes : (params.preservePrefixes ? [params.preservePrefixes] : [])),
idValuePrefix = '#',
idValuePostfix = '.';
/**
* 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];
// quit if <style> or <script> present ('force' param prevents quitting)
if (!params.force) {
if (item.isElem(styleOrScript)) {
hasStyleOrScript = true;
continue;
}
// Don't remove IDs if the whole SVG consists only of defs.
if (item.isElem('defs') && item.parentNode.isElem('svg')) {
var hasDefsOnly = true;
for (var j = i + 1; j < items.content.length; j++) {
if (items.content[j].isElem()) {
hasDefsOnly = false;
break;
}
}
if (hasDefsOnly) {
break;
}
}
}
// …and don't remove any ID if yes
if (item.isElem()) {
item.eachAttr(function(attr) {
var key, match;
// save IDs
if (attr.name === 'id') {
key = attr.value;
if (IDs.has(key)) {
item.removeAttr('id'); // remove repeated id
} else {
IDs.set(key, item);
}
return;
}
// save references
if (referencesProps.has(attr.name) && (match = attr.value.match(regReferencesUrl))) {
key = match[2]; // url() reference
} else if (
attr.local === 'href' && (match = attr.value.match(regReferencesHref)) ||
attr.name === 'begin' && (match = attr.value.match(regReferencesBegin))
) {
key = match[1]; // href reference
}
if (key) {
var ref = referencesIDs.get(key) || [];
ref.push(attr);
referencesIDs.set(key, ref);
}
});
}
// go deeper
if (item.content) {
monkeys(item);
}
}
return items;
}
data = monkeys(data);
if (hasStyleOrScript) {
return data;
}
const idPreserved = id => preserveIDs.has(id) || idMatchesPrefix(preserveIDPrefixes, id);
for (var ref of referencesIDs) {
var key = ref[0];
if (IDs.has(key)) {
// replace referenced IDs with the minified ones
if (params.minify && !idPreserved(key)) {
do {
currentIDstring = getIDstring(currentID = generateID(currentID), params);
} while (idPreserved(currentIDstring));
IDs.get(key).attr('id').value = currentIDstring;
for (var attr of ref[1]) {
attr.value = attr.value.includes(idValuePrefix) ?
attr.value.replace(idValuePrefix + key, idValuePrefix + currentIDstring) :
attr.value.replace(key + idValuePostfix, currentIDstring + idValuePostfix);
}
}
// don't remove referenced IDs
IDs.delete(key);
}
}
// remove non-referenced IDs attributes from elements
if (params.remove) {
for(var keyElem of IDs) {
if (!idPreserved(keyElem[0])) {
keyElem[1].removeAttr('id');
}
}
}
return data;
};
/**
* Check if an ID starts with any one of a list of strings.
*
* @param {Array} of prefix strings
* @param {String} current ID
* @return {Boolean} if currentID starts with one of the strings in prefixArray
*/
function idMatchesPrefix(prefixArray, currentID) {
if (!currentID) return false;
for (var prefix of prefixArray) if (currentID.startsWith(prefix)) return true;
return false;
}
/**
* 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;
return str + arr.map(i => generateIDchars[i]).join('');
}

View file

@ -0,0 +1,139 @@
'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');
} else if (elem) {
roundedListArr.push(elem);
}
});
roundedList = roundedListArr.join(' ');
$prop.value = roundedList;
}
};

View file

@ -0,0 +1,88 @@
'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 floatPrecision = params.floatPrecision;
if (item.hasAttr('viewBox')) {
var nums = item.attr('viewBox').value.split(/\s,?\s*|,\s*/g);
item.attr('viewBox').value = nums.map(function(value) {
var num = +value;
return isNaN(num) ? value : +num.toFixed(floatPrecision);
}).join(' ');
}
item.eachAttr(function(attr) {
// The `version` attribute is a text string and cannot be rounded
if (attr.name === 'version') { return }
var match = attr.value.match(regNumericValues);
// if attribute value matches regNumericValues
if (match) {
// round it to the fixed precision
var num = +(+match[1]).toFixed(floatPrecision),
units = match[3] || '';
// convert absolute values to pixels
if (params.convertToPx && units && (units in absoluteLengths)) {
var pxNum = +(absoluteLengths[units] * match[1]).toFixed(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;
}
});
}
};

87
assets_old/node_modules/svgo/plugins/collapseGroups.js generated vendored Normal file
View file

@ -0,0 +1,87 @@
'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('filter') &&
!(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 (inner.hasAttr(attr.name, 'inherit')) {
inner.attr(attr.name).value = attr.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);
}
}
});
}
};

130
assets_old/node_modules/svgo/plugins/convertColors.js generated vendored Normal file
View file

@ -0,0 +1,130 @@
'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) {
var lowerVal = val.toLowerCase();
if (lowerVal in collections.colorsShortNames) {
val = collections.colorsShortNames[lowerVal];
}
}
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();
}

View file

@ -0,0 +1,39 @@
'use strict';
exports.type = 'perItem';
exports.active = true;
exports.description = 'converts non-eccentric <ellipse>s to <circle>s';
/**
* Converts non-eccentric <ellipse>s to <circle>s.
*
* @see http://www.w3.org/TR/SVG/shapes.html
*
* @param {Object} item current iteration item
* @return {Boolean} if false, item will be filtered out
*
* @author Taylor Hunt
*/
exports.fn = function(item) {
if (item.isElem('ellipse')) {
var rx = item.attr('rx').value || 0;
var ry = item.attr('ry').value || 0;
if (rx === ry ||
rx === 'auto' || ry === 'auto' // SVG2
) {
var radius = rx !== 'auto' ? rx : ry;
item.renameElem('circle');
item.removeAttr(['rx', 'ry']);
item.addAttr({
name: 'r',
value: radius,
prefix: '',
local: 'r',
});
}
}
return;
};

971
assets_old/node_modules/svgo/plugins/convertPathData.js generated vendored Normal file
View file

@ -0,0 +1,971 @@
'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,
noSpaceAfterFlags: true,
forceAbsolutePath: false
};
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,
hasStrokeLinecap;
/**
* 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 stroke = item.computedAttr('stroke'),
strokeLinecap = item.computedAttr('stroke');
hasStrokeLinecap = stroke && stroke != 'none' && strokeLinecap && strokeLinecap != 'butt';
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;
var prevAngle = findArcAngle(prevData,
{
center: [prevData[4] + circle.center[0], prevData[5] + circle.center[1]],
radius: circle.radius
}
);
angle += prevAngle;
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 && !hasStrokeLinecap) {
// 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 or forceAbsolutePath is true.
// v-20 -> V0
// Don't convert if it fits following previous instruction.
// l20 30-10-50 instead of l20 30L20 30
if (
params.forceAbsolutePath || (
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.hypot(point1[0] - point2[0], point1[1] - point2[1]);
}
/**
* Returns coordinates of the curve point corresponding to the certain t
* a·(1 - t)³·p1 + b·(1 - t)²·t·p2 + c·(1 - t)··p3 + d··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 && radius < 1e15 &&
[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 circle.
*
* @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 previous curve fits the given circle.
*
* @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) {
var strData = '';
if (item.data) {
strData = cleanupOutData(roundData(item.data.slice()), params);
}
return pathString + item.instruction + strData;
}, '');
}

View file

@ -0,0 +1,149 @@
'use strict';
exports.type = 'perItem';
exports.active = true;
exports.description = 'converts basic shapes to more compact path form';
exports.params = {
convertArcs: false
};
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, params) {
var convertArcs = params && params.convertArcs;
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');
} else if (item.isElem('circle') && convertArcs) {
var cx = +(item.attr('cx') || none).value;
var cy = +(item.attr('cy') || none).value;
var r = +(item.attr('r') || none).value;
if (isNaN(cx - cy + r)) {
return;
}
var cPathData =
'M' + cx + ' ' + (cy - r) +
'A' + r + ' ' + r + ' 0 1 0 ' + cx + ' ' + (cy + r) +
'A' + r + ' ' + r + ' 0 1 0 ' + cx + ' ' + (cy - r) +
'Z';
item.addAttr({
name: 'd',
value: cPathData,
prefix: '',
local: 'd',
});
item.renameElem('path').removeAttr(['cx', 'cy', 'r']);
} else if (item.isElem('ellipse') && convertArcs) {
var ecx = +(item.attr('cx') || none).value;
var ecy = +(item.attr('cy') || none).value;
var rx = +(item.attr('rx') || none).value;
var ry = +(item.attr('ry') || none).value;
if (isNaN(ecx - ecy + rx - ry)) {
return;
}
var ePathData =
'M' + ecx + ' ' + (ecy - ry) +
'A' + rx + ' ' + ry + ' 0 1 0 ' + ecx + ' ' + (ecy + ry) +
'A' + rx + ' ' + ry + ' 0 1 0 ' + ecx + ' ' + (ecy - ry) +
'Z';
item.addAttr({
name: 'd',
value: ePathData,
prefix: '',
local: 'd',
});
item.renameElem('path').removeAttr(['cx', 'cy', 'rx', 'ry']);
}
};

View file

@ -0,0 +1,125 @@
/* jshint quotmark: false */
'use strict';
exports.type = 'perItem';
exports.active = true;
exports.description = 'converts style to attributes';
exports.params = {
keepImportant: false
};
var 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*|$)',
// Important rule
rImportant = '(\\s*!important(?![-(\w]))?',
// Final RegExp to parse CSS declarations.
regDeclarationBlock = new RegExp(rAttr + ':' + rValue + rImportant + 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, params) {
/* 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);) {
if (!params.keepImportant || !rule[3]) {
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;
});
Object.assign(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, '|') + ')';
}

View file

@ -0,0 +1,363 @@
'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,
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 = Object.assign({}, 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;
}

245
assets_old/node_modules/svgo/plugins/inlineStyles.js generated vendored Normal file
View file

@ -0,0 +1,245 @@
'use strict';
exports.type = 'full';
exports.active = true;
exports.params = {
onlyMatchedOnce: true,
removeMatchedSelectors: true,
useMqs: ['', 'screen'],
usePseudos: ['']
};
exports.description = 'inline styles (additional options)';
var csstree = require('css-tree'),
cssTools = require('../lib/css-tools');
/**
* Moves + merges styles from style elements to element styles
*
* Options
* onlyMatchedOnce (default: true)
* inline only selectors that match once
*
* removeMatchedSelectors (default: true)
* clean up matched selectors,
* leave selectors that hadn't matched
*
* useMqs (default: ['', 'screen'])
* what media queries to be used
* empty string element for styles outside media queries
*
* usePseudos (default: [''])
* what pseudo-classes/-elements to be used
* empty string element for all non-pseudo-classes and/or -elements
*
* @param {Object} document document element
* @param {Object} opts plugin params
*
* @author strarsis <strarsis@gmail.com>
*/
exports.fn = function(document, opts) {
// collect <style/>s
var styleEls = document.querySelectorAll('style');
//no <styles/>s, nothing to do
if (styleEls === null) {
return document;
}
var styles = [],
selectors = [];
for (var styleEl of styleEls) {
if (styleEl.isEmpty() || styleEl.closestElem('foreignObject')) {
// skip empty <style/>s or <foreignObject> content.
continue;
}
var cssStr = cssTools.getCssStr(styleEl);
// collect <style/>s and their css ast
var cssAst = {};
try {
cssAst = csstree.parse(cssStr, {
parseValue: false,
parseCustomProperty: false
});
} catch (parseError) {
// console.warn('Warning: Parse error of styles of <style/> element, skipped. Error details: ' + parseError);
continue;
}
styles.push({
styleEl: styleEl,
cssAst: cssAst
});
selectors = selectors.concat(cssTools.flattenToSelectors(cssAst));
}
// filter for mediaqueries to be used or without any mediaquery
var selectorsMq = cssTools.filterByMqs(selectors, opts.useMqs);
// filter for pseudo elements to be used
var selectorsPseudo = cssTools.filterByPseudos(selectorsMq, opts.usePseudos);
// remove PseudoClass from its SimpleSelector for proper matching
cssTools.cleanPseudos(selectorsPseudo);
// stable sort selectors
var sortedSelectors = cssTools.sortSelectors(selectorsPseudo).reverse();
var selector,
selectedEl;
// match selectors
for (selector of sortedSelectors) {
var selectorStr = csstree.generate(selector.item.data),
selectedEls = null;
try {
selectedEls = document.querySelectorAll(selectorStr);
} catch (selectError) {
if (selectError.constructor === SyntaxError) {
// console.warn('Warning: Syntax error when trying to select \n\n' + selectorStr + '\n\n, skipped. Error details: ' + selectError);
continue;
}
throw selectError;
}
if (selectedEls === null) {
// nothing selected
continue;
}
selector.selectedEls = selectedEls;
}
// apply <style/> styles to matched elements
for (selector of sortedSelectors) {
if(!selector.selectedEls) {
continue;
}
if (opts.onlyMatchedOnce && selector.selectedEls !== null && selector.selectedEls.length > 1) {
// skip selectors that match more than once if option onlyMatchedOnce is enabled
continue;
}
// apply <style/> to matched elements
for (selectedEl of selector.selectedEls) {
if (selector.rule === null) {
continue;
}
// merge declarations
csstree.walk(selector.rule, {visit: 'Declaration', enter: function(styleCsstreeDeclaration) {
// existing inline styles have higher priority
// no inline styles, external styles, external styles used
// inline styles, external styles same priority as inline styles, inline styles used
// inline styles, external styles higher priority than inline styles, external styles used
var styleDeclaration = cssTools.csstreeToStyleDeclaration(styleCsstreeDeclaration);
if (selectedEl.style.getPropertyValue(styleDeclaration.name) !== null &&
selectedEl.style.getPropertyPriority(styleDeclaration.name) >= styleDeclaration.priority) {
return;
}
selectedEl.style.setProperty(styleDeclaration.name, styleDeclaration.value, styleDeclaration.priority);
}});
}
if (opts.removeMatchedSelectors && selector.selectedEls !== null && selector.selectedEls.length > 0) {
// clean up matching simple selectors if option removeMatchedSelectors is enabled
selector.rule.prelude.children.remove(selector.item);
}
}
if (!opts.removeMatchedSelectors) {
return document; // no further processing required
}
// clean up matched class + ID attribute values
for (selector of sortedSelectors) {
if(!selector.selectedEls) {
continue;
}
if (opts.onlyMatchedOnce && selector.selectedEls !== null && selector.selectedEls.length > 1) {
// skip selectors that match more than once if option onlyMatchedOnce is enabled
continue;
}
for (selectedEl of selector.selectedEls) {
// class
var firstSubSelector = selector.item.data.children.first();
if(firstSubSelector.type === 'ClassSelector') {
selectedEl.class.remove(firstSubSelector.name);
}
// clean up now empty class attributes
if(typeof selectedEl.class.item(0) === 'undefined') {
selectedEl.removeAttr('class');
}
// ID
if(firstSubSelector.type === 'IdSelector') {
selectedEl.removeAttr('id', firstSubSelector.name);
}
}
}
// clean up now empty elements
for (var style of styles) {
csstree.walk(style.cssAst, {visit: 'Rule', enter: function(node, item, list) {
// clean up <style/> atrules without any rulesets left
if (node.type === 'Atrule' &&
// only Atrules containing rulesets
node.block !== null &&
node.block.children.isEmpty()) {
list.remove(item);
return;
}
// clean up <style/> rulesets without any css selectors left
if (node.type === 'Rule' &&
node.prelude.children.isEmpty()) {
list.remove(item);
}
}});
if (style.cssAst.children.isEmpty()) {
// clean up now emtpy <style/>s
var styleParentEl = style.styleEl.parentNode;
styleParentEl.spliceContent(styleParentEl.content.indexOf(style.styleEl), 1);
if (styleParentEl.elem === 'defs' &&
styleParentEl.content.length === 0) {
// also clean up now empty <def/>s
var defsParentEl = styleParentEl.parentNode;
defsParentEl.spliceContent(defsParentEl.content.indexOf(styleParentEl), 1);
}
continue;
}
// update existing, left over <style>s
cssTools.setCssStr(style.styleEl, csstree.generate(style.cssAst));
}
return document;
};

73
assets_old/node_modules/svgo/plugins/mergePaths.js generated vendored Normal file
View file

@ -0,0 +1,73 @@
'use strict';
exports.type = 'perItem';
exports.active = true;
exports.description = 'merges multiple paths in one if possible';
exports.params = {
collapseRepeated: true,
force: false,
leadingZero: true,
negativeExtraSpace: true,
noSpaceAfterFlags: 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 && (params.force || !intersects(prevPathJS, curPathJS))) {
js2path(prevContentItem, prevPathJS.concat(curPathJS), params);
return false;
}
}
prevContentItem = contentItem;
prevContentItemKeys = null;
return true;
});
};

160
assets_old/node_modules/svgo/plugins/minifyStyles.js generated vendored Executable file
View file

@ -0,0 +1,160 @@
'use strict';
exports.type = 'full';
exports.active = true;
exports.description = 'minifies styles and removes unused styles based on usage data';
exports.params = {
// ... CSSO options goes here
// additional
usage: {
force: false, // force to use usage data even if it unsafe (document contains <script> or on* attributes)
ids: true,
classes: true,
tags: true
}
};
var csso = require('csso');
/**
* Minifies styles (<style> element + style attribute) using CSSO
*
* @author strarsis <strarsis@gmail.com>
*/
exports.fn = function(ast, options) {
options = options || {};
var minifyOptionsForStylesheet = cloneObject(options);
var minifyOptionsForAttribute = cloneObject(options);
var elems = findStyleElems(ast);
minifyOptionsForStylesheet.usage = collectUsageData(ast, options);
minifyOptionsForAttribute.usage = null;
elems.forEach(function(elem) {
if (elem.isElem('style')) {
// <style> element
var styleCss = elem.content[0].text || elem.content[0].cdata || [];
var DATA = styleCss.indexOf('>') >= 0 || styleCss.indexOf('<') >= 0 ? 'cdata' : 'text';
elem.content[0][DATA] = csso.minify(styleCss, minifyOptionsForStylesheet).css;
} else {
// style attribute
var elemStyle = elem.attr('style').value;
elem.attr('style').value = csso.minifyBlock(elemStyle, minifyOptionsForAttribute).css;
}
});
return ast;
};
function cloneObject(obj) {
var result = {};
for (var key in obj) {
result[key] = obj[key];
}
return result;
}
function findStyleElems(ast) {
function walk(items, styles) {
for (var i = 0; i < items.content.length; i++) {
var item = items.content[i];
// go deeper
if (item.content) {
walk(item, styles);
}
if (item.isElem('style') && !item.isEmpty()) {
styles.push(item);
} else if (item.isElem() && item.hasAttr('style')) {
styles.push(item);
}
}
return styles;
}
return walk(ast, []);
}
function shouldFilter(options, name) {
if ('usage' in options === false) {
return true;
}
if (options.usage && name in options.usage === false) {
return true;
}
return Boolean(options.usage && options.usage[name]);
}
function collectUsageData(ast, options) {
function walk(items, usageData) {
for (var i = 0; i < items.content.length; i++) {
var item = items.content[i];
// go deeper
if (item.content) {
walk(item, usageData);
}
if (item.isElem('script')) {
safe = false;
}
if (item.isElem()) {
usageData.tags[item.elem] = true;
if (item.hasAttr('id')) {
usageData.ids[item.attr('id').value] = true;
}
if (item.hasAttr('class')) {
item.attr('class').value.replace(/^\s+|\s+$/g, '').split(/\s+/).forEach(function(className) {
usageData.classes[className] = true;
});
}
if (item.attrs && Object.keys(item.attrs).some(function(name) { return /^on/i.test(name); })) {
safe = false;
}
}
}
return usageData;
}
var safe = true;
var usageData = {};
var hasData = false;
var rawData = walk(ast, {
ids: Object.create(null),
classes: Object.create(null),
tags: Object.create(null)
});
if (!safe && options.usage && options.usage.force) {
safe = true;
}
for (var key in rawData) {
if (shouldFilter(options, key)) {
usageData[key] = Object.keys(rawData[key]);
hasData = true;
}
}
return safe && hasData ? usageData : null;
}

View file

@ -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;
}

View file

@ -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');
}
};

243
assets_old/node_modules/svgo/plugins/prefixIds.js generated vendored Executable file
View file

@ -0,0 +1,243 @@
'use strict';
exports.type = 'perItem';
exports.active = false;
exports.params = {
delim: '__',
prefixIds: true,
prefixClassNames: true,
};
exports.description = 'prefix IDs';
var path = require('path'),
csstree = require('css-tree'),
unquote = require('unquote'),
collections = require('./_collections.js'),
referencesProps = collections.referencesProps,
rxId = /^#(.*)$/, // regular expression for matching an ID + extracing its name
addPrefix = null;
// Escapes a string for being used as ID
var escapeIdentifierName = function(str) {
return str.replace(/[\. ]/g, '_');
};
// Matches an #ID value, captures the ID name
var matchId = function(urlVal) {
var idUrlMatches = urlVal.match(rxId);
if (idUrlMatches === null) {
return false;
}
return idUrlMatches[1];
};
// Matches an url(...) value, captures the URL
var matchUrl = function(val) {
var urlMatches = /url\((.*?)\)/gi.exec(val);
if (urlMatches === null) {
return false;
}
return urlMatches[1];
};
// Checks if attribute is empty
var attrNotEmpty = function(attr) {
return (attr && attr.value && attr.value.length > 0);
};
// prefixes an #ID
var prefixId = function(val) {
var idName = matchId(val);
if (!idName) {
return false;
}
return '#' + addPrefix(idName);
};
// attr.value helper methods
// prefixes a class attribute value
var addPrefixToClassAttr = function(attr) {
if (!attrNotEmpty(attr)) {
return;
}
attr.value = attr.value.split(/\s+/).map(addPrefix).join(' ');
};
// prefixes an ID attribute value
var addPrefixToIdAttr = function(attr) {
if (!attrNotEmpty(attr)) {
return;
}
attr.value = addPrefix(attr.value);
};
// prefixes a href attribute value
var addPrefixToHrefAttr = function(attr) {
if (!attrNotEmpty(attr)) {
return;
}
var idPrefixed = prefixId(attr.value);
if (!idPrefixed) {
return;
}
attr.value = idPrefixed;
};
// prefixes an URL attribute value
var addPrefixToUrlAttr = function(attr) {
if (!attrNotEmpty(attr)) {
return;
}
// url(...) in value
var urlVal = matchUrl(attr.value);
if (!urlVal) {
return;
}
var idPrefixed = prefixId(urlVal);
if (!idPrefixed) {
return;
}
attr.value = 'url(' + idPrefixed + ')';
};
/**
* Prefixes identifiers
*
* @param {Object} node node
* @param {Object} opts plugin params
* @param {Object} extra plugin extra information
*
* @author strarsis <strarsis@gmail.com>
*/
exports.fn = function(node, opts, extra) {
// skip subsequent passes when multipass is used
if(extra.multipassCount && extra.multipassCount > 0) {
return node;
}
// prefix, from file name or option
var prefix = 'prefix';
if (opts.prefix) {
if (typeof opts.prefix === 'function') {
prefix = opts.prefix(node, extra);
} else {
prefix = opts.prefix;
}
} else if (opts.prefix === false) {
prefix = false;
} else if (extra && extra.path && extra.path.length > 0) {
var filename = path.basename(extra.path);
prefix = filename;
}
// prefixes a normal value
addPrefix = function(name) {
if(prefix === false){
return escapeIdentifierName(name);
}
return escapeIdentifierName(prefix + opts.delim + name);
};
// <style/> property values
if (node.elem === 'style') {
if (node.isEmpty()) {
// skip empty <style/>s
return node;
}
var cssStr = node.content[0].text || node.content[0].cdata || [];
var cssAst = {};
try {
cssAst = csstree.parse(cssStr, {
parseValue: true,
parseCustomProperty: false
});
} catch (parseError) {
console.warn('Warning: Parse error of styles of <style/> element, skipped. Error details: ' + parseError);
return node;
}
var idPrefixed = '';
csstree.walk(cssAst, function(node) {
// #ID, .class
if (((opts.prefixIds && node.type === 'IdSelector') ||
(opts.prefixClassNames && node.type === 'ClassSelector')) &&
node.name) {
node.name = addPrefix(node.name);
return;
}
// url(...) in value
if (node.type === 'Url' &&
node.value.value && node.value.value.length > 0) {
idPrefixed = prefixId(unquote(node.value.value));
if (!idPrefixed) {
return;
}
node.value.value = idPrefixed;
}
});
// update <style>s
node.content[0].text = csstree.generate(cssAst);
return node;
}
// element attributes
if (!node.attrs) {
return node;
}
// Nodes
if(opts.prefixIds) {
// ID
addPrefixToIdAttr(node.attrs.id);
}
if(opts.prefixClassNames) {
// Class
addPrefixToClassAttr(node.attrs.class);
}
// References
// href
addPrefixToHrefAttr(node.attrs.href);
// (xlink:)href (deprecated, must be still supported)
addPrefixToHrefAttr(node.attrs['xlink:href']);
// (referenceable) properties
for (var referencesProp of referencesProps) {
addPrefixToUrlAttr(node.attrs[referencesProp]);
}
return node;
};

View file

@ -0,0 +1,70 @@
'use strict';
exports.type = 'perItem';
exports.active = false;
exports.description = 'removes attributes of elements that match a css selector';
/**
* Removes attributes of elements that match a css selector.
*
* @param {Object} item current iteration item
* @param {Object} params plugin params
* @return {Boolean} if false, item will be filtered out
*
* @example
* <caption>A selector removing a single attribute</caption>
* plugins:
* - removeAttributesBySelector:
* selector: "[fill='#00ff00']"
* attributes: "fill"
*
* <rect x="0" y="0" width="100" height="100" fill="#00ff00" stroke="#00ff00"/>
*
* <rect x="0" y="0" width="100" height="100" stroke="#00ff00"/>
*
* <caption>A selector removing multiple attributes</caption>
* plugins:
* - removeAttributesBySelector:
* selector: "[fill='#00ff00']"
* attributes:
* - fill
* - stroke
*
* <rect x="0" y="0" width="100" height="100" fill="#00ff00" stroke="#00ff00"/>
*
* <rect x="0" y="0" width="100" height="100"/>
*
* <caption>Multiple selectors removing attributes</caption>
* plugins:
* - removeAttributesBySelector:
* selectors:
* - selector: "[fill='#00ff00']"
* attributes: "fill"
*
* - selector: "#remove"
* attributes:
* - stroke
* - id
*
* <rect x="0" y="0" width="100" height="100" fill="#00ff00" stroke="#00ff00"/>
*
* <rect x="0" y="0" width="100" height="100"/>
*
* @see {@link https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors|MDN CSS Selectors}
*
* @author Bradley Mease
*/
exports.fn = function(item, params) {
var selectors = Array.isArray(params.selectors) ? params.selectors : [params];
selectors.map(function(i) {
if (item.matches(i.selector)) {
item.removeAttr(i.attributes);
}
});
};

150
assets_old/node_modules/svgo/plugins/removeAttrs.js generated vendored Normal file
View file

@ -0,0 +1,150 @@
'use strict';
var DEFAULT_SEPARATOR = ':';
exports.type = 'perItem';
exports.active = false;
exports.description = 'removes specified attributes';
exports.params = {
elemSeparator: DEFAULT_SEPARATOR,
preserveCurrentColor: false,
attrs: []
};
/**
* Remove attributes
*
* @param elemSeparator
* format: string
*
* @param preserveCurrentColor
* format: boolean
*
* @param attrs:
*
* format: [ element* : attribute* : value* ]
*
* element : regexp (wrapped into ^...$), single * or omitted > all elements (must be present when value is used)
* attribute : regexp (wrapped into ^...$)
* value : regexp (wrapped into ^...$), single * or omitted > all values
*
* examples:
*
* > basic: remove fill attribute
* ---
* removeAttrs:
* attrs: 'fill'
*
* > remove fill attribute on path element
* ---
* attrs: 'path:fill'
*
* > remove fill attribute on path element where value is none
* ---
* attrs: 'path:fill:none'
*
*
* > 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)'
*
* [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()) {
var elemSeparator = typeof params.elemSeparator == 'string' ? params.elemSeparator : DEFAULT_SEPARATOR;
var preserveCurrentColor = typeof params.preserveCurrentColor == 'boolean' ? params.preserveCurrentColor : false;
// prepare patterns
var patterns = params.attrs.map(function(pattern) {
// if no element separators (:), assume it's attribute name, and apply to all elements *regardless of value*
if (pattern.indexOf(elemSeparator) === -1) {
pattern = ['.*', elemSeparator, pattern, elemSeparator, '.*'].join('');
// if only 1 separator, assume it's element and attribute name, and apply regardless of attribute value
} else if (pattern.split(elemSeparator).length < 3) {
pattern = [pattern, elemSeparator, '.*'].join('');
}
// create regexps for element, attribute name, and attribute value
return pattern.split(elemSeparator)
.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;
var value = attr.value;
var isFillCurrentColor = preserveCurrentColor && name == 'fill' && value == 'currentColor';
var isStrokeCurrentColor = preserveCurrentColor && name == 'stroke' && value == 'currentColor';
if (!(isFillCurrentColor || isStrokeCurrentColor)) {
// matches attribute name
if (pattern[1].test(name)) {
// matches attribute value
if (pattern[2].test(attr.value)) {
item.removeAttr(name);
}
}
}
});
}
});
}
};

27
assets_old/node_modules/svgo/plugins/removeComments.js generated vendored Normal file
View file

@ -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;
}
};

32
assets_old/node_modules/svgo/plugins/removeDesc.js generated vendored Normal file
View file

@ -0,0 +1,32 @@
'use strict';
exports.type = 'perItem';
exports.active = true;
exports.params = {
removeAny: true
};
exports.description = 'removes <desc>';
var standardDescs = /^(Created with|Created using)/;
/**
* 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));
};

View file

@ -0,0 +1,49 @@
'use strict';
exports.type = 'perItem';
exports.active = false;
exports.description = 'removes width and height in presence of viewBox (opposite to removeViewBox, disable it first)';
/**
* Remove width/height attributes and add the viewBox attribute if it's missing
*
* @example
* <svg width="100" height="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')) {
if (item.hasAttr('viewBox')) {
item.removeAttr('width');
item.removeAttr('height');
} else if (
item.hasAttr('width') &&
item.hasAttr('height') &&
!isNaN(Number(item.attr('width').value)) &&
!isNaN(Number(item.attr('height').value))
) {
item.addAttr({
name: 'viewBox',
value:
'0 0 ' +
Number(item.attr('width').value) +
' ' +
Number(item.attr('height').value),
prefix: '',
local: 'viewBox'
});
item.removeAttr('width');
item.removeAttr('height');
}
}
};

40
assets_old/node_modules/svgo/plugins/removeDoctype.js generated vendored Normal file
View file

@ -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;
}
};

View file

@ -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;
}
}
};

View file

@ -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);
}
};

View file

@ -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);
}
});
}
};

View file

@ -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')));
};

View file

@ -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;
};

View file

@ -0,0 +1,225 @@
'use strict';
exports.type = 'perItem';
exports.active = true;
exports.description = 'removes hidden elements (zero sized, with absent attributes)';
exports.params = {
isHidden: true,
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) {
// Removes hidden elements
// https://www.w3schools.com/cssref/pr_class_visibility.asp
if (
params.isHidden &&
item.hasAttr('visibility', 'hidden')
) return false;
// 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;
}
};

23
assets_old/node_modules/svgo/plugins/removeMetadata.js generated vendored Normal file
View file

@ -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');
};

View file

@ -0,0 +1,37 @@
'use strict';
exports.type = 'perItem';
exports.active = true;
exports.description = 'removes non-inheritable groups presentational attributes';
var inheritableAttrs = require('./_collections').inheritableAttrs,
attrsGroups = require('./_collections').attrsGroups,
applyGroups = require('./_collections').presentationNonInheritableGroupAttrs;
/**
* 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) &&
!~inheritableAttrs.indexOf(attr.name) &&
!~applyGroups.indexOf(attr.name)
) {
item.removeAttr(attr.name);
}
});
}
};

View file

@ -0,0 +1,133 @@
'use strict';
exports.type = 'perItem';
exports.active = false;
exports.description = 'removes elements that are drawn outside of the viewbox (disabled by default)';
var SVGO = require('../lib/svgo.js'),
_path = require('./_path.js'),
intersects = _path.intersects,
path2js = _path.path2js,
viewBox,
viewBoxJS;
/**
* Remove elements that are drawn outside of the viewbox.
*
* @param {Object} item current iteration item
* @return {Boolean} if false, item will be filtered out
*
* @author JoshyPHP
*/
exports.fn = function(item) {
if (item.isElem('path') && item.hasAttr('d') && typeof viewBox !== 'undefined')
{
// Consider that any item with a transform attribute or a M instruction
// within the viewBox is visible
if (hasTransform(item) || pathMovesWithinViewBox(item.attr('d').value))
{
return true;
}
var pathJS = path2js(item);
if (pathJS.length === 2)
{
// Use a closed clone of the path if it's too short for intersects()
pathJS = JSON.parse(JSON.stringify(pathJS));
pathJS.push({ instruction: 'z' });
}
return intersects(viewBoxJS, pathJS);
}
if (item.isElem('svg'))
{
parseViewBox(item);
}
return true;
};
/**
* Test whether given item or any of its ancestors has a transform attribute.
*
* @param {String} path
* @return {Boolean}
*/
function hasTransform(item)
{
return item.hasAttr('transform') || (item.parentNode && hasTransform(item.parentNode));
}
/**
* Parse the viewBox coordinates and compute the JS representation of its path.
*
* @param {Object} svg svg element item
*/
function parseViewBox(svg)
{
var viewBoxData = '';
if (svg.hasAttr('viewBox'))
{
// Remove commas and plus signs, normalize and trim whitespace
viewBoxData = svg.attr('viewBox').value;
}
else if (svg.hasAttr('height') && svg.hasAttr('width'))
{
viewBoxData = '0 0 ' + svg.attr('width').value + ' ' + svg.attr('height').value;
}
// Remove commas and plus signs, normalize and trim whitespace
viewBoxData = viewBoxData.replace(/[,+]|px/g, ' ').replace(/\s+/g, ' ').replace(/^\s*|\s*$/g, '');
// Ensure that the dimensions are 4 values separated by space
var m = /^(-?\d*\.?\d+) (-?\d*\.?\d+) (\d*\.?\d+) (\d*\.?\d+)$/.exec(viewBoxData);
if (!m)
{
return;
}
// Store the viewBox boundaries
viewBox = {
left: parseFloat(m[1]),
top: parseFloat(m[2]),
right: parseFloat(m[1]) + parseFloat(m[3]),
bottom: parseFloat(m[2]) + parseFloat(m[4])
};
var path = new SVGO().createContentItem({
elem: 'path',
prefix: '',
local: 'path'
});
path.addAttr({
name: 'd',
prefix: '',
local: 'd',
value: 'M' + m[1] + ' ' + m[2] + 'h' + m[3] + 'v' + m[4] + 'H' + m[1] + 'z'
});
viewBoxJS = path2js(path);
}
/**
* Test whether given path has a M instruction with coordinates within the viewBox.
*
* @param {String} path
* @return {Boolean}
*/
function pathMovesWithinViewBox(path)
{
var regexp = /M\s*(-?\d*\.?\d+)(?!\d)\s*(-?\d*\.?\d+)/g, m;
while (null !== (m = regexp.exec(path)))
{
if (m[1] >= viewBox.left && m[1] <= viewBox.right && m[2] >= viewBox.top && m[2] <= viewBox.bottom)
{
return true;
}
}
return false;
}

View file

@ -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;
}
};

View file

@ -0,0 +1,23 @@
'use strict';
exports.type = 'perItem';
exports.active = false;
exports.description = 'removes <script> elements (disabled by default)';
/**
* Remove <script>.
*
* https://www.w3.org/TR/SVG/script.html
*
* @param {Object} item current iteration item
* @return {Boolean} if false, item will be filtered out
*
* @author Patrick Klingemann
*/
exports.fn = function(item) {
return !item.isElem('script');
};

View file

@ -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');
};

23
assets_old/node_modules/svgo/plugins/removeTitle.js generated vendored Normal file
View file

@ -0,0 +1,23 @@
'use strict';
exports.type = 'perItem';
exports.active = true;
exports.description = 'removes <title>';
/**
* Remove <title>.
*
* 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');
};

View file

@ -0,0 +1,150 @@
'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,
keepAriaAttrs: true,
keepRoleAttr: false
};
var collections = require('./_collections'),
elems = collections.elems,
attrsGroups = collections.attrsGroups,
elemsGroups = collections.elemsGroups,
attrsGroupsDefaults = collections.attrsGroupsDefaults,
attrsInheritable = collections.inheritableAttrs,
applyGroups = collections.presentationNonInheritableGroupAttrs;
// 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) &&
(!params.keepAriaAttrs || attr.name.indexOf('aria-') != 0) &&
(!params.keepRoleAttr || attr.name != 'role')
) {
if (
// unknown attrs
(
params.unknownAttrs &&
elems[elem].attrs.indexOf(attr.name) === -1
) ||
// attrs with default values
(
params.defaultAttrs &&
!item.hasAttr('id') &&
elems[elem].defaults &&
elems[elem].defaults[attr.name] === attr.value && (
attrsInheritable.indexOf(attr.name) < 0 ||
!item.parentNode.computedAttr(attr.name)
)
) ||
// useless overrides
(
params.uselessOverrides &&
!item.hasAttr('id') &&
applyGroups.indexOf(attr.name) < 0 &&
attrsInheritable.indexOf(attr.name) > -1 &&
item.parentNode.computedAttr(attr.name, attr.value)
)
) {
item.removeAttr(attr.name);
}
}
});
}
}
};

109
assets_old/node_modules/svgo/plugins/removeUnusedNS.js generated vendored Normal file
View file

@ -0,0 +1,109 @@
'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;
}
}
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;
};

View file

@ -0,0 +1,53 @@
'use strict';
exports.type = 'perItem';
exports.active = true;
exports.description = 'removes elements in <defs> without id';
var nonRendering = require('./_collections').elemsGroups.nonRendering;
/**
* 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')) {
if (item.content) {
item.content = getUsefulItems(item, []);
}
if (item.isEmpty()) return false;
} else if (item.isElem(nonRendering) && !item.hasAttr('id')) {
return false;
}
};
function getUsefulItems(item, usefulItems) {
item.content.forEach(function(child) {
if (child.hasAttr('id') || child.isElem('style')) {
usefulItems.push(child);
child.parentNode = item;
} else if (!child.isEmpty()) {
child.content = getUsefulItems(child, usefulItems);
}
});
return usefulItems;
}

View file

@ -0,0 +1,100 @@
'use strict';
exports.type = 'perItem';
exports.active = true;
exports.description = 'removes useless stroke and fill attributes';
exports.params = {
stroke: true,
fill: true,
removeNone: false,
hasStyleOrScript: false
};
var shape = require('./_collections').elemsGroups.shape,
regStrokeProps = /^stroke/,
regFillProps = /^fill-/,
styleOrScript = ['style', 'script'];
/**
* 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)) {
params.hasStyleOrScript = true;
}
if (!params.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'
});
}
}
if (params.removeNone &&
(!stroke || item.hasAttr('stroke') && item.attr('stroke').value=='none') &&
(!fill || item.hasAttr('fill') && item.attr('fill').value=='none')) {
return false;
}
}
};

48
assets_old/node_modules/svgo/plugins/removeViewBox.js generated vendored Normal file
View file

@ -0,0 +1,48 @@
'use strict';
exports.type = 'perItem';
exports.active = true;
exports.description = 'removes viewBox attribute when possible';
var viewBoxElems = ['svg', 'pattern', 'symbol'];
/**
* 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 nums = item.attr('viewBox').value.split(/[ ,]+/g);
if (
nums[0] === '0' &&
nums[1] === '0' &&
item.attr('width').value.replace(/px$/, '') === nums[2] && // could use parseFloat too
item.attr('height').value.replace(/px$/, '') === nums[3]
) {
item.removeAttr('viewBox');
}
}
};

28
assets_old/node_modules/svgo/plugins/removeXMLNS.js generated vendored Normal file
View file

@ -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');
}
};

View file

@ -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');
};

168
assets_old/node_modules/svgo/plugins/reusePaths.js generated vendored Normal file
View file

@ -0,0 +1,168 @@
/**
* @license
* The MIT License
*
* Copyright © 20122016 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 © 20122016 Кир Белевич
*
* Данная лицензия разрешает лицам, получившим копию
* данного
* программного обеспечения и сопутствующей
* документации
* (в дальнейшем именуемыми «Программное Обеспечение»),
* безвозмездно
* использовать Программное Обеспечение без
* ограничений, включая
* неограниченное право на использование, копирование,
* изменение,
* добавление, публикацию, распространение,
* сублицензирование
* и/или продажу копий Программного Обеспечения, также
* как и лицам,
* которым предоставляется данное Программное
* Обеспечение,
* при соблюдении следующих условий:
*
* Указанное выше уведомление об авторском праве и
* данные условия
* должны быть включены во все копии или значимые части
* данного
* Программного Обеспечения.
*
* ДАННОЕ ПРОГРАММНОЕ ОБЕСПЕЧЕНИЕ ПРЕДОСТАВЛЯЕТСЯ «КАК
* ЕСТЬ»,
* БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ, ЯВНО ВЫРАЖЕННЫХ ИЛИ
* ПОДРАЗУМЕВАЕМЫХ,
* ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИВАЯСЬ ГАРАНТИЯМИ ТОВАРНОЙ
* ПРИГОДНОСТИ,
* СООТВЕТСТВИЯ ПО ЕГО КОНКРЕТНОМУ НАЗНАЧЕНИЮ И
* ОТСУТСТВИЯ НАРУШЕНИЙ
* ПРАВ. НИ В КАКОМ СЛУЧАЕ АВТОРЫ ИЛИ ПРАВООБЛАДАТЕЛИ НЕ
* НЕСУТ
* ОТВЕТСТВЕННОСТИ ПО ИСКАМ О ВОЗМЕЩЕНИИ УЩЕРБА, УБЫТКОВ
* ИЛИ ДРУГИХ
* ТРЕБОВАНИЙ ПО ДЕЙСТВУЮЩИМ КОНТРАКТАМ, ДЕЛИКТАМ ИЛИ
* ИНОМУ,
* ВОЗНИКШИМ ИЗ, ИМЕЮЩИМ ПРИЧИНОЙ ИЛИ СВЯЗАННЫМ С
* ПРОГРАММНЫМ
* ОБЕСПЕЧЕНИЕМ ИЛИ ИСПОЛЬЗОВАНИЕМ ПРОГРАММНОГО
* ОБЕСПЕЧЕНИЯ
* ИЛИ ИНЫМИ ДЕЙСТВИЯМИ С ПРОГРАММНЫМ ОБЕСПЕЧЕНИЕМ.
*/
'use strict';
var JSAPI = require('../lib/svgo/jsAPI');
exports.type = 'full';
exports.active = false;
exports.description = 'Finds <path> elements with the same d, fill, and ' +
'stroke, and converts them to <use> elements ' +
'referencing a single <path> def.';
/**
* Finds <path> elements with the same d, fill, and stroke, and converts them to
* <use> elements referencing a single <path> def.
*
* @author Jacob Howcroft
*/
exports.fn = function(data) {
const seen = new Map();
let count = 0;
const defs = [];
traverse(data, item => {
if (!item.isElem('path') || !item.hasAttr('d')) {
return;
}
const d = item.attr('d').value;
const fill = (item.hasAttr('fill') && item.attr('fill').value) || '';
const stroke = (item.hasAttr('stroke') && item.attr('stroke').value) || '';
const key = d + ';s:' + stroke + ';f:' + fill;
const hasSeen = seen.get(key);
if (!hasSeen) {
seen.set(key, {elem: item, reused: false});
return;
}
if (!hasSeen.reused) {
hasSeen.reused = true;
if (!hasSeen.elem.hasAttr('id')) {
hasSeen.elem.addAttr({name: 'id', local: 'id',
prefix: '', value: 'reuse-' + (count++)});
}
defs.push(hasSeen.elem);
}
item = convertToUse(item, hasSeen.elem.attr('id').value);
});
const defsTag = new JSAPI({
elem: 'defs', prefix: '', local: 'defs', content: [], attrs: []}, data);
data.content[0].spliceContent(0, 0, defsTag);
for (let def of defs) {
// Remove class and style before copying to avoid circular refs in
// JSON.stringify. This is fine because we don't actually want class or
// style information to be copied.
const style = def.style;
const defClass = def.class;
delete def.style;
delete def.class;
const defClone = def.clone();
def.style = style;
def.class = defClass;
defClone.removeAttr('transform');
defsTag.spliceContent(0, 0, defClone);
// Convert the original def to a use so the first usage isn't duplicated.
def = convertToUse(def, defClone.attr('id').value);
def.removeAttr('id');
}
return data;
};
/** */
function convertToUse(item, href) {
item.renameElem('use');
item.removeAttr('d');
item.removeAttr('stroke');
item.removeAttr('fill');
item.addAttr({name: 'xlink:href', local: 'xlink:href',
prefix: 'none', value: '#' + href});
delete item.pathJS;
return item;
}
/** */
function traverse(parent, callback) {
if (parent.isEmpty()) {
return;
}
for (let child of parent.content) {
callback(child);
traverse(child, callback);
}
}

84
assets_old/node_modules/svgo/plugins/sortAttrs.js generated vendored Normal file
View file

@ -0,0 +1,84 @@
'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,
xmlnsOrder = params.xmlnsOrder || 'front';
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 (xmlnsOrder == 'front') {
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;
}
};

View file

@ -0,0 +1,47 @@
'use strict';
exports.type = 'perItem';
exports.active = true;
exports.description = 'Sorts children of <defs> to improve compression';
/**
* Sorts children of defs in order to improve compression.
* Sorted first by frequency then by element name length then by element name (to ensure grouping).
*
* @param {Object} item current iteration item
* @return {Boolean} if false, item will be filtered out
*
* @author David Leston
*/
exports.fn = function(item) {
if (item.isElem('defs')) {
if (item.content) {
var frequency = item.content.reduce(function (frequency, child) {
if (child.elem in frequency) {
frequency[child.elem]++;
} else {
frequency[child.elem] = 1;
}
return frequency;
}, {});
item.content.sort(function (a, b) {
var frequencyComparison = frequency[b.elem] - frequency[a.elem];
if (frequencyComparison !== 0 ) {
return frequencyComparison;
}
var lengthComparison = b.elem.length - a.elem.length;
if (lengthComparison !== 0) {
return lengthComparison;
}
return a.elem != b.elem ? a.elem > b.elem ? -1 : 1 : 0;
});
}
return true;
}
};