更新前端静态网页获取方式,放弃使用后端获取api

This commit is contained in:
2025-09-09 10:47:51 +08:00
parent 6889ca37e5
commit 44a4f1bae1
25558 changed files with 2463152 additions and 153 deletions

75
frontend/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
frontend/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
frontend/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
frontend/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
frontend/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
frontend/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
frontend/node_modules/svgo/bin/svgo generated vendored Executable file
View File

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

View File

@@ -0,0 +1,165 @@
'use strict';
const colorConvert = require('color-convert');
const wrapAnsi16 = (fn, offset) => function () {
const code = fn.apply(colorConvert, arguments);
return `\u001B[${code + offset}m`;
};
const wrapAnsi256 = (fn, offset) => function () {
const code = fn.apply(colorConvert, arguments);
return `\u001B[${38 + offset};5;${code}m`;
};
const wrapAnsi16m = (fn, offset) => function () {
const rgb = fn.apply(colorConvert, arguments);
return `\u001B[${38 + offset};2;${rgb[0]};${rgb[1]};${rgb[2]}m`;
};
function assembleStyles() {
const codes = new Map();
const styles = {
modifier: {
reset: [0, 0],
// 21 isn't widely supported and 22 does the same thing
bold: [1, 22],
dim: [2, 22],
italic: [3, 23],
underline: [4, 24],
inverse: [7, 27],
hidden: [8, 28],
strikethrough: [9, 29]
},
color: {
black: [30, 39],
red: [31, 39],
green: [32, 39],
yellow: [33, 39],
blue: [34, 39],
magenta: [35, 39],
cyan: [36, 39],
white: [37, 39],
gray: [90, 39],
// Bright color
redBright: [91, 39],
greenBright: [92, 39],
yellowBright: [93, 39],
blueBright: [94, 39],
magentaBright: [95, 39],
cyanBright: [96, 39],
whiteBright: [97, 39]
},
bgColor: {
bgBlack: [40, 49],
bgRed: [41, 49],
bgGreen: [42, 49],
bgYellow: [43, 49],
bgBlue: [44, 49],
bgMagenta: [45, 49],
bgCyan: [46, 49],
bgWhite: [47, 49],
// Bright color
bgBlackBright: [100, 49],
bgRedBright: [101, 49],
bgGreenBright: [102, 49],
bgYellowBright: [103, 49],
bgBlueBright: [104, 49],
bgMagentaBright: [105, 49],
bgCyanBright: [106, 49],
bgWhiteBright: [107, 49]
}
};
// Fix humans
styles.color.grey = styles.color.gray;
for (const groupName of Object.keys(styles)) {
const group = styles[groupName];
for (const styleName of Object.keys(group)) {
const style = group[styleName];
styles[styleName] = {
open: `\u001B[${style[0]}m`,
close: `\u001B[${style[1]}m`
};
group[styleName] = styles[styleName];
codes.set(style[0], style[1]);
}
Object.defineProperty(styles, groupName, {
value: group,
enumerable: false
});
Object.defineProperty(styles, 'codes', {
value: codes,
enumerable: false
});
}
const ansi2ansi = n => n;
const rgb2rgb = (r, g, b) => [r, g, b];
styles.color.close = '\u001B[39m';
styles.bgColor.close = '\u001B[49m';
styles.color.ansi = {
ansi: wrapAnsi16(ansi2ansi, 0)
};
styles.color.ansi256 = {
ansi256: wrapAnsi256(ansi2ansi, 0)
};
styles.color.ansi16m = {
rgb: wrapAnsi16m(rgb2rgb, 0)
};
styles.bgColor.ansi = {
ansi: wrapAnsi16(ansi2ansi, 10)
};
styles.bgColor.ansi256 = {
ansi256: wrapAnsi256(ansi2ansi, 10)
};
styles.bgColor.ansi16m = {
rgb: wrapAnsi16m(rgb2rgb, 10)
};
for (let key of Object.keys(colorConvert)) {
if (typeof colorConvert[key] !== 'object') {
continue;
}
const suite = colorConvert[key];
if (key === 'ansi16') {
key = 'ansi';
}
if ('ansi16' in suite) {
styles.color.ansi[key] = wrapAnsi16(suite.ansi16, 0);
styles.bgColor.ansi[key] = wrapAnsi16(suite.ansi16, 10);
}
if ('ansi256' in suite) {
styles.color.ansi256[key] = wrapAnsi256(suite.ansi256, 0);
styles.bgColor.ansi256[key] = wrapAnsi256(suite.ansi256, 10);
}
if ('rgb' in suite) {
styles.color.ansi16m[key] = wrapAnsi16m(suite.rgb, 0);
styles.bgColor.ansi16m[key] = wrapAnsi16m(suite.rgb, 10);
}
}
return styles;
}
// Make the export immutable
Object.defineProperty(module, 'exports', {
enumerable: true,
get: assembleStyles
});

View File

@@ -0,0 +1,9 @@
MIT License
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -0,0 +1,56 @@
{
"name": "ansi-styles",
"version": "3.2.1",
"description": "ANSI escape codes for styling strings in the terminal",
"license": "MIT",
"repository": "chalk/ansi-styles",
"author": {
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
"url": "sindresorhus.com"
},
"engines": {
"node": ">=4"
},
"scripts": {
"test": "xo && ava",
"screenshot": "svg-term --command='node screenshot' --out=screenshot.svg --padding=3 --width=55 --height=3 --at=1000 --no-cursor"
},
"files": [
"index.js"
],
"keywords": [
"ansi",
"styles",
"color",
"colour",
"colors",
"terminal",
"console",
"cli",
"string",
"tty",
"escape",
"formatting",
"rgb",
"256",
"shell",
"xterm",
"log",
"logging",
"command-line",
"text"
],
"dependencies": {
"color-convert": "^1.9.0"
},
"devDependencies": {
"ava": "*",
"babel-polyfill": "^6.23.0",
"svg-term-cli": "^2.1.1",
"xo": "*"
},
"ava": {
"require": "babel-polyfill"
}
}

View File

@@ -0,0 +1,147 @@
# ansi-styles [![Build Status](https://travis-ci.org/chalk/ansi-styles.svg?branch=master)](https://travis-ci.org/chalk/ansi-styles)
> [ANSI escape codes](http://en.wikipedia.org/wiki/ANSI_escape_code#Colors_and_Styles) for styling strings in the terminal
You probably want the higher-level [chalk](https://github.com/chalk/chalk) module for styling your strings.
<img src="https://cdn.rawgit.com/chalk/ansi-styles/8261697c95bf34b6c7767e2cbe9941a851d59385/screenshot.svg" width="900">
## Install
```
$ npm install ansi-styles
```
## Usage
```js
const style = require('ansi-styles');
console.log(`${style.green.open}Hello world!${style.green.close}`);
// Color conversion between 16/256/truecolor
// NOTE: If conversion goes to 16 colors or 256 colors, the original color
// may be degraded to fit that color palette. This means terminals
// that do not support 16 million colors will best-match the
// original color.
console.log(style.bgColor.ansi.hsl(120, 80, 72) + 'Hello world!' + style.bgColor.close);
console.log(style.color.ansi256.rgb(199, 20, 250) + 'Hello world!' + style.color.close);
console.log(style.color.ansi16m.hex('#ABCDEF') + 'Hello world!' + style.color.close);
```
## API
Each style has an `open` and `close` property.
## Styles
### Modifiers
- `reset`
- `bold`
- `dim`
- `italic` *(Not widely supported)*
- `underline`
- `inverse`
- `hidden`
- `strikethrough` *(Not widely supported)*
### Colors
- `black`
- `red`
- `green`
- `yellow`
- `blue`
- `magenta`
- `cyan`
- `white`
- `gray` ("bright black")
- `redBright`
- `greenBright`
- `yellowBright`
- `blueBright`
- `magentaBright`
- `cyanBright`
- `whiteBright`
### Background colors
- `bgBlack`
- `bgRed`
- `bgGreen`
- `bgYellow`
- `bgBlue`
- `bgMagenta`
- `bgCyan`
- `bgWhite`
- `bgBlackBright`
- `bgRedBright`
- `bgGreenBright`
- `bgYellowBright`
- `bgBlueBright`
- `bgMagentaBright`
- `bgCyanBright`
- `bgWhiteBright`
## Advanced usage
By default, you get a map of styles, but the styles are also available as groups. They are non-enumerable so they don't show up unless you access them explicitly. This makes it easier to expose only a subset in a higher-level module.
- `style.modifier`
- `style.color`
- `style.bgColor`
###### Example
```js
console.log(style.color.green.open);
```
Raw escape codes (i.e. without the CSI escape prefix `\u001B[` and render mode postfix `m`) are available under `style.codes`, which returns a `Map` with the open codes as keys and close codes as values.
###### Example
```js
console.log(style.codes.get(36));
//=> 39
```
## [256 / 16 million (TrueColor) support](https://gist.github.com/XVilka/8346728)
`ansi-styles` uses the [`color-convert`](https://github.com/Qix-/color-convert) package to allow for converting between various colors and ANSI escapes, with support for 256 and 16 million colors.
To use these, call the associated conversion function with the intended output, for example:
```js
style.color.ansi.rgb(100, 200, 15); // RGB to 16 color ansi foreground code
style.bgColor.ansi.rgb(100, 200, 15); // RGB to 16 color ansi background code
style.color.ansi256.hsl(120, 100, 60); // HSL to 256 color ansi foreground code
style.bgColor.ansi256.hsl(120, 100, 60); // HSL to 256 color ansi foreground code
style.color.ansi16m.hex('#C0FFEE'); // Hex (RGB) to 16 million color foreground code
style.bgColor.ansi16m.hex('#C0FFEE'); // Hex (RGB) to 16 million color background code
```
## Related
- [ansi-escapes](https://github.com/sindresorhus/ansi-escapes) - ANSI escape codes for manipulating the terminal
## Maintainers
- [Sindre Sorhus](https://github.com/sindresorhus)
- [Josh Junon](https://github.com/qix-)
## License
MIT

228
frontend/node_modules/svgo/node_modules/chalk/index.js generated vendored Normal file
View File

@@ -0,0 +1,228 @@
'use strict';
const escapeStringRegexp = require('escape-string-regexp');
const ansiStyles = require('ansi-styles');
const stdoutColor = require('supports-color').stdout;
const template = require('./templates.js');
const isSimpleWindowsTerm = process.platform === 'win32' && !(process.env.TERM || '').toLowerCase().startsWith('xterm');
// `supportsColor.level` → `ansiStyles.color[name]` mapping
const levelMapping = ['ansi', 'ansi', 'ansi256', 'ansi16m'];
// `color-convert` models to exclude from the Chalk API due to conflicts and such
const skipModels = new Set(['gray']);
const styles = Object.create(null);
function applyOptions(obj, options) {
options = options || {};
// Detect level if not set manually
const scLevel = stdoutColor ? stdoutColor.level : 0;
obj.level = options.level === undefined ? scLevel : options.level;
obj.enabled = 'enabled' in options ? options.enabled : obj.level > 0;
}
function Chalk(options) {
// We check for this.template here since calling `chalk.constructor()`
// by itself will have a `this` of a previously constructed chalk object
if (!this || !(this instanceof Chalk) || this.template) {
const chalk = {};
applyOptions(chalk, options);
chalk.template = function () {
const args = [].slice.call(arguments);
return chalkTag.apply(null, [chalk.template].concat(args));
};
Object.setPrototypeOf(chalk, Chalk.prototype);
Object.setPrototypeOf(chalk.template, chalk);
chalk.template.constructor = Chalk;
return chalk.template;
}
applyOptions(this, options);
}
// Use bright blue on Windows as the normal blue color is illegible
if (isSimpleWindowsTerm) {
ansiStyles.blue.open = '\u001B[94m';
}
for (const key of Object.keys(ansiStyles)) {
ansiStyles[key].closeRe = new RegExp(escapeStringRegexp(ansiStyles[key].close), 'g');
styles[key] = {
get() {
const codes = ansiStyles[key];
return build.call(this, this._styles ? this._styles.concat(codes) : [codes], this._empty, key);
}
};
}
styles.visible = {
get() {
return build.call(this, this._styles || [], true, 'visible');
}
};
ansiStyles.color.closeRe = new RegExp(escapeStringRegexp(ansiStyles.color.close), 'g');
for (const model of Object.keys(ansiStyles.color.ansi)) {
if (skipModels.has(model)) {
continue;
}
styles[model] = {
get() {
const level = this.level;
return function () {
const open = ansiStyles.color[levelMapping[level]][model].apply(null, arguments);
const codes = {
open,
close: ansiStyles.color.close,
closeRe: ansiStyles.color.closeRe
};
return build.call(this, this._styles ? this._styles.concat(codes) : [codes], this._empty, model);
};
}
};
}
ansiStyles.bgColor.closeRe = new RegExp(escapeStringRegexp(ansiStyles.bgColor.close), 'g');
for (const model of Object.keys(ansiStyles.bgColor.ansi)) {
if (skipModels.has(model)) {
continue;
}
const bgModel = 'bg' + model[0].toUpperCase() + model.slice(1);
styles[bgModel] = {
get() {
const level = this.level;
return function () {
const open = ansiStyles.bgColor[levelMapping[level]][model].apply(null, arguments);
const codes = {
open,
close: ansiStyles.bgColor.close,
closeRe: ansiStyles.bgColor.closeRe
};
return build.call(this, this._styles ? this._styles.concat(codes) : [codes], this._empty, model);
};
}
};
}
const proto = Object.defineProperties(() => {}, styles);
function build(_styles, _empty, key) {
const builder = function () {
return applyStyle.apply(builder, arguments);
};
builder._styles = _styles;
builder._empty = _empty;
const self = this;
Object.defineProperty(builder, 'level', {
enumerable: true,
get() {
return self.level;
},
set(level) {
self.level = level;
}
});
Object.defineProperty(builder, 'enabled', {
enumerable: true,
get() {
return self.enabled;
},
set(enabled) {
self.enabled = enabled;
}
});
// See below for fix regarding invisible grey/dim combination on Windows
builder.hasGrey = this.hasGrey || key === 'gray' || key === 'grey';
// `__proto__` is used because we must return a function, but there is
// no way to create a function with a different prototype
builder.__proto__ = proto; // eslint-disable-line no-proto
return builder;
}
function applyStyle() {
// Support varags, but simply cast to string in case there's only one arg
const args = arguments;
const argsLen = args.length;
let str = String(arguments[0]);
if (argsLen === 0) {
return '';
}
if (argsLen > 1) {
// Don't slice `arguments`, it prevents V8 optimizations
for (let a = 1; a < argsLen; a++) {
str += ' ' + args[a];
}
}
if (!this.enabled || this.level <= 0 || !str) {
return this._empty ? '' : str;
}
// Turns out that on Windows dimmed gray text becomes invisible in cmd.exe,
// see https://github.com/chalk/chalk/issues/58
// If we're on Windows and we're dealing with a gray color, temporarily make 'dim' a noop.
const originalDim = ansiStyles.dim.open;
if (isSimpleWindowsTerm && this.hasGrey) {
ansiStyles.dim.open = '';
}
for (const code of this._styles.slice().reverse()) {
// Replace any instances already present with a re-opening code
// otherwise only the part of the string until said closing code
// will be colored, and the rest will simply be 'plain'.
str = code.open + str.replace(code.closeRe, code.open) + code.close;
// Close the styling before a linebreak and reopen
// after next line to fix a bleed issue on macOS
// https://github.com/chalk/chalk/pull/92
str = str.replace(/\r?\n/g, `${code.close}$&${code.open}`);
}
// Reset the original `dim` if we changed it to work around the Windows dimmed gray issue
ansiStyles.dim.open = originalDim;
return str;
}
function chalkTag(chalk, strings) {
if (!Array.isArray(strings)) {
// If chalk() was called by itself or with a string,
// return the string itself as a string.
return [].slice.call(arguments, 1).join(' ');
}
const args = [].slice.call(arguments, 2);
const parts = [strings.raw[0]];
for (let i = 1; i < strings.length; i++) {
parts.push(String(args[i - 1]).replace(/[{}\\]/g, '\\$&'));
parts.push(String(strings.raw[i]));
}
return template(chalk, parts.join(''));
}
Object.defineProperties(Chalk.prototype, styles);
module.exports = Chalk(); // eslint-disable-line new-cap
module.exports.supportsColor = stdoutColor;
module.exports.default = module.exports; // For TypeScript

View File

@@ -0,0 +1,93 @@
// @flow strict
type TemplateStringsArray = $ReadOnlyArray<string>;
export type Level = $Values<{
None: 0,
Basic: 1,
Ansi256: 2,
TrueColor: 3
}>;
export type ChalkOptions = {|
enabled?: boolean,
level?: Level
|};
export type ColorSupport = {|
level: Level,
hasBasic: boolean,
has256: boolean,
has16m: boolean
|};
export interface Chalk {
(...text: string[]): string,
(text: TemplateStringsArray, ...placeholders: string[]): string,
constructor(options?: ChalkOptions): Chalk,
enabled: boolean,
level: Level,
rgb(r: number, g: number, b: number): Chalk,
hsl(h: number, s: number, l: number): Chalk,
hsv(h: number, s: number, v: number): Chalk,
hwb(h: number, w: number, b: number): Chalk,
bgHex(color: string): Chalk,
bgKeyword(color: string): Chalk,
bgRgb(r: number, g: number, b: number): Chalk,
bgHsl(h: number, s: number, l: number): Chalk,
bgHsv(h: number, s: number, v: number): Chalk,
bgHwb(h: number, w: number, b: number): Chalk,
hex(color: string): Chalk,
keyword(color: string): Chalk,
+reset: Chalk,
+bold: Chalk,
+dim: Chalk,
+italic: Chalk,
+underline: Chalk,
+inverse: Chalk,
+hidden: Chalk,
+strikethrough: Chalk,
+visible: Chalk,
+black: Chalk,
+red: Chalk,
+green: Chalk,
+yellow: Chalk,
+blue: Chalk,
+magenta: Chalk,
+cyan: Chalk,
+white: Chalk,
+gray: Chalk,
+grey: Chalk,
+blackBright: Chalk,
+redBright: Chalk,
+greenBright: Chalk,
+yellowBright: Chalk,
+blueBright: Chalk,
+magentaBright: Chalk,
+cyanBright: Chalk,
+whiteBright: Chalk,
+bgBlack: Chalk,
+bgRed: Chalk,
+bgGreen: Chalk,
+bgYellow: Chalk,
+bgBlue: Chalk,
+bgMagenta: Chalk,
+bgCyan: Chalk,
+bgWhite: Chalk,
+bgBlackBright: Chalk,
+bgRedBright: Chalk,
+bgGreenBright: Chalk,
+bgYellowBright: Chalk,
+bgBlueBright: Chalk,
+bgMagentaBright: Chalk,
+bgCyanBright: Chalk,
+bgWhiteBrigh: Chalk,
supportsColor: ColorSupport
};
declare module.exports: Chalk;

View File

@@ -0,0 +1,9 @@
MIT License
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -0,0 +1,71 @@
{
"name": "chalk",
"version": "2.4.2",
"description": "Terminal string styling done right",
"license": "MIT",
"repository": "chalk/chalk",
"engines": {
"node": ">=4"
},
"scripts": {
"test": "xo && tsc --project types && flow --max-warnings=0 && nyc ava",
"bench": "matcha benchmark.js",
"coveralls": "nyc report --reporter=text-lcov | coveralls"
},
"files": [
"index.js",
"templates.js",
"types/index.d.ts",
"index.js.flow"
],
"keywords": [
"color",
"colour",
"colors",
"terminal",
"console",
"cli",
"string",
"str",
"ansi",
"style",
"styles",
"tty",
"formatting",
"rgb",
"256",
"shell",
"xterm",
"log",
"logging",
"command-line",
"text"
],
"dependencies": {
"ansi-styles": "^3.2.1",
"escape-string-regexp": "^1.0.5",
"supports-color": "^5.3.0"
},
"devDependencies": {
"ava": "*",
"coveralls": "^3.0.0",
"execa": "^0.9.0",
"flow-bin": "^0.68.0",
"import-fresh": "^2.0.0",
"matcha": "^0.7.0",
"nyc": "^11.0.2",
"resolve-from": "^4.0.0",
"typescript": "^2.5.3",
"xo": "*"
},
"types": "types/index.d.ts",
"xo": {
"envs": [
"node",
"mocha"
],
"ignores": [
"test/_flow.js"
]
}
}

314
frontend/node_modules/svgo/node_modules/chalk/readme.md generated vendored Normal file
View File

@@ -0,0 +1,314 @@
<h1 align="center">
<br>
<br>
<img width="320" src="media/logo.svg" alt="Chalk">
<br>
<br>
<br>
</h1>
> Terminal string styling done right
[![Build Status](https://travis-ci.org/chalk/chalk.svg?branch=master)](https://travis-ci.org/chalk/chalk) [![Coverage Status](https://coveralls.io/repos/github/chalk/chalk/badge.svg?branch=master)](https://coveralls.io/github/chalk/chalk?branch=master) [![](https://img.shields.io/badge/unicorn-approved-ff69b4.svg)](https://www.youtube.com/watch?v=9auOCbH5Ns4) [![XO code style](https://img.shields.io/badge/code_style-XO-5ed9c7.svg)](https://github.com/xojs/xo) [![Mentioned in Awesome Node.js](https://awesome.re/mentioned-badge.svg)](https://github.com/sindresorhus/awesome-nodejs)
### [See what's new in Chalk 2](https://github.com/chalk/chalk/releases/tag/v2.0.0)
<img src="https://cdn.rawgit.com/chalk/ansi-styles/8261697c95bf34b6c7767e2cbe9941a851d59385/screenshot.svg" alt="" width="900">
## Highlights
- Expressive API
- Highly performant
- Ability to nest styles
- [256/Truecolor color support](#256-and-truecolor-color-support)
- Auto-detects color support
- Doesn't extend `String.prototype`
- Clean and focused
- Actively maintained
- [Used by ~23,000 packages](https://www.npmjs.com/browse/depended/chalk) as of December 31, 2017
## Install
```console
$ npm install chalk
```
<a href="https://www.patreon.com/sindresorhus">
<img src="https://c5.patreon.com/external/logo/become_a_patron_button@2x.png" width="160">
</a>
## Usage
```js
const chalk = require('chalk');
console.log(chalk.blue('Hello world!'));
```
Chalk comes with an easy to use composable API where you just chain and nest the styles you want.
```js
const chalk = require('chalk');
const log = console.log;
// Combine styled and normal strings
log(chalk.blue('Hello') + ' World' + chalk.red('!'));
// Compose multiple styles using the chainable API
log(chalk.blue.bgRed.bold('Hello world!'));
// Pass in multiple arguments
log(chalk.blue('Hello', 'World!', 'Foo', 'bar', 'biz', 'baz'));
// Nest styles
log(chalk.red('Hello', chalk.underline.bgBlue('world') + '!'));
// Nest styles of the same type even (color, underline, background)
log(chalk.green(
'I am a green line ' +
chalk.blue.underline.bold('with a blue substring') +
' that becomes green again!'
));
// ES2015 template literal
log(`
CPU: ${chalk.red('90%')}
RAM: ${chalk.green('40%')}
DISK: ${chalk.yellow('70%')}
`);
// ES2015 tagged template literal
log(chalk`
CPU: {red ${cpu.totalPercent}%}
RAM: {green ${ram.used / ram.total * 100}%}
DISK: {rgb(255,131,0) ${disk.used / disk.total * 100}%}
`);
// Use RGB colors in terminal emulators that support it.
log(chalk.keyword('orange')('Yay for orange colored text!'));
log(chalk.rgb(123, 45, 67).underline('Underlined reddish color'));
log(chalk.hex('#DEADED').bold('Bold gray!'));
```
Easily define your own themes:
```js
const chalk = require('chalk');
const error = chalk.bold.red;
const warning = chalk.keyword('orange');
console.log(error('Error!'));
console.log(warning('Warning!'));
```
Take advantage of console.log [string substitution](https://nodejs.org/docs/latest/api/console.html#console_console_log_data_args):
```js
const name = 'Sindre';
console.log(chalk.green('Hello %s'), name);
//=> 'Hello Sindre'
```
## API
### chalk.`<style>[.<style>...](string, [string...])`
Example: `chalk.red.bold.underline('Hello', 'world');`
Chain [styles](#styles) and call the last one as a method with a string argument. Order doesn't matter, and later styles take precedent in case of a conflict. This simply means that `chalk.red.yellow.green` is equivalent to `chalk.green`.
Multiple arguments will be separated by space.
### chalk.enabled
Color support is automatically detected, as is the level (see `chalk.level`). However, if you'd like to simply enable/disable Chalk, you can do so via the `.enabled` property.
Chalk is enabled by default unless explicitly disabled via the constructor or `chalk.level` is `0`.
If you need to change this in a reusable module, create a new instance:
```js
const ctx = new chalk.constructor({enabled: false});
```
### chalk.level
Color support is automatically detected, but you can override it by setting the `level` property. You should however only do this in your own code as it applies globally to all Chalk consumers.
If you need to change this in a reusable module, create a new instance:
```js
const ctx = new chalk.constructor({level: 0});
```
Levels are as follows:
0. All colors disabled
1. Basic color support (16 colors)
2. 256 color support
3. Truecolor support (16 million colors)
### chalk.supportsColor
Detect whether the terminal [supports color](https://github.com/chalk/supports-color). Used internally and handled for you, but exposed for convenience.
Can be overridden by the user with the flags `--color` and `--no-color`. For situations where using `--color` is not possible, add the environment variable `FORCE_COLOR=1` to forcefully enable color or `FORCE_COLOR=0` to forcefully disable. The use of `FORCE_COLOR` overrides all other color support checks.
Explicit 256/Truecolor mode can be enabled using the `--color=256` and `--color=16m` flags, respectively.
## Styles
### Modifiers
- `reset`
- `bold`
- `dim`
- `italic` *(Not widely supported)*
- `underline`
- `inverse`
- `hidden`
- `strikethrough` *(Not widely supported)*
- `visible` (Text is emitted only if enabled)
### Colors
- `black`
- `red`
- `green`
- `yellow`
- `blue` *(On Windows the bright version is used since normal blue is illegible)*
- `magenta`
- `cyan`
- `white`
- `gray` ("bright black")
- `redBright`
- `greenBright`
- `yellowBright`
- `blueBright`
- `magentaBright`
- `cyanBright`
- `whiteBright`
### Background colors
- `bgBlack`
- `bgRed`
- `bgGreen`
- `bgYellow`
- `bgBlue`
- `bgMagenta`
- `bgCyan`
- `bgWhite`
- `bgBlackBright`
- `bgRedBright`
- `bgGreenBright`
- `bgYellowBright`
- `bgBlueBright`
- `bgMagentaBright`
- `bgCyanBright`
- `bgWhiteBright`
## Tagged template literal
Chalk can be used as a [tagged template literal](http://exploringjs.com/es6/ch_template-literals.html#_tagged-template-literals).
```js
const chalk = require('chalk');
const miles = 18;
const calculateFeet = miles => miles * 5280;
console.log(chalk`
There are {bold 5280 feet} in a mile.
In {bold ${miles} miles}, there are {green.bold ${calculateFeet(miles)} feet}.
`);
```
Blocks are delimited by an opening curly brace (`{`), a style, some content, and a closing curly brace (`}`).
Template styles are chained exactly like normal Chalk styles. The following two statements are equivalent:
```js
console.log(chalk.bold.rgb(10, 100, 200)('Hello!'));
console.log(chalk`{bold.rgb(10,100,200) Hello!}`);
```
Note that function styles (`rgb()`, `hsl()`, `keyword()`, etc.) may not contain spaces between parameters.
All interpolated values (`` chalk`${foo}` ``) are converted to strings via the `.toString()` method. All curly braces (`{` and `}`) in interpolated value strings are escaped.
## 256 and Truecolor color support
Chalk supports 256 colors and [Truecolor](https://gist.github.com/XVilka/8346728) (16 million colors) on supported terminal apps.
Colors are downsampled from 16 million RGB values to an ANSI color format that is supported by the terminal emulator (or by specifying `{level: n}` as a Chalk option). For example, Chalk configured to run at level 1 (basic color support) will downsample an RGB value of #FF0000 (red) to 31 (ANSI escape for red).
Examples:
- `chalk.hex('#DEADED').underline('Hello, world!')`
- `chalk.keyword('orange')('Some orange text')`
- `chalk.rgb(15, 100, 204).inverse('Hello!')`
Background versions of these models are prefixed with `bg` and the first level of the module capitalized (e.g. `keyword` for foreground colors and `bgKeyword` for background colors).
- `chalk.bgHex('#DEADED').underline('Hello, world!')`
- `chalk.bgKeyword('orange')('Some orange text')`
- `chalk.bgRgb(15, 100, 204).inverse('Hello!')`
The following color models can be used:
- [`rgb`](https://en.wikipedia.org/wiki/RGB_color_model) - Example: `chalk.rgb(255, 136, 0).bold('Orange!')`
- [`hex`](https://en.wikipedia.org/wiki/Web_colors#Hex_triplet) - Example: `chalk.hex('#FF8800').bold('Orange!')`
- [`keyword`](https://www.w3.org/wiki/CSS/Properties/color/keywords) (CSS keywords) - Example: `chalk.keyword('orange').bold('Orange!')`
- [`hsl`](https://en.wikipedia.org/wiki/HSL_and_HSV) - Example: `chalk.hsl(32, 100, 50).bold('Orange!')`
- [`hsv`](https://en.wikipedia.org/wiki/HSL_and_HSV) - Example: `chalk.hsv(32, 100, 100).bold('Orange!')`
- [`hwb`](https://en.wikipedia.org/wiki/HWB_color_model) - Example: `chalk.hwb(32, 0, 50).bold('Orange!')`
- `ansi16`
- `ansi256`
## Windows
If you're on Windows, do yourself a favor and use [`cmder`](http://cmder.net/) instead of `cmd.exe`.
## Origin story
[colors.js](https://github.com/Marak/colors.js) used to be the most popular string styling module, but it has serious deficiencies like extending `String.prototype` which causes all kinds of [problems](https://github.com/yeoman/yo/issues/68) and the package is unmaintained. Although there are other packages, they either do too much or not enough. Chalk is a clean and focused alternative.
## Related
- [chalk-cli](https://github.com/chalk/chalk-cli) - CLI for this module
- [ansi-styles](https://github.com/chalk/ansi-styles) - ANSI escape codes for styling strings in the terminal
- [supports-color](https://github.com/chalk/supports-color) - Detect whether a terminal supports color
- [strip-ansi](https://github.com/chalk/strip-ansi) - Strip ANSI escape codes
- [strip-ansi-stream](https://github.com/chalk/strip-ansi-stream) - Strip ANSI escape codes from a stream
- [has-ansi](https://github.com/chalk/has-ansi) - Check if a string has ANSI escape codes
- [ansi-regex](https://github.com/chalk/ansi-regex) - Regular expression for matching ANSI escape codes
- [wrap-ansi](https://github.com/chalk/wrap-ansi) - Wordwrap a string with ANSI escape codes
- [slice-ansi](https://github.com/chalk/slice-ansi) - Slice a string with ANSI escape codes
- [color-convert](https://github.com/qix-/color-convert) - Converts colors between different models
- [chalk-animation](https://github.com/bokub/chalk-animation) - Animate strings in the terminal
- [gradient-string](https://github.com/bokub/gradient-string) - Apply color gradients to strings
- [chalk-pipe](https://github.com/LitoMore/chalk-pipe) - Create chalk style schemes with simpler style strings
- [terminal-link](https://github.com/sindresorhus/terminal-link) - Create clickable links in the terminal
## Maintainers
- [Sindre Sorhus](https://github.com/sindresorhus)
- [Josh Junon](https://github.com/qix-)
## License
MIT

View File

@@ -0,0 +1,128 @@
'use strict';
const TEMPLATE_REGEX = /(?:\\(u[a-f\d]{4}|x[a-f\d]{2}|.))|(?:\{(~)?(\w+(?:\([^)]*\))?(?:\.\w+(?:\([^)]*\))?)*)(?:[ \t]|(?=\r?\n)))|(\})|((?:.|[\r\n\f])+?)/gi;
const STYLE_REGEX = /(?:^|\.)(\w+)(?:\(([^)]*)\))?/g;
const STRING_REGEX = /^(['"])((?:\\.|(?!\1)[^\\])*)\1$/;
const ESCAPE_REGEX = /\\(u[a-f\d]{4}|x[a-f\d]{2}|.)|([^\\])/gi;
const ESCAPES = new Map([
['n', '\n'],
['r', '\r'],
['t', '\t'],
['b', '\b'],
['f', '\f'],
['v', '\v'],
['0', '\0'],
['\\', '\\'],
['e', '\u001B'],
['a', '\u0007']
]);
function unescape(c) {
if ((c[0] === 'u' && c.length === 5) || (c[0] === 'x' && c.length === 3)) {
return String.fromCharCode(parseInt(c.slice(1), 16));
}
return ESCAPES.get(c) || c;
}
function parseArguments(name, args) {
const results = [];
const chunks = args.trim().split(/\s*,\s*/g);
let matches;
for (const chunk of chunks) {
if (!isNaN(chunk)) {
results.push(Number(chunk));
} else if ((matches = chunk.match(STRING_REGEX))) {
results.push(matches[2].replace(ESCAPE_REGEX, (m, escape, chr) => escape ? unescape(escape) : chr));
} else {
throw new Error(`Invalid Chalk template style argument: ${chunk} (in style '${name}')`);
}
}
return results;
}
function parseStyle(style) {
STYLE_REGEX.lastIndex = 0;
const results = [];
let matches;
while ((matches = STYLE_REGEX.exec(style)) !== null) {
const name = matches[1];
if (matches[2]) {
const args = parseArguments(name, matches[2]);
results.push([name].concat(args));
} else {
results.push([name]);
}
}
return results;
}
function buildStyle(chalk, styles) {
const enabled = {};
for (const layer of styles) {
for (const style of layer.styles) {
enabled[style[0]] = layer.inverse ? null : style.slice(1);
}
}
let current = chalk;
for (const styleName of Object.keys(enabled)) {
if (Array.isArray(enabled[styleName])) {
if (!(styleName in current)) {
throw new Error(`Unknown Chalk style: ${styleName}`);
}
if (enabled[styleName].length > 0) {
current = current[styleName].apply(current, enabled[styleName]);
} else {
current = current[styleName];
}
}
}
return current;
}
module.exports = (chalk, tmp) => {
const styles = [];
const chunks = [];
let chunk = [];
// eslint-disable-next-line max-params
tmp.replace(TEMPLATE_REGEX, (m, escapeChar, inverse, style, close, chr) => {
if (escapeChar) {
chunk.push(unescape(escapeChar));
} else if (style) {
const str = chunk.join('');
chunk = [];
chunks.push(styles.length === 0 ? str : buildStyle(chalk, styles)(str));
styles.push({inverse, styles: parseStyle(style)});
} else if (close) {
if (styles.length === 0) {
throw new Error('Found extraneous } in Chalk template literal');
}
chunks.push(buildStyle(chalk, styles)(chunk.join('')));
chunk = [];
styles.pop();
} else {
chunk.push(chr);
}
});
chunks.push(chunk.join(''));
if (styles.length > 0) {
const errMsg = `Chalk template literal is missing ${styles.length} closing bracket${styles.length === 1 ? '' : 's'} (\`}\`)`;
throw new Error(errMsg);
}
return chunks.join('');
};

View File

@@ -0,0 +1,97 @@
// Type definitions for Chalk
// Definitions by: Thomas Sauer <https://github.com/t-sauer>
export const enum Level {
None = 0,
Basic = 1,
Ansi256 = 2,
TrueColor = 3
}
export interface ChalkOptions {
enabled?: boolean;
level?: Level;
}
export interface ChalkConstructor {
new (options?: ChalkOptions): Chalk;
(options?: ChalkOptions): Chalk;
}
export interface ColorSupport {
level: Level;
hasBasic: boolean;
has256: boolean;
has16m: boolean;
}
export interface Chalk {
(...text: string[]): string;
(text: TemplateStringsArray, ...placeholders: string[]): string;
constructor: ChalkConstructor;
enabled: boolean;
level: Level;
rgb(r: number, g: number, b: number): this;
hsl(h: number, s: number, l: number): this;
hsv(h: number, s: number, v: number): this;
hwb(h: number, w: number, b: number): this;
bgHex(color: string): this;
bgKeyword(color: string): this;
bgRgb(r: number, g: number, b: number): this;
bgHsl(h: number, s: number, l: number): this;
bgHsv(h: number, s: number, v: number): this;
bgHwb(h: number, w: number, b: number): this;
hex(color: string): this;
keyword(color: string): this;
readonly reset: this;
readonly bold: this;
readonly dim: this;
readonly italic: this;
readonly underline: this;
readonly inverse: this;
readonly hidden: this;
readonly strikethrough: this;
readonly visible: this;
readonly black: this;
readonly red: this;
readonly green: this;
readonly yellow: this;
readonly blue: this;
readonly magenta: this;
readonly cyan: this;
readonly white: this;
readonly gray: this;
readonly grey: this;
readonly blackBright: this;
readonly redBright: this;
readonly greenBright: this;
readonly yellowBright: this;
readonly blueBright: this;
readonly magentaBright: this;
readonly cyanBright: this;
readonly whiteBright: this;
readonly bgBlack: this;
readonly bgRed: this;
readonly bgGreen: this;
readonly bgYellow: this;
readonly bgBlue: this;
readonly bgMagenta: this;
readonly bgCyan: this;
readonly bgWhite: this;
readonly bgBlackBright: this;
readonly bgRedBright: this;
readonly bgGreenBright: this;
readonly bgYellowBright: this;
readonly bgBlueBright: this;
readonly bgMagentaBright: this;
readonly bgCyanBright: this;
readonly bgWhiteBright: this;
}
declare const chalk: Chalk & { supportsColor: ColorSupport };
export default chalk

View File

@@ -0,0 +1,54 @@
# 1.0.0 - 2016-01-07
- Removed: unused speed test
- Added: Automatic routing between previously unsupported conversions
([#27](https://github.com/Qix-/color-convert/pull/27))
- Removed: `xxx2xxx()` and `xxx2xxxRaw()` functions
([#27](https://github.com/Qix-/color-convert/pull/27))
- Removed: `convert()` class
([#27](https://github.com/Qix-/color-convert/pull/27))
- Changed: all functions to lookup dictionary
([#27](https://github.com/Qix-/color-convert/pull/27))
- Changed: `ansi` to `ansi256`
([#27](https://github.com/Qix-/color-convert/pull/27))
- Fixed: argument grouping for functions requiring only one argument
([#27](https://github.com/Qix-/color-convert/pull/27))
# 0.6.0 - 2015-07-23
- Added: methods to handle
[ANSI](https://en.wikipedia.org/wiki/ANSI_escape_code#Colors) 16/256 colors:
- rgb2ansi16
- rgb2ansi
- hsl2ansi16
- hsl2ansi
- hsv2ansi16
- hsv2ansi
- hwb2ansi16
- hwb2ansi
- cmyk2ansi16
- cmyk2ansi
- keyword2ansi16
- keyword2ansi
- ansi162rgb
- ansi162hsl
- ansi162hsv
- ansi162hwb
- ansi162cmyk
- ansi162keyword
- ansi2rgb
- ansi2hsl
- ansi2hsv
- ansi2hwb
- ansi2cmyk
- ansi2keyword
([#18](https://github.com/harthur/color-convert/pull/18))
# 0.5.3 - 2015-06-02
- Fixed: hsl2hsv does not return `NaN` anymore when using `[0,0,0]`
([#15](https://github.com/harthur/color-convert/issues/15))
---
Check out commit logs for older releases

View File

@@ -0,0 +1,21 @@
Copyright (c) 2011-2016 Heather Arthur <fayearthur@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -0,0 +1,68 @@
# color-convert
[![Build Status](https://travis-ci.org/Qix-/color-convert.svg?branch=master)](https://travis-ci.org/Qix-/color-convert)
Color-convert is a color conversion library for JavaScript and node.
It converts all ways between `rgb`, `hsl`, `hsv`, `hwb`, `cmyk`, `ansi`, `ansi16`, `hex` strings, and CSS `keyword`s (will round to closest):
```js
var convert = require('color-convert');
convert.rgb.hsl(140, 200, 100); // [96, 48, 59]
convert.keyword.rgb('blue'); // [0, 0, 255]
var rgbChannels = convert.rgb.channels; // 3
var cmykChannels = convert.cmyk.channels; // 4
var ansiChannels = convert.ansi16.channels; // 1
```
# Install
```console
$ npm install color-convert
```
# API
Simply get the property of the _from_ and _to_ conversion that you're looking for.
All functions have a rounded and unrounded variant. By default, return values are rounded. To get the unrounded (raw) results, simply tack on `.raw` to the function.
All 'from' functions have a hidden property called `.channels` that indicates the number of channels the function expects (not including alpha).
```js
var convert = require('color-convert');
// Hex to LAB
convert.hex.lab('DEADBF'); // [ 76, 21, -2 ]
convert.hex.lab.raw('DEADBF'); // [ 75.56213190997677, 20.653827952644754, -2.290532499330533 ]
// RGB to CMYK
convert.rgb.cmyk(167, 255, 4); // [ 35, 0, 98, 0 ]
convert.rgb.cmyk.raw(167, 255, 4); // [ 34.509803921568626, 0, 98.43137254901961, 0 ]
```
### Arrays
All functions that accept multiple arguments also support passing an array.
Note that this does **not** apply to functions that convert from a color that only requires one value (e.g. `keyword`, `ansi256`, `hex`, etc.)
```js
var convert = require('color-convert');
convert.rgb.hex(123, 45, 67); // '7B2D43'
convert.rgb.hex([123, 45, 67]); // '7B2D43'
```
## Routing
Conversions that don't have an _explicitly_ defined conversion (in [conversions.js](conversions.js)), but can be converted by means of sub-conversions (e.g. XYZ -> **RGB** -> CMYK), are automatically routed together. This allows just about any color model supported by `color-convert` to be converted to any other model, so long as a sub-conversion path exists. This is also true for conversions requiring more than one step in between (e.g. LCH -> **LAB** -> **XYZ** -> **RGB** -> Hex).
Keep in mind that extensive conversions _may_ result in a loss of precision, and exist only to be complete. For a list of "direct" (single-step) conversions, see [conversions.js](conversions.js).
# Contribute
If there is a new model you would like to support, or want to add a direct conversion between two existing models, please send us a pull request.
# License
Copyright &copy; 2011-2016, Heather Arthur and Josh Junon. Licensed under the [MIT License](LICENSE).

View File

@@ -0,0 +1,868 @@
/* MIT license */
var cssKeywords = require('color-name');
// NOTE: conversions should only return primitive values (i.e. arrays, or
// values that give correct `typeof` results).
// do not use box values types (i.e. Number(), String(), etc.)
var reverseKeywords = {};
for (var key in cssKeywords) {
if (cssKeywords.hasOwnProperty(key)) {
reverseKeywords[cssKeywords[key]] = key;
}
}
var convert = module.exports = {
rgb: {channels: 3, labels: 'rgb'},
hsl: {channels: 3, labels: 'hsl'},
hsv: {channels: 3, labels: 'hsv'},
hwb: {channels: 3, labels: 'hwb'},
cmyk: {channels: 4, labels: 'cmyk'},
xyz: {channels: 3, labels: 'xyz'},
lab: {channels: 3, labels: 'lab'},
lch: {channels: 3, labels: 'lch'},
hex: {channels: 1, labels: ['hex']},
keyword: {channels: 1, labels: ['keyword']},
ansi16: {channels: 1, labels: ['ansi16']},
ansi256: {channels: 1, labels: ['ansi256']},
hcg: {channels: 3, labels: ['h', 'c', 'g']},
apple: {channels: 3, labels: ['r16', 'g16', 'b16']},
gray: {channels: 1, labels: ['gray']}
};
// hide .channels and .labels properties
for (var model in convert) {
if (convert.hasOwnProperty(model)) {
if (!('channels' in convert[model])) {
throw new Error('missing channels property: ' + model);
}
if (!('labels' in convert[model])) {
throw new Error('missing channel labels property: ' + model);
}
if (convert[model].labels.length !== convert[model].channels) {
throw new Error('channel and label counts mismatch: ' + model);
}
var channels = convert[model].channels;
var labels = convert[model].labels;
delete convert[model].channels;
delete convert[model].labels;
Object.defineProperty(convert[model], 'channels', {value: channels});
Object.defineProperty(convert[model], 'labels', {value: labels});
}
}
convert.rgb.hsl = function (rgb) {
var r = rgb[0] / 255;
var g = rgb[1] / 255;
var b = rgb[2] / 255;
var min = Math.min(r, g, b);
var max = Math.max(r, g, b);
var delta = max - min;
var h;
var s;
var l;
if (max === min) {
h = 0;
} else if (r === max) {
h = (g - b) / delta;
} else if (g === max) {
h = 2 + (b - r) / delta;
} else if (b === max) {
h = 4 + (r - g) / delta;
}
h = Math.min(h * 60, 360);
if (h < 0) {
h += 360;
}
l = (min + max) / 2;
if (max === min) {
s = 0;
} else if (l <= 0.5) {
s = delta / (max + min);
} else {
s = delta / (2 - max - min);
}
return [h, s * 100, l * 100];
};
convert.rgb.hsv = function (rgb) {
var rdif;
var gdif;
var bdif;
var h;
var s;
var r = rgb[0] / 255;
var g = rgb[1] / 255;
var b = rgb[2] / 255;
var v = Math.max(r, g, b);
var diff = v - Math.min(r, g, b);
var diffc = function (c) {
return (v - c) / 6 / diff + 1 / 2;
};
if (diff === 0) {
h = s = 0;
} else {
s = diff / v;
rdif = diffc(r);
gdif = diffc(g);
bdif = diffc(b);
if (r === v) {
h = bdif - gdif;
} else if (g === v) {
h = (1 / 3) + rdif - bdif;
} else if (b === v) {
h = (2 / 3) + gdif - rdif;
}
if (h < 0) {
h += 1;
} else if (h > 1) {
h -= 1;
}
}
return [
h * 360,
s * 100,
v * 100
];
};
convert.rgb.hwb = function (rgb) {
var r = rgb[0];
var g = rgb[1];
var b = rgb[2];
var h = convert.rgb.hsl(rgb)[0];
var w = 1 / 255 * Math.min(r, Math.min(g, b));
b = 1 - 1 / 255 * Math.max(r, Math.max(g, b));
return [h, w * 100, b * 100];
};
convert.rgb.cmyk = function (rgb) {
var r = rgb[0] / 255;
var g = rgb[1] / 255;
var b = rgb[2] / 255;
var c;
var m;
var y;
var k;
k = Math.min(1 - r, 1 - g, 1 - b);
c = (1 - r - k) / (1 - k) || 0;
m = (1 - g - k) / (1 - k) || 0;
y = (1 - b - k) / (1 - k) || 0;
return [c * 100, m * 100, y * 100, k * 100];
};
/**
* See https://en.m.wikipedia.org/wiki/Euclidean_distance#Squared_Euclidean_distance
* */
function comparativeDistance(x, y) {
return (
Math.pow(x[0] - y[0], 2) +
Math.pow(x[1] - y[1], 2) +
Math.pow(x[2] - y[2], 2)
);
}
convert.rgb.keyword = function (rgb) {
var reversed = reverseKeywords[rgb];
if (reversed) {
return reversed;
}
var currentClosestDistance = Infinity;
var currentClosestKeyword;
for (var keyword in cssKeywords) {
if (cssKeywords.hasOwnProperty(keyword)) {
var value = cssKeywords[keyword];
// Compute comparative distance
var distance = comparativeDistance(rgb, value);
// Check if its less, if so set as closest
if (distance < currentClosestDistance) {
currentClosestDistance = distance;
currentClosestKeyword = keyword;
}
}
}
return currentClosestKeyword;
};
convert.keyword.rgb = function (keyword) {
return cssKeywords[keyword];
};
convert.rgb.xyz = function (rgb) {
var r = rgb[0] / 255;
var g = rgb[1] / 255;
var b = rgb[2] / 255;
// assume sRGB
r = r > 0.04045 ? Math.pow(((r + 0.055) / 1.055), 2.4) : (r / 12.92);
g = g > 0.04045 ? Math.pow(((g + 0.055) / 1.055), 2.4) : (g / 12.92);
b = b > 0.04045 ? Math.pow(((b + 0.055) / 1.055), 2.4) : (b / 12.92);
var x = (r * 0.4124) + (g * 0.3576) + (b * 0.1805);
var y = (r * 0.2126) + (g * 0.7152) + (b * 0.0722);
var z = (r * 0.0193) + (g * 0.1192) + (b * 0.9505);
return [x * 100, y * 100, z * 100];
};
convert.rgb.lab = function (rgb) {
var xyz = convert.rgb.xyz(rgb);
var x = xyz[0];
var y = xyz[1];
var z = xyz[2];
var l;
var a;
var b;
x /= 95.047;
y /= 100;
z /= 108.883;
x = x > 0.008856 ? Math.pow(x, 1 / 3) : (7.787 * x) + (16 / 116);
y = y > 0.008856 ? Math.pow(y, 1 / 3) : (7.787 * y) + (16 / 116);
z = z > 0.008856 ? Math.pow(z, 1 / 3) : (7.787 * z) + (16 / 116);
l = (116 * y) - 16;
a = 500 * (x - y);
b = 200 * (y - z);
return [l, a, b];
};
convert.hsl.rgb = function (hsl) {
var h = hsl[0] / 360;
var s = hsl[1] / 100;
var l = hsl[2] / 100;
var t1;
var t2;
var t3;
var rgb;
var val;
if (s === 0) {
val = l * 255;
return [val, val, val];
}
if (l < 0.5) {
t2 = l * (1 + s);
} else {
t2 = l + s - l * s;
}
t1 = 2 * l - t2;
rgb = [0, 0, 0];
for (var i = 0; i < 3; i++) {
t3 = h + 1 / 3 * -(i - 1);
if (t3 < 0) {
t3++;
}
if (t3 > 1) {
t3--;
}
if (6 * t3 < 1) {
val = t1 + (t2 - t1) * 6 * t3;
} else if (2 * t3 < 1) {
val = t2;
} else if (3 * t3 < 2) {
val = t1 + (t2 - t1) * (2 / 3 - t3) * 6;
} else {
val = t1;
}
rgb[i] = val * 255;
}
return rgb;
};
convert.hsl.hsv = function (hsl) {
var h = hsl[0];
var s = hsl[1] / 100;
var l = hsl[2] / 100;
var smin = s;
var lmin = Math.max(l, 0.01);
var sv;
var v;
l *= 2;
s *= (l <= 1) ? l : 2 - l;
smin *= lmin <= 1 ? lmin : 2 - lmin;
v = (l + s) / 2;
sv = l === 0 ? (2 * smin) / (lmin + smin) : (2 * s) / (l + s);
return [h, sv * 100, v * 100];
};
convert.hsv.rgb = function (hsv) {
var h = hsv[0] / 60;
var s = hsv[1] / 100;
var v = hsv[2] / 100;
var hi = Math.floor(h) % 6;
var f = h - Math.floor(h);
var p = 255 * v * (1 - s);
var q = 255 * v * (1 - (s * f));
var t = 255 * v * (1 - (s * (1 - f)));
v *= 255;
switch (hi) {
case 0:
return [v, t, p];
case 1:
return [q, v, p];
case 2:
return [p, v, t];
case 3:
return [p, q, v];
case 4:
return [t, p, v];
case 5:
return [v, p, q];
}
};
convert.hsv.hsl = function (hsv) {
var h = hsv[0];
var s = hsv[1] / 100;
var v = hsv[2] / 100;
var vmin = Math.max(v, 0.01);
var lmin;
var sl;
var l;
l = (2 - s) * v;
lmin = (2 - s) * vmin;
sl = s * vmin;
sl /= (lmin <= 1) ? lmin : 2 - lmin;
sl = sl || 0;
l /= 2;
return [h, sl * 100, l * 100];
};
// http://dev.w3.org/csswg/css-color/#hwb-to-rgb
convert.hwb.rgb = function (hwb) {
var h = hwb[0] / 360;
var wh = hwb[1] / 100;
var bl = hwb[2] / 100;
var ratio = wh + bl;
var i;
var v;
var f;
var n;
// wh + bl cant be > 1
if (ratio > 1) {
wh /= ratio;
bl /= ratio;
}
i = Math.floor(6 * h);
v = 1 - bl;
f = 6 * h - i;
if ((i & 0x01) !== 0) {
f = 1 - f;
}
n = wh + f * (v - wh); // linear interpolation
var r;
var g;
var b;
switch (i) {
default:
case 6:
case 0: r = v; g = n; b = wh; break;
case 1: r = n; g = v; b = wh; break;
case 2: r = wh; g = v; b = n; break;
case 3: r = wh; g = n; b = v; break;
case 4: r = n; g = wh; b = v; break;
case 5: r = v; g = wh; b = n; break;
}
return [r * 255, g * 255, b * 255];
};
convert.cmyk.rgb = function (cmyk) {
var c = cmyk[0] / 100;
var m = cmyk[1] / 100;
var y = cmyk[2] / 100;
var k = cmyk[3] / 100;
var r;
var g;
var b;
r = 1 - Math.min(1, c * (1 - k) + k);
g = 1 - Math.min(1, m * (1 - k) + k);
b = 1 - Math.min(1, y * (1 - k) + k);
return [r * 255, g * 255, b * 255];
};
convert.xyz.rgb = function (xyz) {
var x = xyz[0] / 100;
var y = xyz[1] / 100;
var z = xyz[2] / 100;
var r;
var g;
var b;
r = (x * 3.2406) + (y * -1.5372) + (z * -0.4986);
g = (x * -0.9689) + (y * 1.8758) + (z * 0.0415);
b = (x * 0.0557) + (y * -0.2040) + (z * 1.0570);
// assume sRGB
r = r > 0.0031308
? ((1.055 * Math.pow(r, 1.0 / 2.4)) - 0.055)
: r * 12.92;
g = g > 0.0031308
? ((1.055 * Math.pow(g, 1.0 / 2.4)) - 0.055)
: g * 12.92;
b = b > 0.0031308
? ((1.055 * Math.pow(b, 1.0 / 2.4)) - 0.055)
: b * 12.92;
r = Math.min(Math.max(0, r), 1);
g = Math.min(Math.max(0, g), 1);
b = Math.min(Math.max(0, b), 1);
return [r * 255, g * 255, b * 255];
};
convert.xyz.lab = function (xyz) {
var x = xyz[0];
var y = xyz[1];
var z = xyz[2];
var l;
var a;
var b;
x /= 95.047;
y /= 100;
z /= 108.883;
x = x > 0.008856 ? Math.pow(x, 1 / 3) : (7.787 * x) + (16 / 116);
y = y > 0.008856 ? Math.pow(y, 1 / 3) : (7.787 * y) + (16 / 116);
z = z > 0.008856 ? Math.pow(z, 1 / 3) : (7.787 * z) + (16 / 116);
l = (116 * y) - 16;
a = 500 * (x - y);
b = 200 * (y - z);
return [l, a, b];
};
convert.lab.xyz = function (lab) {
var l = lab[0];
var a = lab[1];
var b = lab[2];
var x;
var y;
var z;
y = (l + 16) / 116;
x = a / 500 + y;
z = y - b / 200;
var y2 = Math.pow(y, 3);
var x2 = Math.pow(x, 3);
var z2 = Math.pow(z, 3);
y = y2 > 0.008856 ? y2 : (y - 16 / 116) / 7.787;
x = x2 > 0.008856 ? x2 : (x - 16 / 116) / 7.787;
z = z2 > 0.008856 ? z2 : (z - 16 / 116) / 7.787;
x *= 95.047;
y *= 100;
z *= 108.883;
return [x, y, z];
};
convert.lab.lch = function (lab) {
var l = lab[0];
var a = lab[1];
var b = lab[2];
var hr;
var h;
var c;
hr = Math.atan2(b, a);
h = hr * 360 / 2 / Math.PI;
if (h < 0) {
h += 360;
}
c = Math.sqrt(a * a + b * b);
return [l, c, h];
};
convert.lch.lab = function (lch) {
var l = lch[0];
var c = lch[1];
var h = lch[2];
var a;
var b;
var hr;
hr = h / 360 * 2 * Math.PI;
a = c * Math.cos(hr);
b = c * Math.sin(hr);
return [l, a, b];
};
convert.rgb.ansi16 = function (args) {
var r = args[0];
var g = args[1];
var b = args[2];
var value = 1 in arguments ? arguments[1] : convert.rgb.hsv(args)[2]; // hsv -> ansi16 optimization
value = Math.round(value / 50);
if (value === 0) {
return 30;
}
var ansi = 30
+ ((Math.round(b / 255) << 2)
| (Math.round(g / 255) << 1)
| Math.round(r / 255));
if (value === 2) {
ansi += 60;
}
return ansi;
};
convert.hsv.ansi16 = function (args) {
// optimization here; we already know the value and don't need to get
// it converted for us.
return convert.rgb.ansi16(convert.hsv.rgb(args), args[2]);
};
convert.rgb.ansi256 = function (args) {
var r = args[0];
var g = args[1];
var b = args[2];
// we use the extended greyscale palette here, with the exception of
// black and white. normal palette only has 4 greyscale shades.
if (r === g && g === b) {
if (r < 8) {
return 16;
}
if (r > 248) {
return 231;
}
return Math.round(((r - 8) / 247) * 24) + 232;
}
var ansi = 16
+ (36 * Math.round(r / 255 * 5))
+ (6 * Math.round(g / 255 * 5))
+ Math.round(b / 255 * 5);
return ansi;
};
convert.ansi16.rgb = function (args) {
var color = args % 10;
// handle greyscale
if (color === 0 || color === 7) {
if (args > 50) {
color += 3.5;
}
color = color / 10.5 * 255;
return [color, color, color];
}
var mult = (~~(args > 50) + 1) * 0.5;
var r = ((color & 1) * mult) * 255;
var g = (((color >> 1) & 1) * mult) * 255;
var b = (((color >> 2) & 1) * mult) * 255;
return [r, g, b];
};
convert.ansi256.rgb = function (args) {
// handle greyscale
if (args >= 232) {
var c = (args - 232) * 10 + 8;
return [c, c, c];
}
args -= 16;
var rem;
var r = Math.floor(args / 36) / 5 * 255;
var g = Math.floor((rem = args % 36) / 6) / 5 * 255;
var b = (rem % 6) / 5 * 255;
return [r, g, b];
};
convert.rgb.hex = function (args) {
var integer = ((Math.round(args[0]) & 0xFF) << 16)
+ ((Math.round(args[1]) & 0xFF) << 8)
+ (Math.round(args[2]) & 0xFF);
var string = integer.toString(16).toUpperCase();
return '000000'.substring(string.length) + string;
};
convert.hex.rgb = function (args) {
var match = args.toString(16).match(/[a-f0-9]{6}|[a-f0-9]{3}/i);
if (!match) {
return [0, 0, 0];
}
var colorString = match[0];
if (match[0].length === 3) {
colorString = colorString.split('').map(function (char) {
return char + char;
}).join('');
}
var integer = parseInt(colorString, 16);
var r = (integer >> 16) & 0xFF;
var g = (integer >> 8) & 0xFF;
var b = integer & 0xFF;
return [r, g, b];
};
convert.rgb.hcg = function (rgb) {
var r = rgb[0] / 255;
var g = rgb[1] / 255;
var b = rgb[2] / 255;
var max = Math.max(Math.max(r, g), b);
var min = Math.min(Math.min(r, g), b);
var chroma = (max - min);
var grayscale;
var hue;
if (chroma < 1) {
grayscale = min / (1 - chroma);
} else {
grayscale = 0;
}
if (chroma <= 0) {
hue = 0;
} else
if (max === r) {
hue = ((g - b) / chroma) % 6;
} else
if (max === g) {
hue = 2 + (b - r) / chroma;
} else {
hue = 4 + (r - g) / chroma + 4;
}
hue /= 6;
hue %= 1;
return [hue * 360, chroma * 100, grayscale * 100];
};
convert.hsl.hcg = function (hsl) {
var s = hsl[1] / 100;
var l = hsl[2] / 100;
var c = 1;
var f = 0;
if (l < 0.5) {
c = 2.0 * s * l;
} else {
c = 2.0 * s * (1.0 - l);
}
if (c < 1.0) {
f = (l - 0.5 * c) / (1.0 - c);
}
return [hsl[0], c * 100, f * 100];
};
convert.hsv.hcg = function (hsv) {
var s = hsv[1] / 100;
var v = hsv[2] / 100;
var c = s * v;
var f = 0;
if (c < 1.0) {
f = (v - c) / (1 - c);
}
return [hsv[0], c * 100, f * 100];
};
convert.hcg.rgb = function (hcg) {
var h = hcg[0] / 360;
var c = hcg[1] / 100;
var g = hcg[2] / 100;
if (c === 0.0) {
return [g * 255, g * 255, g * 255];
}
var pure = [0, 0, 0];
var hi = (h % 1) * 6;
var v = hi % 1;
var w = 1 - v;
var mg = 0;
switch (Math.floor(hi)) {
case 0:
pure[0] = 1; pure[1] = v; pure[2] = 0; break;
case 1:
pure[0] = w; pure[1] = 1; pure[2] = 0; break;
case 2:
pure[0] = 0; pure[1] = 1; pure[2] = v; break;
case 3:
pure[0] = 0; pure[1] = w; pure[2] = 1; break;
case 4:
pure[0] = v; pure[1] = 0; pure[2] = 1; break;
default:
pure[0] = 1; pure[1] = 0; pure[2] = w;
}
mg = (1.0 - c) * g;
return [
(c * pure[0] + mg) * 255,
(c * pure[1] + mg) * 255,
(c * pure[2] + mg) * 255
];
};
convert.hcg.hsv = function (hcg) {
var c = hcg[1] / 100;
var g = hcg[2] / 100;
var v = c + g * (1.0 - c);
var f = 0;
if (v > 0.0) {
f = c / v;
}
return [hcg[0], f * 100, v * 100];
};
convert.hcg.hsl = function (hcg) {
var c = hcg[1] / 100;
var g = hcg[2] / 100;
var l = g * (1.0 - c) + 0.5 * c;
var s = 0;
if (l > 0.0 && l < 0.5) {
s = c / (2 * l);
} else
if (l >= 0.5 && l < 1.0) {
s = c / (2 * (1 - l));
}
return [hcg[0], s * 100, l * 100];
};
convert.hcg.hwb = function (hcg) {
var c = hcg[1] / 100;
var g = hcg[2] / 100;
var v = c + g * (1.0 - c);
return [hcg[0], (v - c) * 100, (1 - v) * 100];
};
convert.hwb.hcg = function (hwb) {
var w = hwb[1] / 100;
var b = hwb[2] / 100;
var v = 1 - b;
var c = v - w;
var g = 0;
if (c < 1) {
g = (v - c) / (1 - c);
}
return [hwb[0], c * 100, g * 100];
};
convert.apple.rgb = function (apple) {
return [(apple[0] / 65535) * 255, (apple[1] / 65535) * 255, (apple[2] / 65535) * 255];
};
convert.rgb.apple = function (rgb) {
return [(rgb[0] / 255) * 65535, (rgb[1] / 255) * 65535, (rgb[2] / 255) * 65535];
};
convert.gray.rgb = function (args) {
return [args[0] / 100 * 255, args[0] / 100 * 255, args[0] / 100 * 255];
};
convert.gray.hsl = convert.gray.hsv = function (args) {
return [0, 0, args[0]];
};
convert.gray.hwb = function (gray) {
return [0, 100, gray[0]];
};
convert.gray.cmyk = function (gray) {
return [0, 0, 0, gray[0]];
};
convert.gray.lab = function (gray) {
return [gray[0], 0, 0];
};
convert.gray.hex = function (gray) {
var val = Math.round(gray[0] / 100 * 255) & 0xFF;
var integer = (val << 16) + (val << 8) + val;
var string = integer.toString(16).toUpperCase();
return '000000'.substring(string.length) + string;
};
convert.rgb.gray = function (rgb) {
var val = (rgb[0] + rgb[1] + rgb[2]) / 3;
return [val / 255 * 100];
};

View File

@@ -0,0 +1,78 @@
var conversions = require('./conversions');
var route = require('./route');
var convert = {};
var models = Object.keys(conversions);
function wrapRaw(fn) {
var wrappedFn = function (args) {
if (args === undefined || args === null) {
return args;
}
if (arguments.length > 1) {
args = Array.prototype.slice.call(arguments);
}
return fn(args);
};
// preserve .conversion property if there is one
if ('conversion' in fn) {
wrappedFn.conversion = fn.conversion;
}
return wrappedFn;
}
function wrapRounded(fn) {
var wrappedFn = function (args) {
if (args === undefined || args === null) {
return args;
}
if (arguments.length > 1) {
args = Array.prototype.slice.call(arguments);
}
var result = fn(args);
// we're assuming the result is an array here.
// see notice in conversions.js; don't use box types
// in conversion functions.
if (typeof result === 'object') {
for (var len = result.length, i = 0; i < len; i++) {
result[i] = Math.round(result[i]);
}
}
return result;
};
// preserve .conversion property if there is one
if ('conversion' in fn) {
wrappedFn.conversion = fn.conversion;
}
return wrappedFn;
}
models.forEach(function (fromModel) {
convert[fromModel] = {};
Object.defineProperty(convert[fromModel], 'channels', {value: conversions[fromModel].channels});
Object.defineProperty(convert[fromModel], 'labels', {value: conversions[fromModel].labels});
var routes = route(fromModel);
var routeModels = Object.keys(routes);
routeModels.forEach(function (toModel) {
var fn = routes[toModel];
convert[fromModel][toModel] = wrapRounded(fn);
convert[fromModel][toModel].raw = wrapRaw(fn);
});
});
module.exports = convert;

View File

@@ -0,0 +1,46 @@
{
"name": "color-convert",
"description": "Plain color conversion functions",
"version": "1.9.3",
"author": "Heather Arthur <fayearthur@gmail.com>",
"license": "MIT",
"repository": "Qix-/color-convert",
"scripts": {
"pretest": "xo",
"test": "node test/basic.js"
},
"keywords": [
"color",
"colour",
"convert",
"converter",
"conversion",
"rgb",
"hsl",
"hsv",
"hwb",
"cmyk",
"ansi",
"ansi16"
],
"files": [
"index.js",
"conversions.js",
"css-keywords.js",
"route.js"
],
"xo": {
"rules": {
"default-case": 0,
"no-inline-comments": 0,
"operator-linebreak": 0
}
},
"devDependencies": {
"chalk": "1.1.1",
"xo": "0.11.2"
},
"dependencies": {
"color-name": "1.1.3"
}
}

View File

@@ -0,0 +1,97 @@
var conversions = require('./conversions');
/*
this function routes a model to all other models.
all functions that are routed have a property `.conversion` attached
to the returned synthetic function. This property is an array
of strings, each with the steps in between the 'from' and 'to'
color models (inclusive).
conversions that are not possible simply are not included.
*/
function buildGraph() {
var graph = {};
// https://jsperf.com/object-keys-vs-for-in-with-closure/3
var models = Object.keys(conversions);
for (var len = models.length, i = 0; i < len; i++) {
graph[models[i]] = {
// http://jsperf.com/1-vs-infinity
// micro-opt, but this is simple.
distance: -1,
parent: null
};
}
return graph;
}
// https://en.wikipedia.org/wiki/Breadth-first_search
function deriveBFS(fromModel) {
var graph = buildGraph();
var queue = [fromModel]; // unshift -> queue -> pop
graph[fromModel].distance = 0;
while (queue.length) {
var current = queue.pop();
var adjacents = Object.keys(conversions[current]);
for (var len = adjacents.length, i = 0; i < len; i++) {
var adjacent = adjacents[i];
var node = graph[adjacent];
if (node.distance === -1) {
node.distance = graph[current].distance + 1;
node.parent = current;
queue.unshift(adjacent);
}
}
}
return graph;
}
function link(from, to) {
return function (args) {
return to(from(args));
};
}
function wrapConversion(toModel, graph) {
var path = [graph[toModel].parent, toModel];
var fn = conversions[graph[toModel].parent][toModel];
var cur = graph[toModel].parent;
while (graph[cur].parent) {
path.unshift(graph[cur].parent);
fn = link(conversions[graph[cur].parent][cur], fn);
cur = graph[cur].parent;
}
fn.conversion = path;
return fn;
}
module.exports = function (fromModel) {
var graph = deriveBFS(fromModel);
var conversion = {};
var models = Object.keys(graph);
for (var len = models.length, i = 0; i < len; i++) {
var toModel = models[i];
var node = graph[toModel];
if (node.parent === null) {
// no possible conversion, or this node is the source model.
continue;
}
conversion[toModel] = wrapConversion(toModel, graph);
}
return conversion;
};

View File

@@ -0,0 +1,43 @@
{
"env": {
"browser": true,
"node": true,
"commonjs": true,
"es6": true
},
"extends": "eslint:recommended",
"rules": {
"strict": 2,
"indent": 0,
"linebreak-style": 0,
"quotes": 0,
"semi": 0,
"no-cond-assign": 1,
"no-constant-condition": 1,
"no-duplicate-case": 1,
"no-empty": 1,
"no-ex-assign": 1,
"no-extra-boolean-cast": 1,
"no-extra-semi": 1,
"no-fallthrough": 1,
"no-func-assign": 1,
"no-global-assign": 1,
"no-implicit-globals": 2,
"no-inner-declarations": ["error", "functions"],
"no-irregular-whitespace": 2,
"no-loop-func": 1,
"no-multi-str": 1,
"no-mixed-spaces-and-tabs": 1,
"no-proto": 1,
"no-sequences": 1,
"no-throw-literal": 1,
"no-unmodified-loop-condition": 1,
"no-useless-call": 1,
"no-void": 1,
"no-with": 2,
"wrap-iife": 1,
"no-redeclare": 1,
"no-unused-vars": ["error", { "vars": "all", "args": "none" }],
"no-sparse-arrays": 1
}
}

View File

@@ -0,0 +1,107 @@
//this will affect all the git repos
git config --global core.excludesfile ~/.gitignore
//update files since .ignore won't if already tracked
git rm --cached <file>
# Compiled source #
###################
*.com
*.class
*.dll
*.exe
*.o
*.so
# Packages #
############
# it's better to unpack these files and commit the raw source
# git has its own built in compression methods
*.7z
*.dmg
*.gz
*.iso
*.jar
*.rar
*.tar
*.zip
# Logs and databases #
######################
*.log
*.sql
*.sqlite
# OS generated files #
######################
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
# Icon?
ehthumbs.db
Thumbs.db
.cache
.project
.settings
.tmproj
*.esproj
nbproject
# Numerous always-ignore extensions #
#####################################
*.diff
*.err
*.orig
*.rej
*.swn
*.swo
*.swp
*.vi
*~
*.sass-cache
*.grunt
*.tmp
# Dreamweaver added files #
###########################
_notes
dwsync.xml
# Komodo #
###########################
*.komodoproject
.komodotools
# Node #
#####################
node_modules
# Bower #
#####################
bower_components
# Folders to ignore #
#####################
.hg
.svn
.CVS
intermediate
publish
.idea
.graphics
_test
_archive
uploads
tmp
# Vim files to ignore #
#######################
.VimballRecord
.netrwhist
bundle.*
_demo

View File

@@ -0,0 +1,8 @@
The MIT License (MIT)
Copyright (c) 2015 Dmitry Ivanov
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.

View File

@@ -0,0 +1,11 @@
A JSON with color names and its values. Based on http://dev.w3.org/csswg/css-color/#named-colors.
[![NPM](https://nodei.co/npm/color-name.png?mini=true)](https://nodei.co/npm/color-name/)
```js
var colors = require('color-name');
colors.red //[255,0,0]
```
<a href="LICENSE"><img src="https://upload.wikimedia.org/wikipedia/commons/0/0c/MIT_logo.svg" width="120"/></a>

View File

@@ -0,0 +1,152 @@
'use strict'
module.exports = {
"aliceblue": [240, 248, 255],
"antiquewhite": [250, 235, 215],
"aqua": [0, 255, 255],
"aquamarine": [127, 255, 212],
"azure": [240, 255, 255],
"beige": [245, 245, 220],
"bisque": [255, 228, 196],
"black": [0, 0, 0],
"blanchedalmond": [255, 235, 205],
"blue": [0, 0, 255],
"blueviolet": [138, 43, 226],
"brown": [165, 42, 42],
"burlywood": [222, 184, 135],
"cadetblue": [95, 158, 160],
"chartreuse": [127, 255, 0],
"chocolate": [210, 105, 30],
"coral": [255, 127, 80],
"cornflowerblue": [100, 149, 237],
"cornsilk": [255, 248, 220],
"crimson": [220, 20, 60],
"cyan": [0, 255, 255],
"darkblue": [0, 0, 139],
"darkcyan": [0, 139, 139],
"darkgoldenrod": [184, 134, 11],
"darkgray": [169, 169, 169],
"darkgreen": [0, 100, 0],
"darkgrey": [169, 169, 169],
"darkkhaki": [189, 183, 107],
"darkmagenta": [139, 0, 139],
"darkolivegreen": [85, 107, 47],
"darkorange": [255, 140, 0],
"darkorchid": [153, 50, 204],
"darkred": [139, 0, 0],
"darksalmon": [233, 150, 122],
"darkseagreen": [143, 188, 143],
"darkslateblue": [72, 61, 139],
"darkslategray": [47, 79, 79],
"darkslategrey": [47, 79, 79],
"darkturquoise": [0, 206, 209],
"darkviolet": [148, 0, 211],
"deeppink": [255, 20, 147],
"deepskyblue": [0, 191, 255],
"dimgray": [105, 105, 105],
"dimgrey": [105, 105, 105],
"dodgerblue": [30, 144, 255],
"firebrick": [178, 34, 34],
"floralwhite": [255, 250, 240],
"forestgreen": [34, 139, 34],
"fuchsia": [255, 0, 255],
"gainsboro": [220, 220, 220],
"ghostwhite": [248, 248, 255],
"gold": [255, 215, 0],
"goldenrod": [218, 165, 32],
"gray": [128, 128, 128],
"green": [0, 128, 0],
"greenyellow": [173, 255, 47],
"grey": [128, 128, 128],
"honeydew": [240, 255, 240],
"hotpink": [255, 105, 180],
"indianred": [205, 92, 92],
"indigo": [75, 0, 130],
"ivory": [255, 255, 240],
"khaki": [240, 230, 140],
"lavender": [230, 230, 250],
"lavenderblush": [255, 240, 245],
"lawngreen": [124, 252, 0],
"lemonchiffon": [255, 250, 205],
"lightblue": [173, 216, 230],
"lightcoral": [240, 128, 128],
"lightcyan": [224, 255, 255],
"lightgoldenrodyellow": [250, 250, 210],
"lightgray": [211, 211, 211],
"lightgreen": [144, 238, 144],
"lightgrey": [211, 211, 211],
"lightpink": [255, 182, 193],
"lightsalmon": [255, 160, 122],
"lightseagreen": [32, 178, 170],
"lightskyblue": [135, 206, 250],
"lightslategray": [119, 136, 153],
"lightslategrey": [119, 136, 153],
"lightsteelblue": [176, 196, 222],
"lightyellow": [255, 255, 224],
"lime": [0, 255, 0],
"limegreen": [50, 205, 50],
"linen": [250, 240, 230],
"magenta": [255, 0, 255],
"maroon": [128, 0, 0],
"mediumaquamarine": [102, 205, 170],
"mediumblue": [0, 0, 205],
"mediumorchid": [186, 85, 211],
"mediumpurple": [147, 112, 219],
"mediumseagreen": [60, 179, 113],
"mediumslateblue": [123, 104, 238],
"mediumspringgreen": [0, 250, 154],
"mediumturquoise": [72, 209, 204],
"mediumvioletred": [199, 21, 133],
"midnightblue": [25, 25, 112],
"mintcream": [245, 255, 250],
"mistyrose": [255, 228, 225],
"moccasin": [255, 228, 181],
"navajowhite": [255, 222, 173],
"navy": [0, 0, 128],
"oldlace": [253, 245, 230],
"olive": [128, 128, 0],
"olivedrab": [107, 142, 35],
"orange": [255, 165, 0],
"orangered": [255, 69, 0],
"orchid": [218, 112, 214],
"palegoldenrod": [238, 232, 170],
"palegreen": [152, 251, 152],
"paleturquoise": [175, 238, 238],
"palevioletred": [219, 112, 147],
"papayawhip": [255, 239, 213],
"peachpuff": [255, 218, 185],
"peru": [205, 133, 63],
"pink": [255, 192, 203],
"plum": [221, 160, 221],
"powderblue": [176, 224, 230],
"purple": [128, 0, 128],
"rebeccapurple": [102, 51, 153],
"red": [255, 0, 0],
"rosybrown": [188, 143, 143],
"royalblue": [65, 105, 225],
"saddlebrown": [139, 69, 19],
"salmon": [250, 128, 114],
"sandybrown": [244, 164, 96],
"seagreen": [46, 139, 87],
"seashell": [255, 245, 238],
"sienna": [160, 82, 45],
"silver": [192, 192, 192],
"skyblue": [135, 206, 235],
"slateblue": [106, 90, 205],
"slategray": [112, 128, 144],
"slategrey": [112, 128, 144],
"snow": [255, 250, 250],
"springgreen": [0, 255, 127],
"steelblue": [70, 130, 180],
"tan": [210, 180, 140],
"teal": [0, 128, 128],
"thistle": [216, 191, 216],
"tomato": [255, 99, 71],
"turquoise": [64, 224, 208],
"violet": [238, 130, 238],
"wheat": [245, 222, 179],
"white": [255, 255, 255],
"whitesmoke": [245, 245, 245],
"yellow": [255, 255, 0],
"yellowgreen": [154, 205, 50]
};

View File

@@ -0,0 +1,25 @@
{
"name": "color-name",
"version": "1.1.3",
"description": "A list of color names and its values",
"main": "index.js",
"scripts": {
"test": "node test.js"
},
"repository": {
"type": "git",
"url": "git@github.com:dfcreative/color-name.git"
},
"keywords": [
"color-name",
"color",
"color-keyword",
"keyword"
],
"author": "DY <dfcreative@gmail.com>",
"license": "MIT",
"bugs": {
"url": "https://github.com/dfcreative/color-name/issues"
},
"homepage": "https://github.com/dfcreative/color-name"
}

View File

@@ -0,0 +1,7 @@
'use strict'
var names = require('./');
var assert = require('assert');
assert.deepEqual(names.red, [255,0,0]);
assert.deepEqual(names.aliceblue, [240,248,255]);

View File

@@ -0,0 +1,11 @@
Copyright (c) Felix Böhm
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
THIS IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -0,0 +1,221 @@
# css-select [![NPM version](http://img.shields.io/npm/v/css-select.svg)](https://npmjs.org/package/css-select) [![Build Status](https://travis-ci.org/fb55/css-select.svg?branch=master)](http://travis-ci.org/fb55/css-select) [![Downloads](https://img.shields.io/npm/dm/css-select.svg)](https://npmjs.org/package/css-select) [![Coverage](https://coveralls.io/repos/fb55/css-select/badge.svg?branch=master)](https://coveralls.io/r/fb55/css-select)
a CSS selector compiler/engine
## What?
css-select turns CSS selectors into functions that tests if elements match them. When searching for elements, testing is executed "from the top", similar to how browsers execute CSS selectors.
In its default configuration, css-select queries the DOM structure of the [`domhandler`](https://github.com/fb55/domhandler) module (also known as htmlparser2 DOM).
It uses [`domutils`](https://github.com/fb55/domutils) as its default adapter over the DOM structure. See Options below for details on querying alternative DOM structures.
__Features:__
- Full implementation of CSS3 selectors
- Partial implementation of jQuery/Sizzle extensions
- Very high test coverage
- Pretty good performance
## Why?
The traditional approach of executing CSS selectors, named left-to-right execution, is to execute every component of the selector in order, from left to right _(duh)_. The execution of the selector `a b` for example will first query for `a` elements, then search these for `b` elements. (That's the approach of eg. [`Sizzle`](https://github.com/jquery/sizzle), [`nwmatcher`](https://github.com/dperini/nwmatcher/) and [`qwery`](https://github.com/ded/qwery).)
While this works, it has some downsides: Children of `a`s will be checked multiple times; first, to check if they are also `a`s, then, for every superior `a` once, if they are `b`s. Using [Big O notation](http://en.wikipedia.org/wiki/Big_O_notation), that would be `O(n^(k+1))`, where `k` is the number of descendant selectors (that's the space in the example above).
The far more efficient approach is to first look for `b` elements, then check if they have superior `a` elements: Using big O notation again, that would be `O(n)`. That's called right-to-left execution.
And that's what css-select does and why it's quite performant.
## How does it work?
By building a stack of functions.
_Wait, what?_
Okay, so let's suppose we want to compile the selector `a b` again, for right-to-left execution. We start by _parsing_ the selector, which means we turn the selector into an array of the building-blocks of the selector, so we can distinguish them easily. That's what the [`css-what`](https://github.com/fb55/css-what) module is for, if you want to have a look.
Anyway, after parsing, we end up with an array like this one:
```js
[
{ type: 'tag', name: 'a' },
{ type: 'descendant' },
{ type: 'tag', name: 'b' }
]
```
Actually, this array is wrapped in another array, but that's another story (involving commas in selectors).
Now that we know the meaning of every part of the selector, we can compile it. That's where it becomes interesting.
The basic idea is to turn every part of the selector into a function, which takes an element as its only argument. The function checks whether a passed element matches its part of the selector: If it does, the element is passed to the next turned-into-a-function part of the selector, which does the same. If an element is accepted by all parts of the selector, it _matches_ the selector and double rainbow ALL THE WAY.
As said before, we want to do right-to-left execution with all the big O improvements nonsense, so elements are passed from the rightmost part of the selector (`b` in our example) to the leftmost (~~which would be `c`~~ of course `a`).
_//TODO: More in-depth description. Implementation details. Build a spaceship._
## API
```js
const CSSselect = require("css-select");
```
__Note:__ css-select throws errors when invalid selectors are passed to it, contrary to the behavior in browsers, which swallow them. This is done to aid with writing css selectors, but can be unexpected when processing arbitrary strings.
#### `CSSselect(query, elems, options)`
Queries `elems`, returns an array containing all matches.
- `query` can be either a CSS selector or a function.
- `elems` can be either an array of elements, or a single element. If it is an element, its children will be queried.
- `options` is described below.
Aliases: `CSSselect.selectAll(query, elems)`, `CSSselect.iterate(query, elems)`.
#### `CSSselect.compile(query)`
Compiles the query, returns a function.
#### `CSSselect.is(elem, query, options)`
Tests whether or not an element is matched by `query`. `query` can be either a CSS selector or a function.
#### `CSSselect.selectOne(query, elems, options)`
Arguments are the same as for `CSSselect(query, elems)`. Only returns the first match, or `null` if there was no match.
### Options
- `xmlMode`: When enabled, tag names will be case-sensitive. Default: `false`.
- `strict`: Limits the module to only use CSS3 selectors. Default: `false`.
- `rootFunc`: The last function in the stack, will be called with the last element that's looked at. Should return `true`.
- `adapter`: The adapter to use when interacting with the backing DOM structure. By default it uses [`domutils`](https://github.com/fb55/domutils).
#### Custom Adapters
A custom adapter must implement the following functions:
```
isTag, existsOne, getAttributeValue, getChildren, getName, getParent,
getSiblings, getText, hasAttrib, removeSubsets, findAll, findOne
```
The method signature notation used below should be fairly intuitive - if not,
see the [`rtype`](https://github.com/ericelliott/rtype) or
[`TypeScript`](https://www.typescriptlang.org/) docs, as it is very similar to
both of those. You may also want to look at
-[`domutils`](https://github.com/fb55/domutils) to see the default
-implementation, or at
-[`css-select-browser-adapter`](https://github.com/nrkn/css-select-browser-adapter/blob/master/index.js)
-for an implementation backed by the DOM.
```ts
{
// is the node a tag?
isTag: ( node:Node ) => isTag:Boolean,
// does at least one of passed element nodes pass the test predicate?
existsOne: ( test:Predicate, elems:[ElementNode] ) => existsOne:Boolean,
// get the attribute value
getAttributeValue: ( elem:ElementNode, name:String ) => value:String,
// get the node's children
getChildren: ( node:Node ) => children:[Node],
// get the name of the tag
getName: ( elem:ElementNode ) => tagName:String,
// get the parent of the node
getParent: ( node:Node ) => parentNode:Node,
/*
get the siblings of the node. Note that unlike jQuery's `siblings` method,
this is expected to include the current node as well
*/
getSiblings: ( node:Node ) => siblings:[Node],
// get the text content of the node, and its children if it has any
getText: ( node:Node ) => text:String,
// does the element have the named attribute?
hasAttrib: ( elem:ElementNode, name:String ) => hasAttrib:Boolean,
// takes an array of nodes, and removes any duplicates, as well as any nodes
// whose ancestors are also in the array
removeSubsets: ( nodes:[Node] ) => unique:[Node],
// finds all of the element nodes in the array that match the test predicate,
// as well as any of their children that match it
findAll: ( test:Predicate, nodes:[Node] ) => elems:[ElementNode],
// finds the first node in the array that matches the test predicate, or one
// of its children
findOne: ( test:Predicate, elems:[ElementNode] ) => findOne:ElementNode,
/*
The adapter can also optionally include an equals method, if your DOM
structure needs a custom equality test to compare two objects which refer
to the same underlying node. If not provided, `css-select` will fall back to
`a === b`.
*/
equals: ( a:Node, b:Node ) => Boolean
}
```
## Supported selectors
_As defined by CSS 4 and / or jQuery._
* Universal (`*`)
* Tag (`<tagname>`)
* Descendant (` `)
* Child (`>`)
* Parent (`<`) *
* Sibling (`+`)
* Adjacent (`~`)
* Attribute (`[attr=foo]`), with supported comparisons:
* `[attr]` (existential)
* `=`
* `~=`
* `|=`
* `*=`
* `^=`
* `$=`
* `!=` *
* Also, `i` can be added after the comparison to make the comparison case-insensitive (eg. `[attr=foo i]`) *
* Pseudos:
* `:not`
* `:contains` *
* `:icontains` * (case-insensitive version of `:contains`)
* `:has` *
* `:root`
* `:empty`
* `:parent` *
* `:[first|last]-child[-of-type]`
* `:only-of-type`, `:only-child`
* `:nth-[last-]child[-of-type]`
* `:link`
* `:visited`, `:hover`, `:active` * (these depend on optional Adapter methods, so these will work only if implemented in Adapter)
* `:selected` *, `:checked`
* `:enabled`, `:disabled`
* `:required`, `:optional`
* `:header`, `:button`, `:input`, `:text`, `:checkbox`, `:file`, `:password`, `:reset`, `:radio` etc. *
* `:matches` *
__*__: Not part of CSS3
---
License: BSD-2-Clause
## Security contact information
To report a security vulnerability, please use the [Tidelift security contact](https://tidelift.com/security).
Tidelift will coordinate the fix and disclosure.
## `css-select` for enterprise
Available as part of the Tidelift Subscription
The maintainers of `css-select` and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. [Learn more.](https://tidelift.com/subscription/pkg/npm-css-select?utm_source=npm-css-select&utm_medium=referral&utm_campaign=enterprise&utm_term=repo)

View File

@@ -0,0 +1,219 @@
export = CSSselect;
/**
* Alias for CSSselect.selectAll(query, elems, options).
* @see [CSSselect.compile] for supported selector queries.
*/
declare function CSSselect<Node, ElementNode extends Node>(
query: CSSselect.Query,
elems: Array<ElementNode> | ElementNode,
options?: CSSselect.Options<Node, ElementNode>
): Array<ElementNode>;
declare namespace CSSselect {
type Predicate<Value> = (v: Value) => boolean;
interface Adapter<Node, ElementNode extends Node> {
/**
* is the node a tag?
*/
isTag(node: Node): node is ElementNode;
/**
* Does at least one of passed element nodes pass the test predicate?
*/
existsOne(test: Predicate<ElementNode>, elems: Array<ElementNode>): boolean;
/**
* get the attribute value.
*/
getAttributeValue(elem: ElementNode, name: string): string;
/**
* get the node's children
*/
getChildren(node: Node): Array<Node>;
/**
* get the name of the tag
*/
getName(elem: ElementNode): string;
/**
* get the parent of the node
*/
getParent(node: Node): Node;
/*
Get the siblings of the node. Note that unlike jQuery's `siblings` method,
this is expected to include the current node as well
*/
getSiblings(node: Node): Array<Node>;
/*
* Get the text content of the node, and its children if it has any.
*/
getText(node: Node): string;
/**
* Does the element have the named attribute?
*/
hasAttrib(elem: ElementNode, name: string): boolean;
/**
* takes an array of nodes, and removes any duplicates, as well as any
* nodes whose ancestors are also in the array.
*/
removeSubsets(nodes: Array<Node>): Array<Node>;
/**
* finds all of the element nodes in the array that match the test predicate,
* as well as any of their children that match it.
*/
findAll(test: Predicate<ElementNode>, nodes: Array<Node>): Array<ElementNode>;
/**
* finds the first node in the array that matches the test predicate, or one
* of its children.
*/
findOne(test: Predicate<ElementNode>, elems: Array<ElementNode>): ElementNode | undefined,
/**
The adapter can also optionally include an equals method, if your DOM
structure needs a custom equality test to compare two objects which refer
to the same underlying node. If not provided, `css-select` will fall back to
`a === b`.
*/
equals?: (a: Node, b: Node) => boolean;
/**
* is the element in hovered state?
*/
isHovered?: (elem: ElementNode) => boolean;
/**
* is the element in visited state?
*/
isVisited?: (elem: ElementNode) => boolean;
/**
* is the element in active state?
*/
isActive?: (elem: ElementNode) => boolean;
}
// TODO default types to the domutil/httpparser2 types
interface Options<Node, ElementNode extends Node> {
/**
* When enabled, tag names will be case-sensitive. Default: false.
*/
xmlMode?: boolean;
/**
* Limits the module to only use CSS3 selectors. Default: false.
*/
strict?: boolean;
/**
* The last function in the stack, will be called with the last element
* that's looked at. Should return true.
*/
rootFunc?: (element: ElementNode) => true;
/**
* The adapter to use when interacting with the backing DOM structure. By
* default it uses domutils.
*/
adapter?: Adapter<Node, ElementNode>;
}
type CompiledQuery = (node: any) => boolean;
type Query = string | CompiledQuery;
/**
* Compiles the query, returns a function.
*
* Supported simple selectors:
* * Universal (*)
* * Tag (<tagname>)
* * Attribute ([attr=foo]), with supported comparisons:
* * [attr] (existential)
* * =
* * ~=
* * |=
* * *=
* * ^=
* * $=
* * !=
* * Can be case insensitive (E.g. [attr=foo i])
* * Pseudos:
* * :not
* * :root
* * :empty
* * :[first|last]-child[-of-type]
* * :only-of-type, :only-child
* * :nth-[last-]child[-of-type]
* * :link, :visited (the latter doesn't match any elements)
* * :checked
* * :enabled, :disabled
* * :required, :optional
* * Nonstandard Pseudos (available when strict mode is not enabled):
* * `:contains`
* * `:icontains` (case-insensitive version of :contains)
* * `:has`
* * `:parent`
* * `:selected`
* * `:header, :button, :input, :text, :checkbox, :file, :password, :reset, :radio etc.
* * :matches
*
* Supported Combinators:
*
* * Descendant (` `)
* * Child (`>`)
* * Parent (`<`) (when strict mode is not enabled)
* * Sibling (`~`)
* * Adjacent (`+`)
*/
function compile(query: string): CompiledQuery;
/**
* @template Node The generic Node type for the DOM adapter being used.
* @template ElementNode The Node type for elements for the DOM adapter being used.
* @param elems Elements to query. If it is an element, its children will be queried..
* @param query can be either a CSS selector string or a compiled query function.
* @param [options] options for querying the document.
* @see CSSselect.compile for supported selector queries.
* @returns All matching elements.
*/
function selectAll<Node, ElementNode extends Node>(
query: Query,
elems: Array<ElementNode> | ElementNode,
options?: Options<Node, ElementNode>
): Array<ElementNode>;
/**
* @template Node The generic Node type for the DOM adapter being used.
* @template ElementNode The Node type for elements for the DOM adapter being used.
* @param elems Elements to query. If it is an element, its children will be queried..
* @param query can be either a CSS selector string or a compiled query function.
* @param [options] options for querying the document.
* @see CSSselect.compile for supported selector queries.
* @returns the first match, or null if there was no match.
*/
function selectOne<Node, ElementNode extends Node>(
query: Query,
elems: Array<ElementNode> | ElementNode,
options?: Options<Node, ElementNode>
): ElementNode | null;
/**
* Tests whether or not an element is matched by query.
*
* @template Node The generic Node type for the DOM adapter being used.
* @template ElementNode The Node type for elements for the DOM adapter being used.
* @param elem The element to test if it matches the query.
* @param query can be either a CSS selector string or a compiled query function.
* @param [options] options for querying the document.
* @see CSSselect.compile for supported selector queries.
* @returns
*/
function is<Node, ElementNode extends Node>(
elem: ElementNode,
query: Query,
options?: Options<Node, ElementNode>
): boolean;
}

View File

@@ -0,0 +1,94 @@
"use strict";
module.exports = CSSselect;
var DomUtils = require("domutils");
var falseFunc = require("boolbase").falseFunc;
var compileRaw = require("./lib/compile.js");
function wrapCompile(func) {
return function addAdapter(selector, options, context) {
options = options || {};
options.adapter = options.adapter || DomUtils;
return func(selector, options, context);
};
}
var compile = wrapCompile(compileRaw);
var compileUnsafe = wrapCompile(compileRaw.compileUnsafe);
function getSelectorFunc(searchFunc) {
return function select(query, elems, options) {
options = options || {};
options.adapter = options.adapter || DomUtils;
if (typeof query !== "function") {
query = compileUnsafe(query, options, elems);
}
if (query.shouldTestNextSiblings) {
elems = appendNextSiblings((options && options.context) || elems, options.adapter);
}
if (!Array.isArray(elems)) elems = options.adapter.getChildren(elems);
else elems = options.adapter.removeSubsets(elems);
return searchFunc(query, elems, options);
};
}
function getNextSiblings(elem, adapter) {
var siblings = adapter.getSiblings(elem);
if (!Array.isArray(siblings)) return [];
siblings = siblings.slice(0);
while (siblings.shift() !== elem);
return siblings;
}
function appendNextSiblings(elems, adapter) {
// Order matters because jQuery seems to check the children before the siblings
if (!Array.isArray(elems)) elems = [elems];
var newElems = elems.slice(0);
for (var i = 0, len = elems.length; i < len; i++) {
var nextSiblings = getNextSiblings(newElems[i], adapter);
newElems.push.apply(newElems, nextSiblings);
}
return newElems;
}
var selectAll = getSelectorFunc(function selectAll(query, elems, options) {
return query === falseFunc || !elems || elems.length === 0 ? [] : options.adapter.findAll(query, elems);
});
var selectOne = getSelectorFunc(function selectOne(query, elems, options) {
return query === falseFunc || !elems || elems.length === 0 ? null : options.adapter.findOne(query, elems);
});
function is(elem, query, options) {
options = options || {};
options.adapter = options.adapter || DomUtils;
return (typeof query === "function" ? query : compile(query, options))(elem);
}
/*
the exported interface
*/
function CSSselect(query, elems, options) {
return selectAll(query, elems, options);
}
CSSselect.compile = compile;
CSSselect.filters = compileRaw.Pseudos.filters;
CSSselect.pseudos = compileRaw.Pseudos.pseudos;
CSSselect.selectAll = selectAll;
CSSselect.selectOne = selectOne;
CSSselect.is = is;
//legacy methods (might be removed)
CSSselect.parse = compile;
CSSselect.iterate = selectAll;
//hooks
CSSselect._compileUnsafe = compileUnsafe;
CSSselect._compileToken = compileRaw.compileToken;

View File

@@ -0,0 +1,47 @@
{
"name": "css-select",
"version": "2.1.0",
"description": "a CSS selector compiler/engine",
"author": "Felix Boehm <me@feedic.com>",
"keywords": [
"css",
"selector",
"sizzle"
],
"repository": {
"type": "git",
"url": "git://github.com/fb55/css-select.git"
},
"files": [
"index.js",
"index.d.ts",
"lib"
],
"dependencies": {
"boolbase": "^1.0.0",
"css-what": "^3.2.1",
"domutils": "^1.7.0",
"nth-check": "^1.0.2"
},
"devDependencies": {
"cheerio-soupselect": "^0.1.1",
"coveralls": "^3.0.2",
"eslint": "^6.0.0",
"expect.js": "^0.3.1",
"htmlparser2": "^4.0.0",
"istanbul": "^0.4.5",
"mocha": "^6.0.0",
"mocha-lcov-reporter": "^1.3.0"
},
"scripts": {
"test": "mocha && npm run lint",
"lint": "eslint index.js lib/*.js test/*.js",
"lcov": "istanbul cover _mocha --report lcovonly -- -R spec",
"coveralls": "npm run lint && npm run lcov && (cat coverage/lcov.info | coveralls || exit 0)"
},
"license": "BSD-2-Clause",
"types": "index.d.ts",
"prettier": {
"tabWidth": 4
}
}

View File

@@ -0,0 +1,11 @@
Copyright (c) Felix Böhm
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
THIS IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -0,0 +1,55 @@
{
"author": "Felix Böhm <me@feedic.com> (http://feedic.com)",
"name": "css-what",
"description": "a CSS selector parser",
"version": "3.4.2",
"funding": "https://github.com/sponsors/fb55",
"repository": {
"url": "https://github.com/fb55/css-what"
},
"main": "lib/index.js",
"types": "lib/index.d.ts",
"files": [
"lib/**/*"
],
"scripts": {
"test": "jest --coverage -u && npm run lint",
"coverage": "cat coverage/lcov.info | coveralls",
"lint": "npm run lint:es && npm run lint:prettier",
"lint:es": "eslint src",
"lint:prettier": "npm run prettier -- --check",
"format": "npm run format:es && npm run format:prettier",
"format:es": "npm run lint:es -- --fix",
"format:prettier": "npm run prettier -- --write",
"prettier": "prettier '**/*.{ts,md,json,yml}'",
"build": "tsc",
"prepare": "npm run build"
},
"dependencies": {},
"devDependencies": {
"@types/jest": "^26.0.3",
"@types/node": "^14.0.5",
"@typescript-eslint/eslint-plugin": "^4.1.0",
"@typescript-eslint/parser": "^4.1.0",
"coveralls": "^3.0.5",
"eslint": "^7.0.0",
"eslint-config-prettier": "^6.0.0",
"eslint-plugin-node": "^11.1.0",
"jest": "^26.0.1",
"prettier": "^2.0.5",
"ts-jest": "^26.0.0",
"typescript": "^4.0.2"
},
"optionalDependencies": {},
"engines": {
"node": ">= 6"
},
"license": "BSD-2-Clause",
"jest": {
"preset": "ts-jest",
"testEnvironment": "node"
},
"prettier": {
"tabWidth": 4
}
}

View File

@@ -0,0 +1,70 @@
# css-what [![Build Status](https://secure.travis-ci.org/fb55/css-what.svg?branch=master)](http://travis-ci.org/fb55/css-what)
a CSS selector parser
## Example
```js
const CSSwhat = require("css-what")
CSSwhat.parse("foo[bar]:baz")
~> [
[
{ type: "tag", name: "foo" },
{
type: "attribute",
name: "bar",
action: "exists",
value: "",
ignoreCase: false
},
{ type: "pseudo", name: "baz", data: null }
]
]
```
## API
**`CSSwhat.parse(str, options)` - Parses `str`, optionally with the passed `options`.**
The function returns a two-dimensional array. The first array represents selectors separated by commas (eg. `sub1, sub2`), the second contains the relevant tokens for that selector. Possible token types are:
| name | attributes | example | output |
| ---------------- | --------------------------------------- | ------------- | ---------------------------------------------------------------------------------------- |
| `tag` | `name` | `div` | `{ type: 'tag', name: 'div' }` |
| `universal` | - | `*` | `{ type: 'universal' }` |
| `pseudo` | `name`, `data` | `:name(data)` | `{ type: 'pseudo', name: 'name', data: 'data' }` |
| `pseudo` | `name`, `data` | `:name` | `{ type: 'pseudo', name: 'name', data: null }` |
| `pseudo-element` | `name` | `::name` | `{ type: 'pseudo-element', name: 'name' }` |
| `attribute` | `name`, `action`, `value`, `ignoreCase` | `[attr]` | `{ type: 'attribute', name: 'attr', action: 'exists', value: '', ignoreCase: false }` |
| `attribute` | `name`, `action`, `value`, `ignoreCase` | `[attr=val]` | `{ type: 'attribute', name: 'attr', action: 'equals', value: 'val', ignoreCase: false }` |
| `attribute` | `name`, `action`, `value`, `ignoreCase` | `[attr^=val]` | `{ type: 'attribute', name: 'attr', action: 'start', value: 'val', ignoreCase: false }` |
| `attribute` | `name`, `action`, `value`, `ignoreCase` | `[attr$=val]` | `{ type: 'attribute', name: 'attr', action: 'end', value: 'val', ignoreCase: false }` |
| `child` | - | `>` | `{ type: 'child' }` |
| `parent` | - | `<` | `{ type: 'parent' }` |
| `sibling` | - | `~` | `{ type: 'sibling' }` |
| `adjacent` | - | `+` | `{ type: 'adjacent' }` |
| `descendant` | - | | `{ type: 'descendant' }` |
**Options:**
- `lowerCaseTags`: When false, tag names will not be lowercased. Defaults to `true`.
- `lowerCaseAttributeNames`: When false, attribute names will not be lowercased. Defaults to `true`.
- `xmlMode`: When `true`, `xmlMode` implies both `lowerCaseTags` and `lowerCaseAttributeNames` are set to `false`.
**`CSSwhat.stringify(selector)` - Turns `selector` back into a string.**
---
License: BSD-2-Clause
## Security contact information
To report a security vulnerability, please use the [Tidelift security contact](https://tidelift.com/security).
Tidelift will coordinate the fix and disclosure.
## `css-what` for enterprise
Available as part of the Tidelift Subscription
The maintainers of `css-what` and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. [Learn more.](https://tidelift.com/subscription/pkg/npm-css-what?utm_source=npm-css-what&utm_medium=referral&utm_campaign=enterprise&utm_term=repo)

View File

@@ -0,0 +1,11 @@
License
(The MIT License)
Copyright (c) 2014 The cheeriojs contributors
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.

View File

@@ -0,0 +1 @@
Renders a DOM node or an array of DOM nodes to a string.

View File

@@ -0,0 +1,102 @@
{
"elementNames" : {
"altglyph" : "altGlyph",
"altglyphdef" : "altGlyphDef",
"altglyphitem" : "altGlyphItem",
"animatecolor" : "animateColor",
"animatemotion" : "animateMotion",
"animatetransform" : "animateTransform",
"clippath" : "clipPath",
"feblend" : "feBlend",
"fecolormatrix" : "feColorMatrix",
"fecomponenttransfer" : "feComponentTransfer",
"fecomposite" : "feComposite",
"feconvolvematrix" : "feConvolveMatrix",
"fediffuselighting" : "feDiffuseLighting",
"fedisplacementmap" : "feDisplacementMap",
"fedistantlight" : "feDistantLight",
"fedropshadow" : "feDropShadow",
"feflood" : "feFlood",
"fefunca" : "feFuncA",
"fefuncb" : "feFuncB",
"fefuncg" : "feFuncG",
"fefuncr" : "feFuncR",
"fegaussianblur" : "feGaussianBlur",
"feimage" : "feImage",
"femerge" : "feMerge",
"femergenode" : "feMergeNode",
"femorphology" : "feMorphology",
"feoffset" : "feOffset",
"fepointlight" : "fePointLight",
"fespecularlighting" : "feSpecularLighting",
"fespotlight" : "feSpotLight",
"fetile" : "feTile",
"feturbulence" : "feTurbulence",
"foreignobject" : "foreignObject",
"glyphref" : "glyphRef",
"lineargradient" : "linearGradient",
"radialgradient" : "radialGradient",
"textpath" : "textPath"
},
"attributeNames" : {
"definitionurl" : "definitionURL",
"attributename" : "attributeName",
"attributetype" : "attributeType",
"basefrequency" : "baseFrequency",
"baseprofile" : "baseProfile",
"calcmode" : "calcMode",
"clippathunits" : "clipPathUnits",
"diffuseconstant" : "diffuseConstant",
"edgemode" : "edgeMode",
"filterunits" : "filterUnits",
"glyphref" : "glyphRef",
"gradienttransform" : "gradientTransform",
"gradientunits" : "gradientUnits",
"kernelmatrix" : "kernelMatrix",
"kernelunitlength" : "kernelUnitLength",
"keypoints" : "keyPoints",
"keysplines" : "keySplines",
"keytimes" : "keyTimes",
"lengthadjust" : "lengthAdjust",
"limitingconeangle" : "limitingConeAngle",
"markerheight" : "markerHeight",
"markerunits" : "markerUnits",
"markerwidth" : "markerWidth",
"maskcontentunits" : "maskContentUnits",
"maskunits" : "maskUnits",
"numoctaves" : "numOctaves",
"pathlength" : "pathLength",
"patterncontentunits" : "patternContentUnits",
"patterntransform" : "patternTransform",
"patternunits" : "patternUnits",
"pointsatx" : "pointsAtX",
"pointsaty" : "pointsAtY",
"pointsatz" : "pointsAtZ",
"preservealpha" : "preserveAlpha",
"preserveaspectratio" : "preserveAspectRatio",
"primitiveunits" : "primitiveUnits",
"refx" : "refX",
"refy" : "refY",
"repeatcount" : "repeatCount",
"repeatdur" : "repeatDur",
"requiredextensions" : "requiredExtensions",
"requiredfeatures" : "requiredFeatures",
"specularconstant" : "specularConstant",
"specularexponent" : "specularExponent",
"spreadmethod" : "spreadMethod",
"startoffset" : "startOffset",
"stddeviation" : "stdDeviation",
"stitchtiles" : "stitchTiles",
"surfacescale" : "surfaceScale",
"systemlanguage" : "systemLanguage",
"tablevalues" : "tableValues",
"targetx" : "targetX",
"targety" : "targetY",
"textlength" : "textLength",
"viewbox" : "viewBox",
"viewtarget" : "viewTarget",
"xchannelselector" : "xChannelSelector",
"ychannelselector" : "yChannelSelector",
"zoomandpan" : "zoomAndPan"
}
}

View File

@@ -0,0 +1,17 @@
export interface DomSerializerOptions {
xmlMode?: boolean | 'foreign';
decodeEntities?: boolean;
}
/**
* Renders a DOM node or an array of DOM nodes to a string.
*
* Can be thought of as the equivalent of the `outerHTML` of the passed node(s).
*
* @param nodes Nodes to be rendered.
* @param options Changes serialization behavior
*/
export default function render(
nodes: {} | {}[],
options?: DomSerializerOptions
): string;

View File

@@ -0,0 +1,183 @@
/*
Module dependencies
*/
var ElementType = require('domelementtype');
var entities = require('entities');
/* mixed-case SVG and MathML tags & attributes
recognized by the HTML parser, see
https://html.spec.whatwg.org/multipage/parsing.html#parsing-main-inforeign
*/
var foreignNames = require('./foreignNames.json');
foreignNames.elementNames.__proto__ = null; /* use as a simple dictionary */
foreignNames.attributeNames.__proto__ = null;
var unencodedElements = {
__proto__: null,
style: true,
script: true,
xmp: true,
iframe: true,
noembed: true,
noframes: true,
plaintext: true,
noscript: true
};
/*
Format attributes
*/
function formatAttrs(attributes, opts) {
if (!attributes) return;
var output = '';
var value;
// Loop through the attributes
for (var key in attributes) {
value = attributes[key];
if (output) {
output += ' ';
}
if (opts.xmlMode === 'foreign') {
/* fix up mixed-case attribute names */
key = foreignNames.attributeNames[key] || key;
}
output += key;
if ((value !== null && value !== '') || opts.xmlMode) {
output +=
'="' +
(opts.decodeEntities
? entities.encodeXML(value)
: value.replace(/\"/g, '&quot;')) +
'"';
}
}
return output;
}
/*
Self-enclosing tags (stolen from node-htmlparser)
*/
var singleTag = {
__proto__: null,
area: true,
base: true,
basefont: true,
br: true,
col: true,
command: true,
embed: true,
frame: true,
hr: true,
img: true,
input: true,
isindex: true,
keygen: true,
link: true,
meta: true,
param: true,
source: true,
track: true,
wbr: true
};
var render = (module.exports = function(dom, opts) {
if (!Array.isArray(dom) && !dom.cheerio) dom = [dom];
opts = opts || {};
var output = '';
for (var i = 0; i < dom.length; i++) {
var elem = dom[i];
if (elem.type === 'root') output += render(elem.children, opts);
else if (ElementType.isTag(elem)) output += renderTag(elem, opts);
else if (elem.type === ElementType.Directive)
output += renderDirective(elem);
else if (elem.type === ElementType.Comment) output += renderComment(elem);
else if (elem.type === ElementType.CDATA) output += renderCdata(elem);
else output += renderText(elem, opts);
}
return output;
});
var foreignModeIntegrationPoints = [
'mi',
'mo',
'mn',
'ms',
'mtext',
'annotation-xml',
'foreignObject',
'desc',
'title'
];
function renderTag(elem, opts) {
// Handle SVG / MathML in HTML
if (opts.xmlMode === 'foreign') {
/* fix up mixed-case element names */
elem.name = foreignNames.elementNames[elem.name] || elem.name;
/* exit foreign mode at integration points */
if (
elem.parent &&
foreignModeIntegrationPoints.indexOf(elem.parent.name) >= 0
)
opts = Object.assign({}, opts, { xmlMode: false });
}
if (!opts.xmlMode && ['svg', 'math'].indexOf(elem.name) >= 0) {
opts = Object.assign({}, opts, { xmlMode: 'foreign' });
}
var tag = '<' + elem.name;
var attribs = formatAttrs(elem.attribs, opts);
if (attribs) {
tag += ' ' + attribs;
}
if (opts.xmlMode && (!elem.children || elem.children.length === 0)) {
tag += '/>';
} else {
tag += '>';
if (elem.children) {
tag += render(elem.children, opts);
}
if (!singleTag[elem.name] || opts.xmlMode) {
tag += '</' + elem.name + '>';
}
}
return tag;
}
function renderDirective(elem) {
return '<' + elem.data + '>';
}
function renderText(elem, opts) {
var data = elem.data || '';
// if entities weren't decoded, no need to encode them back
if (
opts.decodeEntities &&
!(elem.parent && elem.parent.name in unencodedElements)
) {
data = entities.encodeXML(data);
}
return data;
}
function renderCdata(elem) {
return '<![CDATA[' + elem.children[0].data + ']]>';
}
function renderComment(elem) {
return '<!--' + elem.data + '-->';
}

View File

@@ -0,0 +1,40 @@
{
"name": "dom-serializer",
"version": "0.2.2",
"description": "render dom nodes to string",
"author": "Felix Boehm <me@feedic.com>",
"keywords": [
"html",
"xml",
"render"
],
"repository": {
"type": "git",
"url": "git://github.com/cheeriojs/dom-renderer.git"
},
"main": "./index.js",
"files": [
"index.js",
"index.d.ts",
"foreignNames.json"
],
"dependencies": {
"domelementtype": "^2.0.1",
"entities": "^2.0.0"
},
"devDependencies": {
"cheerio": "^1.0.0-rc.2",
"expect.js": "~0.3.1",
"htmlparser2": "^3.10.0",
"lodash": "^4.17.11",
"mocha": "^6.2.0",
"xyz": "^3.0.0"
},
"scripts": {
"test": "mocha test.js"
},
"prettier": {
"singleQuote": true
},
"license": "MIT"
}

View File

@@ -0,0 +1,5 @@
sudo: true
language: node_js
node_js:
- 8

View File

@@ -0,0 +1,11 @@
Copyright (c) Felix Böhm
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
THIS IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -0,0 +1,14 @@
var DomUtils = module.exports;
[
require("./lib/stringify"),
require("./lib/traversal"),
require("./lib/manipulation"),
require("./lib/querying"),
require("./lib/legacy"),
require("./lib/helpers")
].forEach(function(ext){
Object.keys(ext).forEach(function(key){
DomUtils[key] = ext[key].bind(DomUtils);
});
});

View File

@@ -0,0 +1,11 @@
Copyright (c) Felix Böhm
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
THIS IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -0,0 +1,15 @@
//Types of elements found in the DOM
module.exports = {
Text: "text", //Text
Directive: "directive", //<? ... ?>
Comment: "comment", //<!-- ... -->
Script: "script", //<script> tags
Style: "style", //<style> tags
Tag: "tag", //Any tag
CDATA: "cdata", //<![CDATA[ ... ]]>
Doctype: "doctype",
isTag: function(elem){
return elem.type === "tag" || elem.type === "script" || elem.type === "style";
}
};

View File

@@ -0,0 +1,16 @@
{
"name": "domelementtype",
"version": "1.3.1",
"description": "all the types of nodes in htmlparser2's dom",
"main": "index.js",
"repository": {
"type": "git",
"url": "git://github.com/fb55/domelementtype.git"
},
"keywords": [
"dom",
"htmlparser2"
],
"author": "Felix Boehm <me@feedic.com>",
"license": "BSD-2-Clause"
}

View File

@@ -0,0 +1 @@
all the types of nodes in htmlparser2's dom

View File

@@ -0,0 +1,47 @@
{
"name": "domutils",
"version": "1.7.0",
"description": "utilities for working with htmlparser2's dom",
"main": "index.js",
"directories": {
"test": "tests"
},
"scripts": {
"test": "mocha test/tests/**.js && jshint index.js test/**/*.js lib/*.js"
},
"repository": {
"type": "git",
"url": "git://github.com/FB55/domutils.git"
},
"keywords": [
"dom",
"htmlparser2"
],
"dependencies": {
"dom-serializer": "0",
"domelementtype": "1"
},
"devDependencies": {
"htmlparser2": "~3.9.2",
"domhandler": "2",
"jshint": "~2.9.4",
"mocha": "~3.2.0"
},
"author": "Felix Boehm <me@feedic.com>",
"license": "BSD-2-Clause",
"jshintConfig": {
"proto": true,
"unused": true,
"eqnull": true,
"undef": true,
"quotmark": "double",
"eqeqeq": true,
"trailing": true,
"node": true,
"globals": {
"describe": true,
"it": true,
"beforeEach": true
}
}
}

View File

@@ -0,0 +1,3 @@
Utilities for working with htmlparser2's dom
[![Build Status](https://travis-ci.org/fb55/domutils.svg?branch=master)](https://travis-ci.org/fb55/domutils)

View File

@@ -0,0 +1,6 @@
var makeDom = require("./utils").makeDom;
var markup = Array(21).join(
"<?xml><tag1 id='asdf'> <script>text</script> <!-- comment --> <tag2> text </tag1>"
);
module.exports = makeDom(markup);

View File

@@ -0,0 +1,89 @@
var makeDom = require("../utils").makeDom;
var helpers = require("../..");
var assert = require("assert");
describe("helpers", function() {
describe("removeSubsets", function() {
var removeSubsets = helpers.removeSubsets;
var dom = makeDom("<div><p><span></span></p><p></p></div>")[0];
it("removes identical trees", function() {
var matches = removeSubsets([dom, dom]);
assert.equal(matches.length, 1);
});
it("Removes subsets found first", function() {
var matches = removeSubsets([dom, dom.children[0].children[0]]);
assert.equal(matches.length, 1);
});
it("Removes subsets found last", function() {
var matches = removeSubsets([dom.children[0], dom]);
assert.equal(matches.length, 1);
});
it("Does not remove unique trees", function() {
var matches = removeSubsets([dom.children[0], dom.children[1]]);
assert.equal(matches.length, 2);
});
});
describe("compareDocumentPosition", function() {
var compareDocumentPosition = helpers.compareDocumentPosition;
var markup = "<div><p><span></span></p><a></a></div>";
var dom = makeDom(markup)[0];
var p = dom.children[0];
var span = p.children[0];
var a = dom.children[1];
it("reports when the first node occurs before the second indirectly", function() {
assert.equal(compareDocumentPosition(span, a), 2);
});
it("reports when the first node contains the second", function() {
assert.equal(compareDocumentPosition(p, span), 10);
});
it("reports when the first node occurs after the second indirectly", function() {
assert.equal(compareDocumentPosition(a, span), 4);
});
it("reports when the first node is contained by the second", function() {
assert.equal(compareDocumentPosition(span, p), 20);
});
it("reports when the nodes belong to separate documents", function() {
var other = makeDom(markup)[0].children[0].children[0];
assert.equal(compareDocumentPosition(span, other), 1);
});
it("reports when the nodes are identical", function() {
assert.equal(compareDocumentPosition(span, span), 0);
});
});
describe("uniqueSort", function() {
var uniqueSort = helpers.uniqueSort;
var dom, p, span, a;
beforeEach(function() {
dom = makeDom("<div><p><span></span></p><a></a></div>")[0];
p = dom.children[0];
span = p.children[0];
a = dom.children[1];
});
it("leaves unique elements untouched", function() {
assert.deepEqual(uniqueSort([p, a]), [p, a]);
});
it("removes duplicate elements", function() {
assert.deepEqual(uniqueSort([p, a, p]), [p, a]);
});
it("sorts nodes in document order", function() {
assert.deepEqual(uniqueSort([a, dom, span, p]), [dom, p, span, a]);
});
});
});

View File

@@ -0,0 +1,119 @@
var DomUtils = require("../..");
var fixture = require("../fixture");
var assert = require("assert");
// Set up expected structures
var expected = {
idAsdf: fixture[1],
tag2: [],
typeScript: []
};
for (var idx = 0; idx < 20; ++idx) {
expected.tag2.push(fixture[idx*2 + 1].children[5]);
expected.typeScript.push(fixture[idx*2 + 1].children[1]);
}
describe("legacy", function() {
describe("getElements", function() {
var getElements = DomUtils.getElements;
it("returns the node with the specified ID", function() {
assert.deepEqual(
getElements({ id: "asdf" }, fixture, true, 1),
[expected.idAsdf]
);
});
it("returns empty array for unknown IDs", function() {
assert.deepEqual(getElements({ id: "asdfs" }, fixture, true), []);
});
it("returns the nodes with the specified tag name", function() {
assert.deepEqual(
getElements({ tag_name:"tag2" }, fixture, true),
expected.tag2
);
});
it("returns empty array for unknown tag names", function() {
assert.deepEqual(
getElements({ tag_name : "asdfs" }, fixture, true),
[]
);
});
it("returns the nodes with the specified tag type", function() {
assert.deepEqual(
getElements({ tag_type: "script" }, fixture, true),
expected.typeScript
);
});
it("returns empty array for unknown tag types", function() {
assert.deepEqual(
getElements({ tag_type: "video" }, fixture, true),
[]
);
});
});
describe("getElementById", function() {
var getElementById = DomUtils.getElementById;
it("returns the specified node", function() {
assert.equal(
expected.idAsdf,
getElementById("asdf", fixture, true)
);
});
it("returns `null` for unknown IDs", function() {
assert.equal(null, getElementById("asdfs", fixture, true));
});
});
describe("getElementsByTagName", function() {
var getElementsByTagName = DomUtils.getElementsByTagName;
it("returns the specified nodes", function() {
assert.deepEqual(
getElementsByTagName("tag2", fixture, true),
expected.tag2
);
});
it("returns empty array for unknown tag names", function() {
assert.deepEqual(
getElementsByTagName("tag23", fixture, true),
[]
);
});
});
describe("getElementsByTagType", function() {
var getElementsByTagType = DomUtils.getElementsByTagType;
it("returns the specified nodes", function() {
assert.deepEqual(
getElementsByTagType("script", fixture, true),
expected.typeScript
);
});
it("returns empty array for unknown tag types", function() {
assert.deepEqual(
getElementsByTagType("video", fixture, true),
[]
);
});
});
describe("getOuterHTML", function() {
var getOuterHTML = DomUtils.getOuterHTML;
it("Correctly renders the outer HTML", function() {
assert.equal(
getOuterHTML(fixture[1]),
"<tag1 id=\"asdf\"> <script>text</script> <!-- comment --> <tag2> text </tag2></tag1>"
);
});
});
describe("getInnerHTML", function() {
var getInnerHTML = DomUtils.getInnerHTML;
it("Correctly renders the inner HTML", function() {
assert.equal(
getInnerHTML(fixture[1]),
" <script>text</script> <!-- comment --> <tag2> text </tag2>"
);
});
});
});

View File

@@ -0,0 +1,17 @@
var makeDom = require("../utils").makeDom;
var traversal = require("../..");
var assert = require("assert");
describe("traversal", function() {
describe("hasAttrib", function() {
var hasAttrib = traversal.hasAttrib;
it("doesn't throw on text nodes", function() {
var dom = makeDom("textnode");
assert.doesNotThrow(function() {
hasAttrib(dom[0], "some-attrib");
});
});
});
});

View File

@@ -0,0 +1,9 @@
var htmlparser = require("htmlparser2");
exports.makeDom = function(markup) {
var handler = new htmlparser.DomHandler(),
parser = new htmlparser.Parser(handler);
parser.write(markup);
parser.done();
return handler.dom;
};

View File

@@ -0,0 +1,11 @@
'use strict';
var matchOperatorsRe = /[|\\{}()[\]^$+*?.]/g;
module.exports = function (str) {
if (typeof str !== 'string') {
throw new TypeError('Expected a string');
}
return str.replace(matchOperatorsRe, '\\$&');
};

View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@@ -0,0 +1,41 @@
{
"name": "escape-string-regexp",
"version": "1.0.5",
"description": "Escape RegExp special characters",
"license": "MIT",
"repository": "sindresorhus/escape-string-regexp",
"author": {
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
"url": "sindresorhus.com"
},
"maintainers": [
"Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)",
"Joshua Boy Nicolai Appelman <joshua@jbna.nl> (jbna.nl)"
],
"engines": {
"node": ">=0.8.0"
},
"scripts": {
"test": "xo && ava"
},
"files": [
"index.js"
],
"keywords": [
"escape",
"regex",
"regexp",
"re",
"regular",
"expression",
"string",
"str",
"special",
"characters"
],
"devDependencies": {
"ava": "*",
"xo": "*"
}
}

View File

@@ -0,0 +1,27 @@
# escape-string-regexp [![Build Status](https://travis-ci.org/sindresorhus/escape-string-regexp.svg?branch=master)](https://travis-ci.org/sindresorhus/escape-string-regexp)
> Escape RegExp special characters
## Install
```
$ npm install --save escape-string-regexp
```
## Usage
```js
const escapeStringRegexp = require('escape-string-regexp');
const escapedString = escapeStringRegexp('how much $ for a unicorn?');
//=> 'how much \$ for a unicorn\?'
new RegExp(escapedString);
```
## License
MIT © [Sindre Sorhus](http://sindresorhus.com)

View File

@@ -0,0 +1,8 @@
'use strict';
module.exports = (flag, argv) => {
argv = argv || process.argv;
const prefix = flag.startsWith('-') ? '' : (flag.length === 1 ? '-' : '--');
const pos = argv.indexOf(prefix + flag);
const terminatorPos = argv.indexOf('--');
return pos !== -1 && (terminatorPos === -1 ? true : pos < terminatorPos);
};

View File

@@ -0,0 +1,9 @@
MIT License
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -0,0 +1,44 @@
{
"name": "has-flag",
"version": "3.0.0",
"description": "Check if argv has a specific flag",
"license": "MIT",
"repository": "sindresorhus/has-flag",
"author": {
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
"url": "sindresorhus.com"
},
"engines": {
"node": ">=4"
},
"scripts": {
"test": "xo && ava"
},
"files": [
"index.js"
],
"keywords": [
"has",
"check",
"detect",
"contains",
"find",
"flag",
"cli",
"command-line",
"argv",
"process",
"arg",
"args",
"argument",
"arguments",
"getopt",
"minimist",
"optimist"
],
"devDependencies": {
"ava": "*",
"xo": "*"
}
}

View File

@@ -0,0 +1,70 @@
# has-flag [![Build Status](https://travis-ci.org/sindresorhus/has-flag.svg?branch=master)](https://travis-ci.org/sindresorhus/has-flag)
> Check if [`argv`](https://nodejs.org/docs/latest/api/process.html#process_process_argv) has a specific flag
Correctly stops looking after an `--` argument terminator.
## Install
```
$ npm install has-flag
```
## Usage
```js
// foo.js
const hasFlag = require('has-flag');
hasFlag('unicorn');
//=> true
hasFlag('--unicorn');
//=> true
hasFlag('f');
//=> true
hasFlag('-f');
//=> true
hasFlag('foo=bar');
//=> true
hasFlag('foo');
//=> false
hasFlag('rainbow');
//=> false
```
```
$ node foo.js -f --unicorn --foo=bar -- --rainbow
```
## API
### hasFlag(flag, [argv])
Returns a boolean for whether the flag exists.
#### flag
Type: `string`
CLI flag to look for. The `--` prefix is optional.
#### argv
Type: `string[]`<br>
Default: `process.argv`
CLI arguments.
## License
MIT © [Sindre Sorhus](https://sindresorhus.com)

View File

@@ -0,0 +1,11 @@
Copyright (c) Felix Böhm
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
THIS IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -0,0 +1,51 @@
# nth-check [![Build Status](https://travis-ci.org/fb55/nth-check.svg)](https://travis-ci.org/fb55/nth-check)
A performant nth-check parser & compiler.
### About
This module can be used to parse & compile nth-checks, as they are found in CSS 3's `nth-child()` and `nth-last-of-type()`.
`nth-check` focusses on speed, providing optimized functions for different kinds of nth-child formulas, while still following the [spec](http://www.w3.org/TR/css3-selectors/#nth-child-pseudo).
### API
```js
var nthCheck = require("nth-check");
```
##### `nthCheck(formula)`
First parses, then compiles the formula.
##### `nthCheck.parse(formula)`
Parses the expression, throws a `SyntaxError` if it fails, otherwise returns an array containing two elements.
__Example:__
```js
nthCheck.parse("2n+3") //[2, 3]
```
##### `nthCheck.compile([a, b])`
Takes an array with two elements (as returned by `.parse`) and returns a highly optimized function.
If the formula doesn't match any elements, it returns [`boolbase`](https://github.com/fb55/boolbase)'s `falseFunc`, otherwise, a function accepting an _index_ is returned, which returns whether or not a passed _index_ matches the formula. (Note: The spec starts counting at `1`, the returned function at `0`).
__Example:__
```js
var check = nthCheck.compile([2, 3]);
check(0) //false
check(1) //false
check(2) //true
check(3) //false
check(4) //true
check(5) //false
check(6) //true
```
---
License: BSD

View File

@@ -0,0 +1,40 @@
module.exports = compile;
var BaseFuncs = require("boolbase"),
trueFunc = BaseFuncs.trueFunc,
falseFunc = BaseFuncs.falseFunc;
/*
returns a function that checks if an elements index matches the given rule
highly optimized to return the fastest solution
*/
function compile(parsed){
var a = parsed[0],
b = parsed[1] - 1;
//when b <= 0, a*n won't be possible for any matches when a < 0
//besides, the specification says that no element is matched when a and b are 0
if(b < 0 && a <= 0) return falseFunc;
//when a is in the range -1..1, it matches any element (so only b is checked)
if(a ===-1) return function(pos){ return pos <= b; };
if(a === 0) return function(pos){ return pos === b; };
//when b <= 0 and a === 1, they match any element
if(a === 1) return b < 0 ? trueFunc : function(pos){ return pos >= b; };
//when a > 0, modulo can be used to check if there is a match
var bMod = b % a;
if(bMod < 0) bMod += a;
if(a > 1){
return function(pos){
return pos >= b && pos % a === bMod;
};
}
a *= -1; //make `a` positive
return function(pos){
return pos <= b && pos % a === bMod;
};
}

View File

@@ -0,0 +1,9 @@
var parse = require("./parse.js"),
compile = require("./compile.js");
module.exports = function nthCheck(formula){
return compile(parse(formula));
};
module.exports.parse = parse;
module.exports.compile = compile;

View File

@@ -0,0 +1,32 @@
{
"name": "nth-check",
"version": "1.0.2",
"description": "performant nth-check parser & compiler",
"main": "index.js",
"scripts": {
"test": "node test"
},
"repository": {
"type": "git",
"url": "https://github.com/fb55/nth-check"
},
"files": [
"compile.js",
"index.js",
"parse.js"
],
"keywords": [
"nth-child",
"nth",
"css"
],
"author": "Felix Boehm <me@feedic.com>",
"license": "BSD-2-Clause",
"bugs": {
"url": "https://github.com/fb55/nth-check/issues"
},
"homepage": "https://github.com/fb55/nth-check",
"dependencies": {
"boolbase": "~1.0.0"
}
}

View File

@@ -0,0 +1,40 @@
module.exports = parse;
//following http://www.w3.org/TR/css3-selectors/#nth-child-pseudo
//[ ['-'|'+']? INTEGER? {N} [ S* ['-'|'+'] S* INTEGER ]?
var re_nthElement = /^([+\-]?\d*n)?\s*(?:([+\-]?)\s*(\d+))?$/;
/*
parses a nth-check formula, returns an array of two numbers
*/
function parse(formula){
formula = formula.trim().toLowerCase();
if(formula === "even"){
return [2, 0];
} else if(formula === "odd"){
return [2, 1];
} else {
var parsed = formula.match(re_nthElement);
if(!parsed){
throw new SyntaxError("n-th rule couldn't be parsed ('" + formula + "')");
}
var a;
if(parsed[1]){
a = parseInt(parsed[1], 10);
if(isNaN(a)){
if(parsed[1].charAt(0) === "-") a = -1;
else a = 1;
}
} else a = 0;
return [
a,
parsed[3] ? parseInt((parsed[2] || "") + parsed[3], 10) : 0
];
}
}

View File

@@ -0,0 +1,5 @@
'use strict';
module.exports = {
stdout: false,
stderr: false
};

View File

@@ -0,0 +1,131 @@
'use strict';
const os = require('os');
const hasFlag = require('has-flag');
const env = process.env;
let forceColor;
if (hasFlag('no-color') ||
hasFlag('no-colors') ||
hasFlag('color=false')) {
forceColor = false;
} else if (hasFlag('color') ||
hasFlag('colors') ||
hasFlag('color=true') ||
hasFlag('color=always')) {
forceColor = true;
}
if ('FORCE_COLOR' in env) {
forceColor = env.FORCE_COLOR.length === 0 || parseInt(env.FORCE_COLOR, 10) !== 0;
}
function translateLevel(level) {
if (level === 0) {
return false;
}
return {
level,
hasBasic: true,
has256: level >= 2,
has16m: level >= 3
};
}
function supportsColor(stream) {
if (forceColor === false) {
return 0;
}
if (hasFlag('color=16m') ||
hasFlag('color=full') ||
hasFlag('color=truecolor')) {
return 3;
}
if (hasFlag('color=256')) {
return 2;
}
if (stream && !stream.isTTY && forceColor !== true) {
return 0;
}
const min = forceColor ? 1 : 0;
if (process.platform === 'win32') {
// Node.js 7.5.0 is the first version of Node.js to include a patch to
// libuv that enables 256 color output on Windows. Anything earlier and it
// won't work. However, here we target Node.js 8 at minimum as it is an LTS
// release, and Node.js 7 is not. Windows 10 build 10586 is the first Windows
// release that supports 256 colors. Windows 10 build 14931 is the first release
// that supports 16m/TrueColor.
const osRelease = os.release().split('.');
if (
Number(process.versions.node.split('.')[0]) >= 8 &&
Number(osRelease[0]) >= 10 &&
Number(osRelease[2]) >= 10586
) {
return Number(osRelease[2]) >= 14931 ? 3 : 2;
}
return 1;
}
if ('CI' in env) {
if (['TRAVIS', 'CIRCLECI', 'APPVEYOR', 'GITLAB_CI'].some(sign => sign in env) || env.CI_NAME === 'codeship') {
return 1;
}
return min;
}
if ('TEAMCITY_VERSION' in env) {
return /^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env.TEAMCITY_VERSION) ? 1 : 0;
}
if (env.COLORTERM === 'truecolor') {
return 3;
}
if ('TERM_PROGRAM' in env) {
const version = parseInt((env.TERM_PROGRAM_VERSION || '').split('.')[0], 10);
switch (env.TERM_PROGRAM) {
case 'iTerm.app':
return version >= 3 ? 3 : 2;
case 'Apple_Terminal':
return 2;
// No default
}
}
if (/-256(color)?$/i.test(env.TERM)) {
return 2;
}
if (/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(env.TERM)) {
return 1;
}
if ('COLORTERM' in env) {
return 1;
}
if (env.TERM === 'dumb') {
return min;
}
return min;
}
function getSupportLevel(stream) {
const level = supportsColor(stream);
return translateLevel(level);
}
module.exports = {
supportsColor: getSupportLevel,
stdout: getSupportLevel(process.stdout),
stderr: getSupportLevel(process.stderr)
};

View File

@@ -0,0 +1,9 @@
MIT License
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -0,0 +1,53 @@
{
"name": "supports-color",
"version": "5.5.0",
"description": "Detect whether a terminal supports color",
"license": "MIT",
"repository": "chalk/supports-color",
"author": {
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
"url": "sindresorhus.com"
},
"engines": {
"node": ">=4"
},
"scripts": {
"test": "xo && ava"
},
"files": [
"index.js",
"browser.js"
],
"keywords": [
"color",
"colour",
"colors",
"terminal",
"console",
"cli",
"ansi",
"styles",
"tty",
"rgb",
"256",
"shell",
"xterm",
"command-line",
"support",
"supports",
"capability",
"detect",
"truecolor",
"16m"
],
"dependencies": {
"has-flag": "^3.0.0"
},
"devDependencies": {
"ava": "^0.25.0",
"import-fresh": "^2.0.0",
"xo": "^0.20.0"
},
"browser": "browser.js"
}

View File

@@ -0,0 +1,66 @@
# supports-color [![Build Status](https://travis-ci.org/chalk/supports-color.svg?branch=master)](https://travis-ci.org/chalk/supports-color)
> Detect whether a terminal supports color
## Install
```
$ npm install supports-color
```
## Usage
```js
const supportsColor = require('supports-color');
if (supportsColor.stdout) {
console.log('Terminal stdout supports color');
}
if (supportsColor.stdout.has256) {
console.log('Terminal stdout supports 256 colors');
}
if (supportsColor.stderr.has16m) {
console.log('Terminal stderr supports 16 million colors (truecolor)');
}
```
## API
Returns an `Object` with a `stdout` and `stderr` property for testing either streams. Each property is an `Object`, or `false` if color is not supported.
The `stdout`/`stderr` objects specifies a level of support for color through a `.level` property and a corresponding flag:
- `.level = 1` and `.hasBasic = true`: Basic color support (16 colors)
- `.level = 2` and `.has256 = true`: 256 color support
- `.level = 3` and `.has16m = true`: Truecolor support (16 million colors)
## Info
It obeys the `--color` and `--no-color` CLI flags.
Can be overridden by the user with the flags `--color` and `--no-color`. For situations where using `--color` is not possible, add the environment variable `FORCE_COLOR=1` to forcefully enable color or `FORCE_COLOR=0` to forcefully disable. The use of `FORCE_COLOR` overrides all other color support checks.
Explicit 256/Truecolor mode can be enabled using the `--color=256` and `--color=16m` flags, respectively.
## Related
- [supports-color-cli](https://github.com/chalk/supports-color-cli) - CLI for this module
- [chalk](https://github.com/chalk/chalk) - Terminal string styling done right
## Maintainers
- [Sindre Sorhus](https://github.com/sindresorhus)
- [Josh Junon](https://github.com/qix-)
## License
MIT

79
frontend/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
frontend/node_modules/svgo/plugins/_collections.js generated vendored Normal file

File diff suppressed because it is too large Load Diff

988
frontend/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
frontend/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
frontend/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
frontend/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
frontend/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
frontend/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
frontend/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)·t²·p3 + d·t³·p4,
* where pN are control points and p1 is zero due to relative coordinates.
*
* @param {Array} curve array of curve points coordinates
* @param {Number} t parametric position from 0 to 1
* @return {Array} Point coordinates
*/
function getCubicBezierPoint(curve, t) {
var sqrT = t * t,
cubT = sqrT * t,
mt = 1 - t,
sqrMt = mt * mt;
return [
3 * sqrMt * t * curve[0] + 3 * mt * sqrT * curve[2] + cubT * curve[4],
3 * sqrMt * t * curve[1] + 3 * mt * sqrT * curve[3] + cubT * curve[5]
];
}
/**
* Finds circle by 3 points of the curve and checks if the curve fits the found circle.
*
* @param {Array} curve
* @return {Object|undefined} circle
*/
function findCircle(curve) {
var midPoint = getCubicBezierPoint(curve, 1/2),
m1 = [midPoint[0] / 2, midPoint[1] / 2],
m2 = [(midPoint[0] + curve[4]) / 2, (midPoint[1] + curve[5]) / 2],
center = getIntersection([
m1[0], m1[1],
m1[0] + m1[1], m1[1] - m1[0],
m2[0], m2[1],
m2[0] + (m2[1] - midPoint[1]), m2[1] - (m2[0] - midPoint[0])
]),
radius = center && getDistance([0, 0], center),
tolerance = Math.min(arcThreshold * error, arcTolerance * radius / 100);
if (center && 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, '|') + ')';
}

363
frontend/node_modules/svgo/plugins/convertTransform.js generated vendored Normal file
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
frontend/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
frontend/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
frontend/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;
}

Some files were not shown because too many files have changed in this diff Show More