V1_commit_RGC

This commit is contained in:
2026-02-11 13:57:54 +01:00
commit ef397eedac
4901 changed files with 292881 additions and 0 deletions

248
SuiviREForamteur/node_modules/svg-pathdata/CHANGELOG.md generated vendored Normal file
View File

@@ -0,0 +1,248 @@
## [6.0.3](https://github.com/nfroidure/svg-pathdata/compare/v6.0.2...v6.0.3) (2021-09-18)
# [6.0.2](https://github.com/nfroidure/svg-pathdata/compare/v6.0.1...v6.0.2) (2021-09-17)
# [6.0.1](https://github.com/nfroidure/svg-pathdata/compare/v6.0.0...v6.0.1) (2021-09-12)
# [6.0.0](https://github.com/nfroidure/svg-pathdata/compare/v5.0.5...v6.0.0) (2021-04-02)
## [5.0.5](https://github.com/nfroidure/svg-pathdata/compare/v5.0.4...v5.0.5) (2020-06-06)
## [5.0.4](https://github.com/nfroidure/svg-pathdata/compare/v4.0.0...v5.0.4) (2020-02-14)
### Bug Fixes
* **parser:** fix parsing merged numbers with arc flags ([d55d9f0](https://github.com/nfroidure/svg-pathdata/commit/d55d9f0db00c1bb341eecaea786ca05dd2c51e95))
## [5.0.3](https://github.com/nfroidure/svg-pathdata/compare/v4.0.0...v5.0.3) (2020-02-04)
<a name="5.0.2"></a>
## [5.0.2](https://github.com/nfroidure/svg-pathdata/compare/v5.0.1...v5.0.2) (2018-06-05)
<a name="5.0.1"></a>
## [5.0.1](https://github.com/nfroidure/svg-pathdata/compare/v5.0.0...v5.0.1) (2018-06-03)
<a name="5.0.0"></a>
# [5.0.0](https://github.com/nfroidure/svg-pathdata/compare/v4.0.0...v5.0.0) (2018-06-02)
<a name="4.0.1"></a>
## [4.0.1](https://github.com/nfroidure/svg-pathdata/compare/v4.0.0...v4.0.1) (2017-08-22)
<a name="4.0.0"></a>
# [4.0.0](https://github.com/nfroidure/svg-pathdata/compare/v3.2.3...v4.0.0) (2017-08-22)
<a name="3.2.3"></a>
## [3.2.3](https://github.com/nfroidure/svg-pathdata/compare/v3.2.2...v3.2.3) (2017-08-13)
<a name="3.2.2"></a>
## [3.2.2](https://github.com/nfroidure/svg-pathdata/compare/v3.2.1...v3.2.2) (2017-08-13)
<a name="3.2.1"></a>
## [3.2.1](https://github.com/nfroidure/svg-pathdata/compare/v3.2.0...v3.2.1) (2017-08-13)
<a name="3.2.0"></a>
# [3.2.0](https://github.com/nfroidure/svg-pathdata/compare/v3.1.1...v3.2.0) (2017-08-12)
<a name="3.1.1"></a>
## [3.1.1](https://github.com/nfroidure/svg-pathdata/compare/v3.1.0...v3.1.1) (2017-08-12)
<a name="3.1.0"></a>
# [3.1.0](https://github.com/nfroidure/SVGPathData/compare/v3.0.0...v3.1.0) (2017-05-19)
<a name="3.0.0"></a>
# [3.0.0](https://github.com/nfroidure/SVGPathData/compare/v2.0.3...v3.0.0) (2017-05-02)
<a name="2.0.3"></a>
## [2.0.3](https://github.com/nfroidure/SVGPathData/compare/v2.0.2...v2.0.3) (2017-04-21)
<a name="2.0.2"></a>
## [2.0.2](https://github.com/nfroidure/SVGPathData/compare/v2.0.1...v2.0.2) (2017-04-05)
### Bug Fixes
* **build:** Fix tests and regenerate the changelog ([fa281fa](https://github.com/nfroidure/SVGPathData/commit/fa281fa))
### build
* **metapak-nfroidure:** Add metapak-nfroidure ([6be898c](https://github.com/nfroidure/SVGPathData/commit/6be898c))
### Code Refactoring
* **dist:** No more build ([8ce46da](https://github.com/nfroidure/SVGPathData/commit/8ce46da))
### BREAKING CHANGES
* **dist:** No more dist, please transpile in your own builds.
* **metapak-nfroidure:** Since the eslint --fix option were used, there may be some breaking features but
this very old codebase really need a total cleanup.
### v2.0.0 (2017/02/22 08:23 +00:00)
- [8a33721](https://github.com/nfroidure/SVGPathData/commit/8a33721a08ee1cf837ebf41699c6ab93648ad998) 2.0.0 (@NaridaL)
- [8c840ab](https://github.com/nfroidure/SVGPathData/commit/8c840ab66ee30139921a9d7d75c3f042d422e97a) Changed x1/y1 and x2/y2 around for C and c commands. (@NaridaL)
- [#20](https://github.com/nfroidure/SVGPathData/pull/20) Normalization and Sanitation Transformers (@NaridaL)
- [214f5ee](https://github.com/nfroidure/SVGPathData/commit/214f5ee4718792c17ef703ab4c34e3c0a2b6dfe0) Added transformers: (@NaridaL)
### v1.0.4 (2016/11/07 15:18 +00:00)
- [bb3beb7](https://github.com/nfroidure/SVGPathData/commit/bb3beb7fe18cf933254dd02ca22677bc95e4c993) 1.0.4 (@huerlisi)
- [#13](https://github.com/nfroidure/SVGPathData/pull/13) Ignore the coverage/ directory in git (@nfroidure)
- [#14](https://github.com/nfroidure/SVGPathData/pull/14) Use master branch travis badge in README (@nfroidure)
- [56cbd18](https://github.com/nfroidure/SVGPathData/commit/56cbd186d27a21fce3c21fddc3399e26e985e99a) Use master branch travis badge in README (@huerlisi)
- [5293f0b](https://github.com/nfroidure/SVGPathData/commit/5293f0bce88e4a2a18bc4e3679f4b3f53d9c86b6) Ignore the coverage/ directory in git (@huerlisi)
- [#9](https://github.com/nfroidure/SVGPathData/pull/9) Support transforming arc commands (@rhendric)
- [#11](https://github.com/nfroidure/SVGPathData/pull/11) Moveto commands start a new subpath (@rhendric)
- [#10](https://github.com/nfroidure/SVGPathData/pull/10) Remove Grunt references from Travis (@rhendric)
- [9906542](https://github.com/nfroidure/SVGPathData/commit/9906542f722e830e19ca401ccec1d33e6a8474ce) Support transforming arc commands (@rhendric)
- [25d1dc9](https://github.com/nfroidure/SVGPathData/commit/25d1dc90d2a66573e04b339d9139838625380b84) Fix test expectations (@rhendric)
- [c9e3747](https://github.com/nfroidure/SVGPathData/commit/c9e3747afdfd269a320e3ff9d474e83a56a2cecb) Remove Grunt references from Travis (@rhendric)
- [efc5f29](https://github.com/nfroidure/SVGPathData/commit/efc5f298340adb19374b967e11b40e09a892358f) Moveto commands start a new subpath (@rhendric)
### v1.0.3 (2015/11/20 20:08 +00:00)
- [d52943d](https://github.com/nfroidure/SVGPathData/commit/d52943d3aa4ef339f8e29fb321e5a23fb415c8c0) 1.0.3 (@nfroidure)
- [06fbcd1](https://github.com/nfroidure/SVGPathData/commit/06fbcd18a10ac0e4ed43fa2acb87e79ab0963355) Cannot use preversion lint right now, too much work (@nfroidure)
- [7d3d11e](https://github.com/nfroidure/SVGPathData/commit/7d3d11e4d9be6214d5e5a1da94761cb983ab9f80) Suppressing some linting errors (@nfroidure)
- [7337440](https://github.com/nfroidure/SVGPathData/commit/7337440e21037d83d66cfb051f60c2e7013c5c22) Updating deps (@nfroidure)
- [17a3934](https://github.com/nfroidure/SVGPathData/commit/17a39346a14b3aae7fca4240d818f16e5712bacb) Removing grunt (@nfroidure)
- [06d6a69](https://github.com/nfroidure/SVGPathData/commit/06d6a69abb42cdf01aff1ec40af50490c7e5c9c4) Adding eslint config file (@nfroidure)
### v1.0.2 (2015/10/10 10:57 +00:00)
- [3aa2cd6](https://github.com/nfroidure/SVGPathData/commit/3aa2cd603e9ef078b2394a5463dfcc6267fa1a21) 1.0.2 (@nfroidure)
- [179416d](https://github.com/nfroidure/SVGPathData/commit/179416d7ed7cbb7a5e4417a89b9528e865e31932) Fixing the arc reverted issue #44 (@nfroidure)
### v1.0.1 (2015/06/27 08:41 +00:00)
- [a8f1fb6](https://github.com/nfroidure/SVGPathData/commit/a8f1fb63ea3d1ace5038ec278911c50d807913cc) 1.0.1 (@nfroidure)
- [027ba05](https://github.com/nfroidure/SVGPathData/commit/027ba0540c2ee368df9b4adeb8e0c70a578264da) Suppressing hints (@nfroidure)
- [183ccd8](https://github.com/nfroidure/SVGPathData/commit/183ccd8b4dec15fa70a6bbcc8ed47d855689c83e) Cleaning up repo (@nfroidure)
- [7418a31](https://github.com/nfroidure/SVGPathData/commit/7418a3174c8b49e26e06229d7a0a06d0233afd81) Update deps, set the engines to Node > 0.10 (@nfroidure)
### v1.0.0 (2014/11/16 16:05 +00:00)
- [d043a52](https://github.com/nfroidure/SVGPathData/commit/d043a522d1e759a19e2b9a241772839f403a8f46) 1.0.0 (@nfroidure)
- [da9671b](https://github.com/nfroidure/SVGPathData/commit/da9671b5eed778a07b094e8a92d589e32b684943) Fixing rel 2 abs for multipath pathdatas (@nfroidure)
- [68d0e70](https://github.com/nfroidure/SVGPathData/commit/68d0e70a749de73c7d6d0279219b487b9f0e7d64) Adding the forgotten licence file closes #7 (@nfroidure)
- [2b7bd20](https://github.com/nfroidure/SVGPathData/commit/2b7bd200a3be95afb5cd9c534b08846f4edd7339) Updating version number (@nfroidure)
- [2b1e277](https://github.com/nfroidure/SVGPathData/commit/2b1e277a6e36f8fc6e5880d323b8534aa46dab56) Removing unecessary dependency (@nfroidure)
- [cf3f3e4](https://github.com/nfroidure/SVGPathData/commit/cf3f3e4ee2a0a9495eb7f1958a03d8037d488926) Do not use data event anymore (@nfroidure)
- [5cb5c80](https://github.com/nfroidure/SVGPathData/commit/5cb5c805a333d314641f2dbaa449385054e444f0) Improved transform functions (@nfroidure)
- [1f567e1](https://github.com/nfroidure/SVGPathData/commit/1f567e11c2d5e086dfa1689e6772eae2eeeef0d8) Improved transform function (@nfroidure)
- [4724965](https://github.com/nfroidure/SVGPathData/commit/47249651346f98e7ee30cab32579f6ac8edf3c2c) New version (@nfroidure)
- [2d726ec](https://github.com/nfroidure/SVGPathData/commit/2d726ecb8e2dcd3ac3d6006e53a84f82e8e03dff) Fucking grunt-browserify (@nfroidure)
- [3587d82](https://github.com/nfroidure/SVGPathData/commit/3587d82648965988f32053901c1669ac584c4621) Adding forgottent tests (@nfroidure)
- [5a29acb](https://github.com/nfroidure/SVGPathData/commit/5a29acb45605db5d715acedd4238a1e046bd3372) Removing errors that cannot happen (@nfroidure)
- [3425078](https://github.com/nfroidure/SVGPathData/commit/342507854c0ad5e1894108b7cf4a742e2c289e3e) Adding forgotten new operator for errors (@nfroidure)
- [54b7538](https://github.com/nfroidure/SVGPathData/commit/54b75386eecc0c518fb2f1dfb190bf91bfcb3ad3) No more EOF and STATE_ENDED for the parser (@nfroidure)
- [f2609e3](https://github.com/nfroidure/SVGPathData/commit/f2609e3dc78d801e1e112644b211e41ca246cbf7) Fixing encoder output to buffer modewq (@nfroidure)
- [2c03487](https://github.com/nfroidure/SVGPathData/commit/2c0348746bbacb4da7d2e97cd0e2d18fc5df5fd7) Improving code coverage, allowing constructors omission (@nfroidure)
- [237898e](https://github.com/nfroidure/SVGPathData/commit/237898e4cd1e9a762f836a265295a658c4a8f5f6) Updating dependencies (@nfroidure)
- [d35369c](https://github.com/nfroidure/SVGPathData/commit/d35369c12e93b6c20cbd9846f0eab15652ca034e) Fix matrix transformation formula closes #2 (@nfroidure)
- [e218385](https://github.com/nfroidure/SVGPathData/commit/e218385b4e2bb238231a5a86a05d0e604d125123) Fixing tests, improving A to C transformer (@nfroidure)
- [49fe80a](https://github.com/nfroidure/SVGPathData/commit/49fe80af60a4dedc68341466f86aa93d67d19882) New version 0.0.4 (@nfroidure)
- [a0e8a63](https://github.com/nfroidure/SVGPathData/commit/a0e8a63f160cc5dad0b4eb702dfb712785467f66) Added stats (@nfroidure)
- [#3](https://github.com/nfroidure/SVGPathData/pull/3) Depend on readable-stream from npm (@Raynos)
- [#4](https://github.com/nfroidure/SVGPathData/pull/4) clean up the scripts (@calvinmetcalf)
- [0c2cfde](https://github.com/nfroidure/SVGPathData/commit/0c2cfde170ca5f7621a4f6bc246f319aa5ae02d5) change | to && (@calvinmetcalf)
- [071215f](https://github.com/nfroidure/SVGPathData/commit/071215ff3d78db451e4aa2e39b8c9cee28b5668c) clean up the scripts (@calvinmetcalf)
- [19a4daa](https://github.com/nfroidure/SVGPathData/commit/19a4daaee107a25f9c422dc05c317c12808c94ca) convert other files to readable-stream too (@Raynos)
- [50dd97a](https://github.com/nfroidure/SVGPathData/commit/50dd97ab76f37c36ccf6519c2cd0ffd841ca0f98) depend on readable-stream in p.json (@Raynos)
- [181f63b](https://github.com/nfroidure/SVGPathData/commit/181f63b7eb1e79f80a258626da913123af5f73c3) Use readable-stream instead (@Raynos)
- [ce11d07](https://github.com/nfroidure/SVGPathData/commit/ce11d07e8d04ef446d4e49f83c582a88a1f49c68) Readme fix (@nfroidure)
- [c521987](https://github.com/nfroidure/SVGPathData/commit/c5219871629b8fafb8cea85a0ed158080af8acb0) Added coverage tests (@nfroidure)
- [11d22fc](https://github.com/nfroidure/SVGPathData/commit/11d22fc3360cd44e166e4a46935f94196ba19dce) Added a round transformation (@nfroidure)
- [0bf6fa4](https://github.com/nfroidure/SVGPathData/commit/0bf6fa4a20deba65e61b63d33a3e56ab7fdef675) Do not parse incomplete L,M,S incomplete commands anymore (@nfroidure)
- [653a4d3](https://github.com/nfroidure/SVGPathData/commit/653a4d3b214e13682aa0ecba80b71aaf069e540a) Improved sapegin test (@nfroidure)
- [60ee34e](https://github.com/nfroidure/SVGPathData/commit/60ee34ef8da8a798f2dfd7642555dcb71b83186e) Added sapegin test (@nfroidure)
- [908da2a](https://github.com/nfroidure/SVGPathData/commit/908da2a4ce2cf69990d73a267e7e124ca955008c) Added arc to curve conversionwq (@nfroidure)
- [b341fde](https://github.com/nfroidure/SVGPathData/commit/b341fdef1503ff0eb414a5b1bbcd9eb40cd75dbd) Main file is the src not the build (@nfroidure)
- [0d8608e](https://github.com/nfroidure/SVGPathData/commit/0d8608e9ead3fff8b22e37581098bdda7eb6dc99) Version updated (@nfroidure)
- [28a1cd1](https://github.com/nfroidure/SVGPathData/commit/28a1cd11205e8876d8a17112fcb5bd261a337685) Tests updated (@nfroidure)
- [63ac182](https://github.com/nfroidure/SVGPathData/commit/63ac182d17c8f99cf8cba8c978bfc05102832d1c) Fix for X/Y transforms (@nfroidure)
- [b4196ce](https://github.com/nfroidure/SVGPathData/commit/b4196ce375c43e1dd66659abf3b25e1c2f6e6d8e) Removed unnecessary absolute conversions (@nfroidure)
- [4a38ad0](https://github.com/nfroidure/SVGPathData/commit/4a38ad09fe38c32a97a790e88605b0a28efc3c92) Added x symetry (@nfroidure)
- [e34a0e3](https://github.com/nfroidure/SVGPathData/commit/e34a0e34ae7ccc1572920dc43e3c58c993885513) Based y symetry on other transformations (@nfroidure)
- [392152d](https://github.com/nfroidure/SVGPathData/commit/392152dc8aafcb3709d5c83915437e0c56638f51) Checking transformations arguments (@nfroidure)
- [177f586](https://github.com/nfroidure/SVGPathData/commit/177f5867e376fd8bcc6c8da77c8829c3296e07ee) Updated REAMDE and package.json (@nfroidure)
- [60a2819](https://github.com/nfroidure/SVGPathData/commit/60a2819bc2ce39c039f34169b58791195d73df56) Some transformations converted to their idioins matrixes (@nfroidure)
- [a24a2a5](https://github.com/nfroidure/SVGPathData/commit/a24a2a55efd1a5b740133967786cddc5cc6c4823) Skew transformations added2 (@nfroidure)
- [930b9c4](https://github.com/nfroidure/SVGPathData/commit/930b9c4f9a823b57a22a1f2061d4cd7c35a83c9f) Skew transformations added (@nfroidure)
- [7bc0390](https://github.com/nfroidure/SVGPathData/commit/7bc03902ffd6723f53f263d5ae875d727803f961) Rotation transformation added (@nfroidure)
- [3191815](https://github.com/nfroidure/SVGPathData/commit/31918152a99e30b856cd2c527aecb437d076cb41) Added scale transformation (@nfroidure)
- [0e15916](https://github.com/nfroidure/SVGPathData/commit/0e1591638e0c0e9da0de9f4de59f3cb0e68ff4c4) Added translation transformation (@nfroidure)
- [6cfd826](https://github.com/nfroidure/SVGPathData/commit/6cfd826478cbe52b100a7632027046dfca59fd5b) Fix for y symetry problems (@nfroidure)
- [7d0576c](https://github.com/nfroidure/SVGPathData/commit/7d0576c6f83c61d449fac26b67d6b54ee3ea7655) Support decpoint separated numbers 2 (@nfroidure)
- [92391ec](https://github.com/nfroidure/SVGPathData/commit/92391eca9f73a2007c3f155977a19a7d7dd56e0e) Support sign separated numbers 2 (@nfroidure)
- [5b536c1](https://github.com/nfroidure/SVGPathData/commit/5b536c17b9e754d5d8dd569422bb4b30d7a41739) Support sign separated numbers (@nfroidure)
- [d37ea0a](https://github.com/nfroidure/SVGPathData/commit/d37ea0aee50de8fc311d652dd76c43094d1dcfd5) Added ySymetry transformer2 (@nfroidure)
- [647fdf4](https://github.com/nfroidure/SVGPathData/commit/647fdf4ce9f99411d2433247af5bbdde32ea2759) Added ySymetry transformer (@nfroidure)
- [377518f](https://github.com/nfroidure/SVGPathData/commit/377518fc292a08ec6b292262f46454f7d91071b5) Added toRel transformer2 (@nfroidure)
- [dd00037](https://github.com/nfroidure/SVGPathData/commit/dd0003784e04086890f76a1abadd4d4871a8695e) Added toAbs transformer2 (@nfroidure)
- [d0d8332](https://github.com/nfroidure/SVGPathData/commit/d0d833242c9121dfe0a1f171ebea9f7744631958) Added toAbs transformer (@nfroidure)
- [b1e24a6](https://github.com/nfroidure/SVGPathData/commit/b1e24a63c4b3646e5af996b12c80abd53b4614cc) Now based on Node stream module (@nfroidure)
- [1bfbeea](https://github.com/nfroidure/SVGPathData/commit/1bfbeea6b429762477473b958e90739cb782b6aa) Updated dependencies (@nfroidure)
- [a267550](https://github.com/nfroidure/SVGPathData/commit/a267550c013538d23b2ba292d0f9358d950f4b8c) Added the distribution file (@nfroidure)
- [b8f0c7e](https://github.com/nfroidure/SVGPathData/commit/b8f0c7ee00367aac72177b689455d049c3ff2915) Added encoding use samples (@nfroidure)
- [bbd8955](https://github.com/nfroidure/SVGPathData/commit/bbd8955eb82ff57f1dd57cdb0f3cdff4868070a4) Switch to line to n+1 move to declarated commands (@nfroidure)
- [667f390](https://github.com/nfroidure/SVGPathData/commit/667f390209048f63e4e2cca3ae714e5821cbe70c) Added an encoder (@nfroidure)
- [78ef5ce](https://github.com/nfroidure/SVGPathData/commit/78ef5ce99598a6fc0edf9f83306f86e4ff9d3571) Contributing (@nfroidure)
- [c6d4db4](https://github.com/nfroidure/SVGPathData/commit/c6d4db4cc5879fdefd7697d2bba44b60f337e6e3) Added usage in the README file (@nfroidure)
- [bd69b1c](https://github.com/nfroidure/SVGPathData/commit/bd69b1ce492492d4b1b60d5e1d632558427bc1bd) Const naming uniformized (@nfroidure)
- [3b21f06](https://github.com/nfroidure/SVGPathData/commit/3b21f06e40c91a1761b5c5a86b5fb36d0044f690) New Grunt/Package files (@nfroidure)
- [f84959e](https://github.com/nfroidure/SVGPathData/commit/f84959e2833af79024ed356a5cdabbc331a5e028) Small refactoring (@nfroidure)
- [726e85f](https://github.com/nfroidure/SVGPathData/commit/726e85f575550ef13ff85a74ba312ee48fb2ac78) Added eliptic arc commands error detection tests (@nfroidure)
- [7bb6671](https://github.com/nfroidure/SVGPathData/commit/7bb6671b59ad35f73fa81d61cbc75f5424a099c0) Added eliptic arc commands (@nfroidure)
- [7099de1](https://github.com/nfroidure/SVGPathData/commit/7099de12fda674ad43f9200d1f92d81110dfe43f) Added smooth quadratic curve to commands (@nfroidure)
- [97c7575](https://github.com/nfroidure/SVGPathData/commit/97c7575823eb6f0a4215ba8c0b2387724ce75d5f) Added quadratic curve to commands (@nfroidure)
- [0499dcb](https://github.com/nfroidure/SVGPathData/commit/0499dcbe01caf609fb55e888376b2fd6aab14f00) Added curve to commands2 (@nfroidure)
- [fdb154e](https://github.com/nfroidure/SVGPathData/commit/fdb154e6fd07eab2b49737c32e2c14e2c9bd603a) Added curve to commands (@nfroidure)
- [111c42c](https://github.com/nfroidure/SVGPathData/commit/111c42cd3f4c115dfa93c171acc7fcc8bf605ea0) Better syntax error handling (@nfroidure)
- [52727ae](https://github.com/nfroidure/SVGPathData/commit/52727ae6303a7ca4c3f2817d6e41051ea679698b) Added smooth curveto commands (@nfroidure)
- [4fae609](https://github.com/nfroidure/SVGPathData/commit/4fae609bb17b1f866af6b47074762c9613d271c7) Added line to and closepath commands parsing (@nfroidure)
- [d7cdfad](https://github.com/nfroidure/SVGPathData/commit/d7cdfadf1024eb4d7bd51f6d6d487a4577b5a524) Move to commands parsing added (@nfroidure)
- [d10264e](https://github.com/nfroidure/SVGPathData/commit/d10264eda8d10b5200cffdfe8d08a239b4679c42) parse mthod returns commands (@nfroidure)
- [280ffe0](https://github.com/nfroidure/SVGPathData/commit/280ffe072cebe7abc2ec3bab2fb563e76a326bca) Build info (@nfroidure)
- [ac6b856](https://github.com/nfroidure/SVGPathData/commit/ac6b856c9c0338042ec10f45b0da9ce151d42411) Added vertical/horizontal commands2 (@nfroidure)
- [f785f6b](https://github.com/nfroidure/SVGPathData/commit/f785f6bf1a558caf1e60bb4d561b37139a082f61) Added vertical/horizontal commands (@nfroidure)
- [2f9b8da](https://github.com/nfroidure/SVGPathData/commit/2f9b8da11568d0079c101277ea8ec103e2434df1) Full support for numbers parsing (@nfroidure)
- [699bf87](https://github.com/nfroidure/SVGPathData/commit/699bf87bb27ed93b5075155308b48a1a574b015a) Fixed tests (@nfroidure)
- [04450cc](https://github.com/nfroidure/SVGPathData/commit/04450cc0938a5d883338362ceb167ca59e9d1c7f) First Commit (@nfroidure)

20
SuiviREForamteur/node_modules/svg-pathdata/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,20 @@
The MIT License (MIT)
Copyright © 2017 Nicolas Froidure
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.

162
SuiviREForamteur/node_modules/svg-pathdata/README.md generated vendored Normal file
View File

@@ -0,0 +1,162 @@
# svg-pathdata
> Manipulate SVG path data (path[d] attribute content) simply and efficiently.
[![NPM version](https://badge.fury.io/js/svg-pathdata.svg)](https://npmjs.org/package/svg-pathdata)
[![Run tests](https://github.com/nfroidure/svg-pathdata/actions/workflows/test.yml/badge.svg)](https://github.com/nfroidure/svg-pathdata/actions/workflows/test.yml)
[![Dependency Status](https://david-dm.org/nfroidure/svg-pathdata.svg)](https://david-dm.org/nfroidure/svg-pathdata)
[![devDependency Status](https://david-dm.org/nfroidure/svg-pathdata/dev-status.svg)](https://david-dm.org/nfroidure/svg-pathdata#info=devDependencies)
[![Coverage Status](https://coveralls.io/repos/nfroidure/svg-pathdata/badge.svg?branch=master)](https://coveralls.io/r/nfroidure/svg-pathdata?branch=master)
[![Code Climate](https://codeclimate.com/github/nfroidure/svg-pathdata.svg)](https://codeclimate.com/github/nfroidure/svg-pathdata)
[![Dependency Status](https://dependencyci.com/github/nfroidure/svg-pathdata/badge)](https://dependencyci.com/github/nfroidure/svg-pathdata)
## Usage
Install the module:
```sh
npm install --save svg-pathdata
```
or add the [bundle](https://github.com/nfroidure/svg-pathdata/blob/master/lib/SVGPathData.js) to a script in your HTML.
Then in your JavaScript files:
```js
const {SVGPathData, SVGPathDataTransformer, SVGPathDataEncoder, SVGPathDataParser} = require('svg-pathdata');
```
With import syntax in TypeScript/ES6:
```ts
import {SVGPathData, SVGPathDataTransformer, SVGPathDataEncoder, SVGPathDataParser} from 'svg-pathdata';
```
Without modules, using the global in the bundle:
```js
const {SVGPathData, SVGPathDataTransformer, SVGPathDataEncoder, SVGPathDataParser} = svgpathdata;
```
## Reading PathData
```js
const pathData = new SVGPathData (`
M 10 10
H 60
V 60
L 10 60
Z`);
console.log(pathData.commands);
// [ {type: SVGPathData.MOVE_TO, relative: false, x: 10, y: 10},
// {type: SVGPathData.HORIZ_LINE_TO, relative: false, x: 60},
// {type: SVGPathData.VERT_LINE_TO, relative: false, y: 60},
// {type: SVGPathData.LINE_TO, relative: false, x: 10, y: 60},
// {type: SVGPathData.CLOSE_PATH}]
```
## Reading PathData in chunks
```js
const parser = new SVGPathDataParser();
parser.parse(' '); // returns []
parser.parse('M 10'); // returns []
parser.parse(' 10'); // returns [{type: SVGPathData.MOVE_TO, relative: false, x: 10, y: 10 }]
parser.write('H 60'); // returns [{type: SVGPathData.HORIZ_LINE_TO, relative: false, x: 60 }]
parser.write('V'); // returns []
parser.write('60'); // returns [{type: SVGPathData.VERT_LINE_TO, relative: false, y: 60 }]
parser.write('L 10 60 \n Z');
// returns [
// {type: SVGPathData.LINE_TO, relative: false, x: 10, y: 60 },
// {type: SVGPathData.CLOSE_PATH }]
parser.finish(); // tell parser there is no more data: will throw if there are unfinished commands.
```
## Outputting PathData
```js
const pathData = new SVGPathData (`
M 10 10
H 60
V 60
L 10 60
Z`);
// returns "M10 10H60V60L10 60Z"
encodeSVGPath({ type: SVGPathData.MOVE_TO, relative: false, x: 10, y: 10 });
// returns "M10 10"
encodeSVGPath({ type: SVGPathData.HORIZ_LINE_TO, relative: false, x: 60 });
// returns "H60"
encodeSVGPath([
{ type: SVGPathData.VERT_LINE_TO, relative: false, y: 60 },
{ type: SVGPathData.LINE_TO, relative: false, x: 10, y: 60 },
{ type: SVGPathData.CLOSE_PATH}])
// returns "V60L10 60Z"
```
## Transforming PathData
This library can perform transformations on SVG paths. Here is
[an example of that kind of use](https://github.com/nfroidure/svgicons2svgfont/blob/aa6df0211419e9d61c417c63bcc353f0cb2ea0c8/src/index.js#L192).
### Transforming entire paths
```js
new SVGPathData (`
m 10,10
h 60
v 60
l 10,60
z`)
.toAbs()
.encode();
// return s"M10,10 H70 V70 L80,130 Z"
```
### Transforming partial data
Here, we take SVGPathData from stdin and output it transformed to stdout.
```js
const transformingParser = new SVGPathDataParser().toAbs().scale(2, 2);
transformingParser.parse('m 0 0') // returns [{ type: SVGPathData.MOVE_TO, relative: false, x: 0, y: 0 }]
transformingParser.parse('l 2 3') // returns [{ type: SVGPathData.LINE_TO, relative: false, x: 4, y: 6 }]
```
## Supported transformations
You can find all supported transformations in
[src/SVGPathDataTransformer.ts](https://github.com/nfroidure/SVGPathData/blob/master/src/SVGPathDataTransformer.ts#L47).
Additionally, you can create your own by writing a function with the following signature:
```js
type TransformFunction = (command: SVGCommand) => SVGCommand | SVGCommand[];
function SET_X_TO(xValue = 10) {
return function(command) {
command.x = xValue; // transform command objects and return them
return command;
};
};
// Synchronous usage
new SVGPathData('...')
.transform(SET_X_TO(25))
.encode();
// Chunk usage
new SVGPathDataParser().transform(SET_X_TO(25));
```
## Stats
[![NPM](https://nodei.co/npm/svg-pathdata.png?downloads=true&stars=true)](https://nodei.co/npm/svg-pathdata/)
[![NPM](https://nodei.co/npm-dl/svg-pathdata.png)](https://nodei.co/npm/svg-pathdata/)
## Contributing
Clone this project, run:
```sh
npm install; npm test
```
# License
[MIT](https://github.com/nfroidure/svg-pathdata/blob/master/LICENSE)

View File

@@ -0,0 +1,2 @@
export * from "./lib/SVGPathData";
export as namespace svgpathdata;

View File

@@ -0,0 +1,69 @@
// Karma configuration
// Generated on Tue Oct 15 2013 15:27:53 GMT+0200 (CEST)
module.exports = function(config) {
config.set({
// base path, that will be used to resolve files and exclude
basePath: '',
// frameworks to use
frameworks: ['mocha', 'chai'],
// list of files / patterns to load in the browser
files: [
'dist/SVGPathData.js',
'tests/**/*.mocha.js'
],
// list of files to exclude
exclude: [
],
// test results reporter to use
// possible values: 'dots', 'progress', 'junit', 'growl', 'coverage'
reporters: ['progress'],
// web server port
port: 9876,
// enable / disable colors in the output (reporters and logs)
colors: true,
// level of logging
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
logLevel: config.LOG_INFO,
// enable / disable watching file and executing tests whenever any file changes
autoWatch: true,
// Start these browsers, currently available:
// - Chrome
// - ChromeCanary
// - Firefox
// - Opera
// - Safari (only Mac)
// - PhantomJS
// - IE (only Windows)
browsers: ['Chrome', 'Firefox', 'PhantomJS'],
// If browser does not capture in given timeout [ms], kill it
captureTimeout: 60000,
// Continuous Integration mode
// if true, it capture browsers, run tests and exit
singleRun: false
});
};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,43 @@
import { TransformableSVG } from "./TransformableSVG";
import { SVGCommand } from "./types";
export declare class SVGPathData extends TransformableSVG {
commands: SVGCommand[];
constructor(content: string | SVGCommand[]);
encode(): string;
getBounds(): import("./types").TransformFunction & {
minX: number;
maxX: number;
minY: number;
maxY: number;
};
transform(transformFunction: (input: SVGCommand) => SVGCommand | SVGCommand[]): this;
static encode(commands: SVGCommand[]): string;
static parse(path: string): SVGCommand[];
static readonly CLOSE_PATH: 1;
static readonly MOVE_TO: 2;
static readonly HORIZ_LINE_TO: 4;
static readonly VERT_LINE_TO: 8;
static readonly LINE_TO: 16;
static readonly CURVE_TO: 32;
static readonly SMOOTH_CURVE_TO: 64;
static readonly QUAD_TO: 128;
static readonly SMOOTH_QUAD_TO: 256;
static readonly ARC: 512;
static readonly LINE_COMMANDS: number;
static readonly DRAWING_COMMANDS: number;
}
export declare const COMMAND_ARG_COUNTS: {
2: number;
16: number;
4: number;
8: number;
1: number;
128: number;
256: number;
32: number;
64: number;
512: number;
};
export { encodeSVGPath } from "./SVGPathDataEncoder";
export { SVGPathDataParser } from "./SVGPathDataParser";
export { SVGPathDataTransformer } from "./SVGPathDataTransformer";

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,2 @@
import { SVGCommand } from "./types";
export declare function encodeSVGPath(commands: SVGCommand | SVGCommand[]): string;

View File

@@ -0,0 +1,19 @@
import { TransformableSVG } from "./TransformableSVG";
import { SVGCommand, TransformFunction } from "./types";
export declare class SVGPathDataParser extends TransformableSVG {
private curNumber;
private curCommandType;
private curCommandRelative;
private canParseCommandOrComma;
private curNumberHasExp;
private curNumberHasExpDigits;
private curNumberHasDecimal;
private curArgs;
constructor();
finish(commands?: SVGCommand[]): SVGCommand[];
parse(str: string, commands?: SVGCommand[]): SVGCommand[];
/**
* Return a wrapper around this parser which applies the transformation on parsed commands.
*/
transform(transform: TransformFunction): this;
}

View File

@@ -0,0 +1,28 @@
import { SVGCommand, TransformFunction } from "./types";
export declare namespace SVGPathDataTransformer {
function ROUND(roundVal?: number): (command: any) => any;
function TO_ABS(): (command: any) => any;
function TO_REL(): (command: any) => any;
function NORMALIZE_HVZ(normalizeZ?: boolean, normalizeH?: boolean, normalizeV?: boolean): (command: any) => any;
function NORMALIZE_ST(): (command: any) => any;
function QT_TO_C(): (command: any) => any;
function INFO(f: (command: any, prevXAbs: number, prevYAbs: number, pathStartXAbs: number, pathStartYAbs: number) => any | any[]): (command: any) => any;
function SANITIZE(EPS?: number): (command: any) => any;
function MATRIX(a: number, b: number, c: number, d: number, e: number, f: number): (command: any) => any;
function ROTATE(a: number, x?: number, y?: number): (command: any) => any;
function TRANSLATE(dX: number, dY?: number): (command: any) => any;
function SCALE(dX: number, dY?: number): (command: any) => any;
function SKEW_X(a: number): (command: any) => any;
function SKEW_Y(a: number): (command: any) => any;
function X_AXIS_SYMMETRY(xOffset?: number): (command: any) => any;
function Y_AXIS_SYMMETRY(yOffset?: number): (command: any) => any;
function A_TO_C(): (command: any) => any;
function ANNOTATE_ARCS(): (command: any) => any;
function CLONE(): (c: SVGCommand) => SVGCommand;
function CALCULATE_BOUNDS(): TransformFunction & {
minX: number;
maxX: number;
minY: number;
maxY: number;
};
}

View File

@@ -0,0 +1,21 @@
import { TransformFunction } from "./types";
export declare abstract class TransformableSVG {
round(x?: number): this;
toAbs(): this;
toRel(): this;
normalizeHVZ(a?: boolean, b?: boolean, c?: boolean): this;
normalizeST(): this;
qtToC(): this;
aToC(): this;
sanitize(eps?: number): this;
translate(x: number, y?: number): this;
scale(x: number, y?: number): this;
rotate(a: number, x?: number, y?: number): this;
matrix(a: number, b: number, c: number, d: number, e: number, f: number): this;
skewX(a: number): this;
skewY(a: number): this;
xSymmetry(xOffset?: number): this;
ySymmetry(yOffset?: number): this;
annotateArcs(): this;
abstract transform(transformFunction: TransformFunction): this;
}

View File

@@ -0,0 +1,28 @@
import { CommandA, CommandC } from "./types";
export declare function rotate([x, y]: [number, number], rad: number): number[];
export declare function assertNumbers(...numbers: number[]): boolean;
/**
* https://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes
* Fixes rX and rY.
* Ensures lArcFlag and sweepFlag are 0 or 1
* Adds center coordinates: command.cX, command.cY (relative or absolute, depending on command.relative)
* Adds start and end arc parameters (in degrees): command.phi1, command.phi2; phi1 < phi2 iff. c.sweepFlag == true
*/
export declare function annotateArcCommand(c: CommandA, x1: number, y1: number): void;
/**
* Solves a quadratic system of equations of the form
* a * x + b * y = c
* x² + y² = 1
* This can be understood as the intersection of the unit circle with a line.
* => y = (c - a x) / b
* => x² + (c - a x)² / b² = 1
* => x² b² + c² - 2 c a x + a² x² = b²
* => (a² + b²) x² - 2 a c x + (c² - b²) = 0
*/
export declare function intersectionUnitCircleLine(a: number, b: number, c: number): [number, number][];
export declare const DEG: number;
export declare function lerp(a: number, b: number, t: number): number;
export declare function arcAt(c: number, x1: number, x2: number, phiDeg: number): number;
export declare function bezierRoot(x0: number, x1: number, x2: number, x3: number): number[];
export declare function bezierAt(x0: number, x1: number, x2: number, x3: number, t: number): number;
export declare function a2c(arc: CommandA, x0: number, y0: number): CommandC[];

View File

@@ -0,0 +1,75 @@
import { SVGPathData } from "./SVGPathData";
export declare type CommandM = {
relative: boolean;
type: typeof SVGPathData.MOVE_TO;
x: number;
y: number;
};
export declare type CommandL = {
relative: boolean;
type: typeof SVGPathData.LINE_TO;
x: number;
y: number;
};
export declare type CommandH = {
relative: boolean;
type: typeof SVGPathData.HORIZ_LINE_TO;
x: number;
};
export declare type CommandV = {
relative: boolean;
type: typeof SVGPathData.VERT_LINE_TO;
y: number;
};
export declare type CommandZ = {
type: typeof SVGPathData.CLOSE_PATH;
};
export declare type CommandQ = {
relative: boolean;
type: typeof SVGPathData.QUAD_TO;
x1: number;
y1: number;
x: number;
y: number;
};
export declare type CommandT = {
relative: boolean;
type: typeof SVGPathData.SMOOTH_QUAD_TO;
x: number;
y: number;
};
export declare type CommandC = {
relative: boolean;
type: typeof SVGPathData.CURVE_TO;
x1: number;
y1: number;
x2: number;
y2: number;
x: number;
y: number;
};
export declare type CommandS = {
relative: boolean;
type: typeof SVGPathData.SMOOTH_CURVE_TO;
x2: number;
y2: number;
x: number;
y: number;
};
export declare type CommandA = {
relative: boolean;
type: typeof SVGPathData.ARC;
rX: number;
rY: number;
xRot: number;
sweepFlag: 0 | 1;
lArcFlag: 0 | 1;
x: number;
y: number;
cX?: number;
cY?: number;
phi1?: number;
phi2?: number;
};
export declare type SVGCommand = CommandM | CommandL | CommandH | CommandV | CommandZ | CommandQ | CommandT | CommandC | CommandS | CommandA;
export declare type TransformFunction = (input: SVGCommand) => SVGCommand | SVGCommand[];

View File

@@ -0,0 +1,95 @@
{
"name": "svg-pathdata",
"version": "6.0.3",
"description": "Manipulate SVG path data (path[d] attribute content) simply and efficiently.",
"main": "lib/SVGPathData.cjs",
"module": "lib/SVGPathData.module.js",
"exports": {
"import": "./lib/SVGPathData.module.js",
"require": "./lib/SVGPathData.cjs"
},
"type": "module",
"types": "lib/SVGPathData.d.ts",
"scripts": {
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s",
"cli": "env NODE_ENV=${NODE_ENV:-cli}",
"cover": "istanbul cover _mocha --report html -- tests/*.mocha.js -R spec -t 5000",
"coveralls": "istanbul cover _mocha --report lcovonly -- tests/*.mocha.js -R spec -t 5000 && cat ./coverage/lcov.info | coveralls && rm -rf ./coverage",
"cz": "env NODE_ENV=${NODE_ENV:-cli} git cz",
"lint": "eslint tests/*.mocha.js && tslint -p tsconfig.json",
"preversion": "npm run test:ci",
"test": "mocha tests/*.mocha.js",
"version": "npm run changelog && git add CHANGELOG.md",
"test:ci": "npm run lint && npm run build && npm run test",
"build": "rollup -c rollup.config.js",
"watch": "rollup -c rollup.config.js -w"
},
"repository": {
"type": "git",
"url": "https://github.com/nfroidure/svg-pathdata.git"
},
"keywords": [
"svg",
"path",
"data",
"parser",
"encoder",
"transformer",
"reader",
"writer",
"stream",
"typescript"
],
"author": "Nicolas Froidure",
"contributors": [
{
"name": "Anders Kaseorg",
"email": "andersk@mit.edu"
}
],
"license": "MIT",
"bugs": {
"url": "https://github.com/nfroidure/SVGPathData/issues"
},
"engines": {
"node": ">=12.0.0"
},
"devDependencies": {
"@rollup/plugin-typescript": "^8.2.1",
"chai": "^4.3.4",
"chai-stats": "^0.3.0",
"commitizen": "^4.2.3",
"conventional-changelog-cli": "^2.1.1",
"coveralls": "^3.1.0",
"cz-conventional-changelog": "^3.3.0",
"eslint": "^7.23.0",
"eslint-config-simplifield": "^12.0.0",
"istanbul": "0.4.5",
"mocha": "^9.0.2",
"mocha-lcov-reporter": "1.3.0",
"rollup": "^2.44.0",
"rollup-plugin-terser": "^7.0.2",
"tslib": "2.1.0",
"tslint": "^6.1.3",
"typescript": "^4.2.3"
},
"config": {
"commitizen": {
"path": "./node_modules/cz-conventional-changelog"
}
},
"greenkeeper": {
"ignore": [
"debug",
"eslint",
"eslint-config-simplifield",
"mocha",
"mocha-lcov-reporter",
"commitizen",
"cz-conventional-changelog",
"coveralls",
"istanbul",
"conventional-changelog-cli"
]
}
}

View File

@@ -0,0 +1,90 @@
import { encodeSVGPath } from "./SVGPathDataEncoder";
import { SVGPathDataParser } from "./SVGPathDataParser";
import { SVGPathDataTransformer } from "./SVGPathDataTransformer";
import { TransformableSVG } from "./TransformableSVG";
import { SVGCommand } from "./types";
export class SVGPathData extends TransformableSVG {
commands: SVGCommand[];
constructor(content: string | SVGCommand[]) {
super();
if ("string" === typeof content) {
this.commands = SVGPathData.parse(content);
} else {
this.commands = content;
}
}
encode() {
return SVGPathData.encode(this.commands);
}
getBounds() {
const boundsTransform = SVGPathDataTransformer.CALCULATE_BOUNDS();
this.transform(boundsTransform);
return boundsTransform;
}
transform(
transformFunction: (input: SVGCommand) => SVGCommand | SVGCommand[],
) {
const newCommands = [];
for (const command of this.commands) {
const transformedCommand = transformFunction(command);
if (Array.isArray(transformedCommand)) {
newCommands.push(...transformedCommand);
} else {
newCommands.push(transformedCommand);
}
}
this.commands = newCommands;
return this;
}
static encode(commands: SVGCommand[]) {
return encodeSVGPath(commands);
}
static parse(path: string) {
const parser = new SVGPathDataParser();
const commands: SVGCommand[] = [];
parser.parse(path, commands);
parser.finish(commands);
return commands;
}
static readonly CLOSE_PATH: 1 = 1;
static readonly MOVE_TO: 2 = 2;
static readonly HORIZ_LINE_TO: 4 = 4;
static readonly VERT_LINE_TO: 8 = 8;
static readonly LINE_TO: 16 = 16;
static readonly CURVE_TO: 32 = 32;
static readonly SMOOTH_CURVE_TO: 64 = 64;
static readonly QUAD_TO: 128 = 128;
static readonly SMOOTH_QUAD_TO: 256 = 256;
static readonly ARC: 512 = 512;
static readonly LINE_COMMANDS = SVGPathData.LINE_TO | SVGPathData.HORIZ_LINE_TO | SVGPathData.VERT_LINE_TO;
static readonly DRAWING_COMMANDS = SVGPathData.HORIZ_LINE_TO | SVGPathData.VERT_LINE_TO | SVGPathData.LINE_TO |
SVGPathData.CURVE_TO | SVGPathData.SMOOTH_CURVE_TO | SVGPathData.QUAD_TO |
SVGPathData.SMOOTH_QUAD_TO | SVGPathData.ARC;
}
export const COMMAND_ARG_COUNTS = {
[SVGPathData.MOVE_TO]: 2,
[SVGPathData.LINE_TO]: 2,
[SVGPathData.HORIZ_LINE_TO]: 1,
[SVGPathData.VERT_LINE_TO]: 1,
[SVGPathData.CLOSE_PATH]: 0,
[SVGPathData.QUAD_TO]: 4,
[SVGPathData.SMOOTH_QUAD_TO]: 2,
[SVGPathData.CURVE_TO]: 6,
[SVGPathData.SMOOTH_CURVE_TO]: 4,
[SVGPathData.ARC]: 7,
};
export {encodeSVGPath} from "./SVGPathDataEncoder";
export {SVGPathDataParser} from "./SVGPathDataParser";
export {SVGPathDataTransformer} from "./SVGPathDataTransformer";

View File

@@ -0,0 +1,62 @@
import { SVGPathData } from "./SVGPathData";
import { SVGCommand } from "./types";
// Encode SVG PathData
// http://www.w3.org/TR/SVG/paths.html#PathDataBNF
// Private consts : Char groups
const WSP = " ";
export function encodeSVGPath(commands: SVGCommand | SVGCommand[]) {
let str = "";
if (!Array.isArray(commands)) {
commands = [commands];
}
for (let i = 0; i < commands.length; i++) {
const command = commands[i];
if (command.type === SVGPathData.CLOSE_PATH) {
str += "z";
} else if (command.type === SVGPathData.HORIZ_LINE_TO) {
str += (command.relative ? "h" : "H") +
command.x;
} else if (command.type === SVGPathData.VERT_LINE_TO) {
str += (command.relative ? "v" : "V") +
command.y;
} else if (command.type === SVGPathData.MOVE_TO) {
str += (command.relative ? "m" : "M") +
command.x + WSP + command.y;
} else if (command.type === SVGPathData.LINE_TO) {
str += (command.relative ? "l" : "L") +
command.x + WSP + command.y;
} else if (command.type === SVGPathData.CURVE_TO) {
str += (command.relative ? "c" : "C") +
command.x1 + WSP + command.y1 +
WSP + command.x2 + WSP + command.y2 +
WSP + command.x + WSP + command.y;
} else if (command.type === SVGPathData.SMOOTH_CURVE_TO) {
str += (command.relative ? "s" : "S") +
command.x2 + WSP + command.y2 +
WSP + command.x + WSP + command.y;
} else if (command.type === SVGPathData.QUAD_TO) {
str += (command.relative ? "q" : "Q") +
command.x1 + WSP + command.y1 +
WSP + command.x + WSP + command.y;
} else if (command.type === SVGPathData.SMOOTH_QUAD_TO) {
str += (command.relative ? "t" : "T") +
command.x + WSP + command.y;
} else if (command.type === SVGPathData.ARC) {
str += (command.relative ? "a" : "A") +
command.rX + WSP + command.rY +
WSP + command.xRot +
WSP + (+command.lArcFlag) + WSP + (+command.sweepFlag) +
WSP + command.x + WSP + command.y;
} else {
// Unknown command
throw new Error(
`Unexpected command type "${ (command as any).type}" at index ${i}.`);
}
}
return str;
}

View File

@@ -0,0 +1,290 @@
// Parse SVG PathData
// http://www.w3.org/TR/SVG/paths.html#PathDataBNF
import { COMMAND_ARG_COUNTS, SVGPathData } from "./SVGPathData";
import { TransformableSVG } from "./TransformableSVG";
import { SVGCommand, TransformFunction } from "./types";
// Private consts : Char groups
const isWhiteSpace = (c: string) =>
" " === c || "\t" === c || "\r" === c || "\n" === c;
const isDigit = (c: string) =>
"0".charCodeAt(0) <= c.charCodeAt(0) && c.charCodeAt(0) <= "9".charCodeAt(0);
const COMMANDS = "mMzZlLhHvVcCsSqQtTaA";
export class SVGPathDataParser extends TransformableSVG {
private curNumber: string = "";
private curCommandType: SVGCommand["type"] | -1 = -1;
private curCommandRelative = false;
private canParseCommandOrComma = true;
private curNumberHasExp = false;
private curNumberHasExpDigits = false;
private curNumberHasDecimal = false;
private curArgs: number[] = [];
constructor() {
super();
}
finish(commands: SVGCommand[] = []) {
this.parse(" ", commands);
// Adding residual command
if (0 !== this.curArgs.length || !this.canParseCommandOrComma) {
throw new SyntaxError("Unterminated command at the path end.");
}
return commands;
}
parse(str: string, commands: SVGCommand[] = []) {
const finishCommand = (command: SVGCommand) => {
commands.push(command);
this.curArgs.length = 0;
this.canParseCommandOrComma = true;
};
for (let i = 0; i < str.length; i++) {
const c = str[i];
// White spaces parsing
const isAArcFlag = this.curCommandType === SVGPathData.ARC &&
(this.curArgs.length === 3 || this.curArgs.length === 4) &&
this.curNumber.length === 1 &&
(this.curNumber === "0" || this.curNumber === "1");
const isEndingDigit = isDigit(c) && (
(this.curNumber === "0" && c === "0") ||
isAArcFlag
);
if (
isDigit(c) &&
!isEndingDigit
) {
this.curNumber += c;
this.curNumberHasExpDigits = this.curNumberHasExp;
continue;
}
if ("e" === c || "E" === c) {
this.curNumber += c;
this.curNumberHasExp = true;
continue;
}
if (
("-" === c || "+" === c) &&
this.curNumberHasExp &&
!this.curNumberHasExpDigits
) {
this.curNumber += c;
continue;
}
// if we already have a ".", it means we are starting a new number
if ("." === c && !this.curNumberHasExp && !this.curNumberHasDecimal && !isAArcFlag) {
this.curNumber += c;
this.curNumberHasDecimal = true;
continue;
}
// New number
if (this.curNumber && -1 !== this.curCommandType) {
const val = Number(this.curNumber);
if (isNaN(val)) {
throw new SyntaxError(`Invalid number ending at ${i}`);
}
if (this.curCommandType === SVGPathData.ARC) {
if (0 === this.curArgs.length || 1 === this.curArgs.length) {
if (0 > val) {
throw new SyntaxError(
`Expected positive number, got "${val}" at index "${i}"`,
);
}
} else if (3 === this.curArgs.length || 4 === this.curArgs.length) {
if ("0" !== this.curNumber && "1" !== this.curNumber) {
throw new SyntaxError(
`Expected a flag, got "${this.curNumber}" at index "${i}"`,
);
}
}
}
this.curArgs.push(val);
if (this.curArgs.length === COMMAND_ARG_COUNTS[this.curCommandType]) {
if (SVGPathData.HORIZ_LINE_TO === this.curCommandType) {
finishCommand({
type: SVGPathData.HORIZ_LINE_TO,
relative: this.curCommandRelative,
x: val,
});
} else if (SVGPathData.VERT_LINE_TO === this.curCommandType) {
finishCommand({
type: SVGPathData.VERT_LINE_TO,
relative: this.curCommandRelative,
y: val,
});
// Move to / line to / smooth quadratic curve to commands (x, y)
} else if (
this.curCommandType === SVGPathData.MOVE_TO ||
this.curCommandType === SVGPathData.LINE_TO ||
this.curCommandType === SVGPathData.SMOOTH_QUAD_TO
) {
finishCommand({
type: this.curCommandType,
relative: this.curCommandRelative,
x: this.curArgs[0],
y: this.curArgs[1],
} as SVGCommand);
// Switch to line to state
if (SVGPathData.MOVE_TO === this.curCommandType) {
this.curCommandType = SVGPathData.LINE_TO;
}
} else if (this.curCommandType === SVGPathData.CURVE_TO) {
finishCommand({
type: SVGPathData.CURVE_TO,
relative: this.curCommandRelative,
x1: this.curArgs[0],
y1: this.curArgs[1],
x2: this.curArgs[2],
y2: this.curArgs[3],
x: this.curArgs[4],
y: this.curArgs[5],
});
} else if (this.curCommandType === SVGPathData.SMOOTH_CURVE_TO) {
finishCommand({
type: SVGPathData.SMOOTH_CURVE_TO,
relative: this.curCommandRelative,
x2: this.curArgs[0],
y2: this.curArgs[1],
x: this.curArgs[2],
y: this.curArgs[3],
});
} else if (this.curCommandType === SVGPathData.QUAD_TO) {
finishCommand({
type: SVGPathData.QUAD_TO,
relative: this.curCommandRelative,
x1: this.curArgs[0],
y1: this.curArgs[1],
x: this.curArgs[2],
y: this.curArgs[3],
});
} else if (this.curCommandType === SVGPathData.ARC) {
finishCommand({
type: SVGPathData.ARC,
relative: this.curCommandRelative,
rX: this.curArgs[0],
rY: this.curArgs[1],
xRot: this.curArgs[2],
lArcFlag: this.curArgs[3] as 0 | 1,
sweepFlag: this.curArgs[4] as 0 | 1,
x: this.curArgs[5],
y: this.curArgs[6],
});
}
}
this.curNumber = "";
this.curNumberHasExpDigits = false;
this.curNumberHasExp = false;
this.curNumberHasDecimal = false;
this.canParseCommandOrComma = true;
}
// Continue if a white space or a comma was detected
if (isWhiteSpace(c)) {
continue;
}
if ("," === c && this.canParseCommandOrComma) {
// L 0,0, H is not valid:
this.canParseCommandOrComma = false;
continue;
}
// if a sign is detected, then parse the new number
if ("+" === c || "-" === c || "." === c) {
this.curNumber = c;
this.curNumberHasDecimal = "." === c;
continue;
}
// if a 0 is detected, then parse the new number
if (isEndingDigit) {
this.curNumber = c;
this.curNumberHasDecimal = false;
continue;
}
// Adding residual command
if (0 !== this.curArgs.length) {
throw new SyntaxError(`Unterminated command at index ${i}.`);
}
if (!this.canParseCommandOrComma) {
throw new SyntaxError(
`Unexpected character "${c}" at index ${i}. Command cannot follow comma`,
);
}
this.canParseCommandOrComma = false;
// Detecting the next command
if ("z" === c || "Z" === c) {
commands.push({
type: SVGPathData.CLOSE_PATH,
});
this.canParseCommandOrComma = true;
this.curCommandType = -1;
continue;
// Horizontal move to command
} else if ("h" === c || "H" === c) {
this.curCommandType = SVGPathData.HORIZ_LINE_TO;
this.curCommandRelative = "h" === c;
// Vertical move to command
} else if ("v" === c || "V" === c) {
this.curCommandType = SVGPathData.VERT_LINE_TO;
this.curCommandRelative = "v" === c;
// Move to command
} else if ("m" === c || "M" === c) {
this.curCommandType = SVGPathData.MOVE_TO;
this.curCommandRelative = "m" === c;
// Line to command
} else if ("l" === c || "L" === c) {
this.curCommandType = SVGPathData.LINE_TO;
this.curCommandRelative = "l" === c;
// Curve to command
} else if ("c" === c || "C" === c) {
this.curCommandType = SVGPathData.CURVE_TO;
this.curCommandRelative = "c" === c;
// Smooth curve to command
} else if ("s" === c || "S" === c) {
this.curCommandType = SVGPathData.SMOOTH_CURVE_TO;
this.curCommandRelative = "s" === c;
// Quadratic bezier curve to command
} else if ("q" === c || "Q" === c) {
this.curCommandType = SVGPathData.QUAD_TO;
this.curCommandRelative = "q" === c;
// Smooth quadratic bezier curve to command
} else if ("t" === c || "T" === c) {
this.curCommandType = SVGPathData.SMOOTH_QUAD_TO;
this.curCommandRelative = "t" === c;
// Elliptic arc command
} else if ("a" === c || "A" === c) {
this.curCommandType = SVGPathData.ARC;
this.curCommandRelative = "a" === c;
} else {
throw new SyntaxError(`Unexpected character "${c}" at index ${i}.`);
}
}
return commands;
}
/**
* Return a wrapper around this parser which applies the transformation on parsed commands.
*/
transform(transform: TransformFunction) {
const result = Object.create(this, {
parse: {
value(chunk: string, commands: SVGCommand[] = []) {
const parsedCommands = Object.getPrototypeOf(this).parse.call(
this,
chunk,
);
for (const c of parsedCommands) {
const cT = transform(c);
if (Array.isArray(cT)) {
commands.push(...cT);
} else {
commands.push(cT);
}
}
return commands;
},
},
});
return result as this;
}
}

View File

@@ -0,0 +1,620 @@
// Transform SVG PathData
// http://www.w3.org/TR/SVG/paths.html#PathDataBNF
import { a2c, annotateArcCommand, arcAt, assertNumbers, bezierAt, bezierRoot,
intersectionUnitCircleLine } from "./mathUtils";
import { SVGPathData } from "./SVGPathData";
import { SVGCommand, TransformFunction } from "./types";
export namespace SVGPathDataTransformer {
// Predefined transforming functions
// Rounds commands values
export function ROUND(roundVal = 1e13) {
assertNumbers(roundVal);
function rf(val: number) { return Math.round(val * roundVal) / roundVal; }
return function round(command: any) {
if ("undefined" !== typeof command.x1) {
command.x1 = rf(command.x1);
}
if ("undefined" !== typeof command.y1) {
command.y1 = rf(command.y1);
}
if ("undefined" !== typeof command.x2) {
command.x2 = rf(command.x2);
}
if ("undefined" !== typeof command.y2) {
command.y2 = rf(command.y2);
}
if ("undefined" !== typeof command.x) {
command.x = rf(command.x);
}
if ("undefined" !== typeof command.y) {
command.y = rf(command.y);
}
if ("undefined" !== typeof command.rX) {
command.rX = rf(command.rX);
}
if ("undefined" !== typeof command.rY) {
command.rY = rf(command.rY);
}
return command;
};
}
// Relative to absolute commands
export function TO_ABS() {
return INFO((command, prevX, prevY) => {
if (command.relative) {
// x1/y1 values
if ("undefined" !== typeof command.x1) {
command.x1 += prevX;
}
if ("undefined" !== typeof command.y1) {
command.y1 += prevY;
}
// x2/y2 values
if ("undefined" !== typeof command.x2) {
command.x2 += prevX;
}
if ("undefined" !== typeof command.y2) {
command.y2 += prevY;
}
// Finally x/y values
if ("undefined" !== typeof command.x) {
command.x += prevX;
}
if ("undefined" !== typeof command.y) {
command.y += prevY;
}
command.relative = false;
}
return command;
});
}
// Absolute to relative commands
export function TO_REL() {
return INFO((command, prevX, prevY) => {
if (!command.relative) {
// x1/y1 values
if ("undefined" !== typeof command.x1) {
command.x1 -= prevX;
}
if ("undefined" !== typeof command.y1) {
command.y1 -= prevY;
}
// x2/y2 values
if ("undefined" !== typeof command.x2) {
command.x2 -= prevX;
}
if ("undefined" !== typeof command.y2) {
command.y2 -= prevY;
}
// Finally x/y values
if ("undefined" !== typeof command.x) {
command.x -= prevX;
}
if ("undefined" !== typeof command.y) {
command.y -= prevY;
}
command.relative = true;
}
return command;
});
}
// Convert H, V, Z and A with rX = 0 to L
export function NORMALIZE_HVZ(normalizeZ = true, normalizeH = true, normalizeV = true) {
return INFO((command, prevX, prevY, pathStartX, pathStartY) => {
if (isNaN(pathStartX) && !(command.type & SVGPathData.MOVE_TO)) {
throw new Error("path must start with moveto");
}
if (normalizeH && command.type & SVGPathData.HORIZ_LINE_TO) {
command.type = SVGPathData.LINE_TO;
command.y = command.relative ? 0 : prevY;
}
if (normalizeV && command.type & SVGPathData.VERT_LINE_TO) {
command.type = SVGPathData.LINE_TO;
command.x = command.relative ? 0 : prevX;
}
if (normalizeZ && command.type & SVGPathData.CLOSE_PATH) {
command.type = SVGPathData.LINE_TO;
command.x = command.relative ? pathStartX - prevX : pathStartX;
command.y = command.relative ? pathStartY - prevY : pathStartY;
}
if (command.type & SVGPathData.ARC && (0 === command.rX || 0 === command.rY)) {
command.type = SVGPathData.LINE_TO;
delete command.rX;
delete command.rY;
delete command.xRot;
delete command.lArcFlag;
delete command.sweepFlag;
}
return command;
});
}
/*
* Transforms smooth curves and quads to normal curves and quads (SsTt to CcQq)
*/
export function NORMALIZE_ST() {
let prevCurveC2X = NaN;
let prevCurveC2Y = NaN;
let prevQuadCX = NaN;
let prevQuadCY = NaN;
return INFO((command, prevX, prevY) => {
if (command.type & SVGPathData.SMOOTH_CURVE_TO) {
command.type = SVGPathData.CURVE_TO;
prevCurveC2X = isNaN(prevCurveC2X) ? prevX : prevCurveC2X;
prevCurveC2Y = isNaN(prevCurveC2Y) ? prevY : prevCurveC2Y;
command.x1 = command.relative ? prevX - prevCurveC2X : 2 * prevX - prevCurveC2X;
command.y1 = command.relative ? prevY - prevCurveC2Y : 2 * prevY - prevCurveC2Y;
}
if (command.type & SVGPathData.CURVE_TO) {
prevCurveC2X = command.relative ? prevX + command.x2 : command.x2;
prevCurveC2Y = command.relative ? prevY + command.y2 : command.y2;
} else {
prevCurveC2X = NaN;
prevCurveC2Y = NaN;
}
if (command.type & SVGPathData.SMOOTH_QUAD_TO) {
command.type = SVGPathData.QUAD_TO;
prevQuadCX = isNaN(prevQuadCX) ? prevX : prevQuadCX;
prevQuadCY = isNaN(prevQuadCY) ? prevY : prevQuadCY;
command.x1 = command.relative ? prevX - prevQuadCX : 2 * prevX - prevQuadCX;
command.y1 = command.relative ? prevY - prevQuadCY : 2 * prevY - prevQuadCY;
}
if (command.type & SVGPathData.QUAD_TO) {
prevQuadCX = command.relative ? prevX + command.x1 : command.x1;
prevQuadCY = command.relative ? prevY + command.y1 : command.y1;
} else {
prevQuadCX = NaN;
prevQuadCY = NaN;
}
return command;
});
}
/*
* A quadratic bézier curve can be represented by a cubic bézier curve which has
* the same end points as the quadratic and both control points in place of the
* quadratic"s one.
*
* This transformer replaces QqTt commands with Cc commands respectively.
* This is useful for reading path data into a system which only has a
* representation for cubic curves.
*/
export function QT_TO_C() {
let prevQuadX1 = NaN;
let prevQuadY1 = NaN;
return INFO((command, prevX, prevY) => {
if (command.type & SVGPathData.SMOOTH_QUAD_TO) {
command.type = SVGPathData.QUAD_TO;
prevQuadX1 = isNaN(prevQuadX1) ? prevX : prevQuadX1;
prevQuadY1 = isNaN(prevQuadY1) ? prevY : prevQuadY1;
command.x1 = command.relative ? prevX - prevQuadX1 : 2 * prevX - prevQuadX1;
command.y1 = command.relative ? prevY - prevQuadY1 : 2 * prevY - prevQuadY1;
}
if (command.type & SVGPathData.QUAD_TO) {
prevQuadX1 = command.relative ? prevX + command.x1 : command.x1;
prevQuadY1 = command.relative ? prevY + command.y1 : command.y1;
const x1 = command.x1;
const y1 = command.y1;
command.type = SVGPathData.CURVE_TO;
command.x1 = ((command.relative ? 0 : prevX) + x1 * 2) / 3;
command.y1 = ((command.relative ? 0 : prevY) + y1 * 2) / 3;
command.x2 = (command.x + x1 * 2) / 3;
command.y2 = (command.y + y1 * 2) / 3;
} else {
prevQuadX1 = NaN;
prevQuadY1 = NaN;
}
return command;
});
}
export function INFO(
f: (command: any, prevXAbs: number, prevYAbs: number,
pathStartXAbs: number, pathStartYAbs: number) => any | any[]) {
let prevXAbs = 0;
let prevYAbs = 0;
let pathStartXAbs = NaN;
let pathStartYAbs = NaN;
return function transform(command: any) {
if (isNaN(pathStartXAbs) && !(command.type & SVGPathData.MOVE_TO)) {
throw new Error("path must start with moveto");
}
const result = f(command, prevXAbs, prevYAbs, pathStartXAbs, pathStartYAbs);
if (command.type & SVGPathData.CLOSE_PATH) {
prevXAbs = pathStartXAbs;
prevYAbs = pathStartYAbs;
}
if ("undefined" !== typeof command.x) {
prevXAbs = (command.relative ? prevXAbs + command.x : command.x);
}
if ("undefined" !== typeof command.y) {
prevYAbs = (command.relative ? prevYAbs + command.y : command.y);
}
if (command.type & SVGPathData.MOVE_TO) {
pathStartXAbs = prevXAbs;
pathStartYAbs = prevYAbs;
}
return result;
};
}
/*
* remove 0-length segments
*/
export function SANITIZE(EPS = 0) {
assertNumbers(EPS);
let prevCurveC2X = NaN;
let prevCurveC2Y = NaN;
let prevQuadCX = NaN;
let prevQuadCY = NaN;
return INFO((command, prevX, prevY, pathStartX, pathStartY) => {
const abs = Math.abs;
let skip = false;
let x1Rel = 0;
let y1Rel = 0;
if (command.type & SVGPathData.SMOOTH_CURVE_TO) {
x1Rel = isNaN(prevCurveC2X) ? 0 : prevX - prevCurveC2X;
y1Rel = isNaN(prevCurveC2Y) ? 0 : prevY - prevCurveC2Y;
}
if (command.type & (SVGPathData.CURVE_TO | SVGPathData.SMOOTH_CURVE_TO)) {
prevCurveC2X = command.relative ? prevX + command.x2 : command.x2;
prevCurveC2Y = command.relative ? prevY + command.y2 : command.y2;
} else {
prevCurveC2X = NaN;
prevCurveC2Y = NaN;
}
if (command.type & SVGPathData.SMOOTH_QUAD_TO) {
prevQuadCX = isNaN(prevQuadCX) ? prevX : 2 * prevX - prevQuadCX;
prevQuadCY = isNaN(prevQuadCY) ? prevY : 2 * prevY - prevQuadCY;
} else if (command.type & SVGPathData.QUAD_TO) {
prevQuadCX = command.relative ? prevX + command.x1 : command.x1;
prevQuadCY = command.relative ? prevY + command.y1 : command.y2;
} else {
prevQuadCX = NaN;
prevQuadCY = NaN;
}
if (command.type & SVGPathData.LINE_COMMANDS ||
command.type & SVGPathData.ARC && (0 === command.rX || 0 === command.rY || !command.lArcFlag) ||
command.type & SVGPathData.CURVE_TO || command.type & SVGPathData.SMOOTH_CURVE_TO ||
command.type & SVGPathData.QUAD_TO || command.type & SVGPathData.SMOOTH_QUAD_TO) {
const xRel = "undefined" === typeof command.x ? 0 :
(command.relative ? command.x : command.x - prevX);
const yRel = "undefined" === typeof command.y ? 0 :
(command.relative ? command.y : command.y - prevY);
x1Rel = !isNaN(prevQuadCX) ? prevQuadCX - prevX :
"undefined" === typeof command.x1 ? x1Rel :
command.relative ? command.x :
command.x1 - prevX;
y1Rel = !isNaN(prevQuadCY) ? prevQuadCY - prevY :
"undefined" === typeof command.y1 ? y1Rel :
command.relative ? command.y :
command.y1 - prevY;
const x2Rel = "undefined" === typeof command.x2 ? 0 :
(command.relative ? command.x : command.x2 - prevX);
const y2Rel = "undefined" === typeof command.y2 ? 0 :
(command.relative ? command.y : command.y2 - prevY);
if (abs(xRel) <= EPS && abs(yRel) <= EPS &&
abs(x1Rel) <= EPS && abs(y1Rel) <= EPS &&
abs(x2Rel) <= EPS && abs(y2Rel) <= EPS) {
skip = true;
}
}
if (command.type & SVGPathData.CLOSE_PATH) {
if (abs(prevX - pathStartX) <= EPS && abs(prevY - pathStartY) <= EPS) {
skip = true;
}
}
return skip ? [] : command;
});
}
// SVG Transforms : http://www.w3.org/TR/SVGTiny12/coords.html#TransformList
// Matrix : http://apike.ca/prog_svg_transform.html
// a c e
// b d f
export function MATRIX(a: number, b: number, c: number, d: number, e: number, f: number) {
assertNumbers(a, b, c, d, e, f);
return INFO((command, prevX, prevY, pathStartX) => {
const origX1 = command.x1;
const origX2 = command.x2;
// if isNaN(pathStartX), then this is the first command, which is ALWAYS an
// absolute MOVE_TO, regardless what the relative flag says
const comRel = command.relative && !isNaN(pathStartX);
const x = "undefined" !== typeof command.x ? command.x : (comRel ? 0 : prevX);
const y = "undefined" !== typeof command.y ? command.y : (comRel ? 0 : prevY);
if (command.type & SVGPathData.HORIZ_LINE_TO && 0 !== b) {
command.type = SVGPathData.LINE_TO;
command.y = command.relative ? 0 : prevY;
}
if (command.type & SVGPathData.VERT_LINE_TO && 0 !== c) {
command.type = SVGPathData.LINE_TO;
command.x = command.relative ? 0 : prevX;
}
if ("undefined" !== typeof command.x) {
command.x = (command.x * a) + (y * c) + (comRel ? 0 : e);
}
if ("undefined" !== typeof command.y) {
command.y = (x * b) + command.y * d + (comRel ? 0 : f);
}
if ("undefined" !== typeof command.x1) {
command.x1 = command.x1 * a + command.y1 * c + (comRel ? 0 : e);
}
if ("undefined" !== typeof command.y1) {
command.y1 = origX1 * b + command.y1 * d + (comRel ? 0 : f);
}
if ("undefined" !== typeof command.x2) {
command.x2 = command.x2 * a + command.y2 * c + (comRel ? 0 : e);
}
if ("undefined" !== typeof command.y2) {
command.y2 = origX2 * b + command.y2 * d + (comRel ? 0 : f);
}
function sqr(x: number) { return x * x; }
const det = a * d - b * c;
if ("undefined" !== typeof command.xRot) {
// Skip if this is a pure translation
if (1 !== a || 0 !== b || 0 !== c || 1 !== d) {
// Special case for singular matrix
if (0 === det) {
// In the singular case, the arc is compressed to a line. The actual geometric image of the original
// curve under this transform possibly extends beyond the starting and/or ending points of the segment, but
// for simplicity we ignore this detail and just replace this command with a single line segment.
delete command.rX;
delete command.rY;
delete command.xRot;
delete command.lArcFlag;
delete command.sweepFlag;
command.type = SVGPathData.LINE_TO;
} else {
// Convert to radians
const xRot = command.xRot * Math.PI / 180;
// Convert rotated ellipse to general conic form
// x0^2/rX^2 + y0^2/rY^2 - 1 = 0
// x0 = x*cos(xRot) + y*sin(xRot)
// y0 = -x*sin(xRot) + y*cos(xRot)
// --> A*x^2 + B*x*y + C*y^2 - 1 = 0, where
const sinRot = Math.sin(xRot);
const cosRot = Math.cos(xRot);
const xCurve = 1 / sqr(command.rX);
const yCurve = 1 / sqr(command.rY);
const A = sqr(cosRot) * xCurve + sqr(sinRot) * yCurve;
const B = 2 * sinRot * cosRot * (xCurve - yCurve);
const C = sqr(sinRot) * xCurve + sqr(cosRot) * yCurve;
// Apply matrix to A*x^2 + B*x*y + C*y^2 - 1 = 0
// x1 = a*x + c*y
// y1 = b*x + d*y
// (we can ignore e and f, since pure translations don"t affect the shape of the ellipse)
// --> A1*x1^2 + B1*x1*y1 + C1*y1^2 - det^2 = 0, where
const A1 = A * d * d - B * b * d + C * b * b;
const B1 = B * (a * d + b * c) - 2 * (A * c * d + C * a * b);
const C1 = A * c * c - B * a * c + C * a * a;
// Unapply newXRot to get back to axis-aligned ellipse equation
// x1 = x2*cos(newXRot) - y2*sin(newXRot)
// y1 = x2*sin(newXRot) + y2*cos(newXRot)
// A1*x1^2 + B1*x1*y1 + C1*y1^2 - det^2 =
// x2^2*(A1*cos(newXRot)^2 + B1*sin(newXRot)*cos(newXRot) + C1*sin(newXRot)^2)
// + x2*y2*(2*(C1 - A1)*sin(newXRot)*cos(newXRot) + B1*(cos(newXRot)^2 - sin(newXRot)^2))
// + y2^2*(A1*sin(newXRot)^2 - B1*sin(newXRot)*cos(newXRot) + C1*cos(newXRot)^2)
// (which must have the same zeroes as)
// x2^2/newRX^2 + y2^2/newRY^2 - 1
// (so we have)
// 2*(C1 - A1)*sin(newXRot)*cos(newXRot) + B1*(cos(newXRot)^2 - sin(newXRot)^2) = 0
// (A1 - C1)*sin(2*newXRot) = B1*cos(2*newXRot)
// 2*newXRot = atan2(B1, A1 - C1)
const newXRot = ((Math.atan2(B1, A1 - C1) + Math.PI) % Math.PI) / 2;
// For any integer n, (atan2(B1, A1 - C1) + n*pi)/2 is a solution to the above; incrementing n just swaps
// the x and y radii computed below (since that"s what rotating an ellipse by pi/2 does). Choosing the
// rotation between 0 and pi/2 eliminates the ambiguity and leads to more predictable output.
// Finally, we get newRX and newRY from the same-zeroes relationship that gave us newXRot
const newSinRot = Math.sin(newXRot);
const newCosRot = Math.cos(newXRot);
command.rX = Math.abs(det) /
Math.sqrt(A1 * sqr(newCosRot) + B1 * newSinRot * newCosRot + C1 * sqr(newSinRot));
command.rY = Math.abs(det) /
Math.sqrt(A1 * sqr(newSinRot) - B1 * newSinRot * newCosRot + C1 * sqr(newCosRot));
command.xRot = newXRot * 180 / Math.PI;
}
}
}
// sweepFlag needs to be inverted when mirroring shapes
// see http://www.itk.ilstu.edu/faculty/javila/SVG/SVG_drawing1/elliptical_curve.htm
// m 65,10 a 50,25 0 1 0 50,25
// M 65,60 A 50,25 0 1 1 115,35
if ("undefined" !== typeof command.sweepFlag && 0 > det) {
command.sweepFlag = +!command.sweepFlag;
}
return command;
});
}
export function ROTATE(a: number, x = 0, y = 0) {
assertNumbers(a, x, y);
const sin = Math.sin(a);
const cos = Math.cos(a);
return MATRIX(cos, sin, -sin, cos, x - x * cos + y * sin, y - x * sin - y * cos);
}
export function TRANSLATE(dX: number, dY = 0) {
assertNumbers(dX, dY);
return MATRIX(1, 0, 0, 1, dX, dY);
}
export function SCALE(dX: number, dY = dX) {
assertNumbers(dX, dY);
return MATRIX(dX, 0, 0, dY, 0, 0);
}
export function SKEW_X(a: number) {
assertNumbers(a);
return MATRIX(1, 0, Math.atan(a), 1, 0, 0);
}
export function SKEW_Y(a: number) {
assertNumbers(a);
return MATRIX(1, Math.atan(a), 0, 1, 0, 0);
}
export function X_AXIS_SYMMETRY(xOffset = 0) {
assertNumbers(xOffset);
return MATRIX(-1, 0, 0, 1, xOffset, 0);
}
export function Y_AXIS_SYMMETRY(yOffset = 0) {
assertNumbers(yOffset);
return MATRIX(1, 0, 0, -1, 0, yOffset);
}
// Convert arc commands to curve commands
export function A_TO_C() {
return INFO((command, prevX, prevY) => {
if (SVGPathData.ARC === command.type) {
return a2c(command, command.relative ? 0 : prevX, command.relative ? 0 : prevY);
}
return command;
});
}
// @see annotateArcCommand
export function ANNOTATE_ARCS() {
return INFO((c, x1, y1) => {
if (c.relative) {
x1 = 0;
y1 = 0;
}
if (SVGPathData.ARC === c.type) {
annotateArcCommand(c, x1, y1);
}
return c;
});
}
export function CLONE() {
return (c: SVGCommand) => {
const result = {} as SVGCommand;
// tslint:disable-next-line
for (const key in c) {
result[key as keyof SVGCommand] = c[key as keyof SVGCommand];
}
return result;
};
}
// @see annotateArcCommand
export function CALCULATE_BOUNDS() {
const clone = CLONE();
const toAbs = TO_ABS();
const qtToC = QT_TO_C();
const normST = NORMALIZE_ST();
const f: TransformFunction & {minX: number, maxX: number, minY: number, maxY: number} =
INFO((command, prevXAbs, prevYAbs) => {
const c = normST(qtToC(toAbs(clone(command))));
function fixX(absX: number) {
if (absX > f.maxX) { f.maxX = absX; }
if (absX < f.minX) { f.minX = absX; }
}
function fixY(absY: number) {
if (absY > f.maxY) { f.maxY = absY; }
if (absY < f.minY) { f.minY = absY; }
}
if (c.type & SVGPathData.DRAWING_COMMANDS) {
fixX(prevXAbs);
fixY(prevYAbs);
}
if (c.type & SVGPathData.HORIZ_LINE_TO) {
fixX(c.x);
}
if (c.type & SVGPathData.VERT_LINE_TO) {
fixY(c.y);
}
if (c.type & SVGPathData.LINE_TO) {
fixX(c.x);
fixY(c.y);
}
if (c.type & SVGPathData.CURVE_TO) {
// add start and end points
fixX(c.x);
fixY(c.y);
const xDerivRoots = bezierRoot(prevXAbs, c.x1, c.x2, c.x);
for (const derivRoot of xDerivRoots) {
if (0 < derivRoot && 1 > derivRoot) {
fixX(bezierAt(prevXAbs, c.x1, c.x2, c.x, derivRoot));
}
}
const yDerivRoots = bezierRoot(prevYAbs, c.y1, c.y2, c.y);
for (const derivRoot of yDerivRoots) {
if (0 < derivRoot && 1 > derivRoot) {
fixY(bezierAt(prevYAbs, c.y1, c.y2, c.y, derivRoot));
}
}
}
if (c.type & SVGPathData.ARC) {
// add start and end points
fixX(c.x);
fixY(c.y);
annotateArcCommand(c, prevXAbs, prevYAbs);
// p = cos(phi) * xv + sin(phi) * yv
// dp = -sin(phi) * xv + cos(phi) * yv = 0
const xRotRad = c.xRot / 180 * Math.PI;
// points on ellipse for phi = 0° and phi = 90°
const x0 = Math.cos(xRotRad) * c.rX;
const y0 = Math.sin(xRotRad) * c.rX;
const x90 = -Math.sin(xRotRad) * c.rY;
const y90 = Math.cos(xRotRad) * c.rY;
// annotateArcCommand returns phi1 and phi2 such that -180° < phi1 < 180° and phi2 is smaller or greater
// depending on the sweep flag. Calculate phiMin, phiMax such that -180° < phiMin < 180° and phiMin < phiMax
const [phiMin, phiMax] = c.phi1 < c.phi2 ?
[c.phi1, c.phi2] :
(-180 > c.phi2 ? [c.phi2 + 360, c.phi1 + 360] : [c.phi2, c.phi1]);
const normalizeXiEta = ([xi, eta]: [number, number]) => {
const phiRad = Math.atan2(eta, xi);
const phi = phiRad * 180 / Math.PI;
return phi < phiMin ? phi + 360 : phi;
};
// xi = cos(phi), eta = sin(phi)
const xDerivRoots = intersectionUnitCircleLine(x90, -x0, 0).map(normalizeXiEta);
for (const derivRoot of xDerivRoots) {
if (derivRoot > phiMin && derivRoot < phiMax) {
fixX(arcAt(c.cX, x0, x90, derivRoot));
}
}
const yDerivRoots = intersectionUnitCircleLine(y90, -y0, 0).map(normalizeXiEta);
for (const derivRoot of yDerivRoots) {
if (derivRoot > phiMin && derivRoot < phiMax) {
fixY(arcAt(c.cY, y0, y90, derivRoot));
}
}
}
return command;
}) as any;
f.minX = Infinity;
f.maxX = -Infinity;
f.minY = Infinity;
f.maxY = -Infinity;
return f;
}
}

View File

@@ -0,0 +1,74 @@
import { SVGPathDataTransformer } from "./SVGPathDataTransformer";
import { TransformFunction } from "./types";
export abstract class TransformableSVG {
round(x?: number) {
return this.transform(SVGPathDataTransformer.ROUND(x));
}
toAbs() {
return this.transform(SVGPathDataTransformer.TO_ABS());
}
toRel() {
return this.transform(SVGPathDataTransformer.TO_REL());
}
normalizeHVZ(a?: boolean, b?: boolean, c?: boolean) {
return this.transform(SVGPathDataTransformer.NORMALIZE_HVZ(a, b, c));
}
normalizeST() {
return this.transform(SVGPathDataTransformer.NORMALIZE_ST());
}
qtToC() {
return this.transform(SVGPathDataTransformer.QT_TO_C());
}
aToC() {
return this.transform(SVGPathDataTransformer.A_TO_C());
}
sanitize(eps?: number) {
return this.transform(SVGPathDataTransformer.SANITIZE(eps));
}
translate(x: number, y?: number) {
return this.transform(SVGPathDataTransformer.TRANSLATE(x, y));
}
scale(x: number, y?: number) {
return this.transform(SVGPathDataTransformer.SCALE(x, y));
}
rotate(a: number, x?: number, y?: number) {
return this.transform(SVGPathDataTransformer.ROTATE(a, x, y));
}
matrix(a: number, b: number, c: number, d: number, e: number, f: number) {
return this.transform(SVGPathDataTransformer.MATRIX(a, b, c, d, e, f));
}
skewX(a: number) {
return this.transform(SVGPathDataTransformer.SKEW_X(a));
}
skewY(a: number) {
return this.transform(SVGPathDataTransformer.SKEW_Y(a));
}
xSymmetry(xOffset?: number) {
return this.transform(SVGPathDataTransformer.X_AXIS_SYMMETRY(xOffset));
}
ySymmetry(yOffset?: number) {
return this.transform(SVGPathDataTransformer.Y_AXIS_SYMMETRY(yOffset));
}
annotateArcs() {
return this.transform(SVGPathDataTransformer.ANNOTATE_ARCS());
}
abstract transform(transformFunction: TransformFunction): this;
}

View File

@@ -0,0 +1,200 @@
import { SVGPathData } from "./SVGPathData";
import { CommandA, CommandC } from "./types";
export function rotate([x, y]: [number, number], rad: number) {
return [
x * Math.cos(rad) - y * Math.sin(rad),
x * Math.sin(rad) + y * Math.cos(rad),
];
}
const DEBUG_CHECK_NUMBERS = true;
export function assertNumbers(...numbers: number[]) {
if (DEBUG_CHECK_NUMBERS) {
for (let i = 0; i < numbers.length; i++) {
if ("number" !== typeof numbers[i]) {
throw new Error(
`assertNumbers arguments[${i}] is not a number. ${typeof numbers[i]} == typeof ${numbers[i]}`);
}
}
}
return true;
}
const PI = Math.PI;
/**
* https://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes
* Fixes rX and rY.
* Ensures lArcFlag and sweepFlag are 0 or 1
* Adds center coordinates: command.cX, command.cY (relative or absolute, depending on command.relative)
* Adds start and end arc parameters (in degrees): command.phi1, command.phi2; phi1 < phi2 iff. c.sweepFlag == true
*/
export function annotateArcCommand(c: CommandA, x1: number, y1: number) {
c.lArcFlag = (0 === c.lArcFlag) ? 0 : 1;
c.sweepFlag = (0 === c.sweepFlag) ? 0 : 1;
// tslint:disable-next-line
let {rX, rY, x, y} = c;
rX = Math.abs(c.rX);
rY = Math.abs(c.rY);
const [x1_, y1_] = rotate([(x1 - x) / 2, (y1 - y) / 2], -c.xRot / 180 * PI);
const testValue = Math.pow(x1_, 2) / Math.pow(rX, 2) + Math.pow(y1_, 2) / Math.pow(rY, 2);
if (1 < testValue) {
rX *= Math.sqrt(testValue);
rY *= Math.sqrt(testValue);
}
c.rX = rX;
c.rY = rY;
const c_ScaleTemp = (Math.pow(rX, 2) * Math.pow(y1_, 2) + Math.pow(rY, 2) * Math.pow(x1_, 2));
const c_Scale = (c.lArcFlag !== c.sweepFlag ? 1 : -1) *
Math.sqrt(Math.max(0, (Math.pow(rX, 2) * Math.pow(rY, 2) - c_ScaleTemp) / c_ScaleTemp));
const cx_ = rX * y1_ / rY * c_Scale;
const cy_ = -rY * x1_ / rX * c_Scale;
const cRot = rotate([cx_, cy_], c.xRot / 180 * PI);
c.cX = cRot[0] + (x1 + x) / 2;
c.cY = cRot[1] + (y1 + y) / 2;
c.phi1 = Math.atan2((y1_ - cy_) / rY, (x1_ - cx_) / rX);
c.phi2 = Math.atan2((-y1_ - cy_) / rY, (-x1_ - cx_) / rX);
if (0 === c.sweepFlag && c.phi2 > c.phi1) {
c.phi2 -= 2 * PI;
}
if (1 === c.sweepFlag && c.phi2 < c.phi1) {
c.phi2 += 2 * PI;
}
c.phi1 *= 180 / PI;
c.phi2 *= 180 / PI;
}
/**
* Solves a quadratic system of equations of the form
* a * x + b * y = c
* x² + y² = 1
* This can be understood as the intersection of the unit circle with a line.
* => y = (c - a x) / b
* => x² + (c - a x)² / b² = 1
* => x² b² + c² - 2 c a x + a² x² = b²
* => (a² + b²) x² - 2 a c x + (c² - b²) = 0
*/
export function intersectionUnitCircleLine(a: number, b: number, c: number): [number, number][] {
assertNumbers(a, b, c);
// cf. pqFormula
const termSqr = a * a + b * b - c * c;
if (0 > termSqr) {
return [];
} else if (0 === termSqr) {
return [
[
(a * c) / (a * a + b * b),
(b * c) / (a * a + b * b)]];
}
const term = Math.sqrt(termSqr);
return [
[
(a * c + b * term) / (a * a + b * b),
(b * c - a * term) / (a * a + b * b)],
[
(a * c - b * term) / (a * a + b * b),
(b * c + a * term) / (a * a + b * b)]];
}
export const DEG = Math.PI / 180;
export function lerp(a: number, b: number, t: number) {
return (1 - t) * a + t * b;
}
export function arcAt(c: number, x1: number, x2: number, phiDeg: number) {
return c + Math.cos(phiDeg / 180 * PI) * x1 + Math.sin(phiDeg / 180 * PI) * x2;
}
export function bezierRoot(x0: number, x1: number, x2: number, x3: number) {
const EPS = 1e-6;
const x01 = x1 - x0;
const x12 = x2 - x1;
const x23 = x3 - x2;
const a = 3 * x01 + 3 * x23 - 6 * x12;
const b = (x12 - x01) * 6;
const c = 3 * x01;
// solve a * t² + b * t + c = 0
if (Math.abs(a) < EPS) {
// equivalent to b * t + c =>
return [-c / b];
}
return pqFormula(b / a, c / a, EPS);
}
export function bezierAt(x0: number, x1: number, x2: number, x3: number, t: number) {
// console.log(x0, y0, x1, y1, x2, y2, x3, y3, t)
const s = 1 - t;
const c0 = s * s * s;
const c1 = 3 * s * s * t;
const c2 = 3 * s * t * t;
const c3 = t * t * t;
return x0 * c0 + x1 * c1 + x2 * c2 + x3 * c3;
}
function pqFormula(p: number, q: number, PRECISION = 1e-6) {
// 4 times the discriminant:in
const discriminantX4 = p * p / 4 - q;
if (discriminantX4 < -PRECISION) {
return [];
} else if (discriminantX4 <= PRECISION) {
return [-p / 2];
}
const root = Math.sqrt(discriminantX4);
return [-(p / 2) - root, -(p / 2) + root];
}
export function a2c(arc: CommandA, x0: number, y0: number): CommandC[] {
if (!arc.cX) {
annotateArcCommand(arc, x0, y0);
}
const phiMin = Math.min(arc.phi1!, arc.phi2!), phiMax = Math.max(arc.phi1!, arc.phi2!), deltaPhi = phiMax - phiMin;
const partCount = Math.ceil(deltaPhi / 90 );
const result: CommandC[] = new Array(partCount);
let prevX = x0, prevY = y0;
for (let i = 0; i < partCount; i++) {
const phiStart = lerp(arc.phi1!, arc.phi2!, i / partCount);
const phiEnd = lerp(arc.phi1!, arc.phi2!, (i + 1) / partCount);
const deltaPhi = phiEnd - phiStart;
const f = 4 / 3 * Math.tan(deltaPhi * DEG / 4);
// x1/y1, x2/y2 and x/y coordinates on the unit circle for phiStart/phiEnd
const [x1, y1] = [
Math.cos(phiStart * DEG) - f * Math.sin(phiStart * DEG),
Math.sin(phiStart * DEG) + f * Math.cos(phiStart * DEG)];
const [x, y] = [Math.cos(phiEnd * DEG), Math.sin(phiEnd * DEG)];
const [x2, y2] = [x + f * Math.sin(phiEnd * DEG), y - f * Math.cos(phiEnd * DEG)];
result[i] = {relative: arc.relative, type: SVGPathData.CURVE_TO } as any;
const transform = (x: number, y: number) => {
const [xTemp, yTemp] = rotate([x * arc.rX, y * arc.rY], arc.xRot);
return [arc.cX! + xTemp, arc.cY! + yTemp];
};
[result[i].x1, result[i].y1] = transform(x1, y1);
[result[i].x2, result[i].y2] = transform(x2, y2);
[result[i].x, result[i].y] = transform(x, y);
if (arc.relative) {
result[i].x1 -= prevX;
result[i].y1 -= prevY;
result[i].x2 -= prevX;
result[i].y2 -= prevY;
result[i].x -= prevX;
result[i].y -= prevY;
}
[prevX, prevY] = [result[i].x, result[i].y];
}
return result;
}

View File

@@ -0,0 +1,41 @@
import { SVGPathData } from "./SVGPathData";
export type CommandM = { relative: boolean, type: typeof SVGPathData.MOVE_TO, x: number, y: number };
export type CommandL = { relative: boolean, type: typeof SVGPathData.LINE_TO, x: number, y: number };
export type CommandH = { relative: boolean, type: typeof SVGPathData.HORIZ_LINE_TO, x: number };
export type CommandV = { relative: boolean, type: typeof SVGPathData.VERT_LINE_TO, y: number };
export type CommandZ = { type: typeof SVGPathData.CLOSE_PATH };
export type CommandQ = {
relative: boolean;
type: typeof SVGPathData.QUAD_TO;
x1: number;
y1: number;
x: number;
y: number;
};
export type CommandT = { relative: boolean, type: typeof SVGPathData.SMOOTH_QUAD_TO, x: number, y: number };
export type CommandC = {
relative: boolean,
type: typeof SVGPathData.CURVE_TO,
x1: number, y1: number,
x2: number, y2: number,
x: number, y: number };
export type CommandS = {
relative: boolean;
type: typeof SVGPathData.SMOOTH_CURVE_TO;
x2: number;
y2: number;
x: number;
y: number;
};
export type CommandA = {
relative: boolean,
type: typeof SVGPathData.ARC,
rX: number, rY: number,
xRot: number, sweepFlag: 0 | 1, lArcFlag: 0 | 1,
x: number, y: number
cX?: number, cY?: number, phi1?: number, phi2?: number};
export type SVGCommand = CommandM | CommandL | CommandH | CommandV | CommandZ | CommandQ |
CommandT | CommandC | CommandS | CommandA;
export type TransformFunction = (input: SVGCommand) => SVGCommand | SVGCommand[];

View File

@@ -0,0 +1,67 @@
{
"compilerOptions": {
/* Basic Options */
"target": "es5",
/* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', or 'ESNEXT'. */
"module": "ESNEXT",
/* Specify module code generation: 'none', commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
// "lib": [], /* Specify library files to be included in the compilation: */
// "allowJs": true, /* Allow javascript files to be compiled. */
// "checkJs": true, /* Report errors in .js files. */
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
"declaration": true,
/* Generates corresponding '.d.ts' file. */
"sourceMap": true,
"sourceRoot": "./",
/* Generates corresponding '.map' file. */
// "outFile": "./", /* Concatenate and emit output to single file. */
"outDir": "./",
/* Redirect output structure to the directory. */
"rootDir": "./src",
/* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
// "removeComments": true, /* Do not emit comments to output. */
// "noEmit": true, /* Do not emit outputs. */
// "importHelpers": true, /* Import emit helpers from 'tslib'. */
// "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
// "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
/* Strict Type-Checking Options */
"strict": true,
/* Enable all strict type-checking options. */
"noImplicitAny": true,
/* Raise error on expressions and declarations with an implied 'any' type. */
// "strictNullChecks": true, /* Enable strict null checks. */
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
"alwaysStrict": true
/* Parse in strict mode and emit "use strict" for each source file. */
/* Additional Checks */
// "noUnusedLocals": true, /* Report errors on unused locals. */
// "noUnusedParameters": true, /* Report errors on unused parameters. */
// "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
/* Module Resolution Options */
// "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
// "baseUrl": "./", /* Base directory to resolve non-absolute module names. */
// "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
// "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
// "typeRoots": [], /* List of folders to include type definitions from. */
// "types": [], /* Type declaration files to be included in compilation. */
// "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
// "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
/* Source Map Options */
// "sourceRoot": "./", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
// "mapRoot": "./", /* Specify the location where debugger should locate map files instead of generated locations. */
// "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
// "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
/* Experimental Options */
// "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
// "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
},
"include": ["./src/**/*.ts"],
"exclude": ["./lib/**/*.*"]
}

19
SuiviREForamteur/node_modules/svg-pathdata/tslint.json generated vendored Normal file
View File

@@ -0,0 +1,19 @@
{
"defaultSeverity": "error",
"extends": [
"tslint:recommended"
],
"jsRules": {},
"rules": {
"no-shadowed-variable": false,
"one-variable-per-declaration": false,
"variable-name": ["allow-trailing-underscore", "allow-leading-underscore"],
"interface-over-type-literal": false,
"member-access": false,
"no-conditional-assignment": false,
"member-ordering": false,
"no-bitwise": false,
"object-literal-sort-keys": false
},
"rulesDirectory": []
}