Compare commits
107 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
32ac819813 | ||
|
|
c1ded757c7 | ||
|
|
4a592a905c | ||
|
|
ba02d3b162 | ||
|
|
053a0ddbf0 | ||
|
|
6a0a87530c | ||
|
|
1e63e37b71 | ||
|
|
ab8a735034 | ||
|
|
5007c84419 | ||
|
|
8fa61ae164 | ||
|
|
964ad08767 | ||
|
|
4514718d7b | ||
|
|
6042216e77 | ||
|
|
f2e24055a9 | ||
|
|
1ff0448dc4 | ||
|
|
ed172e124e | ||
|
|
9ca54a6e7f | ||
|
|
03b5a627c8 | ||
|
|
95a0f66f76 | ||
|
|
78048fe887 | ||
|
|
6740651f9a | ||
|
|
27de6ca0ff | ||
|
|
fc673df32e | ||
|
|
1918dada8b | ||
|
|
52b29363cc | ||
|
|
3a9e176845 | ||
|
|
828d4cc40a | ||
|
|
1b51ee644c | ||
|
|
670b825d20 | ||
|
|
b4579adc44 | ||
|
|
cde8254743 | ||
|
|
029450a7c9 | ||
|
|
708e34d2fc | ||
|
|
7b744ceaef | ||
|
|
614c0894e2 | ||
|
|
cd32cdb124 | ||
|
|
17a904e086 | ||
|
|
10c538b86b | ||
|
|
3ee0502a4a | ||
|
|
b8d87c8a95 | ||
|
|
b957204d76 | ||
|
|
71c2be59fe | ||
|
|
79582dbddd | ||
|
|
5195c0e9e7 | ||
|
|
b4c9c5978e | ||
|
|
3d1e01b353 | ||
|
|
270c29f757 | ||
|
|
9acc305d31 | ||
|
|
f02df4f826 | ||
|
|
7a709acf01 | ||
|
|
e9a92c04aa | ||
|
|
8922918507 | ||
|
|
7440e65552 | ||
|
|
311b84737f | ||
|
|
892e931219 | ||
|
|
34e0038efb | ||
|
|
48c2cd493f | ||
|
|
2e6355a6de | ||
|
|
a50cb76ed0 | ||
|
|
dd958efae5 | ||
|
|
1639417a55 | ||
|
|
778b146d8e | ||
|
|
1b460e2d29 | ||
|
|
9e3b71a241 | ||
|
|
0ef238ce9d | ||
|
|
785db7c4e7 | ||
|
|
924f967e5a | ||
|
|
219cece5ac | ||
|
|
a492de0db1 | ||
|
|
7ec67d9488 | ||
|
|
a114830e6f | ||
|
|
f9fd064026 | ||
|
|
7883a40985 | ||
|
|
fcffb4163b | ||
|
|
c86af9107c | ||
|
|
644ef27a87 | ||
|
|
4479709788 | ||
|
|
9d70335127 | ||
|
|
1ebdc18934 | ||
|
|
8c790d6804 | ||
|
|
245ee798dc | ||
|
|
0fd557d7bb | ||
|
|
4582ea1c56 | ||
|
|
36e1d30631 | ||
|
|
88ad5aac01 | ||
|
|
4954e0fe21 | ||
|
|
0fdc062e24 | ||
|
|
47ebb31bd9 | ||
|
|
7f8f7b9e99 | ||
|
|
0b90e5f864 | ||
|
|
f08d9f5e56 | ||
|
|
09693390c5 | ||
|
|
21b45dafb6 | ||
|
|
52cb222dfc | ||
|
|
1b9b8a78ba | ||
|
|
2f92a41fbe | ||
|
|
45a82eb336 | ||
|
|
aa965ae198 | ||
|
|
6caebdaf86 | ||
|
|
dba6707e00 | ||
|
|
e370dccbdc | ||
|
|
206a9362c1 | ||
|
|
46f091aefd | ||
|
|
56ae094afb | ||
|
|
a17bb10662 | ||
|
|
084285755f | ||
|
|
d0f3f2251f |
@@ -96,25 +96,36 @@ run_package_tests: &run_package_tests
|
||||
nvm install $NODE_VERSION
|
||||
nvm use $NODE_VERSION
|
||||
node --version
|
||||
|
||||
# install the shields.io dependencies
|
||||
npm ci
|
||||
|
||||
# run the package tests
|
||||
npm run test:package
|
||||
npm run check-types:package
|
||||
|
||||
# delete the sheilds.io dependencies
|
||||
rm -rf node_modules/
|
||||
|
||||
# run a smoke test (render a badge with the CLI)
|
||||
# with only the package dependencies installed
|
||||
cd badge-maker
|
||||
npm link
|
||||
badge cactus grown :green @flat
|
||||
|
||||
package_steps: &package_steps
|
||||
steps:
|
||||
- checkout
|
||||
|
||||
- run:
|
||||
name: Install dependencies
|
||||
name: Install node and npm
|
||||
command: |
|
||||
set +e
|
||||
export NVM_DIR="/opt/circleci/.nvm"
|
||||
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
|
||||
nvm install v12
|
||||
nvm install v14
|
||||
nvm use v12
|
||||
npm install -g npm
|
||||
npm ci
|
||||
environment:
|
||||
CYPRESS_INSTALL_BINARY: 0
|
||||
|
||||
# Run the package tests on each currently supported node version. See:
|
||||
# https://github.com/badges/shields/blob/master/badge-maker/README.md#node-version-support
|
||||
@@ -125,6 +136,7 @@ package_steps: &package_steps
|
||||
mocha_reporter: mocha-junit-reporter
|
||||
MOCHA_FILE: junit/badge-maker/v10/results.xml
|
||||
NODE_VERSION: v10
|
||||
CYPRESS_INSTALL_BINARY: 0
|
||||
name: Run package tests on Node 10
|
||||
|
||||
- run:
|
||||
@@ -133,6 +145,7 @@ package_steps: &package_steps
|
||||
mocha_reporter: mocha-junit-reporter
|
||||
MOCHA_FILE: junit/badge-maker/v12/results.xml
|
||||
NODE_VERSION: v12
|
||||
CYPRESS_INSTALL_BINARY: 0
|
||||
name: Run package tests on Node 12
|
||||
|
||||
- run:
|
||||
@@ -141,6 +154,7 @@ package_steps: &package_steps
|
||||
mocha_reporter: mocha-junit-reporter
|
||||
MOCHA_FILE: junit/badge-maker/v14/results.xml
|
||||
NODE_VERSION: v14
|
||||
CYPRESS_INSTALL_BINARY: 0
|
||||
name: Run package tests on Node 14
|
||||
|
||||
- store_test_results:
|
||||
|
||||
@@ -16,6 +16,8 @@ parserOptions:
|
||||
settings:
|
||||
react:
|
||||
version: '16.8'
|
||||
jsdoc:
|
||||
mode: jsdoc
|
||||
|
||||
plugins:
|
||||
- chai-friendly
|
||||
|
||||
17
.github/ISSUE_TEMPLATE/5_Support_question.md
vendored
17
.github/ISSUE_TEMPLATE/5_Support_question.md
vendored
@@ -1,17 +0,0 @@
|
||||
---
|
||||
name: ❓ Support Question
|
||||
about: Ask a question about shields.io
|
||||
labels: 'question'
|
||||
---
|
||||
|
||||
:question: **Question**
|
||||
|
||||
<!--
|
||||
Ask your question clearly and concisely.
|
||||
|
||||
#support on our [Discord](https://discordapp.com/invite/HjJCwm5)
|
||||
is also a great place to ask questions and get help
|
||||
-->
|
||||
|
||||
<!-- Love Shields? Please consider donating $10 to sustain our activities:
|
||||
👉 https://opencollective.com/shields -->
|
||||
4
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
4
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
contact_links:
|
||||
- name: Support Question
|
||||
url: https://github.com/badges/shields/discussions
|
||||
about: Ask a question about Shields.io
|
||||
@@ -49,8 +49,9 @@ simple changes, like badge additions. These are usually tagged with
|
||||
|
||||
Please review [these impeccable guidelines][code review guidelines].
|
||||
|
||||
You can monitor [issues][] and the [chat room][], and help other people who
|
||||
have questions about contributing to Shields, or using it for their projects.
|
||||
You can monitor [issues][], [discussions][] and the [chat room][], and help
|
||||
other people who have questions about contributing to Shields, or using it
|
||||
for their projects.
|
||||
|
||||
Feel free to reach out to one of the [maintainers][]
|
||||
if you need help getting started.
|
||||
@@ -58,6 +59,7 @@ if you need help getting started.
|
||||
[service badge pr tag]: https://github.com/badges/shields/pulls?q=is%3Apr+is%3Aopen+label%3Aservice-badge
|
||||
[code review guidelines]: https://kickstarter.engineering/a-guide-to-mindful-communication-in-code-reviews-48aab5282e5e
|
||||
[issues]: https://github.com/badges/shields/issues
|
||||
[discussions]: https://github.com/badges/shields/discussions
|
||||
[chat room]: https://discordapp.com/invite/HjJCwm5
|
||||
[maintainers]: https://github.com/badges/shields#project-leaders
|
||||
|
||||
@@ -86,9 +88,9 @@ We're also asking for [one-time \$10 donations](https://opencollective.com/shiel
|
||||
There are three places to get help:
|
||||
|
||||
1. If you're new to the project, a good place to start is the [tutorial][].
|
||||
2. If you need help getting started or implementing a change, [open an issue][]
|
||||
2. If you need help getting started or implementing a change, [start a discussion][discussions]
|
||||
with your question. We promise it's okay to do that. If there is already an
|
||||
issue open for the feature you're working on, you can post there.
|
||||
issue open for the feature you're working on, you can post there directly.
|
||||
3. You can also join the [chat room][] and ask your question there.
|
||||
|
||||
[tutorial]: doc/TUTORIAL.md
|
||||
|
||||
29
README.md
29
README.md
@@ -183,7 +183,6 @@ Maintainers:
|
||||
- [calebcartwright](https://github.com/calebcartwright) (core team)
|
||||
- [chris48s](https://github.com/chris48s) (core team)
|
||||
- [Daniel15](https://github.com/Daniel15) (core team)
|
||||
- [espadrine](https://github.com/espadrine) (core team)
|
||||
- [paulmelnikow](https://github.com/paulmelnikow) (core team)
|
||||
- [platan](https://github.com/platan) (core team)
|
||||
- [PyvesB](https://github.com/PyvesB) (core team)
|
||||
@@ -193,12 +192,12 @@ Operations:
|
||||
|
||||
- [calebcartwright](https://github.com/calebcartwright)
|
||||
- [chris48s](https://github.com/chris48s)
|
||||
- [espadrine](https://github.com/espadrine)
|
||||
- [paulmelnikow](https://github.com/paulmelnikow)
|
||||
- [PyvesB](https://github.com/PyvesB)
|
||||
|
||||
Alumni:
|
||||
|
||||
- [espadrine](https://github.com/espadrine)
|
||||
- [olivierlacan](https://github.com/olivierlacan)
|
||||
|
||||
## Related projects
|
||||
@@ -217,28 +216,6 @@ domain unless specified otherwise.
|
||||
The assets in `logo/` are trademarks of their respective companies and are
|
||||
under their terms and license.
|
||||
|
||||
## Contributors
|
||||
## Community
|
||||
|
||||
This project exists thanks to all the people who contribute. [[Contribute](CONTRIBUTING.md)].
|
||||
<a href="https://github.com/badges/shields/graphs/contributors"><img src="https://opencollective.com/shields/contributors.svg?width=890" /></a>
|
||||
|
||||
## Backers
|
||||
|
||||
Thank you to all our backers! 🙏 [[Become a backer](https://opencollective.com/shields#backer)]
|
||||
|
||||
<a href="https://opencollective.com/shields#backers" target="_blank"><img src="https://opencollective.com/shields/backers.svg?width=890"></a>
|
||||
|
||||
## Sponsors
|
||||
|
||||
Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [[Become a sponsor](https://opencollective.com/shields#sponsor)]
|
||||
|
||||
<a href="https://opencollective.com/shields/sponsor/0/website" target="_blank"><img src="https://opencollective.com/shields/sponsor/0/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/shields/sponsor/1/website" target="_blank"><img src="https://opencollective.com/shields/sponsor/1/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/shields/sponsor/2/website" target="_blank"><img src="https://opencollective.com/shields/sponsor/2/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/shields/sponsor/3/website" target="_blank"><img src="https://opencollective.com/shields/sponsor/3/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/shields/sponsor/4/website" target="_blank"><img src="https://opencollective.com/shields/sponsor/4/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/shields/sponsor/5/website" target="_blank"><img src="https://opencollective.com/shields/sponsor/5/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/shields/sponsor/6/website" target="_blank"><img src="https://opencollective.com/shields/sponsor/6/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/shields/sponsor/7/website" target="_blank"><img src="https://opencollective.com/shields/sponsor/7/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/shields/sponsor/8/website" target="_blank"><img src="https://opencollective.com/shields/sponsor/8/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/shields/sponsor/9/website" target="_blank"><img src="https://opencollective.com/shields/sponsor/9/avatar.svg"></a>
|
||||
Thanks to the people and companies who donate money, services or time to keep the project running. [https://shields.io/community](https://shields.io/community)
|
||||
|
||||
@@ -1,127 +1,127 @@
|
||||
exports['The badge generator SVG should match snapshot 1'] = `
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="90" height="20"><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="90" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="45" height="20" fill="#555"/><rect x="45" width="45" height="20" fill="#4c1"/><rect width="90" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text x="235" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="350">cactus</text><text x="235" y="140" transform="scale(.1)" textLength="350">cactus</text><text x="665" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="350">grown</text><text x="665" y="140" transform="scale(.1)" textLength="350">grown</text></g></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="90" height="20" role="img" aria-label="cactus: grown"><title>cactus: grown</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="90" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="45" height="20" fill="#555"/><rect x="45" width="45" height="20" fill="#4c1"/><rect width="90" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text aria-hidden="true" x="235" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="350">cactus</text><text x="235" y="140" transform="scale(.1)" fill="#fff" textLength="350">cactus</text><text aria-hidden="true" x="665" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="350">grown</text><text x="665" y="140" transform="scale(.1)" fill="#fff" textLength="350">grown</text></g></svg>
|
||||
`
|
||||
|
||||
exports['The badge generator "flat" template badge generation should match snapshots: message/label, no logo 1'] = `
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="90" height="20"><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="90" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="45" height="20" fill="#0f0"/><rect x="45" width="45" height="20" fill="#b3e"/><rect width="90" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text x="235" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="350">cactus</text><text x="235" y="140" transform="scale(.1)" textLength="350">cactus</text><text x="665" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="350">grown</text><text x="665" y="140" transform="scale(.1)" textLength="350">grown</text></g></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="90" height="20" role="img" aria-label="cactus: grown"><title>cactus: grown</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="90" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="45" height="20" fill="#0f0"/><rect x="45" width="45" height="20" fill="#b3e"/><rect width="90" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text aria-hidden="true" x="235" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="350">cactus</text><text x="235" y="140" transform="scale(.1)" fill="#fff" textLength="350">cactus</text><text aria-hidden="true" x="665" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="350">grown</text><text x="665" y="140" transform="scale(.1)" fill="#fff" textLength="350">grown</text></g></svg>
|
||||
`
|
||||
|
||||
exports['The badge generator "flat" template badge generation should match snapshots: message/label, with logo 1'] = `
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="107" height="20"><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="107" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="62" height="20" fill="#0f0"/><rect x="62" width="45" height="20" fill="#b3e"/><rect width="107" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><image x="5" y="3" width="14" height="14" xlink:href="data:image/svg+xml;base64,PHN2ZyB4bWxu"/><text x="405" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="350">cactus</text><text x="405" y="140" transform="scale(.1)" textLength="350">cactus</text><text x="835" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="350">grown</text><text x="835" y="140" transform="scale(.1)" textLength="350">grown</text></g></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="107" height="20" role="img" aria-label="cactus: grown"><title>cactus: grown</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="107" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="62" height="20" fill="#0f0"/><rect x="62" width="45" height="20" fill="#b3e"/><rect width="107" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><image x="5" y="3" width="14" height="14" xlink:href="data:image/svg+xml;base64,PHN2ZyB4bWxu"/><text aria-hidden="true" x="405" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="350">cactus</text><text x="405" y="140" transform="scale(.1)" fill="#fff" textLength="350">cactus</text><text aria-hidden="true" x="835" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="350">grown</text><text x="835" y="140" transform="scale(.1)" fill="#fff" textLength="350">grown</text></g></svg>
|
||||
`
|
||||
|
||||
exports['The badge generator "flat" template badge generation should match snapshots: message only, no logo 1'] = `
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="45" height="20"><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="45" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="0" height="20" fill="#b3e"/><rect x="0" width="45" height="20" fill="#b3e"/><rect width="45" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text x="225" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="350">grown</text><text x="225" y="140" transform="scale(.1)" textLength="350">grown</text></g></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="45" height="20" role="img" aria-label="grown"><title>grown</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="45" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="0" height="20" fill="#b3e"/><rect x="0" width="45" height="20" fill="#b3e"/><rect width="45" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text aria-hidden="true" x="225" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="350">grown</text><text x="225" y="140" transform="scale(.1)" fill="#fff" textLength="350">grown</text></g></svg>
|
||||
`
|
||||
|
||||
exports['The badge generator "flat" template badge generation should match snapshots: message only, with logo 1'] = `
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="63" height="20"><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="63" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="0" height="20" fill="#555"/><rect x="0" width="63" height="20" fill="#b3e"/><rect width="63" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><image x="5" y="3" width="14" height="14" xlink:href="data:image/svg+xml;base64,PHN2ZyB4bWxu"/><text x="405" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="350">grown</text><text x="405" y="140" transform="scale(.1)" textLength="350">grown</text></g></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="63" height="20" role="img" aria-label="grown"><title>grown</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="63" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="0" height="20" fill="#555"/><rect x="0" width="63" height="20" fill="#b3e"/><rect width="63" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><image x="5" y="3" width="14" height="14" xlink:href="data:image/svg+xml;base64,PHN2ZyB4bWxu"/><text aria-hidden="true" x="405" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="350">grown</text><text x="405" y="140" transform="scale(.1)" fill="#fff" textLength="350">grown</text></g></svg>
|
||||
`
|
||||
|
||||
exports['The badge generator "flat" template badge generation should match snapshots: message only, with logo and labelColor 1'] = `
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="69" height="20"><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="69" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="24" height="20" fill="#0f0"/><rect x="24" width="45" height="20" fill="#b3e"/><rect width="69" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><image x="5" y="3" width="14" height="14" xlink:href="data:image/svg+xml;base64,PHN2ZyB4bWxu"/><text x="455" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="350">grown</text><text x="455" y="140" transform="scale(.1)" textLength="350">grown</text></g></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="69" height="20" role="img" aria-label="grown"><title>grown</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="69" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="24" height="20" fill="#0f0"/><rect x="24" width="45" height="20" fill="#b3e"/><rect width="69" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><image x="5" y="3" width="14" height="14" xlink:href="data:image/svg+xml;base64,PHN2ZyB4bWxu"/><text aria-hidden="true" x="455" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="350">grown</text><text x="455" y="140" transform="scale(.1)" fill="#fff" textLength="350">grown</text></g></svg>
|
||||
`
|
||||
|
||||
exports['The badge generator "flat" template badge generation should match snapshots: message/label, with links 1'] = `
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="90" height="20"><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="90" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="45" height="20" fill="#0f0"/><rect x="45" width="45" height="20" fill="#b3e"/><rect width="90" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text x="235" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="350">cactus</text><text x="235" y="140" transform="scale(.1)" textLength="350">cactus</text><text x="665" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="350">grown</text><text x="665" y="140" transform="scale(.1)" textLength="350">grown</text></g><a target="_blank" xlink:href="https://www.google.co.uk/"><rect width="90" height="20" fill="rgba(0,0,0,0)"/></a><a target="_blank" xlink:href="https://shields.io/"><rect width="45" height="20" fill="rgba(0,0,0,0)"/></a></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="90" height="20" ><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="90" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="45" height="20" fill="#0f0"/><rect x="45" width="45" height="20" fill="#b3e"/><rect width="90" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><a target="_blank" xlink:href="https://shields.io/"><rect width="45" x="0" height="20" fill="rgba(0,0,0,0)" /><text aria-hidden="true" x="235" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="350">cactus</text><text x="235" y="140" transform="scale(.1)" fill="#fff" textLength="350">cactus</text></a><a target="_blank" xlink:href="https://www.google.co.uk/"><rect width="45" x="45" height="20" fill="rgba(0,0,0,0)" /><text aria-hidden="true" x="665" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="350">grown</text><text x="665" y="140" transform="scale(.1)" fill="#fff" textLength="350">grown</text></a></g></svg>
|
||||
`
|
||||
|
||||
exports['The badge generator "flat-square" template badge generation should match snapshots: message/label, no logo 1'] = `
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="90" height="20"><g shape-rendering="crispEdges"><rect width="45" height="20" fill="#0f0"/><rect x="45" width="45" height="20" fill="#b3e"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text x="235" y="140" transform="scale(.1)" textLength="350">cactus</text><text x="665" y="140" transform="scale(.1)" textLength="350">grown</text></g></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="90" height="20" role="img" aria-label="cactus: grown"><title>cactus: grown</title><g shape-rendering="crispEdges"><rect width="45" height="20" fill="#0f0"/><rect x="45" width="45" height="20" fill="#b3e"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text x="235" y="140" transform="scale(.1)" fill="#fff" textLength="350">cactus</text><text x="665" y="140" transform="scale(.1)" fill="#fff" textLength="350">grown</text></g></svg>
|
||||
`
|
||||
|
||||
exports['The badge generator "flat-square" template badge generation should match snapshots: message/label, with logo 1'] = `
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="107" height="20"><g shape-rendering="crispEdges"><rect width="62" height="20" fill="#0f0"/><rect x="62" width="45" height="20" fill="#b3e"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><image x="5" y="3" width="14" height="14" xlink:href="data:image/svg+xml;base64,PHN2ZyB4bWxu"/><text x="405" y="140" transform="scale(.1)" textLength="350">cactus</text><text x="835" y="140" transform="scale(.1)" textLength="350">grown</text></g></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="107" height="20" role="img" aria-label="cactus: grown"><title>cactus: grown</title><g shape-rendering="crispEdges"><rect width="62" height="20" fill="#0f0"/><rect x="62" width="45" height="20" fill="#b3e"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><image x="5" y="3" width="14" height="14" xlink:href="data:image/svg+xml;base64,PHN2ZyB4bWxu"/><text x="405" y="140" transform="scale(.1)" fill="#fff" textLength="350">cactus</text><text x="835" y="140" transform="scale(.1)" fill="#fff" textLength="350">grown</text></g></svg>
|
||||
`
|
||||
|
||||
exports['The badge generator "flat-square" template badge generation should match snapshots: message only, no logo 1'] = `
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="45" height="20"><g shape-rendering="crispEdges"><rect width="0" height="20" fill="#b3e"/><rect x="0" width="45" height="20" fill="#b3e"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text x="225" y="140" transform="scale(.1)" textLength="350">grown</text></g></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="45" height="20" role="img" aria-label="grown"><title>grown</title><g shape-rendering="crispEdges"><rect width="0" height="20" fill="#b3e"/><rect x="0" width="45" height="20" fill="#b3e"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text x="225" y="140" transform="scale(.1)" fill="#fff" textLength="350">grown</text></g></svg>
|
||||
`
|
||||
|
||||
exports['The badge generator "flat-square" template badge generation should match snapshots: message only, with logo 1'] = `
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="63" height="20"><g shape-rendering="crispEdges"><rect width="0" height="20" fill="#555"/><rect x="0" width="63" height="20" fill="#b3e"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><image x="5" y="3" width="14" height="14" xlink:href="data:image/svg+xml;base64,PHN2ZyB4bWxu"/><text x="405" y="140" transform="scale(.1)" textLength="350">grown</text></g></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="63" height="20" role="img" aria-label="grown"><title>grown</title><g shape-rendering="crispEdges"><rect width="0" height="20" fill="#555"/><rect x="0" width="63" height="20" fill="#b3e"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><image x="5" y="3" width="14" height="14" xlink:href="data:image/svg+xml;base64,PHN2ZyB4bWxu"/><text x="405" y="140" transform="scale(.1)" fill="#fff" textLength="350">grown</text></g></svg>
|
||||
`
|
||||
|
||||
exports['The badge generator "flat-square" template badge generation should match snapshots: message only, with logo and labelColor 1'] = `
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="69" height="20"><g shape-rendering="crispEdges"><rect width="24" height="20" fill="#0f0"/><rect x="24" width="45" height="20" fill="#b3e"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><image x="5" y="3" width="14" height="14" xlink:href="data:image/svg+xml;base64,PHN2ZyB4bWxu"/><text x="455" y="140" transform="scale(.1)" textLength="350">grown</text></g></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="69" height="20" role="img" aria-label="grown"><title>grown</title><g shape-rendering="crispEdges"><rect width="24" height="20" fill="#0f0"/><rect x="24" width="45" height="20" fill="#b3e"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><image x="5" y="3" width="14" height="14" xlink:href="data:image/svg+xml;base64,PHN2ZyB4bWxu"/><text x="455" y="140" transform="scale(.1)" fill="#fff" textLength="350">grown</text></g></svg>
|
||||
`
|
||||
|
||||
exports['The badge generator "flat-square" template badge generation should match snapshots: message/label, with links 1'] = `
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="90" height="20"><g shape-rendering="crispEdges"><rect width="45" height="20" fill="#0f0"/><rect x="45" width="45" height="20" fill="#b3e"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text x="235" y="140" transform="scale(.1)" textLength="350">cactus</text><text x="665" y="140" transform="scale(.1)" textLength="350">grown</text></g><a target="_blank" xlink:href="https://www.google.co.uk/"><rect width="90" height="20" fill="rgba(0,0,0,0)"/></a><a target="_blank" xlink:href="https://shields.io/"><rect width="45" height="20" fill="rgba(0,0,0,0)"/></a></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="90" height="20" ><g shape-rendering="crispEdges"><rect width="45" height="20" fill="#0f0"/><rect x="45" width="45" height="20" fill="#b3e"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><a target="_blank" xlink:href="https://shields.io/"><rect width="45" x="0" height="20" fill="rgba(0,0,0,0)" /><text x="235" y="140" transform="scale(.1)" fill="#fff" textLength="350">cactus</text></a><a target="_blank" xlink:href="https://www.google.co.uk/"><rect width="45" x="45" height="20" fill="rgba(0,0,0,0)" /><text x="665" y="140" transform="scale(.1)" fill="#fff" textLength="350">grown</text></a></g></svg>
|
||||
`
|
||||
|
||||
exports['The badge generator "plastic" template badge generation should match snapshots: message/label, no logo 1'] = `
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="90" height="18"><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#fff" stop-opacity=".7"/><stop offset=".1" stop-color="#aaa" stop-opacity=".1"/><stop offset=".9" stop-color="#000" stop-opacity=".3"/><stop offset="1" stop-color="#000" stop-opacity=".5"/></linearGradient><clipPath id="r"><rect width="90" height="18" rx="4" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="45" height="18" fill="#0f0"/><rect x="45" width="45" height="18" fill="#b3e"/><rect width="90" height="18" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text x="235" y="140" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="350">cactus</text><text x="235" y="130" transform="scale(.1)" textLength="350">cactus</text><text x="665" y="140" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="350">grown</text><text x="665" y="130" transform="scale(.1)" textLength="350">grown</text></g></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="90" height="18" role="img" aria-label="cactus: grown"><title>cactus: grown</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#fff" stop-opacity=".7"/><stop offset=".1" stop-color="#aaa" stop-opacity=".1"/><stop offset=".9" stop-color="#000" stop-opacity=".3"/><stop offset="1" stop-color="#000" stop-opacity=".5"/></linearGradient><clipPath id="r"><rect width="90" height="18" rx="4" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="45" height="18" fill="#0f0"/><rect x="45" width="45" height="18" fill="#b3e"/><rect width="90" height="18" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text aria-hidden="true" x="235" y="140" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="350">cactus</text><text x="235" y="130" transform="scale(.1)" fill="#fff" textLength="350">cactus</text><text aria-hidden="true" x="665" y="140" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="350">grown</text><text x="665" y="130" transform="scale(.1)" fill="#fff" textLength="350">grown</text></g></svg>
|
||||
`
|
||||
|
||||
exports['The badge generator "plastic" template badge generation should match snapshots: message/label, with logo 1'] = `
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="107" height="18"><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#fff" stop-opacity=".7"/><stop offset=".1" stop-color="#aaa" stop-opacity=".1"/><stop offset=".9" stop-color="#000" stop-opacity=".3"/><stop offset="1" stop-color="#000" stop-opacity=".5"/></linearGradient><clipPath id="r"><rect width="107" height="18" rx="4" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="62" height="18" fill="#0f0"/><rect x="62" width="45" height="18" fill="#b3e"/><rect width="107" height="18" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><image x="5" y="2" width="14" height="14" xlink:href="data:image/svg+xml;base64,PHN2ZyB4bWxu"/><text x="405" y="140" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="350">cactus</text><text x="405" y="130" transform="scale(.1)" textLength="350">cactus</text><text x="835" y="140" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="350">grown</text><text x="835" y="130" transform="scale(.1)" textLength="350">grown</text></g></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="107" height="18" role="img" aria-label="cactus: grown"><title>cactus: grown</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#fff" stop-opacity=".7"/><stop offset=".1" stop-color="#aaa" stop-opacity=".1"/><stop offset=".9" stop-color="#000" stop-opacity=".3"/><stop offset="1" stop-color="#000" stop-opacity=".5"/></linearGradient><clipPath id="r"><rect width="107" height="18" rx="4" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="62" height="18" fill="#0f0"/><rect x="62" width="45" height="18" fill="#b3e"/><rect width="107" height="18" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><image x="5" y="2" width="14" height="14" xlink:href="data:image/svg+xml;base64,PHN2ZyB4bWxu"/><text aria-hidden="true" x="405" y="140" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="350">cactus</text><text x="405" y="130" transform="scale(.1)" fill="#fff" textLength="350">cactus</text><text aria-hidden="true" x="835" y="140" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="350">grown</text><text x="835" y="130" transform="scale(.1)" fill="#fff" textLength="350">grown</text></g></svg>
|
||||
`
|
||||
|
||||
exports['The badge generator "plastic" template badge generation should match snapshots: message only, no logo 1'] = `
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="45" height="18"><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#fff" stop-opacity=".7"/><stop offset=".1" stop-color="#aaa" stop-opacity=".1"/><stop offset=".9" stop-color="#000" stop-opacity=".3"/><stop offset="1" stop-color="#000" stop-opacity=".5"/></linearGradient><clipPath id="r"><rect width="45" height="18" rx="4" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="0" height="18" fill="#b3e"/><rect x="0" width="45" height="18" fill="#b3e"/><rect width="45" height="18" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text x="225" y="140" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="350">grown</text><text x="225" y="130" transform="scale(.1)" textLength="350">grown</text></g></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="45" height="18" role="img" aria-label="grown"><title>grown</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#fff" stop-opacity=".7"/><stop offset=".1" stop-color="#aaa" stop-opacity=".1"/><stop offset=".9" stop-color="#000" stop-opacity=".3"/><stop offset="1" stop-color="#000" stop-opacity=".5"/></linearGradient><clipPath id="r"><rect width="45" height="18" rx="4" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="0" height="18" fill="#b3e"/><rect x="0" width="45" height="18" fill="#b3e"/><rect width="45" height="18" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text aria-hidden="true" x="225" y="140" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="350">grown</text><text x="225" y="130" transform="scale(.1)" fill="#fff" textLength="350">grown</text></g></svg>
|
||||
`
|
||||
|
||||
exports['The badge generator "plastic" template badge generation should match snapshots: message only, with logo 1'] = `
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="63" height="18"><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#fff" stop-opacity=".7"/><stop offset=".1" stop-color="#aaa" stop-opacity=".1"/><stop offset=".9" stop-color="#000" stop-opacity=".3"/><stop offset="1" stop-color="#000" stop-opacity=".5"/></linearGradient><clipPath id="r"><rect width="63" height="18" rx="4" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="0" height="18" fill="#555"/><rect x="0" width="63" height="18" fill="#b3e"/><rect width="63" height="18" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><image x="5" y="2" width="14" height="14" xlink:href="data:image/svg+xml;base64,PHN2ZyB4bWxu"/><text x="405" y="140" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="350">grown</text><text x="405" y="130" transform="scale(.1)" textLength="350">grown</text></g></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="63" height="18" role="img" aria-label="grown"><title>grown</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#fff" stop-opacity=".7"/><stop offset=".1" stop-color="#aaa" stop-opacity=".1"/><stop offset=".9" stop-color="#000" stop-opacity=".3"/><stop offset="1" stop-color="#000" stop-opacity=".5"/></linearGradient><clipPath id="r"><rect width="63" height="18" rx="4" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="0" height="18" fill="#555"/><rect x="0" width="63" height="18" fill="#b3e"/><rect width="63" height="18" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><image x="5" y="2" width="14" height="14" xlink:href="data:image/svg+xml;base64,PHN2ZyB4bWxu"/><text aria-hidden="true" x="405" y="140" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="350">grown</text><text x="405" y="130" transform="scale(.1)" fill="#fff" textLength="350">grown</text></g></svg>
|
||||
`
|
||||
|
||||
exports['The badge generator "plastic" template badge generation should match snapshots: message only, with logo and labelColor 1'] = `
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="69" height="18"><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#fff" stop-opacity=".7"/><stop offset=".1" stop-color="#aaa" stop-opacity=".1"/><stop offset=".9" stop-color="#000" stop-opacity=".3"/><stop offset="1" stop-color="#000" stop-opacity=".5"/></linearGradient><clipPath id="r"><rect width="69" height="18" rx="4" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="24" height="18" fill="#0f0"/><rect x="24" width="45" height="18" fill="#b3e"/><rect width="69" height="18" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><image x="5" y="2" width="14" height="14" xlink:href="data:image/svg+xml;base64,PHN2ZyB4bWxu"/><text x="455" y="140" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="350">grown</text><text x="455" y="130" transform="scale(.1)" textLength="350">grown</text></g></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="69" height="18" role="img" aria-label="grown"><title>grown</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#fff" stop-opacity=".7"/><stop offset=".1" stop-color="#aaa" stop-opacity=".1"/><stop offset=".9" stop-color="#000" stop-opacity=".3"/><stop offset="1" stop-color="#000" stop-opacity=".5"/></linearGradient><clipPath id="r"><rect width="69" height="18" rx="4" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="24" height="18" fill="#0f0"/><rect x="24" width="45" height="18" fill="#b3e"/><rect width="69" height="18" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><image x="5" y="2" width="14" height="14" xlink:href="data:image/svg+xml;base64,PHN2ZyB4bWxu"/><text aria-hidden="true" x="455" y="140" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="350">grown</text><text x="455" y="130" transform="scale(.1)" fill="#fff" textLength="350">grown</text></g></svg>
|
||||
`
|
||||
|
||||
exports['The badge generator "plastic" template badge generation should match snapshots: message/label, with links 1'] = `
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="90" height="18"><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#fff" stop-opacity=".7"/><stop offset=".1" stop-color="#aaa" stop-opacity=".1"/><stop offset=".9" stop-color="#000" stop-opacity=".3"/><stop offset="1" stop-color="#000" stop-opacity=".5"/></linearGradient><clipPath id="r"><rect width="90" height="18" rx="4" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="45" height="18" fill="#0f0"/><rect x="45" width="45" height="18" fill="#b3e"/><rect width="90" height="18" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text x="235" y="140" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="350">cactus</text><text x="235" y="130" transform="scale(.1)" textLength="350">cactus</text><text x="665" y="140" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="350">grown</text><text x="665" y="130" transform="scale(.1)" textLength="350">grown</text></g><a target="_blank" xlink:href="https://www.google.co.uk/"><rect width="90" height="18" fill="rgba(0,0,0,0)"/></a><a target="_blank" xlink:href="https://shields.io/"><rect width="45" height="18" fill="rgba(0,0,0,0)"/></a></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="90" height="18" ><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#fff" stop-opacity=".7"/><stop offset=".1" stop-color="#aaa" stop-opacity=".1"/><stop offset=".9" stop-color="#000" stop-opacity=".3"/><stop offset="1" stop-color="#000" stop-opacity=".5"/></linearGradient><clipPath id="r"><rect width="90" height="18" rx="4" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="45" height="18" fill="#0f0"/><rect x="45" width="45" height="18" fill="#b3e"/><rect width="90" height="18" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><a target="_blank" xlink:href="https://shields.io/"><rect width="45" x="0" height="18" fill="rgba(0,0,0,0)" /><text aria-hidden="true" x="235" y="140" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="350">cactus</text><text x="235" y="130" transform="scale(.1)" fill="#fff" textLength="350">cactus</text></a><a target="_blank" xlink:href="https://www.google.co.uk/"><rect width="45" x="45" height="18" fill="rgba(0,0,0,0)" /><text aria-hidden="true" x="665" y="140" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="350">grown</text><text x="665" y="130" transform="scale(.1)" fill="#fff" textLength="350">grown</text></a></g></svg>
|
||||
`
|
||||
|
||||
exports['The badge generator "for-the-badge" template badge generation should match snapshots: message/label, no logo 1'] = `
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="147" height="28"><g shape-rendering="crispEdges"><rect width="74" height="28" fill="#0f0"/><rect x="74" width="73" height="28" fill="#b3e"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="100"><text x="370" y="175" transform="scale(.1)" textLength="500">CACTUS</text><text x="1105" y="175" font-weight="bold" transform="scale(.1)" textLength="490">GROWN</text></g></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="147" height="28" role="img" aria-label="CACTUS: GROWN"><title>CACTUS: GROWN</title><g shape-rendering="crispEdges"><rect width="74" height="28" fill="#0f0"/><rect x="74" width="73" height="28" fill="#b3e"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="100"><text fill="#fff" x="370" y="175" transform="scale(.1)" textLength="500">CACTUS</text><text fill="#fff" x="1105" y="175" font-weight="bold" transform="scale(.1)" textLength="490">GROWN</text></g></svg>
|
||||
`
|
||||
|
||||
exports['The badge generator "for-the-badge" template badge generation should match snapshots: message/label, with logo 1'] = `
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="164" height="28"><g shape-rendering="crispEdges"><rect width="91" height="28" fill="#0f0"/><rect x="91" width="73" height="28" fill="#b3e"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="100"><image x="9" y="7" width="14" height="14" xlink:href="data:image/svg+xml;base64,PHN2ZyB4bWxu"/><text x="540" y="175" transform="scale(.1)" textLength="500">CACTUS</text><text x="1275" y="175" font-weight="bold" transform="scale(.1)" textLength="490">GROWN</text></g></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="164" height="28" role="img" aria-label="CACTUS: GROWN"><title>CACTUS: GROWN</title><g shape-rendering="crispEdges"><rect width="91" height="28" fill="#0f0"/><rect x="91" width="73" height="28" fill="#b3e"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="100"><image x="9" y="7" width="14" height="14" xlink:href="data:image/svg+xml;base64,PHN2ZyB4bWxu"/><text fill="#fff" x="540" y="175" transform="scale(.1)" textLength="500">CACTUS</text><text fill="#fff" x="1275" y="175" font-weight="bold" transform="scale(.1)" textLength="490">GROWN</text></g></svg>
|
||||
`
|
||||
|
||||
exports['The badge generator "for-the-badge" template badge generation should match snapshots: message only, no logo 1'] = `
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="73" height="28"><g shape-rendering="crispEdges"><rect width="0" height="28" fill="#b3e"/><rect x="0" width="73" height="28" fill="#b3e"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="100"><text x="365" y="175" font-weight="bold" transform="scale(.1)" textLength="490">GROWN</text></g></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="73" height="28" role="img" aria-label="GROWN"><title>GROWN</title><g shape-rendering="crispEdges"><rect width="0" height="28" fill="#b3e"/><rect x="0" width="73" height="28" fill="#b3e"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="100"><text fill="#fff" x="365" y="175" font-weight="bold" transform="scale(.1)" textLength="490">GROWN</text></g></svg>
|
||||
`
|
||||
|
||||
exports['The badge generator "for-the-badge" template badge generation should match snapshots: message only, with logo 1'] = `
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="91" height="28"><g shape-rendering="crispEdges"><rect width="0" height="28" fill="#555"/><rect x="0" width="91" height="28" fill="#b3e"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="100"><image x="9" y="7" width="14" height="14" xlink:href="data:image/svg+xml;base64,PHN2ZyB4bWxu"/><text x="545" y="175" font-weight="bold" transform="scale(.1)" textLength="490">GROWN</text></g></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="91" height="28" role="img" aria-label="GROWN"><title>GROWN</title><g shape-rendering="crispEdges"><rect width="0" height="28" fill="#555"/><rect x="0" width="91" height="28" fill="#b3e"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="100"><image x="9" y="7" width="14" height="14" xlink:href="data:image/svg+xml;base64,PHN2ZyB4bWxu"/><text fill="#fff" x="545" y="175" font-weight="bold" transform="scale(.1)" textLength="490">GROWN</text></g></svg>
|
||||
`
|
||||
|
||||
exports['The badge generator "for-the-badge" template badge generation should match snapshots: message only, with logo and labelColor 1'] = `
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="105" height="28"><g shape-rendering="crispEdges"><rect width="32" height="28" fill="#0f0"/><rect x="32" width="73" height="28" fill="#b3e"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="100"><image x="9" y="7" width="14" height="14" xlink:href="data:image/svg+xml;base64,PHN2ZyB4bWxu"/><text x="230" y="175" transform="scale(.1)" textLength="-60"></text><text x="685" y="175" font-weight="bold" transform="scale(.1)" textLength="490">GROWN</text></g></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="105" height="28" role="img" aria-label="GROWN"><title>GROWN</title><g shape-rendering="crispEdges"><rect width="32" height="28" fill="#0f0"/><rect x="32" width="73" height="28" fill="#b3e"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="100"><image x="9" y="7" width="14" height="14" xlink:href="data:image/svg+xml;base64,PHN2ZyB4bWxu"/><text fill="#fff" x="230" y="175" transform="scale(.1)" textLength="-60"></text><text fill="#fff" x="685" y="175" font-weight="bold" transform="scale(.1)" textLength="490">GROWN</text></g></svg>
|
||||
`
|
||||
|
||||
exports['The badge generator "for-the-badge" template badge generation should match snapshots: message/label, with links 1'] = `
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="147" height="28"><g shape-rendering="crispEdges"><rect width="74" height="28" fill="#0f0"/><rect x="74" width="73" height="28" fill="#b3e"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="100"><text x="370" y="175" transform="scale(.1)" textLength="500">CACTUS</text><text x="1105" y="175" font-weight="bold" transform="scale(.1)" textLength="490">GROWN</text></g><a target="_blank" xlink:href="https://www.google.co.uk/"><rect width="147" height="28" fill="rgba(0,0,0,0)"/></a><a target="_blank" xlink:href="https://shields.io/"><rect width="74" height="28" fill="rgba(0,0,0,0)"/></a></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="147" height="28" ><g shape-rendering="crispEdges"><rect width="74" height="28" fill="#0f0"/><rect x="74" width="73" height="28" fill="#b3e"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="100"><a target="_blank" xlink:href="https://shields.io/"><rect width="74" height="28" fill="rgba(0,0,0,0)"/><text fill="#fff" x="370" y="175" transform="scale(.1)" textLength="500">CACTUS</text></a><a target="_blank" xlink:href="https://www.google.co.uk/"><rect width="73" height="28" x="74" fill="rgba(0,0,0,0)"/><text fill="#fff" x="1105" y="175" font-weight="bold" transform="scale(.1)" textLength="490">GROWN</text></a></g></svg>
|
||||
`
|
||||
|
||||
exports['The badge generator "social" template badge generation should match snapshots: message/label, no logo 1'] = `
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="95" height="20"><style>a #llink:hover{fill:url(#b);stroke:#ccc}a #rlink:hover{fill:#4183c4}</style><linearGradient id="a" x2="0" y2="100%"><stop offset="0" stop-color="#fcfcfc" stop-opacity="0"/><stop offset="1" stop-opacity=".1"/></linearGradient><linearGradient id="b" x2="0" y2="100%"><stop offset="0" stop-color="#ccc" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><g stroke="#d5d5d5"><rect stroke="none" fill="#fcfcfc" x="0.5" y="0.5" width="47" height="19" rx="2"/><rect x="53.5" y="0.5" width="41" height="19" rx="2" fill="#fafafa"/><rect x="53" y="7.5" width="0.5" height="5" stroke="#fafafa"/><path d="M53.5 6.5 l-3 3v1 l3 3" stroke="d5d5d5" fill="#fafafa"/></g><g fill="#333" text-anchor="middle" font-family="Helvetica Neue,Helvetica,Arial,sans-serif" text-rendering="geometricPrecision" font-weight="700" font-size="110px" line-height="14px"><text x="235" y="150" fill="#fff" transform="scale(.1)" textLength="370">Cactus</text><text x="235" y="140" transform="scale(.1)" textLength="370">Cactus</text><text x="735" y="150" fill="#fff" transform="scale(.1)" textLength="330">grown</text><text id="rlink" x="735" y="140" transform="scale(.1)" textLength="330">grown</text></g><rect id="llink" stroke="#d5d5d5" fill="url(#a)" x=".5" y=".5" width="47" height="19" rx="2" /></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="95" height="20" role="img" aria-label="Cactus: grown"><title>Cactus: grown</title><style>a:hover #llink{fill:url(#b);stroke:#ccc}a:hover #rlink{fill:#4183c4}</style><linearGradient id="a" x2="0" y2="100%"><stop offset="0" stop-color="#fcfcfc" stop-opacity="0"/><stop offset="1" stop-opacity=".1"/></linearGradient><linearGradient id="b" x2="0" y2="100%"><stop offset="0" stop-color="#ccc" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><g stroke="#d5d5d5"><rect stroke="none" fill="#fcfcfc" x="0.5" y="0.5" width="47" height="19" rx="2"/><rect x="53.5" y="0.5" width="41" height="19" rx="2" fill="#fafafa"/><rect x="53" y="7.5" width="0.5" height="5" stroke="#fafafa"/><path d="M53.5 6.5 l-3 3v1 l3 3" stroke="d5d5d5" fill="#fafafa"/></g><g aria-hidden="true" fill="#333" text-anchor="middle" font-family="Helvetica Neue,Helvetica,Arial,sans-serif" text-rendering="geometricPrecision" font-weight="700" font-size="110px" line-height="14px"><rect id="llink" stroke="#d5d5d5" fill="url(#a)" x=".5" y=".5" width="47" height="19" rx="2" /><text aria-hidden="true" x="235" y="150" fill="#fff" transform="scale(.1)" textLength="370">Cactus</text><text x="235" y="140" transform="scale(.1)" textLength="370">Cactus</text><text aria-hidden="true" x="735" y="150" fill="#fff" transform="scale(.1)" textLength="330">grown</text><text id="rlink" x="735" y="140" transform="scale(.1)" textLength="330">grown</text></g></svg>
|
||||
`
|
||||
|
||||
exports['The badge generator "social" template badge generation should match snapshots: message/label, with logo 1'] = `
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="112" height="20"><style>a #llink:hover{fill:url(#b);stroke:#ccc}a #rlink:hover{fill:#4183c4}</style><linearGradient id="a" x2="0" y2="100%"><stop offset="0" stop-color="#fcfcfc" stop-opacity="0"/><stop offset="1" stop-opacity=".1"/></linearGradient><linearGradient id="b" x2="0" y2="100%"><stop offset="0" stop-color="#ccc" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><g stroke="#d5d5d5"><rect stroke="none" fill="#fcfcfc" x="0.5" y="0.5" width="64" height="19" rx="2"/><rect x="70.5" y="0.5" width="41" height="19" rx="2" fill="#fafafa"/><rect x="70" y="7.5" width="0.5" height="5" stroke="#fafafa"/><path d="M70.5 6.5 l-3 3v1 l3 3" stroke="d5d5d5" fill="#fafafa"/></g><image x="5" y="3" width="14" height="14" xlink:href="data:image/svg+xml;base64,PHN2ZyB4bWxu"/><g fill="#333" text-anchor="middle" font-family="Helvetica Neue,Helvetica,Arial,sans-serif" text-rendering="geometricPrecision" font-weight="700" font-size="110px" line-height="14px"><text x="405" y="150" fill="#fff" transform="scale(.1)" textLength="370">Cactus</text><text x="405" y="140" transform="scale(.1)" textLength="370">Cactus</text><text x="905" y="150" fill="#fff" transform="scale(.1)" textLength="330">grown</text><text id="rlink" x="905" y="140" transform="scale(.1)" textLength="330">grown</text></g><rect id="llink" stroke="#d5d5d5" fill="url(#a)" x=".5" y=".5" width="64" height="19" rx="2" /></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="112" height="20" role="img" aria-label="Cactus: grown"><title>Cactus: grown</title><style>a:hover #llink{fill:url(#b);stroke:#ccc}a:hover #rlink{fill:#4183c4}</style><linearGradient id="a" x2="0" y2="100%"><stop offset="0" stop-color="#fcfcfc" stop-opacity="0"/><stop offset="1" stop-opacity=".1"/></linearGradient><linearGradient id="b" x2="0" y2="100%"><stop offset="0" stop-color="#ccc" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><g stroke="#d5d5d5"><rect stroke="none" fill="#fcfcfc" x="0.5" y="0.5" width="64" height="19" rx="2"/><rect x="70.5" y="0.5" width="41" height="19" rx="2" fill="#fafafa"/><rect x="70" y="7.5" width="0.5" height="5" stroke="#fafafa"/><path d="M70.5 6.5 l-3 3v1 l3 3" stroke="d5d5d5" fill="#fafafa"/></g><image x="5" y="3" width="14" height="14" xlink:href="data:image/svg+xml;base64,PHN2ZyB4bWxu"/><g aria-hidden="true" fill="#333" text-anchor="middle" font-family="Helvetica Neue,Helvetica,Arial,sans-serif" text-rendering="geometricPrecision" font-weight="700" font-size="110px" line-height="14px"><rect id="llink" stroke="#d5d5d5" fill="url(#a)" x=".5" y=".5" width="64" height="19" rx="2" /><text aria-hidden="true" x="405" y="150" fill="#fff" transform="scale(.1)" textLength="370">Cactus</text><text x="405" y="140" transform="scale(.1)" textLength="370">Cactus</text><text aria-hidden="true" x="905" y="150" fill="#fff" transform="scale(.1)" textLength="330">grown</text><text id="rlink" x="905" y="140" transform="scale(.1)" textLength="330">grown</text></g></svg>
|
||||
`
|
||||
|
||||
exports['The badge generator "social" template badge generation should match snapshots: message only, no logo 1'] = `
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="59" height="20"><style>a #llink:hover{fill:url(#b);stroke:#ccc}a #rlink:hover{fill:#4183c4}</style><linearGradient id="a" x2="0" y2="100%"><stop offset="0" stop-color="#fcfcfc" stop-opacity="0"/><stop offset="1" stop-opacity=".1"/></linearGradient><linearGradient id="b" x2="0" y2="100%"><stop offset="0" stop-color="#ccc" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><g stroke="#d5d5d5"><rect stroke="none" fill="#fcfcfc" x="0.5" y="0.5" width="11" height="19" rx="2"/><rect x="17.5" y="0.5" width="41" height="19" rx="2" fill="#fafafa"/><rect x="17" y="7.5" width="0.5" height="5" stroke="#fafafa"/><path d="M17.5 6.5 l-3 3v1 l3 3" stroke="d5d5d5" fill="#fafafa"/></g><g fill="#333" text-anchor="middle" font-family="Helvetica Neue,Helvetica,Arial,sans-serif" text-rendering="geometricPrecision" font-weight="700" font-size="110px" line-height="14px"><text x="55" y="150" fill="#fff" transform="scale(.1)" textLength="10"></text><text x="55" y="140" transform="scale(.1)" textLength="10"></text><text x="375" y="150" fill="#fff" transform="scale(.1)" textLength="330">grown</text><text id="rlink" x="375" y="140" transform="scale(.1)" textLength="330">grown</text></g><rect id="llink" stroke="#d5d5d5" fill="url(#a)" x=".5" y=".5" width="11" height="19" rx="2" /></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="59" height="20" role="img" aria-label="grown"><title>grown</title><style>a:hover #llink{fill:url(#b);stroke:#ccc}a:hover #rlink{fill:#4183c4}</style><linearGradient id="a" x2="0" y2="100%"><stop offset="0" stop-color="#fcfcfc" stop-opacity="0"/><stop offset="1" stop-opacity=".1"/></linearGradient><linearGradient id="b" x2="0" y2="100%"><stop offset="0" stop-color="#ccc" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><g stroke="#d5d5d5"><rect stroke="none" fill="#fcfcfc" x="0.5" y="0.5" width="11" height="19" rx="2"/><rect x="17.5" y="0.5" width="41" height="19" rx="2" fill="#fafafa"/><rect x="17" y="7.5" width="0.5" height="5" stroke="#fafafa"/><path d="M17.5 6.5 l-3 3v1 l3 3" stroke="d5d5d5" fill="#fafafa"/></g><g aria-hidden="true" fill="#333" text-anchor="middle" font-family="Helvetica Neue,Helvetica,Arial,sans-serif" text-rendering="geometricPrecision" font-weight="700" font-size="110px" line-height="14px"><rect id="llink" stroke="#d5d5d5" fill="url(#a)" x=".5" y=".5" width="11" height="19" rx="2" /><text aria-hidden="true" x="55" y="150" fill="#fff" transform="scale(.1)" textLength="10"></text><text x="55" y="140" transform="scale(.1)" textLength="10"></text><text aria-hidden="true" x="375" y="150" fill="#fff" transform="scale(.1)" textLength="330">grown</text><text id="rlink" x="375" y="140" transform="scale(.1)" textLength="330">grown</text></g></svg>
|
||||
`
|
||||
|
||||
exports['The badge generator "social" template badge generation should match snapshots: message only, with logo 1'] = `
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="73" height="20"><style>a #llink:hover{fill:url(#b);stroke:#ccc}a #rlink:hover{fill:#4183c4}</style><linearGradient id="a" x2="0" y2="100%"><stop offset="0" stop-color="#fcfcfc" stop-opacity="0"/><stop offset="1" stop-opacity=".1"/></linearGradient><linearGradient id="b" x2="0" y2="100%"><stop offset="0" stop-color="#ccc" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><g stroke="#d5d5d5"><rect stroke="none" fill="#fcfcfc" x="0.5" y="0.5" width="25" height="19" rx="2"/><rect x="31.5" y="0.5" width="41" height="19" rx="2" fill="#fafafa"/><rect x="31" y="7.5" width="0.5" height="5" stroke="#fafafa"/><path d="M31.5 6.5 l-3 3v1 l3 3" stroke="d5d5d5" fill="#fafafa"/></g><image x="5" y="3" width="14" height="14" xlink:href="data:image/svg+xml;base64,PHN2ZyB4bWxu"/><g fill="#333" text-anchor="middle" font-family="Helvetica Neue,Helvetica,Arial,sans-serif" text-rendering="geometricPrecision" font-weight="700" font-size="110px" line-height="14px"><text x="195" y="150" fill="#fff" transform="scale(.1)" textLength="10"></text><text x="195" y="140" transform="scale(.1)" textLength="10"></text><text x="515" y="150" fill="#fff" transform="scale(.1)" textLength="330">grown</text><text id="rlink" x="515" y="140" transform="scale(.1)" textLength="330">grown</text></g><rect id="llink" stroke="#d5d5d5" fill="url(#a)" x=".5" y=".5" width="25" height="19" rx="2" /></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="73" height="20" role="img" aria-label="grown"><title>grown</title><style>a:hover #llink{fill:url(#b);stroke:#ccc}a:hover #rlink{fill:#4183c4}</style><linearGradient id="a" x2="0" y2="100%"><stop offset="0" stop-color="#fcfcfc" stop-opacity="0"/><stop offset="1" stop-opacity=".1"/></linearGradient><linearGradient id="b" x2="0" y2="100%"><stop offset="0" stop-color="#ccc" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><g stroke="#d5d5d5"><rect stroke="none" fill="#fcfcfc" x="0.5" y="0.5" width="25" height="19" rx="2"/><rect x="31.5" y="0.5" width="41" height="19" rx="2" fill="#fafafa"/><rect x="31" y="7.5" width="0.5" height="5" stroke="#fafafa"/><path d="M31.5 6.5 l-3 3v1 l3 3" stroke="d5d5d5" fill="#fafafa"/></g><image x="5" y="3" width="14" height="14" xlink:href="data:image/svg+xml;base64,PHN2ZyB4bWxu"/><g aria-hidden="true" fill="#333" text-anchor="middle" font-family="Helvetica Neue,Helvetica,Arial,sans-serif" text-rendering="geometricPrecision" font-weight="700" font-size="110px" line-height="14px"><rect id="llink" stroke="#d5d5d5" fill="url(#a)" x=".5" y=".5" width="25" height="19" rx="2" /><text aria-hidden="true" x="195" y="150" fill="#fff" transform="scale(.1)" textLength="10"></text><text x="195" y="140" transform="scale(.1)" textLength="10"></text><text aria-hidden="true" x="515" y="150" fill="#fff" transform="scale(.1)" textLength="330">grown</text><text id="rlink" x="515" y="140" transform="scale(.1)" textLength="330">grown</text></g></svg>
|
||||
`
|
||||
|
||||
exports['The badge generator "social" template badge generation should match snapshots: message only, with logo and labelColor 1'] = `
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="73" height="20"><style>a #llink:hover{fill:url(#b);stroke:#ccc}a #rlink:hover{fill:#4183c4}</style><linearGradient id="a" x2="0" y2="100%"><stop offset="0" stop-color="#fcfcfc" stop-opacity="0"/><stop offset="1" stop-opacity=".1"/></linearGradient><linearGradient id="b" x2="0" y2="100%"><stop offset="0" stop-color="#ccc" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><g stroke="#d5d5d5"><rect stroke="none" fill="#fcfcfc" x="0.5" y="0.5" width="25" height="19" rx="2"/><rect x="31.5" y="0.5" width="41" height="19" rx="2" fill="#fafafa"/><rect x="31" y="7.5" width="0.5" height="5" stroke="#fafafa"/><path d="M31.5 6.5 l-3 3v1 l3 3" stroke="d5d5d5" fill="#fafafa"/></g><image x="5" y="3" width="14" height="14" xlink:href="data:image/svg+xml;base64,PHN2ZyB4bWxu"/><g fill="#333" text-anchor="middle" font-family="Helvetica Neue,Helvetica,Arial,sans-serif" text-rendering="geometricPrecision" font-weight="700" font-size="110px" line-height="14px"><text x="195" y="150" fill="#fff" transform="scale(.1)" textLength="10"></text><text x="195" y="140" transform="scale(.1)" textLength="10"></text><text x="515" y="150" fill="#fff" transform="scale(.1)" textLength="330">grown</text><text id="rlink" x="515" y="140" transform="scale(.1)" textLength="330">grown</text></g><rect id="llink" stroke="#d5d5d5" fill="url(#a)" x=".5" y=".5" width="25" height="19" rx="2" /></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="73" height="20" role="img" aria-label="grown"><title>grown</title><style>a:hover #llink{fill:url(#b);stroke:#ccc}a:hover #rlink{fill:#4183c4}</style><linearGradient id="a" x2="0" y2="100%"><stop offset="0" stop-color="#fcfcfc" stop-opacity="0"/><stop offset="1" stop-opacity=".1"/></linearGradient><linearGradient id="b" x2="0" y2="100%"><stop offset="0" stop-color="#ccc" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><g stroke="#d5d5d5"><rect stroke="none" fill="#fcfcfc" x="0.5" y="0.5" width="25" height="19" rx="2"/><rect x="31.5" y="0.5" width="41" height="19" rx="2" fill="#fafafa"/><rect x="31" y="7.5" width="0.5" height="5" stroke="#fafafa"/><path d="M31.5 6.5 l-3 3v1 l3 3" stroke="d5d5d5" fill="#fafafa"/></g><image x="5" y="3" width="14" height="14" xlink:href="data:image/svg+xml;base64,PHN2ZyB4bWxu"/><g aria-hidden="true" fill="#333" text-anchor="middle" font-family="Helvetica Neue,Helvetica,Arial,sans-serif" text-rendering="geometricPrecision" font-weight="700" font-size="110px" line-height="14px"><rect id="llink" stroke="#d5d5d5" fill="url(#a)" x=".5" y=".5" width="25" height="19" rx="2" /><text aria-hidden="true" x="195" y="150" fill="#fff" transform="scale(.1)" textLength="10"></text><text x="195" y="140" transform="scale(.1)" textLength="10"></text><text aria-hidden="true" x="515" y="150" fill="#fff" transform="scale(.1)" textLength="330">grown</text><text id="rlink" x="515" y="140" transform="scale(.1)" textLength="330">grown</text></g></svg>
|
||||
`
|
||||
|
||||
exports['The badge generator "social" template badge generation should match snapshots: message/label, with links 1'] = `
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="95" height="20"><style>a #llink:hover{fill:url(#b);stroke:#ccc}a #rlink:hover{fill:#4183c4}</style><linearGradient id="a" x2="0" y2="100%"><stop offset="0" stop-color="#fcfcfc" stop-opacity="0"/><stop offset="1" stop-opacity=".1"/></linearGradient><linearGradient id="b" x2="0" y2="100%"><stop offset="0" stop-color="#ccc" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><g stroke="#d5d5d5"><rect stroke="none" fill="#fcfcfc" x="0.5" y="0.5" width="47" height="19" rx="2"/><rect x="53.5" y="0.5" width="41" height="19" rx="2" fill="#fafafa"/><rect x="53" y="7.5" width="0.5" height="5" stroke="#fafafa"/><path d="M53.5 6.5 l-3 3v1 l3 3" stroke="d5d5d5" fill="#fafafa"/></g><g fill="#333" text-anchor="middle" font-family="Helvetica Neue,Helvetica,Arial,sans-serif" text-rendering="geometricPrecision" font-weight="700" font-size="110px" line-height="14px"><text x="235" y="150" fill="#fff" transform="scale(.1)" textLength="370">Cactus</text><text x="235" y="140" transform="scale(.1)" textLength="370">Cactus</text><text x="735" y="150" fill="#fff" transform="scale(.1)" textLength="330">grown</text><a target="_blank" xlink:href="https://www.google.co.uk/"><text id="rlink" x="735" y="140" transform="scale(.1)" textLength="330">grown</text></a></g><a target="_blank" xlink:href="https://shields.io/"><rect id="llink" stroke="#d5d5d5" fill="url(#a)" x=".5" y=".5" width="47" height="19" rx="2" /></a></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="95" height="20" ><style>a:hover #llink{fill:url(#b);stroke:#ccc}a:hover #rlink{fill:#4183c4}</style><linearGradient id="a" x2="0" y2="100%"><stop offset="0" stop-color="#fcfcfc" stop-opacity="0"/><stop offset="1" stop-opacity=".1"/></linearGradient><linearGradient id="b" x2="0" y2="100%"><stop offset="0" stop-color="#ccc" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><g stroke="#d5d5d5"><rect stroke="none" fill="#fcfcfc" x="0.5" y="0.5" width="47" height="19" rx="2"/><rect x="53.5" y="0.5" width="41" height="19" rx="2" fill="#fafafa"/><rect x="53" y="7.5" width="0.5" height="5" stroke="#fafafa"/><path d="M53.5 6.5 l-3 3v1 l3 3" stroke="d5d5d5" fill="#fafafa"/></g><g aria-hidden="false" fill="#333" text-anchor="middle" font-family="Helvetica Neue,Helvetica,Arial,sans-serif" text-rendering="geometricPrecision" font-weight="700" font-size="110px" line-height="14px"><a target="_blank" xlink:href="https://shields.io/"><text aria-hidden="true" x="235" y="150" fill="#fff" transform="scale(.1)" textLength="370">Cactus</text><text x="235" y="140" transform="scale(.1)" textLength="370">Cactus</text><rect id="llink" stroke="#d5d5d5" fill="url(#a)" x=".5" y=".5" width="47" height="19" rx="2" /></a><a target="_blank" xlink:href="https://www.google.co.uk/"><rect width="42" x="53" height="20" fill="rgba(0,0,0,0)" /><text aria-hidden="true" x="735" y="150" fill="#fff" transform="scale(.1)" textLength="330">grown</text><text id="rlink" x="735" y="140" transform="scale(.1)" textLength="330">grown</text></a></g></svg>
|
||||
`
|
||||
|
||||
exports['The badge generator badges with logos should always produce the same badge badge with logo 1'] = `
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="113" height="20"><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="113" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="54" height="20" fill="#555"/><rect x="54" width="59" height="20" fill="#4c1"/><rect width="113" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><image x="5" y="3" width="14" height="14" xlink:href="data:image/svg+xml;base64,PHN2ZyB4bWxu"/><text x="365" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="270">label</text><text x="365" y="140" transform="scale(.1)" textLength="270">label</text><text x="825" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="490">message</text><text x="825" y="140" transform="scale(.1)" textLength="490">message</text></g></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="113" height="20" role="img" aria-label="label: message"><title>label: message</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="113" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="54" height="20" fill="#555"/><rect x="54" width="59" height="20" fill="#4c1"/><rect width="113" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><image x="5" y="3" width="14" height="14" xlink:href="data:image/svg+xml;base64,PHN2ZyB4bWxu"/><text aria-hidden="true" x="365" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="270">label</text><text x="365" y="140" transform="scale(.1)" fill="#fff" textLength="270">label</text><text aria-hidden="true" x="825" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="490">message</text><text x="825" y="140" transform="scale(.1)" fill="#fff" textLength="490">message</text></g></svg>
|
||||
`
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
lib/make-badge-test-helpers.js
|
||||
lib/**/*.spec.js
|
||||
index.test-d.ts
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
# Changelog
|
||||
|
||||
## 3.2.0
|
||||
|
||||
- Accessibility improvements: Help users of assistive technologies to read the badges when used inline
|
||||
|
||||
## 3.1.0
|
||||
|
||||
- Add TypeScript definitions
|
||||
|
||||
## 3.0.1
|
||||
|
||||
- Fix missing dependency
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
[](https://npmjs.org/package/badge-maker)
|
||||
[](https://npmjs.org/package/badge-maker)
|
||||
[](https://npmjs.org/package/badge-maker)
|
||||
|
||||
## Installation
|
||||
|
||||
@@ -20,9 +21,19 @@ badge build passed :green > mybadge.svg
|
||||
|
||||
### As a library
|
||||
|
||||
With CommonJS in JavaScript,
|
||||
|
||||
```js
|
||||
const { makeBadge, ValidationError } = require('badge-maker')
|
||||
```
|
||||
|
||||
With ESM or TypeScript,
|
||||
|
||||
```ts
|
||||
import { makeBadge, ValidationError } from 'badge-maker'
|
||||
```
|
||||
|
||||
```js
|
||||
const format = {
|
||||
label: 'build',
|
||||
message: 'passed',
|
||||
|
||||
11
badge-maker/index.d.ts
vendored
Normal file
11
badge-maker/index.d.ts
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
interface Format {
|
||||
label?: string
|
||||
message: string
|
||||
labelColor?: string
|
||||
color?: string
|
||||
style?: 'plastic' | 'flat' | 'flat-square' | 'for-the-badge' | 'social'
|
||||
}
|
||||
|
||||
export declare class ValidationError extends Error {}
|
||||
|
||||
export declare function makeBadge(format: Format): string
|
||||
35
badge-maker/index.test-d.ts
Normal file
35
badge-maker/index.test-d.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import { expectType, expectError, expectAssignable } from 'tsd'
|
||||
import { makeBadge, ValidationError } from '.'
|
||||
|
||||
expectError(makeBadge('string is invalid'))
|
||||
expectError(makeBadge({}))
|
||||
expectError(
|
||||
makeBadge({
|
||||
message: 'passed',
|
||||
style: 'invalid style',
|
||||
})
|
||||
)
|
||||
|
||||
expectType<string>(
|
||||
makeBadge({
|
||||
message: 'passed',
|
||||
})
|
||||
)
|
||||
expectType<string>(
|
||||
makeBadge({
|
||||
label: 'build',
|
||||
message: 'passed',
|
||||
})
|
||||
)
|
||||
expectType<string>(
|
||||
makeBadge({
|
||||
label: 'build',
|
||||
message: 'passed',
|
||||
labelColor: 'green',
|
||||
color: 'red',
|
||||
style: 'flat',
|
||||
})
|
||||
)
|
||||
|
||||
const error = new ValidationError()
|
||||
expectAssignable<Error>(error)
|
||||
@@ -39,6 +39,34 @@ function computeWidths({ label, message }) {
|
||||
}
|
||||
}
|
||||
|
||||
function createAccessibleText({ label, message }) {
|
||||
const labelPrefix = label ? `${label}: ` : ''
|
||||
return labelPrefix + message
|
||||
}
|
||||
|
||||
function hasLinks({ links }) {
|
||||
const [leftLink, rightLink] = links || []
|
||||
const hasLeftLink = leftLink && leftLink.length
|
||||
const hasRightLink = rightLink && rightLink.length
|
||||
const hasLink = hasLeftLink && hasRightLink
|
||||
return { hasLink, hasLeftLink, hasRightLink }
|
||||
}
|
||||
|
||||
function shouldWrapBodyWithLink({ links }) {
|
||||
const { hasLeftLink, hasRightLink } = hasLinks({ links })
|
||||
return hasLeftLink && !hasRightLink
|
||||
}
|
||||
|
||||
function renderAriaAttributes({ accessibleText, links }) {
|
||||
const { hasLink } = hasLinks({ links })
|
||||
return hasLink ? '' : `role="img" aria-label="${escapeXml(accessibleText)}"`
|
||||
}
|
||||
|
||||
function renderTitle({ accessibleText, links }) {
|
||||
const { hasLink } = hasLinks({ links })
|
||||
return hasLink ? '' : `<title>${escapeXml(accessibleText)}</title>`
|
||||
}
|
||||
|
||||
function renderLogo({
|
||||
logo,
|
||||
badgeHeight,
|
||||
@@ -65,10 +93,29 @@ function renderLogo({
|
||||
}
|
||||
}
|
||||
|
||||
function renderLink({
|
||||
link,
|
||||
height,
|
||||
textLength,
|
||||
horizPadding,
|
||||
leftMargin,
|
||||
renderedText,
|
||||
}) {
|
||||
const rectHeight = height
|
||||
const rectWidth = textLength + horizPadding * 2
|
||||
const rectX = leftMargin > 1 ? leftMargin + 1 : 0
|
||||
return `<a target="_blank" xlink:href="${escapeXml(link)}">
|
||||
<rect width="${rectWidth}" x="${rectX}" height="${rectHeight}" fill="rgba(0,0,0,0)" />
|
||||
${renderedText}
|
||||
</a>`
|
||||
}
|
||||
|
||||
function renderText({
|
||||
leftMargin,
|
||||
horizPadding = 0,
|
||||
content,
|
||||
link,
|
||||
height,
|
||||
verticalMargin = 0,
|
||||
shadow = false,
|
||||
}) {
|
||||
@@ -87,46 +134,43 @@ function renderText({
|
||||
|
||||
let renderedText = ''
|
||||
if (shadow) {
|
||||
renderedText = `<text x="${x}" y="${shadowMargin}" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="${outTextLength}">${escapedContent}</text>`
|
||||
renderedText = `<text aria-hidden="true" x="${x}" y="${shadowMargin}" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="${outTextLength}">${escapedContent}</text>`
|
||||
}
|
||||
renderedText += `<text x="${x}" y="${textMargin}" transform="scale(.1)" textLength="${outTextLength}">${escapedContent}</text>`
|
||||
renderedText += `<text x="${x}" y="${textMargin}" transform="scale(.1)" fill="#fff" textLength="${outTextLength}">${escapedContent}</text>`
|
||||
|
||||
return {
|
||||
renderedText,
|
||||
renderedText: link
|
||||
? renderLink({
|
||||
link,
|
||||
height,
|
||||
textLength,
|
||||
horizPadding,
|
||||
leftMargin,
|
||||
renderedText,
|
||||
})
|
||||
: renderedText,
|
||||
width: textLength,
|
||||
}
|
||||
}
|
||||
|
||||
function renderLinks({
|
||||
links: [leftLink, rightLink] = [],
|
||||
leftWidth,
|
||||
rightWidth,
|
||||
height,
|
||||
}) {
|
||||
leftLink = escapeXml(leftLink)
|
||||
rightLink = escapeXml(rightLink)
|
||||
const hasLeftLink = leftLink && leftLink.length
|
||||
const hasRightLink = rightLink && rightLink.length
|
||||
const leftLinkWidth = hasRightLink ? leftWidth : leftWidth + rightWidth
|
||||
|
||||
function render({ link, width }) {
|
||||
return `<a target="_blank" xlink:href="${link}"><rect width="${width}" height="${height}" fill="rgba(0,0,0,0)"/></a>`
|
||||
}
|
||||
|
||||
return (
|
||||
(hasRightLink
|
||||
? render({ link: rightLink, width: leftWidth + rightWidth })
|
||||
: '') +
|
||||
(hasLeftLink ? render({ link: leftLink, width: leftLinkWidth }) : '')
|
||||
)
|
||||
}
|
||||
|
||||
function renderBadge({ links, leftWidth, rightWidth, height }, main) {
|
||||
function renderBadge(
|
||||
{ links, leftWidth, rightWidth, height, accessibleText },
|
||||
main
|
||||
) {
|
||||
const width = leftWidth + rightWidth
|
||||
const leftLink = escapeXml(links[0])
|
||||
|
||||
return `
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="${width}" height="${height}">
|
||||
${main}
|
||||
${renderLinks({ links, leftWidth, rightWidth, height })}
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="${width}" height="${height}" ${renderAriaAttributes(
|
||||
{ links, accessibleText }
|
||||
)}>
|
||||
|
||||
${renderTitle({ accessibleText, links })}
|
||||
${
|
||||
shouldWrapBodyWithLink({ links })
|
||||
? `<a target="_blank" xlink:href="${leftLink}">${main}</a>`
|
||||
: main
|
||||
}
|
||||
</svg>`
|
||||
}
|
||||
|
||||
@@ -174,6 +218,8 @@ class Badge {
|
||||
labelColor = '#555'
|
||||
}
|
||||
|
||||
const [leftLink, rightLink] = links
|
||||
|
||||
labelColor = hasLabel || hasLogo ? labelColor : color
|
||||
labelColor = escapeXml(labelColor)
|
||||
color = escapeXml(color)
|
||||
@@ -184,6 +230,8 @@ class Badge {
|
||||
leftMargin: labelMargin,
|
||||
horizPadding,
|
||||
content: label,
|
||||
link: !shouldWrapBodyWithLink({ links }) && leftLink,
|
||||
height: this.constructor.height,
|
||||
verticalMargin: this.constructor.verticalMargin,
|
||||
shadow: this.constructor.shadow,
|
||||
})
|
||||
@@ -205,6 +253,8 @@ class Badge {
|
||||
leftMargin: messageMargin,
|
||||
horizPadding,
|
||||
content: message,
|
||||
link: rightLink,
|
||||
height: this.constructor.height,
|
||||
verticalMargin: this.constructor.verticalMargin,
|
||||
shadow: this.constructor.shadow,
|
||||
})
|
||||
@@ -216,12 +266,17 @@ class Badge {
|
||||
|
||||
const width = leftWidth + rightWidth
|
||||
|
||||
const accessibleText = createAccessibleText({ label, message })
|
||||
|
||||
this.links = links
|
||||
this.leftWidth = leftWidth
|
||||
this.rightWidth = rightWidth
|
||||
this.width = width
|
||||
this.labelColor = labelColor
|
||||
this.color = color
|
||||
this.label = label
|
||||
this.message = message
|
||||
this.accessibleText = accessibleText
|
||||
this.renderedLogo = renderedLogo
|
||||
this.renderedLabel = renderedLabel
|
||||
this.renderedMessage = renderedMessage
|
||||
@@ -255,6 +310,7 @@ class Plastic extends Badge {
|
||||
links: this.links,
|
||||
leftWidth: this.leftWidth,
|
||||
rightWidth: this.rightWidth,
|
||||
accessibleText: this.accessibleText,
|
||||
height: this.constructor.height,
|
||||
},
|
||||
`
|
||||
@@ -307,6 +363,7 @@ class Flat extends Badge {
|
||||
links: this.links,
|
||||
leftWidth: this.leftWidth,
|
||||
rightWidth: this.rightWidth,
|
||||
accessibleText: this.accessibleText,
|
||||
height: this.constructor.height,
|
||||
},
|
||||
`
|
||||
@@ -357,6 +414,7 @@ class FlatSquare extends Badge {
|
||||
links: this.links,
|
||||
leftWidth: this.leftWidth,
|
||||
rightWidth: this.rightWidth,
|
||||
accessibleText: this.accessibleText,
|
||||
height: this.constructor.height,
|
||||
},
|
||||
`
|
||||
@@ -437,8 +495,9 @@ function social({
|
||||
let [leftLink, rightLink] = links
|
||||
leftLink = escapeXml(leftLink)
|
||||
rightLink = escapeXml(rightLink)
|
||||
const hasLeftLink = leftLink && leftLink.length
|
||||
const hasRightLink = rightLink && rightLink.length
|
||||
const { hasLeftLink, hasRightLink, hasLink } = hasLinks({ links })
|
||||
|
||||
const accessibleText = createAccessibleText({ label, message })
|
||||
|
||||
function renderMessageBubble() {
|
||||
const messageBubbleMainX = labelWidth + 6.5
|
||||
@@ -450,16 +509,42 @@ function social({
|
||||
`
|
||||
}
|
||||
|
||||
function renderLabelText() {
|
||||
const rect = `<rect id="llink" stroke="#d5d5d5" fill="url(#a)" x=".5" y=".5" width="${labelWidth}" height="${internalHeight}" rx="2" />`
|
||||
const shadow = `<text aria-hidden="true" x="${labelTextX}" y="150" fill="#fff" transform="scale(.1)" textLength="${labelTextLength}">${escapedLabel}</text>`
|
||||
const text = `<text x="${labelTextX}" y="140" transform="scale(.1)" textLength="${labelTextLength}">${escapedLabel}</text>`
|
||||
if (hasLeftLink && !shouldWrapBodyWithLink({ links })) {
|
||||
return `
|
||||
<a target="_blank" xlink:href="${leftLink}">
|
||||
${shadow}
|
||||
${text}
|
||||
${rect}
|
||||
</a>
|
||||
`
|
||||
}
|
||||
return `
|
||||
${rect}
|
||||
${shadow}
|
||||
${text}
|
||||
`
|
||||
}
|
||||
|
||||
function renderMessageText() {
|
||||
const messageTextX = (labelWidth + messageWidth / 2 + 6) * 10
|
||||
const messageTextLength = (messageWidth - 8) * 10
|
||||
const escapedMessage = escapeXml(message)
|
||||
const shadow = `<text x="${messageTextX}" y="150" fill="#fff" transform="scale(.1)" textLength="${messageTextLength}">${escapedMessage}</text>`
|
||||
const rect = `<rect width="${messageWidth + 1}" x="${
|
||||
labelWidth + 6
|
||||
}" height="${internalHeight + 1}" fill="rgba(0,0,0,0)" />`
|
||||
const shadow = `<text aria-hidden="true" x="${messageTextX}" y="150" fill="#fff" transform="scale(.1)" textLength="${messageTextLength}">${escapedMessage}</text>`
|
||||
const text = `<text id="rlink" x="${messageTextX}" y="140" transform="scale(.1)" textLength="${messageTextLength}">${escapedMessage}</text>`
|
||||
if (hasRightLink) {
|
||||
return `
|
||||
${shadow}
|
||||
<a target="_blank" xlink:href="${rightLink}">${text}</a>
|
||||
<a target="_blank" xlink:href="${rightLink}">
|
||||
${rect}
|
||||
${shadow}
|
||||
${text}
|
||||
</a>
|
||||
`
|
||||
}
|
||||
return `
|
||||
@@ -468,23 +553,16 @@ function social({
|
||||
`
|
||||
}
|
||||
|
||||
function renderLeftLink() {
|
||||
const rect = `<rect id="llink" stroke="#d5d5d5" fill="url(#a)" x=".5" y=".5" width="${labelWidth}" height="${internalHeight}" rx="2" />`
|
||||
if (hasLeftLink) {
|
||||
return `<a target="_blank" xlink:href="${leftLink}">${rect}</a>`
|
||||
}
|
||||
return rect
|
||||
}
|
||||
|
||||
const badge = renderBadge(
|
||||
{
|
||||
links: [],
|
||||
links,
|
||||
leftWidth: labelWidth + 1,
|
||||
rightWidth: hasMessage ? messageWidth + 6 : 0,
|
||||
accessibleText,
|
||||
height: externalHeight,
|
||||
},
|
||||
`
|
||||
<style>a #llink:hover{fill:url(#b);stroke:#ccc}a #rlink:hover{fill:#4183c4}</style>
|
||||
<style>a:hover #llink{fill:url(#b);stroke:#ccc}a:hover #rlink{fill:#4183c4}</style>
|
||||
<linearGradient id="a" x2="0" y2="100%">
|
||||
<stop offset="0" stop-color="#fcfcfc" stop-opacity="0"/>
|
||||
<stop offset="1" stop-opacity=".1"/>
|
||||
@@ -498,12 +576,10 @@ function social({
|
||||
${hasMessage ? renderMessageBubble() : ''}
|
||||
</g>
|
||||
${renderedLogo}
|
||||
<g fill="#333" text-anchor="middle" ${socialFontFamily} text-rendering="geometricPrecision" font-weight="700" font-size="110px" line-height="14px">
|
||||
<text x="${labelTextX}" y="150" fill="#fff" transform="scale(.1)" textLength="${labelTextLength}">${escapedLabel}</text>
|
||||
<text x="${labelTextX}" y="140" transform="scale(.1)" textLength="${labelTextLength}">${escapedLabel}</text>
|
||||
<g aria-hidden="${!hasLink}" fill="#333" text-anchor="middle" ${socialFontFamily} text-rendering="geometricPrecision" font-weight="700" font-size="110px" line-height="14px">
|
||||
${renderLabelText()}
|
||||
${hasMessage ? renderMessageText() : ''}
|
||||
</g>
|
||||
${renderLeftLink()}
|
||||
`
|
||||
)
|
||||
|
||||
@@ -568,13 +644,45 @@ function forTheBadge({
|
||||
color = escapeXml(color)
|
||||
labelColor = escapeXml(labelColor)
|
||||
|
||||
let [leftLink, rightLink] = links
|
||||
leftLink = escapeXml(leftLink)
|
||||
rightLink = escapeXml(rightLink)
|
||||
const { hasLeftLink, hasRightLink } = hasLinks({ links })
|
||||
|
||||
const accessibleText = createAccessibleText({ label, message })
|
||||
|
||||
function renderLabelText() {
|
||||
const labelTextX = ((labelWidth + totalLogoWidth) / 2) * 10
|
||||
const labelTextLength = (labelWidth - (24 + totalLogoWidth)) * 10
|
||||
const escapedLabel = escapeXml(label)
|
||||
return `
|
||||
<text x="${labelTextX}" y="175" transform="scale(.1)" textLength="${labelTextLength}">${escapedLabel}</text>
|
||||
`
|
||||
const text = `<text fill="#fff" x="${labelTextX}" y="175" transform="scale(.1)" textLength="${labelTextLength}">${escapedLabel}</text>`
|
||||
if (hasLeftLink && !shouldWrapBodyWithLink({ links })) {
|
||||
return `
|
||||
<a target="_blank" xlink:href="${leftLink}">
|
||||
<rect width="${leftWidth}" height="${height}" fill="rgba(0,0,0,0)"/>
|
||||
${text}
|
||||
</a>
|
||||
`
|
||||
}
|
||||
return text
|
||||
}
|
||||
|
||||
function renderMessageText() {
|
||||
const text = `<text fill="#fff" x="${
|
||||
(labelWidth + messageWidth / 2) * 10
|
||||
}" y="175" font-weight="bold" transform="scale(.1)" textLength="${
|
||||
(messageWidth - 24) * 10
|
||||
}">
|
||||
${escapeXml(message)}</text>`
|
||||
if (hasRightLink) {
|
||||
return `
|
||||
<a target="_blank" xlink:href="${rightLink}">
|
||||
<rect width="${rightWidth}" height="${height}" x="${labelWidth}" fill="rgba(0,0,0,0)"/>
|
||||
${text}
|
||||
</a>
|
||||
`
|
||||
}
|
||||
return text
|
||||
}
|
||||
|
||||
const badge = renderBadge(
|
||||
@@ -582,6 +690,7 @@ function forTheBadge({
|
||||
links,
|
||||
leftWidth,
|
||||
rightWidth,
|
||||
accessibleText,
|
||||
height,
|
||||
},
|
||||
`
|
||||
@@ -592,12 +701,7 @@ function forTheBadge({
|
||||
<g fill="#fff" text-anchor="middle" ${fontFamily} text-rendering="geometricPrecision" font-size="100">
|
||||
${renderedLogo}
|
||||
${hasLabel ? renderLabelText() : ''}
|
||||
<text x="${
|
||||
(labelWidth + messageWidth / 2) * 10
|
||||
}" y="175" font-weight="bold" transform="scale(.1)" textLength="${
|
||||
(messageWidth - 24) * 10
|
||||
}">
|
||||
${escapeXml(message)}</text>
|
||||
${renderMessageText()}
|
||||
</g>`
|
||||
)
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "badge-maker",
|
||||
"version": "3.0.1",
|
||||
"version": "3.2.0",
|
||||
"description": "Shields.io badge library",
|
||||
"keywords": [
|
||||
"GitHub",
|
||||
@@ -9,6 +9,7 @@
|
||||
"image",
|
||||
"shields.io"
|
||||
],
|
||||
"types": "index.d.ts",
|
||||
"main": "lib/index.js",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -35,7 +36,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"anafanafo": "^1.0.0",
|
||||
"camelcase": "^5.3.1",
|
||||
"camelcase": "^6.0.0",
|
||||
"is-css-color": "^1.0.0"
|
||||
},
|
||||
"scripts": {
|
||||
|
||||
@@ -98,3 +98,4 @@ private:
|
||||
wheelmap_token: 'WHEELMAP_TOKEN'
|
||||
influx_username: 'INFLUX_USERNAME'
|
||||
influx_password: 'INFLUX_PASSWORD'
|
||||
youtube_api_key: 'YOUTUBE_API_KEY'
|
||||
|
||||
@@ -10,3 +10,4 @@ private:
|
||||
twitch_client_id: ...
|
||||
twitch_client_secret: ...
|
||||
wheelmap_token: ...
|
||||
youtube_api_key: ...
|
||||
|
||||
@@ -8,3 +8,4 @@ private:
|
||||
twitch_client_id: '...'
|
||||
twitch_client_secret: '...'
|
||||
wheelmap_token: '...'
|
||||
youtube_api_key: '...'
|
||||
|
||||
@@ -114,7 +114,7 @@ class BaseService {
|
||||
* credentials to the request. For example:
|
||||
* - `{ options: { auth: this.authHelper.basicAuth } }`
|
||||
* - `{ options: { headers: this.authHelper.bearerAuthHeader } }`
|
||||
* - `{ options: { qs: { token: this.authHelper.pass } } }`
|
||||
* - `{ options: { qs: { token: this.authHelper._pass } } }`
|
||||
*
|
||||
* @abstract
|
||||
* @type {module:core/base-service/base~Auth}
|
||||
|
||||
@@ -20,12 +20,12 @@ function setRoutes({ rateLimit }, { server, metricInstance }) {
|
||||
const ipRateLimit = new RateLimit({
|
||||
// Exclude IPs for GitHub Camo, determined experimentally by running e.g.
|
||||
// `curl --insecure -u ":shields-secret" https://s0.shields-server.com/sys/rate-limit`
|
||||
whitelist: /^(?:192\.30\.252\.\d+)|(?:140\.82\.115\.\d+)$/,
|
||||
safelist: /^(?:192\.30\.252\.\d+)|(?:140\.82\.115\.\d+)$/,
|
||||
})
|
||||
const badgeTypeRateLimit = new RateLimit({ maxHitsPerPeriod: 3000 })
|
||||
const refererRateLimit = new RateLimit({
|
||||
maxHitsPerPeriod: 300,
|
||||
whitelist: /^https?:\/\/shields\.io\/$/,
|
||||
safelist: /^https?:\/\/shields\.io\/$/,
|
||||
})
|
||||
|
||||
server.handle((req, res, next) => {
|
||||
|
||||
@@ -10,7 +10,7 @@ module.exports = class RateLimit {
|
||||
this.maxHitsPerPeriod = options.maxHitsPerPeriod || 500
|
||||
this.banned = new Set()
|
||||
this.bannedUrls = new Set()
|
||||
this.whitelist = options.whitelist || /(?!)/ // Matches nothing by default.
|
||||
this.safelist = options.safelist || /(?!)/ // Matches nothing by default.
|
||||
this.interval = setInterval(this.resetHits.bind(this), this.period * 1000)
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ module.exports = class RateLimit {
|
||||
const hitsInCurrentPeriod = this.hits.get(reqParam) || 0
|
||||
if (
|
||||
reqParam != null &&
|
||||
!this.whitelist.test(reqParam) &&
|
||||
!this.safelist.test(reqParam) &&
|
||||
hitsInCurrentPeriod > this.maxHitsPerPeriod
|
||||
) {
|
||||
this.banned.add(reqParam)
|
||||
|
||||
@@ -180,6 +180,7 @@ const privateConfigSchema = Joi.object({
|
||||
wheelmap_token: Joi.string(),
|
||||
influx_username: Joi.string(),
|
||||
influx_password: Joi.string(),
|
||||
youtube_api_key: Joi.string(),
|
||||
}).required()
|
||||
const privateMetricsInfluxConfigSchema = privateConfigSchema.append({
|
||||
influx_username: Joi.string().required(),
|
||||
|
||||
@@ -151,7 +151,7 @@ Description of the code:
|
||||
number of named parameters. These are converted into
|
||||
regular expressions by [`path-to-regexp`][path-to-regexp].
|
||||
Because a service instance won't be created until it's time to handle a request, the route and other metadata must be obtained by examining the classes themselves. [That's why they're marked `static`.][static]
|
||||
- There is additional documentation on conventions for [designing badge URLs](badge-urls)
|
||||
- There is additional documentation on conventions for [designing badge URLs](./badge-urls.md)
|
||||
6. All badges must implement the `async handle()` function that receives parameters to render the badge. Parameters of `handle()` will match the name defined in `route()` Because we're capturing a single variable called `text` our function signature is `async handle({ text })`. `async` is needed to let JavaScript do other things while we are waiting for result from external API. Although in this simple case, we don't make any external calls. Our `handle()` function should return an object with 3 properties:
|
||||
- `label`: the text on the left side of the badge
|
||||
- `message`: the text on the right side of the badge - here we are passing through the parameter we captured in the route regex
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
# Production hosting
|
||||
|
||||
Production hosting is managed by the Shields ops team:
|
||||
|
||||
- [calebcartwright](https://github.com/calebcartwright)
|
||||
- [chris48s](https://github.com/chris48s)
|
||||
- [paulmelnikow](https://github.com/paulmelnikow)
|
||||
- [PyvesB](https://github.com/PyvesB)
|
||||
|
||||
[][operations issues]
|
||||
|
||||
[#ops chat room][ops discord]
|
||||
@@ -9,21 +16,25 @@
|
||||
|
||||
| Component | Subcomponent | People with access |
|
||||
| ----------------------------- | ------------------------------- | ------------------------------------------------------------------------------------------ |
|
||||
| Badge servers | Account owner | @espadrine |
|
||||
| Badge servers | ssh, logs | @espadrine |
|
||||
| Badge servers | Deployment | @espadrine, @paulmelnikow |
|
||||
| Badge servers | Admin endpoints | @espadrine, @paulmelnikow |
|
||||
| shields-production-us | Account owner | @paulmelnikow |
|
||||
| shields-production-us | Full access | @calebcartwright, @chris48s, @paulmelnikow, @pyvesb |
|
||||
| shields-production-us | Access management | @calebcartwright, @chris48s, @paulmelnikow, @pyvesb |
|
||||
| Compose.io Redis | Account owner | @paulmelnikow |
|
||||
| Compose.io Redis | Account access | @paulmelnikow |
|
||||
| Compose.io Redis | Database connection credentials | @espadrine, @paulmelnikow |
|
||||
| Compose.io Redis | Database connection credentials | @calebcartwright, @chris48s, @paulmelnikow, @pyvesb |
|
||||
| Zeit Now | Team owner | @paulmelnikow |
|
||||
| Zeit Now | Team members | @paulmelnikow, @chris48s, @calebcartwright, @platan |
|
||||
| Raster server | Full access as team members | @paulmelnikow, @chris48s, @calebcartwright, @platan |
|
||||
| shields-server.com redirector | Full access as team members | @paulmelnikow, @chris48s, @calebcartwright, @platan |
|
||||
| Cloudflare | Account owner | @espadrine |
|
||||
| Cloudflare | Admin access | @espadrine, @paulmelnikow |
|
||||
| GitHub | OAuth app | @espadrine ([could be transferred to the badges org][oauth transfer]) |
|
||||
| Legacy badge servers | Account owner | @espadrine |
|
||||
| Legacy badge servers | ssh, logs | @espadrine |
|
||||
| Legacy badge servers | Deployment | @espadrine, @paulmelnikow |
|
||||
| Legacy badge servers | Admin endpoints | @espadrine, @paulmelnikow |
|
||||
| Cloudflare (CDN) | Account owner | @espadrine |
|
||||
| Cloudflare (CDN) | Access management | @espadrine |
|
||||
| Cloudflare (CDN) | Admin access | @calebcartwright, @chris48s, @espadrine, @paulmelnikow, @PyvesB |
|
||||
| Twitch | OAuth app | @PyvesB |
|
||||
| YouTube | Account owner | @PyvesB |
|
||||
| OpenStreetMap (for Wheelmap) | Account owner | @paulmelnikow |
|
||||
| DNS | Account owner | @olivierlacan |
|
||||
| DNS | Read-only account access | @espadrine, @paulmelnikow, @chris48s |
|
||||
@@ -52,7 +63,6 @@ Shields has mercifully little persistent state:
|
||||
[github auth admin endpoint]: https://github.com/badges/shields/blob/master/services/github/auth/admin.js
|
||||
[request cache]: https://github.com/badges/shields/blob/master/core/base-service/legacy-request-handler.js#L29-L30
|
||||
[regular-update cache]: https://github.com/badges/shields/blob/master/core/legacy/regular-update.js
|
||||
[oauth transfer]: https://developer.github.com/apps/managing-oauth-apps/transferring-ownership-of-an-oauth-app/
|
||||
|
||||
## Configuration
|
||||
|
||||
|
||||
@@ -228,6 +228,16 @@ displayed on your profile page.
|
||||
|
||||
[wheelmap token]: http://classic.wheelmap.org/en/users/sign_in
|
||||
|
||||
### YouTube
|
||||
|
||||
- `YOUTUBE_API_KEY` (yml: `private.youtube_api_key`)
|
||||
|
||||
The YouTube API requires authentication. To obtain an API key,
|
||||
log in to a Google account, go to the [credentials page][youtube credentials],
|
||||
and create an API key for the YouTube Data API v3.
|
||||
|
||||
[youtube credentials]: https://console.developers.google.com/apis/credentials
|
||||
|
||||
## Error reporting
|
||||
|
||||
- `SENTRY_DSN` (yml: `private.sentry_dsn`)
|
||||
|
||||
@@ -86,7 +86,7 @@ export function constructPath({
|
||||
namedParams: { [k: string]: string }
|
||||
}): { path: string; isComplete: boolean } {
|
||||
let isComplete = true
|
||||
const path = tokens
|
||||
let path = tokens
|
||||
.map(token => {
|
||||
if (typeof token === 'string') {
|
||||
return token.trim()
|
||||
@@ -104,6 +104,7 @@ export function constructPath({
|
||||
}
|
||||
})
|
||||
.join('')
|
||||
path = encodeURI(path)
|
||||
return { path, isComplete }
|
||||
}
|
||||
|
||||
|
||||
@@ -28,6 +28,8 @@ const inputs = [
|
||||
|
||||
export default function DynamicBadgeMaker({
|
||||
baseUrl = document.location.href,
|
||||
}: {
|
||||
baseUrl: string
|
||||
}): JSX.Element {
|
||||
const [values, setValues] = useState<State>({
|
||||
datatype: '',
|
||||
|
||||
@@ -73,6 +73,7 @@ export default function Footer({ baseUrl }: { baseUrl: string }): JSX.Element {
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<SpacedA href="/community">Community</SpacedA>
|
||||
<SpacedA href="https://status.shields.io/">Status</SpacedA>
|
||||
<SpacedA href="https://metrics.shields.io">Metrics</SpacedA>
|
||||
<SpacedA href="https://github.com/badges/shields">GitHub</SpacedA>
|
||||
|
||||
@@ -7,6 +7,8 @@ type State = Record<StateKey, string>
|
||||
|
||||
export default function StaticBadgeMaker({
|
||||
baseUrl = document.location.href,
|
||||
}: {
|
||||
baseUrl: string
|
||||
}): JSX.Element {
|
||||
const [values, setValues] = useState<State>({
|
||||
label: '',
|
||||
|
||||
129
frontend/pages/community.tsx
Normal file
129
frontend/pages/community.tsx
Normal file
@@ -0,0 +1,129 @@
|
||||
import React from 'react'
|
||||
import styled from 'styled-components'
|
||||
import { baseUrl } from '../constants'
|
||||
import Meta from '../components/meta'
|
||||
import Header from '../components/header'
|
||||
import Footer from '../components/footer'
|
||||
import { BaseFont, GlobalStyle, H3 } from '../components/common'
|
||||
|
||||
const MainContainer = styled(BaseFont)`
|
||||
text-align: center;
|
||||
`
|
||||
|
||||
const SponsorContainer = styled.div`
|
||||
display: block;
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
text-align: left;
|
||||
padding-top: 20px;
|
||||
`
|
||||
|
||||
export default function SponsorsPage(): JSX.Element {
|
||||
return (
|
||||
<MainContainer>
|
||||
<GlobalStyle />
|
||||
<Meta />
|
||||
<Header />
|
||||
<H3>Community</H3>
|
||||
|
||||
<SponsorContainer>
|
||||
Shields.io is possible thanks to the people and companies who donate
|
||||
money, services or time to keep the project running.
|
||||
</SponsorContainer>
|
||||
|
||||
<SponsorContainer>
|
||||
<h4>Sponsors</h4>
|
||||
❤️ These companies help us by donating their services to shields:
|
||||
<ul style={{ listStyleType: 'none' }}>
|
||||
<li>
|
||||
<a href="https://www.heroku.com/">
|
||||
<img
|
||||
alt="heroku logo"
|
||||
height="80"
|
||||
src="/images/heroku-logotype-horizontal-purple.svg"
|
||||
/>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://nodeping.com/">
|
||||
<img alt="nodeping logo" height="80" src="/images/nodeping.svg" />
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://sentry.io/">
|
||||
<img
|
||||
alt="sentry logo"
|
||||
height="80"
|
||||
src="/images/sentry-logo-black.svg"
|
||||
/>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
💵 These organisations help keep shields running by donating on
|
||||
OpenCollective. Your organisation can support this project by{' '}
|
||||
<a href="https://opencollective.com/shields#sponsor">
|
||||
becoming a sponsor
|
||||
</a>
|
||||
. Your logo will show up here with a link to your website.
|
||||
<p>
|
||||
<object data="https://opencollective.com/shields/sponsors.svg?avatarHeight=80&width=600" />
|
||||
</p>
|
||||
</SponsorContainer>
|
||||
|
||||
<SponsorContainer>
|
||||
<h4>Backers</h4>
|
||||
💵 Thank you to all our backers who help keep shields running by
|
||||
donating on OpenCollective. You can support this project by{' '}
|
||||
<a href="https://opencollective.com/shields#backer">
|
||||
becoming a backer
|
||||
</a>
|
||||
.
|
||||
<p>
|
||||
<object data="https://opencollective.com/shields/backers.svg?width=600" />
|
||||
</p>
|
||||
</SponsorContainer>
|
||||
|
||||
<SponsorContainer>
|
||||
<h4>Contributors</h4>
|
||||
🙏 This project exists thanks to all the nice people who contribute
|
||||
their time to work on the project.
|
||||
<p>
|
||||
<object data="https://opencollective.com/shields/contributors.svg?width=600" />
|
||||
</p>
|
||||
</SponsorContainer>
|
||||
|
||||
<SponsorContainer>
|
||||
✨ Shields is helped by these companies which provide a free plan for
|
||||
their product or service:
|
||||
<ul>
|
||||
<li>
|
||||
<a href="https://coveralls.io/">Coveralls</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://circleci.com/">CircleCI</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://www.cloudflare.com/">Cloudflare</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://discord.com/">Discord</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://github.com/">GitHub</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://lgtm.com/">LGTM</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://www.netlify.com/">Netlify</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://uptimerobot.com/">Uptime Robot</a>
|
||||
</li>
|
||||
</ul>
|
||||
</SponsorContainer>
|
||||
|
||||
<Footer baseUrl={baseUrl} />
|
||||
</MainContainer>
|
||||
)
|
||||
}
|
||||
@@ -43,7 +43,7 @@ const JsonExampleBlock = styled.code<JsonExampleBlockProps>`
|
||||
white-space: pre;
|
||||
`
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any, react/prop-types
|
||||
function JsonExample({ data }: { [k: string]: any }): JSX.Element {
|
||||
return (
|
||||
<JsonExampleBlock>{JSON.stringify(data, undefined, 2)}</JsonExampleBlock>
|
||||
|
||||
10773
package-lock.json
generated
10773
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
78
package.json
78
package.json
@@ -23,12 +23,12 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@hapi/joi": "^17.1.1",
|
||||
"@sentry/node": "^5.15.5",
|
||||
"@sentry/node": "^5.18.1",
|
||||
"bytes": "^3.1.0",
|
||||
"camelcase": "^5.3.1",
|
||||
"@shields_io/camp": "^18.0.0",
|
||||
"chai-as-promised": "^7.1.1",
|
||||
"chalk": "^3.0.0",
|
||||
"chalk": "^4.1.0",
|
||||
"check-node-version": "^4.0.3",
|
||||
"chrome-web-store-item-property": "~1.2.0",
|
||||
"config": "^3.3.1",
|
||||
@@ -37,30 +37,30 @@
|
||||
"dotenv": "^8.2.0",
|
||||
"emojic": "^1.1.15",
|
||||
"escape-string-regexp": "^4.0.0",
|
||||
"fast-xml-parser": "^3.17.3",
|
||||
"fast-xml-parser": "^3.17.4",
|
||||
"fsos": "^1.1.6",
|
||||
"badge-maker": "file:badge-maker",
|
||||
"glob": "^7.1.6",
|
||||
"graphql": "^14.6.0",
|
||||
"graphql-tag": "^2.10.3",
|
||||
"ioredis": "4.17.1",
|
||||
"graphql": "^14.7.0",
|
||||
"graphql-tag": "^2.10.4",
|
||||
"ioredis": "4.17.3",
|
||||
"joi-extension-semver": "4.1.1",
|
||||
"js-yaml": "^3.14.0",
|
||||
"jsonpath": "~1.0.2",
|
||||
"lodash.countby": "^4.6.0",
|
||||
"lodash.groupby": "^4.6.0",
|
||||
"lodash.times": "^4.3.2",
|
||||
"moment": "^2.26.0",
|
||||
"moment": "^2.27.0",
|
||||
"node-env-flag": "^0.1.0",
|
||||
"parse-link-header": "^1.0.1",
|
||||
"path-to-regexp": "^5.0.0",
|
||||
"pretty-bytes": "^5.3.0",
|
||||
"priorityqueuejs": "^2.0.0",
|
||||
"prom-client": "^11.5.3",
|
||||
"query-string": "^6.12.1",
|
||||
"query-string": "^6.13.1",
|
||||
"request": "~2.88.2",
|
||||
"semver": "~7.3.2",
|
||||
"simple-icons": "2.14.0",
|
||||
"simple-icons": "2.18.0",
|
||||
"xmldom": "~0.2.1",
|
||||
"xpath": "~0.0.27"
|
||||
},
|
||||
@@ -93,7 +93,8 @@
|
||||
"test:services:pr:run": "cross-env NODE_CONFIG_ENV=test mocha core/service-test-runner/cli.js --stdin < pull-request-services.log",
|
||||
"test:services:pr": "run-s --silent test:services:pr:prepare test:services:pr:run",
|
||||
"pretest": "run-s --silent defs features",
|
||||
"test": "run-s --silent --continue-on-error lint test:frontend test:package test:core test:entrypoint check-types:frontend prettier:check",
|
||||
"test": "run-s --silent --continue-on-error lint test:frontend test:package test:core test:entrypoint check-types:package check-types:frontend prettier:check",
|
||||
"check-types:package": "tsd badge-maker",
|
||||
"check-types:frontend": "tsc --noEmit --project .",
|
||||
"depcheck": "check-node-version --node \">= 10.0\"",
|
||||
"postinstall": "run-s --silent depcheck",
|
||||
@@ -140,9 +141,9 @@
|
||||
]
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.10.1",
|
||||
"@babel/polyfill": "^7.10.1",
|
||||
"@babel/register": "7.10.1",
|
||||
"@babel/core": "^7.10.4",
|
||||
"@babel/polyfill": "^7.10.4",
|
||||
"@babel/register": "7.10.4",
|
||||
"@mapbox/react-click-to-select": "^2.2.0",
|
||||
"@types/chai": "^4.2.11",
|
||||
"@types/chai-enzyme": "^0.6.7",
|
||||
@@ -150,27 +151,27 @@
|
||||
"@types/lodash.debounce": "^4.0.6",
|
||||
"@types/lodash.groupby": "^4.6.6",
|
||||
"@types/mocha": "^7.0.2",
|
||||
"@types/node": "^14.0.5",
|
||||
"@types/node": "^14.0.14",
|
||||
"@types/react-helmet": "^6.0.0",
|
||||
"@types/react-modal": "^3.10.5",
|
||||
"@types/react-select": "^3.0.13",
|
||||
"@types/react-modal": "^3.10.6",
|
||||
"@types/react-select": "^3.0.14",
|
||||
"@types/styled-components": "4.1.8",
|
||||
"@typescript-eslint/eslint-plugin": "^2.34.0",
|
||||
"@typescript-eslint/parser": "^2.34.0",
|
||||
"babel-plugin-inline-react-svg": "^1.1.1",
|
||||
"babel-plugin-istanbul": "^6.0.0",
|
||||
"babel-preset-gatsby": "^0.4.7",
|
||||
"babel-preset-gatsby": "^0.5.1",
|
||||
"caller": "^1.0.1",
|
||||
"chai": "^4.1.2",
|
||||
"chai-datetime": "^1.6.0",
|
||||
"chai-datetime": "^1.7.0",
|
||||
"chai-enzyme": "^1.0.0-beta.1",
|
||||
"chai-string": "^1.4.0",
|
||||
"cheerio": "^1.0.0-rc.3",
|
||||
"child-process-promise": "^2.2.1",
|
||||
"clipboard-copy": "^3.1.0",
|
||||
"concurrently": "^5.2.0",
|
||||
"cypress": "^4.7.0",
|
||||
"danger": "^10.2.0",
|
||||
"cypress": "^4.10.0",
|
||||
"danger": "^10.2.1",
|
||||
"danger-plugin-no-test-shortcuts": "^2.0.0",
|
||||
"deepmerge": "^4.2.2",
|
||||
"enzyme": "^3.11.0",
|
||||
@@ -181,55 +182,55 @@
|
||||
"eslint-config-standard-react": "^9.2.0",
|
||||
"eslint-plugin-chai-friendly": "^0.6.0",
|
||||
"eslint-plugin-cypress": "^2.11.1",
|
||||
"eslint-plugin-import": "^2.20.2",
|
||||
"eslint-plugin-jsdoc": "^26.0.0",
|
||||
"eslint-plugin-import": "^2.22.0",
|
||||
"eslint-plugin-jsdoc": "^28.5.1",
|
||||
"eslint-plugin-mocha": "^6.3.0",
|
||||
"eslint-plugin-no-extension-in-require": "^0.2.0",
|
||||
"eslint-plugin-node": "^11.1.0",
|
||||
"eslint-plugin-promise": "^4.2.1",
|
||||
"eslint-plugin-react": "^7.20.0",
|
||||
"eslint-plugin-react": "^7.20.3",
|
||||
"eslint-plugin-react-hooks": "^2.5.1",
|
||||
"eslint-plugin-sort-class-members": "^1.7.0",
|
||||
"eslint-plugin-standard": "^4.0.1",
|
||||
"fetch-ponyfill": "^6.1.0",
|
||||
"fetch-ponyfill": "^6.1.1",
|
||||
"form-data": "^3.0.0",
|
||||
"fs-readfile-promise": "^3.0.1",
|
||||
"gatsby": "2.22.12",
|
||||
"gatsby-plugin-catch-links": "^2.3.3",
|
||||
"gatsby-plugin-page-creator": "^2.3.7",
|
||||
"gatsby-plugin-react-helmet": "^3.3.2",
|
||||
"gatsby-plugin-remove-trailing-slashes": "^2.3.3",
|
||||
"gatsby-plugin-styled-components": "^3.3.2",
|
||||
"gatsby-plugin-typescript": "^2.4.3",
|
||||
"got": "11.1.4",
|
||||
"gatsby": "2.24.2",
|
||||
"gatsby-plugin-catch-links": "^2.3.10",
|
||||
"gatsby-plugin-page-creator": "^2.3.12",
|
||||
"gatsby-plugin-react-helmet": "^3.3.9",
|
||||
"gatsby-plugin-remove-trailing-slashes": "^2.3.10",
|
||||
"gatsby-plugin-styled-components": "^3.3.9",
|
||||
"gatsby-plugin-typescript": "^2.4.13",
|
||||
"got": "11.5.0",
|
||||
"humanize-string": "^2.1.0",
|
||||
"husky": "^4.2.5",
|
||||
"icedfrisby": "3.0.0",
|
||||
"icedfrisby": "4.0.0",
|
||||
"icedfrisby-nock": "^2.0.0",
|
||||
"is-png": "^2.0.0",
|
||||
"is-svg": "^4.2.1",
|
||||
"js-yaml-loader": "^1.2.2",
|
||||
"jsdoc": "^3.6.4",
|
||||
"lint-staged": "^10.2.7",
|
||||
"lint-staged": "^10.2.11",
|
||||
"lodash.debounce": "^4.0.8",
|
||||
"lodash.difference": "^4.5.0",
|
||||
"minimist": "^1.2.5",
|
||||
"mocha": "^7.2.0",
|
||||
"mocha-env-reporter": "^4.0.0",
|
||||
"mocha-junit-reporter": "^1.23.3",
|
||||
"mocha-junit-reporter": "^2.0.0",
|
||||
"mocha-yaml-loader": "^1.0.3",
|
||||
"nock": "13.0.0-beta.5",
|
||||
"nock": "13.0.2",
|
||||
"node-mocks-http": "^1.8.1",
|
||||
"nodemon": "^2.0.4",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"nyc": "^15.0.1",
|
||||
"nyc": "^15.1.0",
|
||||
"opn-cli": "^5.0.0",
|
||||
"portfinder": "^1.0.26",
|
||||
"prettier": "2.0.5",
|
||||
"react": "^16.13.1",
|
||||
"react-dom": "^16.13.1",
|
||||
"react-error-overlay": "^6.0.7",
|
||||
"react-helmet": "^6.0.0",
|
||||
"react-helmet": "^6.1.0",
|
||||
"react-modal": "^3.11.2",
|
||||
"react-pose": "^4.0.10",
|
||||
"react-select": "^3.1.0",
|
||||
@@ -244,6 +245,7 @@
|
||||
"start-server-and-test": "1.11.0",
|
||||
"styled-components": "^5.1.1",
|
||||
"tmp": "0.2.1",
|
||||
"tsd": "^0.12.1",
|
||||
"ts-mocha": "^7.0.0",
|
||||
"typescript": "^3.8.3"
|
||||
},
|
||||
|
||||
@@ -7,6 +7,10 @@ t.create('quality score (valid)')
|
||||
.get('/432.json')
|
||||
.expectBadge({ label: 'quality', message: nonNegativeInteger })
|
||||
|
||||
t.create('quality score (not found)')
|
||||
t.create('quality score (project not found)')
|
||||
.get('/0101.json')
|
||||
.expectBadge({ label: 'quality', message: 'not found' })
|
||||
|
||||
t.create('quality score (no score available)')
|
||||
.get('/2504.json')
|
||||
.expectBadge({ label: 'quality', message: 'no score available' })
|
||||
|
||||
@@ -52,7 +52,26 @@ t.create('license (valid)')
|
||||
.expectBadge({ label: 'license', message: 'MIT' })
|
||||
|
||||
t.create('license (no license)')
|
||||
.get('/license/dns-zone-blacklist-git.json')
|
||||
.get('/license/vscodium-bin.json')
|
||||
.intercept(nock =>
|
||||
nock('https://aur.archlinux.org')
|
||||
.get('/rpc.php')
|
||||
.query({
|
||||
type: 'info',
|
||||
arg: 'vscodium-bin',
|
||||
})
|
||||
.reply(200, {
|
||||
resultcount: 1,
|
||||
results: {
|
||||
License: null,
|
||||
NumVotes: 1,
|
||||
Version: '1',
|
||||
OutOfDate: null,
|
||||
Maintainer: null,
|
||||
LastModified: 1,
|
||||
},
|
||||
})
|
||||
)
|
||||
.expectBadge({ label: 'license', message: 'not specified' })
|
||||
|
||||
t.create('license (package not found)')
|
||||
|
||||
@@ -25,6 +25,7 @@ const otherStatuses = [
|
||||
'building',
|
||||
'canceled',
|
||||
'cancelled',
|
||||
'created',
|
||||
'expired',
|
||||
'initiated',
|
||||
'no builds',
|
||||
|
||||
@@ -32,7 +32,11 @@ module.exports = class CodeclimateCoverage extends BaseJsonService {
|
||||
return [
|
||||
{
|
||||
title: 'Code Climate coverage',
|
||||
namedParams: { format: 'coverage', user: 'jekyll', repo: 'jekyll' },
|
||||
namedParams: {
|
||||
format: 'coverage',
|
||||
user: 'codeclimate',
|
||||
repo: 'codeclimate',
|
||||
},
|
||||
staticPreview: this.render({
|
||||
format: 'coverage',
|
||||
percentage: 95.123,
|
||||
|
||||
@@ -8,14 +8,14 @@ const t = (module.exports = require('../tester').createServiceTester())
|
||||
// https://codeclimate.com/explore
|
||||
|
||||
t.create('test coverage percentage')
|
||||
.get('/coverage/codeclimate/minidoc.json')
|
||||
.get('/coverage/codeclimate/codeclimate.json')
|
||||
.expectBadge({
|
||||
label: 'coverage',
|
||||
message: isIntegerPercentage,
|
||||
})
|
||||
|
||||
t.create('test coverage letter')
|
||||
.get('/coverage-letter/codeclimate/minidoc.json')
|
||||
.get('/coverage-letter/codeclimate/codeclimate.json')
|
||||
.expectBadge({
|
||||
label: 'coverage',
|
||||
message: Joi.equal('A', 'B', 'C', 'D', 'E', 'F'),
|
||||
|
||||
@@ -8,6 +8,21 @@ t.create('version (valid)').get('/Config-Augeas.json').expectBadge({
|
||||
message: isVPlusDottedVersionAtLeastOne,
|
||||
})
|
||||
|
||||
t.create('version (version is a number rather than a string)')
|
||||
.get('/Config-Augeas.json')
|
||||
.intercept(nock =>
|
||||
nock('https://fastapi.metacpan.org')
|
||||
.get('/v1/release/Config-Augeas')
|
||||
.reply(200, {
|
||||
license: ['GPL'],
|
||||
version: 0.88,
|
||||
})
|
||||
)
|
||||
.expectBadge({
|
||||
label: 'cpan',
|
||||
message: 'v0.88',
|
||||
})
|
||||
|
||||
t.create('version (not found)').get('/not-a-package.json').expectBadge({
|
||||
label: 'cpan',
|
||||
message: 'not found',
|
||||
|
||||
@@ -4,7 +4,7 @@ const Joi = require('@hapi/joi')
|
||||
const { BaseJsonService } = require('..')
|
||||
|
||||
const schema = Joi.object({
|
||||
version: Joi.string().required(),
|
||||
version: Joi.alternatives(Joi.string().required(), Joi.number().required()),
|
||||
license: Joi.array().items(Joi.string()).min(1).required(),
|
||||
}).required()
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ const keywords = ['Rust']
|
||||
const crateSchema = Joi.object({
|
||||
crate: Joi.object({
|
||||
downloads: nonNegativeInteger,
|
||||
recent_downloads: nonNegativeInteger,
|
||||
recent_downloads: nonNegativeInteger.allow(null),
|
||||
max_version: Joi.string().required(),
|
||||
}).required(),
|
||||
versions: Joi.array()
|
||||
|
||||
@@ -87,7 +87,7 @@ module.exports = class CratesDownloads extends BaseCratesService {
|
||||
case 'dv':
|
||||
return json.crate ? json.versions[0].downloads : json.version.downloads
|
||||
case 'dr':
|
||||
return json.crate.recent_downloads
|
||||
return json.crate.recent_downloads || 0
|
||||
default:
|
||||
return json.crate ? json.crate.downloads : json.version.downloads
|
||||
}
|
||||
|
||||
@@ -37,6 +37,22 @@ t.create('recent downloads').get('/dr/libc.json').expectBadge({
|
||||
message: isMetric,
|
||||
})
|
||||
|
||||
t.create('recent downloads (null)')
|
||||
.get('/dr/libc.json')
|
||||
.intercept(nock =>
|
||||
nock('https://crates.io')
|
||||
.get('/api/v1/crates/libc')
|
||||
.reply(200, {
|
||||
crate: {
|
||||
downloads: 42,
|
||||
recent_downloads: null,
|
||||
max_version: '0.2.71',
|
||||
},
|
||||
versions: [{ downloads: 42, license: 'MIT OR Apache-2.0' }],
|
||||
})
|
||||
)
|
||||
.expectBadge({ label: 'recent downloads', message: '0' })
|
||||
|
||||
t.create('recent downloads (with version)')
|
||||
.get('/dr/libc/0.2.31.json')
|
||||
.expectBadge({
|
||||
|
||||
60
services/github/github-all-contributors.service.js
Normal file
60
services/github/github-all-contributors.service.js
Normal file
@@ -0,0 +1,60 @@
|
||||
'use strict'
|
||||
|
||||
const Joi = require('@hapi/joi')
|
||||
const { renderContributorBadge } = require('../contributor-count')
|
||||
const { ConditionalGithubAuthV3Service } = require('./github-auth-service')
|
||||
const { fetchJsonFromRepo } = require('./github-common-fetch')
|
||||
const { documentation } = require('./github-helpers')
|
||||
|
||||
const schema = Joi.object({
|
||||
contributors: Joi.array().required(),
|
||||
}).required()
|
||||
|
||||
module.exports = class GithubAllContributorsService extends ConditionalGithubAuthV3Service {
|
||||
static get category() {
|
||||
return 'activity'
|
||||
}
|
||||
|
||||
static get route() {
|
||||
return {
|
||||
base: 'github/all-contributors',
|
||||
pattern: ':user/:repo/:branch*',
|
||||
}
|
||||
}
|
||||
|
||||
static get examples() {
|
||||
return [
|
||||
{
|
||||
title: 'Github All Contributors',
|
||||
namedParams: {
|
||||
repo: 'all-contributors',
|
||||
user: 'all-contributors',
|
||||
branch: 'master',
|
||||
},
|
||||
staticPreview: this.render({ contributorCount: 66 }),
|
||||
documentation,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
static get defaultBadgeData() {
|
||||
return { label: 'all contributors' }
|
||||
}
|
||||
|
||||
static render({ contributorCount }) {
|
||||
return renderContributorBadge({ contributorCount })
|
||||
}
|
||||
|
||||
async handle({ user, repo, branch }) {
|
||||
const { contributors } = await fetchJsonFromRepo(this, {
|
||||
schema,
|
||||
user,
|
||||
repo,
|
||||
branch,
|
||||
filename: '.all-contributorsrc',
|
||||
})
|
||||
|
||||
const contributorCount = contributors.length
|
||||
return this.constructor.render({ contributorCount })
|
||||
}
|
||||
}
|
||||
16
services/github/github-all-contributors.tester.js
Normal file
16
services/github/github-all-contributors.tester.js
Normal file
@@ -0,0 +1,16 @@
|
||||
'use strict'
|
||||
|
||||
const t = (module.exports = require('../tester').createServiceTester())
|
||||
const { isMetric } = require('../test-validators')
|
||||
|
||||
t.create('all-contributors repo')
|
||||
.get('/all-contributors/all-contributors.json')
|
||||
.expectBadge({
|
||||
label: 'all contributors',
|
||||
message: isMetric,
|
||||
})
|
||||
|
||||
t.create('shields repo (not found)').get('/badges/shields.json').expectBadge({
|
||||
label: 'all contributors',
|
||||
message: 'repo not found, branch not found, or .all-contributorsrc missing',
|
||||
})
|
||||
@@ -164,7 +164,7 @@ module.exports = class GithubCommitsSince extends GithubAuthV3Service {
|
||||
: 'repo or version not found'
|
||||
const { ahead_by: commitCount } = await this._requestJson({
|
||||
schema,
|
||||
url: `/repos/${user}/${repo}/compare/${version}...${branch || 'master'}`,
|
||||
url: `/repos/${user}/${repo}/compare/${version}...${branch || 'HEAD'}`,
|
||||
errorMessages: errorMessagesFor(notFoundMessage),
|
||||
})
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ const contentSchema = Joi.object({
|
||||
|
||||
async function fetchRepoContent(
|
||||
serviceInstance,
|
||||
{ user, repo, branch = 'master', filename }
|
||||
{ user, repo, branch = 'HEAD', filename }
|
||||
) {
|
||||
const errorMessages = errorMessagesFor(
|
||||
`repo not found, branch not found, or ${filename} missing`
|
||||
|
||||
@@ -15,6 +15,10 @@ const schema = Joi.object({
|
||||
version: individualValueSchema,
|
||||
}).required()
|
||||
|
||||
const queryParamSchema = Joi.object({
|
||||
filename: Joi.string().regex(/.*manifest\.json$/),
|
||||
})
|
||||
|
||||
const flexibleSchema = Joi.object().required()
|
||||
|
||||
class GithubManifestVersion extends ConditionalGithubAuthV3Service {
|
||||
@@ -26,6 +30,7 @@ class GithubManifestVersion extends ConditionalGithubAuthV3Service {
|
||||
return {
|
||||
base: 'github/manifest-json/v',
|
||||
pattern: ':user/:repo/:branch*',
|
||||
queryParamSchema,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,20 +40,47 @@ class GithubManifestVersion extends ConditionalGithubAuthV3Service {
|
||||
title: 'GitHub manifest version',
|
||||
pattern: ':user/:repo',
|
||||
namedParams: {
|
||||
user: 'RedSparr0w',
|
||||
repo: 'IndieGala-Helper',
|
||||
user: 'sindresorhus',
|
||||
repo: 'show-all-github-issues',
|
||||
},
|
||||
staticPreview: this.render({ version: 2 }),
|
||||
staticPreview: this.render({ version: '1.0.3' }),
|
||||
documentation,
|
||||
},
|
||||
{
|
||||
title: 'GitHub manifest version',
|
||||
pattern: ':user/:repo/:branch',
|
||||
namedParams: {
|
||||
user: 'sindresorhus',
|
||||
repo: 'show-all-github-issues',
|
||||
branch: 'master',
|
||||
},
|
||||
staticPreview: this.render({ version: '1.0.3', branch: 'master' }),
|
||||
documentation,
|
||||
},
|
||||
{
|
||||
title: 'GitHub manifest version (path)',
|
||||
pattern: ':user/:repo',
|
||||
namedParams: {
|
||||
user: 'RedSparr0w',
|
||||
repo: 'IndieGala-Helper',
|
||||
},
|
||||
queryParams: {
|
||||
filename: 'extension/manifest.json',
|
||||
},
|
||||
staticPreview: this.render({ version: 2 }),
|
||||
documentation,
|
||||
},
|
||||
{
|
||||
title: 'GitHub manifest version (path)',
|
||||
pattern: ':user/:repo/:branch',
|
||||
namedParams: {
|
||||
user: 'RedSparr0w',
|
||||
repo: 'IndieGala-Helper',
|
||||
branch: 'master',
|
||||
},
|
||||
queryParams: {
|
||||
filename: 'extension/manifest.json',
|
||||
},
|
||||
staticPreview: this.render({ version: 2, branch: 'master' }),
|
||||
documentation,
|
||||
},
|
||||
@@ -63,13 +95,13 @@ class GithubManifestVersion extends ConditionalGithubAuthV3Service {
|
||||
})
|
||||
}
|
||||
|
||||
async handle({ user, repo, branch }) {
|
||||
async handle({ user, repo, branch }, { filename = 'manifest.json' }) {
|
||||
const { version } = await fetchJsonFromRepo(this, {
|
||||
schema,
|
||||
user,
|
||||
repo,
|
||||
branch,
|
||||
filename: 'manifest.json',
|
||||
filename,
|
||||
})
|
||||
return this.constructor.render({ version, branch })
|
||||
}
|
||||
@@ -84,6 +116,7 @@ class DynamicGithubManifest extends ConditionalGithubAuthV3Service {
|
||||
return {
|
||||
base: 'github/manifest-json',
|
||||
pattern: ':key([^v/][^/]*)/:user/:repo/:branch*',
|
||||
queryParamSchema,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,12 +127,12 @@ class DynamicGithubManifest extends ConditionalGithubAuthV3Service {
|
||||
pattern: ':key/:user/:repo',
|
||||
namedParams: {
|
||||
key: 'permissions',
|
||||
user: 'developit',
|
||||
repo: 'microbundle',
|
||||
user: 'sindresorhus',
|
||||
repo: 'show-all-github-issues',
|
||||
},
|
||||
staticPreview: this.render({
|
||||
key: 'permissions',
|
||||
value: ['bundle', 'rollup', 'micro library'],
|
||||
value: ['webRequest', 'webRequestBlocking'],
|
||||
}),
|
||||
documentation,
|
||||
},
|
||||
@@ -108,10 +141,46 @@ class DynamicGithubManifest extends ConditionalGithubAuthV3Service {
|
||||
pattern: ':key/:user/:repo/:branch',
|
||||
namedParams: {
|
||||
key: 'permissions',
|
||||
user: 'developit',
|
||||
repo: 'microbundle',
|
||||
user: 'sindresorhus',
|
||||
repo: 'show-all-github-issues',
|
||||
branch: 'master',
|
||||
},
|
||||
staticPreview: this.render({
|
||||
key: 'permissions',
|
||||
value: ['webRequest', 'webRequestBlocking'],
|
||||
branch: 'master',
|
||||
}),
|
||||
documentation,
|
||||
},
|
||||
{
|
||||
title: 'GitHub manifest.json dynamic (path)',
|
||||
pattern: ':key/:user/:repo',
|
||||
namedParams: {
|
||||
key: 'permissions',
|
||||
user: 'RedSparr0w',
|
||||
repo: 'IndieGala-Helper',
|
||||
},
|
||||
queryParams: {
|
||||
filename: 'extension/manifest.json',
|
||||
},
|
||||
staticPreview: this.render({
|
||||
key: 'permissions',
|
||||
value: ['bundle', 'rollup', 'micro library'],
|
||||
}),
|
||||
documentation,
|
||||
},
|
||||
{
|
||||
title: 'GitHub manifest.json dynamic (path)',
|
||||
pattern: ':key/:user/:repo/:branch',
|
||||
namedParams: {
|
||||
key: 'permissions',
|
||||
user: 'RedSparr0w',
|
||||
repo: 'IndieGala-Helper',
|
||||
branch: 'master',
|
||||
},
|
||||
queryParams: {
|
||||
filename: 'extension/manifest.json',
|
||||
},
|
||||
staticPreview: this.render({
|
||||
key: 'permissions',
|
||||
value: ['bundle', 'rollup', 'micro library'],
|
||||
@@ -136,7 +205,7 @@ class DynamicGithubManifest extends ConditionalGithubAuthV3Service {
|
||||
})
|
||||
}
|
||||
|
||||
async handle({ key, user, repo, branch }) {
|
||||
async handle({ key, user, repo, branch }, { filename = 'manifest.json' }) {
|
||||
// Not sure `manifest-json/n` was ever advertised, but it was supported.
|
||||
if (key === 'n') {
|
||||
key = 'name'
|
||||
@@ -146,7 +215,7 @@ class DynamicGithubManifest extends ConditionalGithubAuthV3Service {
|
||||
user,
|
||||
repo,
|
||||
branch,
|
||||
filename: 'manifest.json',
|
||||
filename,
|
||||
})
|
||||
const value = transformAndValidate({ data, key })
|
||||
return this.constructor.render({ key, value, branch })
|
||||
|
||||
@@ -11,25 +11,46 @@ const t = (module.exports = new ServiceTester({
|
||||
}))
|
||||
|
||||
t.create('Manifest version')
|
||||
.get('/v/RedSparr0w/IndieGala-Helper.json')
|
||||
.get('/v/sindresorhus/show-all-github-issues.json')
|
||||
.expectBadge({
|
||||
label: 'version',
|
||||
message: isVPlusDottedVersionAtLeastOne,
|
||||
})
|
||||
|
||||
t.create('Manifest name')
|
||||
.get('/n/RedSparr0w/IndieGala-Helper.json')
|
||||
t.create('Manifest version (path)')
|
||||
.get('/v/RedSparr0w/IndieGala-Helper.json?filename=extension/manifest.json')
|
||||
.expectBadge({
|
||||
label: 'version',
|
||||
message: isVPlusDottedVersionAtLeastOne,
|
||||
})
|
||||
|
||||
t.create('Manifest version (path not found)')
|
||||
.get(
|
||||
'/v/RedSparr0w/IndieGala-Helper.json?filename=invalid-directory/manifest.json'
|
||||
)
|
||||
.expectBadge({
|
||||
label: 'version',
|
||||
message:
|
||||
'repo not found, branch not found, or invalid-directory/manifest.json missing',
|
||||
})
|
||||
|
||||
t.create('Manifest name (path)')
|
||||
.get('/n/RedSparr0w/IndieGala-Helper.json?filename=extension/manifest.json')
|
||||
.expectBadge({ label: 'name', message: 'IndieGala Helper' })
|
||||
|
||||
t.create('Manifest array')
|
||||
.get('/permissions/RedSparr0w/IndieGala-Helper.json')
|
||||
t.create('Manifest array (path)')
|
||||
.get(
|
||||
'/permissions/RedSparr0w/IndieGala-Helper.json?filename=extension/manifest.json'
|
||||
)
|
||||
.expectBadge({
|
||||
label: 'permissions',
|
||||
message: Joi.string().regex(/.*?,/),
|
||||
})
|
||||
|
||||
t.create('Manifest object')
|
||||
.get('/background/RedSparr0w/IndieGala-Helper.json')
|
||||
t.create('Manifest object (path)')
|
||||
.get(
|
||||
'/background/RedSparr0w/IndieGala-Helper.json?filename=extension/manifest.json'
|
||||
)
|
||||
.expectBadge({ label: 'manifest', message: 'invalid key value' })
|
||||
|
||||
t.create('Manifest invalid json response')
|
||||
|
||||
@@ -166,7 +166,7 @@ class GithubPackageJsonDependencyVersion extends ConditionalGithubAuthV3Service
|
||||
}
|
||||
|
||||
async handle(
|
||||
{ user, repo, kind, branch = 'master', scope, packageName },
|
||||
{ user, repo, kind, branch = 'HEAD', scope, packageName },
|
||||
{ filename = 'package.json' }
|
||||
) {
|
||||
const {
|
||||
|
||||
@@ -114,7 +114,7 @@ module.exports = class Nycrc extends ConditionalGithubAuthV3Service {
|
||||
schema: pkgJSONSchema,
|
||||
user,
|
||||
repo,
|
||||
branch: 'master',
|
||||
branch: 'HEAD',
|
||||
filename: config,
|
||||
})
|
||||
const nycConfig = pkgJson.c8 || pkgJson.nyc
|
||||
@@ -131,7 +131,7 @@ module.exports = class Nycrc extends ConditionalGithubAuthV3Service {
|
||||
schema: nycrcSchema,
|
||||
user,
|
||||
repo,
|
||||
branch: 'master',
|
||||
branch: 'HEAD',
|
||||
filename: config,
|
||||
}),
|
||||
preferredThreshold
|
||||
|
||||
@@ -26,7 +26,7 @@ t.create('.nycrc in monorepo')
|
||||
.get('/yargs/yargs.json?config=packages/foo/.nycrc.json')
|
||||
.intercept(nock =>
|
||||
nock('https://api.github.com')
|
||||
.get('/repos/yargs/yargs/contents/packages/foo/.nycrc.json?ref=master')
|
||||
.get('/repos/yargs/yargs/contents/packages/foo/.nycrc.json?ref=HEAD')
|
||||
.reply(200, {
|
||||
content: Buffer.from(
|
||||
JSON.stringify({
|
||||
@@ -42,7 +42,7 @@ t.create('.nycrc with no thresholds')
|
||||
.get('/yargs/yargs.json?config=.nycrc')
|
||||
.intercept(nock =>
|
||||
nock('https://api.github.com')
|
||||
.get('/repos/yargs/yargs/contents/.nycrc?ref=master')
|
||||
.get('/repos/yargs/yargs/contents/.nycrc?ref=HEAD')
|
||||
.reply(200, {
|
||||
content: Buffer.from(
|
||||
JSON.stringify({
|
||||
@@ -61,7 +61,7 @@ t.create('package.json with nyc stanza')
|
||||
.get('/yargs/yargs.json?config=package.json')
|
||||
.intercept(nock =>
|
||||
nock('https://api.github.com')
|
||||
.get('/repos/yargs/yargs/contents/package.json?ref=master')
|
||||
.get('/repos/yargs/yargs/contents/package.json?ref=HEAD')
|
||||
.reply(200, {
|
||||
content: Buffer.from(
|
||||
JSON.stringify({
|
||||
@@ -79,7 +79,7 @@ t.create('package.json with nyc stanza, but no thresholds')
|
||||
.get('/yargs/yargs.json?config=package.json')
|
||||
.intercept(nock =>
|
||||
nock('https://api.github.com')
|
||||
.get('/repos/yargs/yargs/contents/package.json?ref=master')
|
||||
.get('/repos/yargs/yargs/contents/package.json?ref=HEAD')
|
||||
.reply(200, {
|
||||
content: Buffer.from(
|
||||
JSON.stringify({
|
||||
|
||||
@@ -93,7 +93,7 @@ module.exports = class OssTracker extends BaseService {
|
||||
const { buffer } = await this.fetch({
|
||||
user,
|
||||
repo,
|
||||
branch: branch || 'master',
|
||||
branch: branch || 'HEAD',
|
||||
})
|
||||
try {
|
||||
const status = buffer.match(/osslifecycle=([a-z]+)/im)[1]
|
||||
|
||||
@@ -47,7 +47,7 @@ t.create('oss metadata in unexpected format')
|
||||
.intercept(
|
||||
nock =>
|
||||
nock('https://raw.githubusercontent.com')
|
||||
.get('/some-user/some-project/master/OSSMETADATA')
|
||||
.get('/some-user/some-project/HEAD/OSSMETADATA')
|
||||
.reply(200, `wrongkey=active`),
|
||||
{
|
||||
'Content-Type': 'text/plain;charset=UTF-8',
|
||||
|
||||
@@ -11,7 +11,7 @@ const schema = Joi.object({
|
||||
}).required(),
|
||||
}).required()
|
||||
|
||||
module.exports = class SubredditSubscribers extends BaseJsonService {
|
||||
module.exports = class RedditSubredditSubscribers extends BaseJsonService {
|
||||
static get category() {
|
||||
return 'social'
|
||||
}
|
||||
@@ -60,6 +60,7 @@ module.exports = class SubredditSubscribers extends BaseJsonService {
|
||||
url: `https://www.reddit.com/r/${subreddit}/about.json`,
|
||||
errorMessages: {
|
||||
404: 'subreddit not found',
|
||||
403: 'subreddit is private',
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
@@ -23,3 +23,22 @@ t.create('subreddit-subscribers (not existing subreddit)')
|
||||
label: 'reddit',
|
||||
message: 'subreddit not found',
|
||||
})
|
||||
|
||||
t.create('subreddit-subscribers (private sub)')
|
||||
.get('/centuryclub.json')
|
||||
.expectBadge({
|
||||
label: 'reddit',
|
||||
message: 'subreddit is private',
|
||||
})
|
||||
|
||||
t.create('subreddit-subscribers (private sub)')
|
||||
.get('/centuryclub.json')
|
||||
.intercept(nock =>
|
||||
nock('https://www.reddit.com/r')
|
||||
.get('/centuryclub/about.json')
|
||||
.reply(200, { kind: 't5', data: {} })
|
||||
)
|
||||
.expectBadge({
|
||||
label: 'reddit',
|
||||
message: 'subreddit not found',
|
||||
})
|
||||
|
||||
96
services/reddit/user-karma.service.js
Normal file
96
services/reddit/user-karma.service.js
Normal file
@@ -0,0 +1,96 @@
|
||||
'use strict'
|
||||
|
||||
const Joi = require('@hapi/joi')
|
||||
const { nonNegativeInteger } = require('../validators')
|
||||
const { metric } = require('../text-formatters')
|
||||
const { BaseJsonService } = require('..')
|
||||
|
||||
const schema = Joi.object({
|
||||
data: Joi.object({
|
||||
link_karma: nonNegativeInteger,
|
||||
comment_karma: nonNegativeInteger,
|
||||
}).required(),
|
||||
}).required()
|
||||
|
||||
module.exports = class RedditUserKarma extends BaseJsonService {
|
||||
static get category() {
|
||||
return 'social'
|
||||
}
|
||||
|
||||
static get route() {
|
||||
return {
|
||||
base: 'reddit/user-karma',
|
||||
pattern: ':variant(link|comment|combined)/:user',
|
||||
}
|
||||
}
|
||||
|
||||
static get examples() {
|
||||
return [
|
||||
{
|
||||
title: 'Reddit User Karma',
|
||||
namedParams: { variant: 'combined', user: 'example' },
|
||||
staticPreview: {
|
||||
label: 'combined karma',
|
||||
message: 56,
|
||||
color: 'red',
|
||||
style: 'social',
|
||||
},
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
static get defaultBadgeData() {
|
||||
return {
|
||||
label: 'reddit karma',
|
||||
namedLogo: 'reddit',
|
||||
}
|
||||
}
|
||||
|
||||
static render({ variant, karma, user }) {
|
||||
const label =
|
||||
variant === 'combined'
|
||||
? `u/${user} karma`
|
||||
: `u/${user} karma (${variant})`
|
||||
return {
|
||||
label,
|
||||
message: metric(karma),
|
||||
color: 'red',
|
||||
link: [`https://www.reddit.com/u/${user}`],
|
||||
}
|
||||
}
|
||||
|
||||
async fetch({ user }) {
|
||||
return this._requestJson({
|
||||
schema,
|
||||
url: `https://www.reddit.com/u/${user}/about.json`,
|
||||
errorMessages: {
|
||||
404: 'user not found',
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
transform({ json, variant }) {
|
||||
let karma
|
||||
if (variant === 'link') {
|
||||
karma = json.data.link_karma
|
||||
} else if (variant === 'comment') {
|
||||
karma = json.data.comment_karma
|
||||
} else {
|
||||
const total = json.data.link_karma + json.data.comment_karma
|
||||
karma = total
|
||||
}
|
||||
|
||||
return { karma }
|
||||
}
|
||||
|
||||
async handle({ variant, user }) {
|
||||
const json = await this.fetch({ user })
|
||||
const { karma } = this.transform({ json, variant })
|
||||
|
||||
return this.constructor.render({
|
||||
variant,
|
||||
karma,
|
||||
user,
|
||||
})
|
||||
}
|
||||
}
|
||||
80
services/reddit/user-karma.tester.js
Normal file
80
services/reddit/user-karma.tester.js
Normal file
@@ -0,0 +1,80 @@
|
||||
'use strict'
|
||||
|
||||
const { isMetric } = require('../test-validators')
|
||||
const t = (module.exports = require('../tester').createServiceTester())
|
||||
|
||||
t.create('user-karma (valid - link)')
|
||||
.get('/link/user_simulator.json')
|
||||
.expectBadge({
|
||||
label: 'u/user_simulator karma (link)',
|
||||
message: isMetric,
|
||||
})
|
||||
|
||||
t.create('user-karma (valid - comment')
|
||||
.get('/comment/user_simulator.json')
|
||||
.expectBadge({
|
||||
label: 'u/user_simulator karma (comment)',
|
||||
message: isMetric,
|
||||
})
|
||||
|
||||
t.create('user-karma (valid - combined)')
|
||||
.get('/combined/user_simulator.json')
|
||||
.expectBadge({
|
||||
label: 'u/user_simulator karma',
|
||||
message: isMetric,
|
||||
})
|
||||
|
||||
t.create('user-karma (non-existing user)')
|
||||
.get('/combined/thisuserdoesnotexistandhopefullyneverwill.json')
|
||||
.expectBadge({
|
||||
label: 'reddit karma',
|
||||
message: 'user not found',
|
||||
})
|
||||
|
||||
t.create('user-karma (link - math check)')
|
||||
.get('/link/user_simulator.json')
|
||||
.intercept(nock =>
|
||||
nock('https://www.reddit.com/u')
|
||||
.get('/user_simulator/about.json')
|
||||
.reply(200, { kind: 't2', data: { link_karma: 20, comment_karma: 80 } })
|
||||
)
|
||||
.expectBadge({
|
||||
label: 'u/user_simulator karma (link)',
|
||||
message: '20',
|
||||
})
|
||||
|
||||
t.create('user-karma (comment - math check)')
|
||||
.get('/comment/user_simulator.json')
|
||||
.intercept(nock =>
|
||||
nock('https://www.reddit.com/u')
|
||||
.get('/user_simulator/about.json')
|
||||
.reply(200, { kind: 't2', data: { link_karma: 20, comment_karma: 80 } })
|
||||
)
|
||||
.expectBadge({
|
||||
label: 'u/user_simulator karma (comment)',
|
||||
message: '80',
|
||||
})
|
||||
|
||||
t.create('user-karma (combined - math check)')
|
||||
.get('/combined/user_simulator.json')
|
||||
.intercept(nock =>
|
||||
nock('https://www.reddit.com/u')
|
||||
.get('/user_simulator/about.json')
|
||||
.reply(200, { kind: 't2', data: { link_karma: 20, comment_karma: 80 } })
|
||||
)
|
||||
.expectBadge({
|
||||
label: 'u/user_simulator karma',
|
||||
message: '100',
|
||||
})
|
||||
|
||||
t.create('user-karma (combined - missing data)')
|
||||
.get('/combined/user_simulator.json')
|
||||
.intercept(nock =>
|
||||
nock('https://www.reddit.com/u')
|
||||
.get('/user_simulator/about.json')
|
||||
.reply(200, { kind: 't2', data: { link_karma: 20 } })
|
||||
)
|
||||
.expectBadge({
|
||||
label: 'reddit karma',
|
||||
message: 'invalid response data',
|
||||
})
|
||||
@@ -81,7 +81,7 @@ module.exports = class TwitchBase extends BaseJsonService {
|
||||
options: {
|
||||
...request.options,
|
||||
headers: {
|
||||
'Client-ID': this.authHelper.user,
|
||||
'Client-ID': this.authHelper._user,
|
||||
Authorization: `Bearer ${await this._twitchToken()}`,
|
||||
...(request.options && request.options.headers),
|
||||
},
|
||||
|
||||
@@ -34,7 +34,9 @@ describe('TwitchStatus', function () {
|
||||
expires_in: 2000000,
|
||||
})
|
||||
|
||||
const statusNock = nock('https://api.twitch.tv')
|
||||
const statusNock = nock('https://api.twitch.tv', {
|
||||
reqheaders: { Authorization: `Bearer ${token}`, 'Client-ID': user },
|
||||
})
|
||||
.get('/helix/streams')
|
||||
.reply(200, {
|
||||
data: [],
|
||||
|
||||
@@ -4,14 +4,17 @@ const t = (module.exports = require('../tester').createServiceTester())
|
||||
|
||||
t.create('status of http://shields.io')
|
||||
.get('/website.json?url=http://shields.io')
|
||||
.timeout(7500)
|
||||
.expectBadge({ label: 'website', message: 'up', color: 'brightgreen' })
|
||||
|
||||
t.create('status of https://shields.io')
|
||||
.get('/website.json?url=https://shields.io')
|
||||
.timeout(7500)
|
||||
.expectBadge({ label: 'website', message: 'up', color: 'brightgreen' })
|
||||
|
||||
t.create('status of nonexistent domain')
|
||||
.get('/website.json?url=http://shields.io.io')
|
||||
.timeout(15000)
|
||||
.expectBadge({ label: 'website', message: 'down', color: 'red' })
|
||||
|
||||
t.create('status when network is off')
|
||||
|
||||
72
services/youtube/youtube-base.js
Normal file
72
services/youtube/youtube-base.js
Normal file
@@ -0,0 +1,72 @@
|
||||
'use strict'
|
||||
|
||||
const Joi = require('@hapi/joi')
|
||||
const { BaseJsonService, NotFound } = require('..')
|
||||
const { metric } = require('../text-formatters')
|
||||
const { nonNegativeInteger } = require('../validators')
|
||||
|
||||
const schema = Joi.object({
|
||||
items: Joi.array()
|
||||
.items(
|
||||
Joi.object({
|
||||
statistics: Joi.object({
|
||||
viewCount: nonNegativeInteger,
|
||||
likeCount: nonNegativeInteger,
|
||||
dislikeCount: nonNegativeInteger,
|
||||
commentCount: nonNegativeInteger,
|
||||
}).required(),
|
||||
})
|
||||
)
|
||||
.required(),
|
||||
}).required()
|
||||
|
||||
module.exports = class YouTubeBase extends BaseJsonService {
|
||||
static get category() {
|
||||
return 'social'
|
||||
}
|
||||
|
||||
static get auth() {
|
||||
return {
|
||||
passKey: 'youtube_api_key',
|
||||
authorizedOrigins: ['https://www.googleapis.com'],
|
||||
isRequired: true,
|
||||
}
|
||||
}
|
||||
|
||||
static get defaultBadgeData() {
|
||||
return { label: 'youtube', color: 'red', namedLogo: 'youtube' }
|
||||
}
|
||||
|
||||
static renderSingleStat({ statistics, statisticName, videoId }) {
|
||||
return {
|
||||
label: `${statisticName}s`,
|
||||
message: metric(statistics[`${statisticName}Count`]),
|
||||
style: 'social',
|
||||
link: `https://www.youtube.com/watch?v=${encodeURIComponent(videoId)}`,
|
||||
}
|
||||
}
|
||||
|
||||
async fetch({ videoId }) {
|
||||
return this._requestJson(
|
||||
this.authHelper.withQueryStringAuth(
|
||||
{ passKey: 'key' },
|
||||
{
|
||||
schema,
|
||||
url: 'https://www.googleapis.com/youtube/v3/videos',
|
||||
options: {
|
||||
qs: { id: videoId, part: 'statistics' },
|
||||
},
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
async handle({ videoId }, queryParams) {
|
||||
const json = await this.fetch({ videoId })
|
||||
if (json.items.length === 0) {
|
||||
throw new NotFound({ prettyMessage: 'video not found' })
|
||||
}
|
||||
const statistics = json.items[0].statistics
|
||||
return this.constructor.render({ statistics, videoId }, queryParams)
|
||||
}
|
||||
}
|
||||
36
services/youtube/youtube-comments.service.js
Normal file
36
services/youtube/youtube-comments.service.js
Normal file
@@ -0,0 +1,36 @@
|
||||
'use strict'
|
||||
|
||||
const YouTubeBase = require('./youtube-base')
|
||||
|
||||
module.exports = class YouTubeComments extends YouTubeBase {
|
||||
static get route() {
|
||||
return {
|
||||
base: 'youtube/comments',
|
||||
pattern: ':videoId',
|
||||
}
|
||||
}
|
||||
|
||||
static get examples() {
|
||||
const preview = this.render({
|
||||
statistics: { commentCount: 209 },
|
||||
videoId: 'wGJHwc5ksMA',
|
||||
})
|
||||
// link[] is not allowed in examples
|
||||
delete preview.link
|
||||
return [
|
||||
{
|
||||
title: 'YouTube Video Comments',
|
||||
namedParams: { videoId: 'wGJHwc5ksMA' },
|
||||
staticPreview: preview,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
static render({ statistics, videoId }) {
|
||||
return super.renderSingleStat({
|
||||
statistics,
|
||||
statisticName: 'comment',
|
||||
videoId,
|
||||
})
|
||||
}
|
||||
}
|
||||
25
services/youtube/youtube-comments.tester.js
Normal file
25
services/youtube/youtube-comments.tester.js
Normal file
@@ -0,0 +1,25 @@
|
||||
'use strict'
|
||||
|
||||
const t = (module.exports = require('../tester').createServiceTester())
|
||||
const { noToken } = require('../test-helpers')
|
||||
const { isMetric } = require('../test-validators')
|
||||
const noYouTubeToken = noToken(require('./youtube-comments.service'))
|
||||
|
||||
t.create('video comment count')
|
||||
.skipWhen(noYouTubeToken)
|
||||
.get('/wGJHwc5ksMA.json')
|
||||
.expectBadge({
|
||||
label: 'comments',
|
||||
message: isMetric,
|
||||
color: 'red',
|
||||
link: ['https://www.youtube.com/watch?v=wGJHwc5ksMA'],
|
||||
})
|
||||
|
||||
t.create('video not found')
|
||||
.skipWhen(noYouTubeToken)
|
||||
.get('/doesnotexist.json')
|
||||
.expectBadge({
|
||||
label: 'youtube',
|
||||
message: 'video not found',
|
||||
color: 'red',
|
||||
})
|
||||
71
services/youtube/youtube-likes.service.js
Normal file
71
services/youtube/youtube-likes.service.js
Normal file
@@ -0,0 +1,71 @@
|
||||
'use strict'
|
||||
|
||||
const Joi = require('@hapi/joi')
|
||||
const { metric } = require('../text-formatters')
|
||||
const YouTubeBase = require('./youtube-base')
|
||||
|
||||
const queryParamSchema = Joi.object({
|
||||
withDislikes: Joi.equal(''),
|
||||
}).required()
|
||||
|
||||
module.exports = class YouTubeLikes extends YouTubeBase {
|
||||
static get route() {
|
||||
return {
|
||||
base: 'youtube/likes',
|
||||
pattern: ':videoId',
|
||||
queryParamSchema,
|
||||
}
|
||||
}
|
||||
|
||||
static get examples() {
|
||||
const previewLikes = this.render({
|
||||
statistics: { likeCount: 7 },
|
||||
videoId: 'abBdk8bSPKU',
|
||||
})
|
||||
const previewVotes = this.render(
|
||||
{
|
||||
statistics: { likeCount: 10236, dislikeCount: 396 },
|
||||
videoId: 'pU9Q6oiQNd0',
|
||||
},
|
||||
{
|
||||
withDislikes: '',
|
||||
}
|
||||
)
|
||||
// link[] is not allowed in examples
|
||||
delete previewLikes.link
|
||||
delete previewVotes.link
|
||||
return [
|
||||
{
|
||||
title: 'YouTube Video Likes',
|
||||
namedParams: { videoId: 'abBdk8bSPKU' },
|
||||
staticPreview: previewLikes,
|
||||
},
|
||||
{
|
||||
title: 'YouTube Video Votes',
|
||||
namedParams: { videoId: 'pU9Q6oiQNd0' },
|
||||
staticPreview: previewVotes,
|
||||
queryParams: {
|
||||
withDislikes: null,
|
||||
},
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
static render({ statistics, videoId }, queryParams) {
|
||||
if (queryParams && typeof queryParams.withDislikes !== 'undefined') {
|
||||
return {
|
||||
label: 'votes',
|
||||
message: `${metric(statistics.likeCount)} 👍 ${metric(
|
||||
statistics.dislikeCount
|
||||
)} 👎`,
|
||||
style: 'social',
|
||||
link: `https://www.youtube.com/watch?v=${encodeURIComponent(videoId)}`,
|
||||
}
|
||||
}
|
||||
return super.renderSingleStat({
|
||||
statistics,
|
||||
statisticName: 'like',
|
||||
videoId,
|
||||
})
|
||||
}
|
||||
}
|
||||
38
services/youtube/youtube-likes.tester.js
Normal file
38
services/youtube/youtube-likes.tester.js
Normal file
@@ -0,0 +1,38 @@
|
||||
'use strict'
|
||||
|
||||
const Joi = require('@hapi/joi')
|
||||
const t = (module.exports = require('../tester').createServiceTester())
|
||||
const { noToken } = require('../test-helpers')
|
||||
const { isMetric } = require('../test-validators')
|
||||
const noYouTubeToken = noToken(require('./youtube-likes.service'))
|
||||
|
||||
t.create('video like count')
|
||||
.skipWhen(noYouTubeToken)
|
||||
.get('/pU9Q6oiQNd0.json')
|
||||
.expectBadge({
|
||||
label: 'likes',
|
||||
message: isMetric,
|
||||
color: 'red',
|
||||
link: ['https://www.youtube.com/watch?v=pU9Q6oiQNd0'],
|
||||
})
|
||||
|
||||
t.create('video vote count')
|
||||
.skipWhen(noYouTubeToken)
|
||||
.get('/pU9Q6oiQNd0.json?withDislikes')
|
||||
.expectBadge({
|
||||
label: 'votes',
|
||||
message: Joi.string().regex(
|
||||
/^([1-9][0-9]*[kMGTPEZY]?|[1-9]\.[1-9][kMGTPEZY]) 👍 ([1-9][0-9]*[kMGTPEZY]?|[1-9]\.[1-9][kMGTPEZY]) 👎$/
|
||||
),
|
||||
color: 'red',
|
||||
link: ['https://www.youtube.com/watch?v=pU9Q6oiQNd0'],
|
||||
})
|
||||
|
||||
t.create('video not found')
|
||||
.skipWhen(noYouTubeToken)
|
||||
.get('/doesnotexist.json?withDislikes')
|
||||
.expectBadge({
|
||||
label: 'youtube',
|
||||
message: 'video not found',
|
||||
color: 'red',
|
||||
})
|
||||
36
services/youtube/youtube-views.service.js
Normal file
36
services/youtube/youtube-views.service.js
Normal file
@@ -0,0 +1,36 @@
|
||||
'use strict'
|
||||
|
||||
const YouTubeBase = require('./youtube-base')
|
||||
|
||||
module.exports = class YouTubeViews extends YouTubeBase {
|
||||
static get route() {
|
||||
return {
|
||||
base: 'youtube/views',
|
||||
pattern: ':videoId',
|
||||
}
|
||||
}
|
||||
|
||||
static get examples() {
|
||||
const preview = this.render({
|
||||
statistics: { viewCount: 14577 },
|
||||
videoId: 'abBdk8bSPKU',
|
||||
})
|
||||
// link[] is not allowed in examples
|
||||
delete preview.link
|
||||
return [
|
||||
{
|
||||
title: 'YouTube Video Views',
|
||||
namedParams: { videoId: 'abBdk8bSPKU' },
|
||||
staticPreview: preview,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
static render({ statistics, videoId }) {
|
||||
return super.renderSingleStat({
|
||||
statistics,
|
||||
statisticName: 'view',
|
||||
videoId,
|
||||
})
|
||||
}
|
||||
}
|
||||
25
services/youtube/youtube-views.tester.js
Normal file
25
services/youtube/youtube-views.tester.js
Normal file
@@ -0,0 +1,25 @@
|
||||
'use strict'
|
||||
|
||||
const t = (module.exports = require('../tester').createServiceTester())
|
||||
const { noToken } = require('../test-helpers')
|
||||
const { isMetric } = require('../test-validators')
|
||||
const noYouTubeToken = noToken(require('./youtube-views.service'))
|
||||
|
||||
t.create('video view count')
|
||||
.skipWhen(noYouTubeToken)
|
||||
.get('/abBdk8bSPKU.json')
|
||||
.expectBadge({
|
||||
label: 'views',
|
||||
message: isMetric,
|
||||
color: 'red',
|
||||
link: ['https://www.youtube.com/watch?v=abBdk8bSPKU'],
|
||||
})
|
||||
|
||||
t.create('video not found')
|
||||
.skipWhen(noYouTubeToken)
|
||||
.get('/doesnotexist.json')
|
||||
.expectBadge({
|
||||
label: 'youtube',
|
||||
message: 'video not found',
|
||||
color: 'red',
|
||||
})
|
||||
3
static/images/heroku-logotype-horizontal-purple.svg
Normal file
3
static/images/heroku-logotype-horizontal-purple.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="268" height="80" viewBox="0 0 268 80">
|
||||
<path fill="#430098" fill-rule="evenodd" d="M64.8,0 C68.776,0 72,3.224 72,7.2 L72,7.2 L72,72.8 C72,76.776 68.776,80 64.8,80 L64.8,80 L7.2,80 C3.224,80 0,76.776 0,72.8 L0,72.8 L0,7.2 C0,3.224 3.224,0 7.2,0 L7.2,0 Z M64.8,4 L7.2,4 C5.436,4 4,5.435 4,7.2 L4,7.2 L4,72.8 C4,74.564 5.436,76 7.2,76 L7.2,76 L64.8,76 C66.565,76 68,74.564 68,72.8 L68,72.8 L68,7.2 C68,5.435 66.565,4 64.8,4 L64.8,4 Z M19,52 L28,60 L19,68 L19,52 Z M27,12 L27,34.711 C30.994,33.411 36.577,32 42,32 C46.945,32 49.905,33.944 51.517,35.575 C54.814625,38.91 54.995191,43.1202378 55.0003112,43.9159307 L55.0002258,68 L47,68 L47,44.11 C46.961,42.243 46.062,40 42,40 C34.230209,40 25.5570898,43.7328438 24.7166549,44.1028638 L24.651,44.132 L19,46.692 L19,12 L27,12 Z M191.995,25 C198.5525,25 205.37,29.165 205.37,39.15 C205.37,49.135 198.5525,53.3 191.995,53.3 C185.3975,53.2975 178.5825,49.135 178.5825,39.15 C178.5825,29.1675 185.3975,25 191.995,25 Z M251.99,25.5175 L251.99,41.805 C251.99,45.5625 253.205,47.2575 256.155,47.2575 C259.1025,47.2575 260.28,45.5625 260.28,41.805 L260.28,25.5175 L267.5,25.5175 L267.5,41.84 C267.5,49.0625 264.0375,53.1875 256.0775,53.1875 C248.1175,53.1875 244.62,49.0625 244.62,41.84 L244.62,25.5175 L251.99,25.5175 Z M220.94,25.5175 L220.94,35.3925 L228.4575,25.5175 L237.005,25.5175 L227.83,36.2775 L237.815,52.785 L229.4875,52.785 L223.04,41.8775 L220.94,44.31 L220.94,52.785 L213.57,52.785 L213.57,25.5175 L220.94,25.5175 Z M140.25,25.5175 L140.25,31.635 L128.165,31.635 L128.165,36.0575 L136.7875,36.0575 L136.7875,41.805 L128.165,41.805 L128.165,46.8525 L140.8775,46.8525 L140.8775,52.785 L120.7975,52.785 L120.7975,25.5175 L140.25,25.5175 Z M159.6175,25.5175 C166.6175,25.5175 170.8925,27.84 170.8925,34.3975 C170.8925,38.67 169.0875,41.1425 165.5125,42.355 L171.2975,52.7825 L163.4875,52.7825 L158.2175,43.315 L156.19,43.315 L156.19,52.7825 L148.9675,52.7825 L148.9675,25.5175 L159.6175,25.5175 Z M94.87,25.5175 L94.87,35.65 L103.935,35.65 L103.935,25.5175 L111.305,25.5175 L111.305,52.7825 L103.935,52.7825 L103.935,41.765 L94.87,41.765 L94.87,52.7825 L87.5,52.7825 L87.5,25.5175 L94.87,25.5175 Z M191.9925,31.0825 C188.1225,31.0825 185.95,34.14 185.95,39.15 C185.95,44.1625 188.125,47.405 191.9925,47.405 C195.825,47.4025 197.9975,44.1625 197.9975,39.15 C197.9975,34.14 195.8225,31.0825 191.9925,31.0825 Z M159.36,31.485 L156.1925,31.485 L156.1925,37.7125 L159.36,37.7125 C162.3825,37.7125 163.7075,36.865 163.7075,34.58 C163.7075,32.295 162.38,31.485 159.36,31.485 Z M55,12 C54.46,16.544 52.618,20.9 49,25 L49,25 L41,25 C44.144,20.875 46.118,16.534 47,12 L47,12 Z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.6 KiB |
1
static/images/nodeping.svg
Normal file
1
static/images/nodeping.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="276" height="63"><g fill="none" fill-rule="evenodd"><path d="M.184 4.530182v44.288h6.528v-32.32l21.568 32.32h6.08v-44.288h-6.528v32.64l-21.12-32.64zm56.704 9.6c-8.384 0-14.336 6.144-14.336 17.728 0 11.648 5.888 17.792 14.336 17.792 8.32 0 14.272-6.144 14.272-17.792 0-11.584-6.016-17.728-14.272-17.728zm0 5.632c4.992 0 8.512 4.16 8.512 12.16 0 7.936-3.52 12.096-8.512 12.096-5.12 0-8.512-4.16-8.512-12.096 0-8 3.456-12.16 8.512-12.16zm44.352-16.192v15.296c-2.24-2.752-5.504-4.736-9.92-4.736-9.344 0-12.8 9.024-12.8 17.792 0 8.768 3.456 17.728 12.8 17.728 4.672 0 8.064-2.24 10.304-5.184v4.352h5.696v-47.296zm-8.384 40.448c-6.464 0-8.576-5.76-8.576-12.096s2.112-12.224 8.512-12.224c4.032 0 6.656 2.368 8.448 5.504v13.376c-1.792 3.264-4.416 5.44-8.384 5.44zm51.456-10.048c.064-.704.128-1.408.128-2.24 0-11.328-6.016-17.6-14.336-17.6s-14.272 6.272-14.272 17.6c0 11.904 6.592 17.92 14.656 17.92 6.08 0 9.856-3.392 11.712-5.952l-4.032-3.52c-1.536 2.24-4.096 3.968-7.424 3.968-4.48 0-8.512-3.136-9.216-10.176zm-14.144-14.336c4.544 0 7.872 3.328 8.576 9.792h-17.216c.64-6.272 3.968-9.792 8.64-9.792z" fill="#f60"/><circle r="5" cy="5.818182" cx="197" fill="#f60"/><path d="M153.27148 4.5292969V48.818359h6.5293V32.306641h11.90234c9.02401 0 14.97657-4.672672 14.97657-13.888672 0-9.1520004-5.95256-13.8886721-14.97657-13.8886721h-18.43164zm6.5293 5.9531251h11.9668c5.248 0 8.76758 2.624 8.76758 8 0 5.44-3.51958 8.064453-8.76758 8.064453h-11.9668V10.482422zM200.184 48.818182v-33.856h-6.08v33.856zM209.912 14.962182v33.856h6.08v-22.976c1.856-4.48 4.864-5.952 8.448-5.952 4.48 0 7.424 2.24 7.424 8.128v20.8h6.08v-21.44c0-9.472-4.736-13.248-11.584-13.248-4.608 0-8.192 1.728-10.688 4.992v-4.16zM259.12891 14.130859c-9.408 0-12.86524 8.510672-12.86524 16.638672s3.45724 16.640625 12.86524 16.640625c4.608 0 7.99828-1.984328 10.23828-4.736328v1.216797c0 7.296-4.03191 10.622828-13.50391 12.798828l.70508 5.441406c12.928-2.496 18.49609-7.489343 18.49609-19.777343V14.962891h-5.69726v3.966797c-2.24-2.752-5.63028-4.798829-10.23828-4.798829zm1.53515 5.503907c4.224 0 6.91113 2.239906 8.70313 5.503906v11.390625c-1.792 3.2-4.47958 5.568359-8.76758 5.568359-6.464 0-8.57617-5.439672-8.57617-11.263672 0-5.76 2.11262-11.199218 8.64062-11.199218z" fill="#111"/></g></svg>
|
||||
|
After Width: | Height: | Size: 2.2 KiB |
1
static/images/sentry-logo-black.svg
Normal file
1
static/images/sentry-logo-black.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 717.11 249.68"><path d="M444.45421 148.31906L391.7068 80.229964h-13.1246V171.5213h13.30244v-69.95051l54.22942 69.95051h11.64261V80.229964h-13.30246zm-132.78737-16.91853h47.23435V119.5445H311.6194V92.062268h53.35208V80.206251h-66.92721v91.291329h67.57928v-11.85602H311.6194zm-55.53359-11.59519c-18.45983-4.41043-23.51047-7.93168-23.51047-16.40873 0-7.658976 6.76978-12.816344 16.85924-12.816344 8.40592 0 16.68141 2.97586 25.25332 9.093565l7.18474-10.125039c-9.48481-7.267737-19.74026-10.670414-32.16537-10.670414-18.08043 0-30.69523 10.670414-30.69523 25.988392 0 16.40873 10.67041 22.08776 30.23285 26.83015 17.20307 3.97176 22.44344 7.70644 22.44344 16.00563 0 8.29922-7.11363 13.49215-18.19901 13.49215-10.75339 0-19.92994-3.55681-29.64002-11.64261l-8.05024 9.57967a56.695472 56.695472 0 0037.23975 13.75296c19.55057 0 32.17724-10.51627 32.17724-26.79458-.0239-13.81225-8.19251-21.19856-29.17766-26.2848zm443.29646-39.56352L671.9356 123.291l-27.26884-43.04918h-15.92261l36.1727 55.17791v36.12528h13.70555v-36.54023l36.16085-54.76296zM468.53378 92.59579h29.91274v78.93735h13.7174V92.59579h29.91275V80.229964h-73.5073zm136.97258 43.29819c13.80039-3.80579 21.34083-13.48031 21.34083-27.26884 0-17.523209-12.85193-28.454456-33.52884-28.454456h-40.45271v91.291326h13.57512v-32.79374h23.0244l23.16665 32.86487h15.8515l-25.0162-35.07008zm-39.12487-8.91576V92.3231h25.609c13.36173 0 21.03256 6.295546 21.03256 17.26237 0 10.5637-8.20436 17.39275-20.89029 17.39275zM105.77525 55.45089a16.302024 16.302024 0 00-28.229161 0L54.308296 95.702065l5.928009 3.402672a113.98374 113.98374 0 0156.707315 91.765573h-16.31387a97.693576 97.693576 0 00-48.609665-77.70434l-5.928008-3.3908-21.649086 37.64284 5.928007 3.40269a54.952636 54.952636 0 0126.628613 40.04961H19.736152a2.6913158 2.6913158 0 01-2.371203-4.04289l10.38587-17.98558a37.785126 37.785126 0 00-11.856017-6.76979l-10.2791668 17.95a16.302024 16.302024 0 0014.1205168 24.44711h51.277271v-6.79349a67.768991 67.768991 0 00-28.146182-55.00006l8.156939-14.13238a84.094727 84.094727 0 0136.231981 69.07316v6.80533h43.452299v-6.79347A127.59446 127.59446 0 0072.803683 90.864811l16.491714-28.608568a2.6913158 2.6913158 0 014.65942 0L165.8734 186.82742a2.6913158 2.6913158 0 01-2.37122 4.04289h-16.82367c.21341 4.54085.23711 9.08172 0 13.61069h16.88295a16.302024 16.302024 0 0014.12053-24.4471z" fill="#221f20"/></svg>
|
||||
|
After Width: | Height: | Size: 2.4 KiB |
Reference in New Issue
Block a user