📦 version 3 (#4756)
* Validate input to BadgeFactory.create() (#3875) * validate input to create() * remove deprecated properties (#3881) * remove BadgeFactory class (#3884) * Template literal templates (#4459) - Remove use of the doT template library and move to generating SVG output using javascript template literals. - Drop SVGO and mostly manually implement the optimisations. - Add a bunch more tests Co-authored-by: Paul Melnikow <github@paulmelnikow.com> * drop raster support in package CLI (#4523) * drop raster support in package CLI * update docs * rename gh-badges package to badge-maker * rename gh-badges dir to badge-maker * update relative imports and other refs to in parent dir 'gh-badges' --> 'badge-maker' * update snyk service tests This change is only tangentially related We've used the shields repo as an example for these tests so moving files around in our repo has a knock-on effect on them * add missing type hints to dev style page * write the changelog/migration guide for v3 * use extension in README CLI example * update CLI help whoops - missed this in #4523 * bump version * update for self-hosting users * README updates * drop .format param from CLI, always output SVG * Change text[] to label and message, Remove JSON output - Change text[] to label and message - Fix message only badge - Remove JSON output format - Update the docs * update package-lock * rename 'template' to 'style' * handle invalid styles in coalesceBadge * ensure makeBadge is passed a string for template in coalesceBadge() issue #4925 * fix (logo/no label text/label color specified) case issue #4926 * add example of (logo/no label text/label color specified) to style debug page * update type defs * padding fix for FTB style Co-authored-by: Paul Melnikow <github@paulmelnikow.com>
This commit is contained in:
@@ -5,8 +5,8 @@ RUN mkdir /usr/src/app/private
|
||||
WORKDIR /usr/src/app
|
||||
|
||||
COPY package.json package-lock.json /usr/src/app/
|
||||
# Without the gh-badges package.json and CLI script in place, `npm ci` will fail.
|
||||
COPY gh-badges /usr/src/app/gh-badges/
|
||||
# Without the badge-maker package.json and CLI script in place, `npm ci` will fail.
|
||||
COPY badge-maker /usr/src/app/badge-maker/
|
||||
|
||||
# We need dev deps to build the front end. We don't need Cypress, though.
|
||||
RUN NODE_ENV=development CYPRESS_INSTALL_BINARY=0 npm ci
|
||||
|
||||
12
README.md
12
README.md
@@ -43,16 +43,16 @@ Every month it serves over 470 million images.
|
||||
This repo hosts:
|
||||
|
||||
- The [Shields.io][shields.io] frontend and server code
|
||||
- An [NPM library for generating badges][gh-badges]
|
||||
- [documentation][gh-badges-docs]
|
||||
- [changelog][gh-badges-changelog]
|
||||
- An [NPM library for generating badges][badge-maker]
|
||||
- [documentation][badge-maker-docs]
|
||||
- [changelog][badge-maker-changelog]
|
||||
- The [badge design specification][badge-spec]
|
||||
|
||||
[shields.io]: https://shields.io/
|
||||
[gh-badges]: https://www.npmjs.com/package/gh-badges
|
||||
[badge-maker]: https://www.npmjs.com/package/badge-maker
|
||||
[badge-spec]: https://github.com/badges/shields/tree/master/spec
|
||||
[gh-badges-docs]: https://github.com/badges/shields/tree/master/gh-badges/README.md
|
||||
[gh-badges-changelog]: https://github.com/badges/shields/tree/master/gh-badges/CHANGELOG.md
|
||||
[badge-maker-docs]: https://github.com/badges/shields/tree/master/badge-maker/README.md
|
||||
[badge-maker-changelog]: https://github.com/badges/shields/tree/master/badge-maker/CHANGELOG.md
|
||||
|
||||
## Examples
|
||||
|
||||
|
||||
@@ -1,19 +1,127 @@
|
||||
exports['The badge generator SVG should always produce the same SVG (unless we have changed something!) 1'] = `
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="90" height="20"><linearGradient id="b" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="a"><rect width="90" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#a)"><path fill="#555" d="M0 0h45v20H0z"/><path fill="#4c1" d="M45 0h45v20H45z"/><path fill="url(#b)" d="M0 0h90v20H0z"/></g><g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" 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>
|
||||
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="DejaVu Sans,Verdana,Geneva,sans-serif" 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>
|
||||
`
|
||||
|
||||
exports['The badge generator badges with logos should always produce the same badge shields GitHub logo custom color (whitesmoke) 1'] = `
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="113" height="20"><linearGradient id="b" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="a"><rect width="113" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#a)"><path fill="#555" d="M0 0h54v20H0z"/><path fill="#4c1" d="M54 0h59v20H54z"/><path fill="url(#b)" d="M0 0h113v20H0z"/></g><g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="110"><image x="5" y="3" width="14" height="14" xlink:href="github"/> <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>
|
||||
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="DejaVu Sans,Verdana,Geneva,sans-serif" 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>
|
||||
`
|
||||
|
||||
exports['The badge generator badges with logos should always produce the same badge shields GitHub logo default color (#333333) 1'] = `
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="113" height="20"><linearGradient id="b" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="a"><rect width="113" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#a)"><path fill="#555" d="M0 0h54v20H0z"/><path fill="#4c1" d="M54 0h59v20H54z"/><path fill="url(#b)" d="M0 0h113v20H0z"/></g><g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="110"><image x="5" y="3" width="14" height="14" xlink:href="github"/> <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>
|
||||
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="DejaVu Sans,Verdana,Geneva,sans-serif" 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>
|
||||
`
|
||||
|
||||
exports['The badge generator badges with logos should always produce the same badge simple-icons javascript logo custom color (rgba(46,204,113,0.8)) 1'] = `
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="113" height="20"><linearGradient id="b" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="a"><rect width="113" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#a)"><path fill="#555" d="M0 0h54v20H0z"/><path fill="#4c1" d="M54 0h59v20H54z"/><path fill="url(#b)" d="M0 0h113v20H0z"/></g><g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="110"><image x="5" y="3" width="14" height="14" xlink:href="javascript"/> <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>
|
||||
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="DejaVu Sans,Verdana,Geneva,sans-serif" 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>
|
||||
`
|
||||
|
||||
exports['The badge generator badges with logos should always produce the same badge simple-icons javascript logo default color (#F7DF1E) 1'] = `
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="113" height="20"><linearGradient id="b" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="a"><rect width="113" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#a)"><path fill="#555" d="M0 0h54v20H0z"/><path fill="#4c1" d="M54 0h59v20H54z"/><path fill="url(#b)" d="M0 0h113v20H0z"/></g><g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="110"><image x="5" y="3" width="14" height="14" xlink:href="javascript"/> <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>
|
||||
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="DejaVu Sans,Verdana,Geneva,sans-serif" 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>
|
||||
`
|
||||
|
||||
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="DejaVu Sans,Verdana,Geneva,sans-serif" 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>
|
||||
`
|
||||
|
||||
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="DejaVu Sans,Verdana,Geneva,sans-serif" 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="NaN" height="20" fill="rgba(0,0,0,0)"/></a><a target="_blank" xlink:href="https://shields.io/"><rect width="undefined" height="20" fill="rgba(0,0,0,0)"/></a></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="DejaVu Sans,Verdana,Geneva,sans-serif" 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>
|
||||
`
|
||||
|
||||
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="DejaVu Sans,Verdana,Geneva,sans-serif" 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>
|
||||
`
|
||||
|
||||
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="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="110"><text x="225" y="140" transform="scale(.1)" 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="DejaVu Sans,Verdana,Geneva,sans-serif" 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>
|
||||
`
|
||||
|
||||
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="DejaVu Sans,Verdana,Geneva,sans-serif" 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>
|
||||
`
|
||||
|
||||
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="DejaVu Sans,Verdana,Geneva,sans-serif" 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="NaN" height="20" fill="rgba(0,0,0,0)"/></a><a target="_blank" xlink:href="https://shields.io/"><rect width="undefined" height="20" fill="rgba(0,0,0,0)"/></a></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="DejaVu Sans,Verdana,Geneva,sans-serif" 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>
|
||||
`
|
||||
|
||||
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="DejaVu Sans,Verdana,Geneva,sans-serif" 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>
|
||||
`
|
||||
|
||||
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="DejaVu Sans,Verdana,Geneva,sans-serif" 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>
|
||||
`
|
||||
|
||||
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="DejaVu Sans,Verdana,Geneva,sans-serif" 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>
|
||||
`
|
||||
|
||||
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="DejaVu Sans,Verdana,Geneva,sans-serif" 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>
|
||||
`
|
||||
|
||||
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="DejaVu Sans,Verdana,Geneva,sans-serif" 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="NaN" height="18" fill="rgba(0,0,0,0)"/></a><a target="_blank" xlink:href="https://shields.io/"><rect width="undefined" height="18" fill="rgba(0,0,0,0)"/></a></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="DejaVu Sans,Verdana,Geneva,sans-serif" 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>
|
||||
`
|
||||
|
||||
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="DejaVu Sans,Verdana,Geneva,sans-serif" 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>
|
||||
`
|
||||
|
||||
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="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="100"><text 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="DejaVu Sans,Verdana,Geneva,sans-serif" 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>
|
||||
`
|
||||
|
||||
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="DejaVu Sans,Verdana,Geneva,sans-serif" 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>
|
||||
`
|
||||
|
||||
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="DejaVu Sans,Verdana,Geneva,sans-serif" 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="NaN" height="28" fill="rgba(0,0,0,0)"/></a><a target="_blank" xlink:href="https://shields.io/"><rect width="undefined" height="28" fill="rgba(0,0,0,0)"/></a></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" 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>
|
||||
`
|
||||
|
||||
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" 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>
|
||||
`
|
||||
|
||||
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" 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>
|
||||
`
|
||||
|
||||
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" 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>
|
||||
`
|
||||
|
||||
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" 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>
|
||||
`
|
||||
|
||||
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" 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>
|
||||
`
|
||||
|
||||
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="DejaVu Sans,Verdana,Geneva,sans-serif" 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>
|
||||
`
|
||||
|
||||
@@ -1,6 +1,67 @@
|
||||
# Changelog
|
||||
|
||||
## 2.2.1
|
||||
## 3.0.0
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
- Package name has changed to `badge-maker` and moved to https://www.npmjs.com/package/badge-maker
|
||||
- `BadgeFactory` class is removed and replaced by `makeBadge()` function.
|
||||
- Deprecated parameters have been removed. In version 2.2.0 the `colorA`, `colorB` and `colorscheme` params were deprecated. In version 3.0.0 these have been removed.
|
||||
- Only SVG output format is now provided. JSON format has been dropped and the `format` key has been removed.
|
||||
- The `text` array has been replaced by `label` and `message` keys.
|
||||
- The `template` key has been renamed `style`.
|
||||
To upgrade from v2.1.1, change your code from:
|
||||
```js
|
||||
const { BadgeFactory } = require('gh-badges')
|
||||
const bf = new BadgeFactory()
|
||||
const svg = bf.create({
|
||||
text: ['build', 'passed'],
|
||||
format: 'svg',
|
||||
template: 'flat-square',
|
||||
})
|
||||
```
|
||||
to:
|
||||
```js
|
||||
const { makeBadge } = require('badge-maker')
|
||||
const svg = makeBadge({
|
||||
label: 'build',
|
||||
message: 'passed',
|
||||
style: 'flat-square',
|
||||
})
|
||||
```
|
||||
- `ValidationError` had been added and inputs are now validated. In previous releases, invalid inputs would be discarded and replaced with defaults. For example, in 2.2.1
|
||||
```js
|
||||
const { BadgeFactory } = require('gh-badges')
|
||||
const bf = new BadgeFactory()
|
||||
const svg = bf.create({
|
||||
text: ['build', 'passed'],
|
||||
template: 'some invalid value',
|
||||
})
|
||||
```
|
||||
would generate an SVG badge. In version >=3
|
||||
```js
|
||||
const { makeBadge } = require('badge-maker')
|
||||
const svg = makeBadge({
|
||||
label: 'build',
|
||||
message: 'passed',
|
||||
style: 'some invalid value',
|
||||
})
|
||||
```
|
||||
will throw a `ValidationError`.
|
||||
- Raster support has been removed from the CLI. It will now only output SVG. On the console, the output of `badge` can be piped to a utility like [imagemagick](https://imagemagick.org/script/command-line-processing.php). If you were previously using
|
||||
```sh
|
||||
badge build passed :green .gif
|
||||
```
|
||||
this could be replaced by
|
||||
```sh
|
||||
badge build passed :green | magick svg:- gif:-
|
||||
```
|
||||
|
||||
### Security
|
||||
|
||||
- Removed dependency on doT library which has known vulnerabilities.
|
||||
|
||||
## 2.2.1 - 2019-05-30
|
||||
|
||||
### Fixes
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
# gh-badges
|
||||
# badge-maker
|
||||
|
||||
[](https://npmjs.org/package/gh-badges)
|
||||
[](https://npmjs.org/package/gh-badges)
|
||||
[](https://npmjs.org/package/badge-maker)
|
||||
[](https://npmjs.org/package/badge-maker)
|
||||
|
||||
## Installation
|
||||
|
||||
```sh
|
||||
npm install gh-badges
|
||||
npm install badge-maker
|
||||
```
|
||||
|
||||
## Usage
|
||||
@@ -14,29 +14,34 @@ npm install gh-badges
|
||||
### On the console
|
||||
|
||||
```sh
|
||||
npm install -g gh-badges
|
||||
badge build passed :green .png > mybadge.png
|
||||
npm install -g badge-maker
|
||||
badge build passed :green > mybadge.svg
|
||||
```
|
||||
|
||||
### As a library
|
||||
|
||||
```js
|
||||
const { BadgeFactory } = require('gh-badges')
|
||||
|
||||
const bf = new BadgeFactory()
|
||||
const { makeBadge, ValidationError } = require('badge-maker')
|
||||
|
||||
const format = {
|
||||
text: ['build', 'passed'],
|
||||
label: 'build',
|
||||
message: 'passed',
|
||||
color: 'green',
|
||||
template: 'flat',
|
||||
}
|
||||
|
||||
const svg = bf.create(format)
|
||||
const svg = makeBadge(format)
|
||||
console.log(svg) // <svg...
|
||||
|
||||
try {
|
||||
makeBadge({})
|
||||
} catch (e) {
|
||||
console.log(e) // ValidationError: Field `message` is required
|
||||
}
|
||||
```
|
||||
|
||||
### Node version support
|
||||
|
||||
The latest version of gh-badges supports all currently maintained Node
|
||||
The latest version of badge-maker supports all currently maintained Node
|
||||
versions. See the [Node Release Schedule][].
|
||||
|
||||
[node release schedule]: https://github.com/nodejs/Release#release-schedule
|
||||
@@ -47,28 +52,17 @@ The format is the following:
|
||||
|
||||
```js
|
||||
{
|
||||
text: [ 'build', 'passed' ], // Textual information shown, in order
|
||||
label: 'build', // (Optional) Badge label
|
||||
message: 'passed', // (Required) Badge message
|
||||
labelColor: '#555', // (Optional) Label color
|
||||
color: '#4c1', // (Optional) Message color
|
||||
|
||||
format: 'svg', // Also supports json
|
||||
|
||||
color: '#4c1',
|
||||
labelColor: '#555',
|
||||
|
||||
// See templates/ for a list of available templates.
|
||||
// (Optional) One of: 'plastic', 'flat', 'flat-square', 'for-the-badge' or 'social'
|
||||
// Each offers a different visual design.
|
||||
template: 'flat',
|
||||
|
||||
// Deprecated attributes:
|
||||
colorscheme: 'green', // Now an alias for `color`.
|
||||
colorB: '#4c1', // Now an alias for `color`.
|
||||
colorA: '#555', // Now an alias for `labelColor`.
|
||||
style: 'flat',
|
||||
}
|
||||
```
|
||||
|
||||
### See also
|
||||
|
||||
- [templates/](./templates) for the `template` option
|
||||
|
||||
## Colors
|
||||
|
||||
There are three ways to specify `color` and `labelColor`:
|
||||
@@ -126,3 +120,12 @@ There are three ways to specify `color` and `labelColor`:
|
||||
[lightslategray]: https://img.shields.io/badge/lightslategray-lightslategray.svg
|
||||
[css color]: https://developer.mozilla.org/en-US/docs/Web/CSS/color_value
|
||||
[css/svg color]: http://www.w3.org/TR/SVG/types.html#DataTypeColor
|
||||
|
||||
## Raster Formats
|
||||
|
||||
Conversion to raster formats is no longer directly supported. In javascript
|
||||
code, SVG badges can be converted to raster formats using a library like
|
||||
[gm](https://www.npmjs.com/package/gm). On the console, the output of `badge`
|
||||
can be piped to a utility like
|
||||
[imagemagick](https://imagemagick.org/script/command-line-processing.php)
|
||||
e.g: `badge build passed :green | magick svg:- gif:-`.
|
||||
@@ -2,23 +2,18 @@
|
||||
|
||||
'use strict'
|
||||
|
||||
const makeBadge = require('./make-badge')
|
||||
const svg2img = require('./svg-to-img')
|
||||
const { namedColors } = require('./color')
|
||||
const { makeBadge } = require('./index')
|
||||
|
||||
if (process.argv.length < 4) {
|
||||
console.log('Usage: badge subject status [:color] [.output] [@style]')
|
||||
console.log(
|
||||
'Or: badge subject status color [labelColor] [.output] [@style]'
|
||||
)
|
||||
console.log('Usage: badge label message [:color] [@style]')
|
||||
console.log('Or: badge label message color [labelColor] [@style]')
|
||||
console.log()
|
||||
console.log(' color, labelColor:')
|
||||
console.log(` one of ${Object.keys(namedColors).join(', ')}.`)
|
||||
console.log(' #xxx (three hex digits)')
|
||||
console.log(' #xxxxxx (six hex digits)')
|
||||
console.log(' color (CSS color)')
|
||||
console.log(' output:')
|
||||
console.log(' svg, png, jpg, or gif')
|
||||
console.log()
|
||||
console.log('Eg: badge cactus grown :green @flat')
|
||||
console.log()
|
||||
@@ -26,14 +21,8 @@ if (process.argv.length < 4) {
|
||||
}
|
||||
|
||||
// Find a format specifier.
|
||||
let format = 'svg'
|
||||
let style = ''
|
||||
for (let i = 4; i < process.argv.length; i++) {
|
||||
if (process.argv[i][0] === '.') {
|
||||
format = process.argv[i].slice(1)
|
||||
process.argv.splice(i, 1)
|
||||
continue
|
||||
}
|
||||
if (process.argv[i][0] === '@') {
|
||||
style = process.argv[i].slice(1)
|
||||
process.argv.splice(i, 1)
|
||||
@@ -41,14 +30,14 @@ for (let i = 4; i < process.argv.length; i++) {
|
||||
}
|
||||
}
|
||||
|
||||
const subject = process.argv[2]
|
||||
const status = process.argv[3]
|
||||
const label = process.argv[2]
|
||||
const message = process.argv[3]
|
||||
let color = process.argv[4] || ':green'
|
||||
const colorA = process.argv[5]
|
||||
const labelColor = process.argv[5]
|
||||
|
||||
const badgeData = { text: [subject, status], format }
|
||||
const badgeData = { label, message }
|
||||
if (style) {
|
||||
badgeData.template = style
|
||||
badgeData.style = style
|
||||
}
|
||||
|
||||
if (color[0] === ':') {
|
||||
@@ -58,28 +47,17 @@ if (color[0] === ':') {
|
||||
console.error('Invalid color scheme.')
|
||||
process.exit(1)
|
||||
}
|
||||
badgeData.colorscheme = color
|
||||
badgeData.color = color
|
||||
} else {
|
||||
badgeData.colorB = color
|
||||
if (colorA) {
|
||||
badgeData.colorA = colorA
|
||||
badgeData.color = color
|
||||
if (labelColor) {
|
||||
badgeData.labelColor = labelColor
|
||||
}
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const svg = makeBadge(badgeData)
|
||||
|
||||
if (/png|jpg|gif/.test(format)) {
|
||||
const data = await svg2img(svg, format)
|
||||
process.stdout.write(data)
|
||||
} else {
|
||||
console.log(svg)
|
||||
}
|
||||
}
|
||||
|
||||
;(async () => {
|
||||
;(() => {
|
||||
try {
|
||||
await main()
|
||||
console.log(makeBadge(badgeData))
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
process.exit(1)
|
||||
@@ -1,7 +1,6 @@
|
||||
'use strict'
|
||||
|
||||
const path = require('path')
|
||||
const isPng = require('is-png')
|
||||
const isSvg = require('is-svg')
|
||||
const { spawn } = require('child-process-promise')
|
||||
const { expect, use } = require('chai')
|
||||
@@ -39,19 +38,4 @@ describe('The CLI', function() {
|
||||
.to.satisfy(isSvg)
|
||||
.and.to.include('#abcdef')
|
||||
})
|
||||
|
||||
it('should produce PNG badges', async function() {
|
||||
const child = runCli(['cactus', 'grown', '.png'])
|
||||
|
||||
// The buffering done by `child-process-promise` doesn't seem correctly to
|
||||
// handle binary data.
|
||||
let chunk
|
||||
child.childProcess.stdout.once('data', data => {
|
||||
chunk = data
|
||||
})
|
||||
|
||||
await child
|
||||
|
||||
expect(chunk).to.satisfy(isPng)
|
||||
})
|
||||
})
|
||||
611
badge-maker/lib/badge-renderers.js
Normal file
611
badge-maker/lib/badge-renderers.js
Normal file
@@ -0,0 +1,611 @@
|
||||
'use strict'
|
||||
|
||||
const anafanafo = require('anafanafo')
|
||||
|
||||
const fontFamily = 'font-family="DejaVu Sans,Verdana,Geneva,sans-serif"'
|
||||
const socialFontFamily =
|
||||
'font-family="Helvetica Neue,Helvetica,Arial,sans-serif"'
|
||||
|
||||
function capitalize(s) {
|
||||
return `${s.charAt(0).toUpperCase()}${s.slice(1)}`
|
||||
}
|
||||
|
||||
function escapeXml(s) {
|
||||
if (s === undefined || typeof s !== 'string') {
|
||||
return undefined
|
||||
} else {
|
||||
return s
|
||||
.replace(/&/g, '&')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>')
|
||||
.replace(/"/g, '"')
|
||||
.replace(/'/g, ''')
|
||||
}
|
||||
}
|
||||
|
||||
function roundUpToOdd(val) {
|
||||
// Increase chances of pixel grid alignment.
|
||||
return val % 2 === 0 ? val + 1 : val
|
||||
}
|
||||
|
||||
function preferredWidthOf(str) {
|
||||
return roundUpToOdd((anafanafo(str) / 10) | 0)
|
||||
}
|
||||
|
||||
function computeWidths({ label, message }) {
|
||||
return {
|
||||
labelWidth: preferredWidthOf(label),
|
||||
messageWidth: preferredWidthOf(message),
|
||||
}
|
||||
}
|
||||
|
||||
function renderLogo({
|
||||
logo,
|
||||
badgeHeight,
|
||||
horizPadding,
|
||||
logoWidth = 14,
|
||||
logoPadding = 0,
|
||||
}) {
|
||||
if (!logo) {
|
||||
return {
|
||||
hasLogo: false,
|
||||
totalLogoWidth: 0,
|
||||
renderedLogo: '',
|
||||
}
|
||||
}
|
||||
const y = (badgeHeight - logoWidth) / 2
|
||||
const x = horizPadding
|
||||
return {
|
||||
hasLogo: true,
|
||||
totalLogoWidth: logoWidth + logoPadding,
|
||||
renderedLogo: `<image x="${x}" y="${y}" width="${logoWidth}" height="14" xlink:href="${escapeXml(
|
||||
logo
|
||||
)}"/>`,
|
||||
}
|
||||
}
|
||||
|
||||
function renderText({
|
||||
leftMargin,
|
||||
horizPadding = 0,
|
||||
content,
|
||||
verticalMargin = 0,
|
||||
shadow = false,
|
||||
}) {
|
||||
if (!content.length) {
|
||||
return { renderedText: '', width: 0 }
|
||||
}
|
||||
|
||||
const textLength = preferredWidthOf(content)
|
||||
const escapedContent = escapeXml(content)
|
||||
|
||||
const shadowMargin = 150 + verticalMargin
|
||||
const textMargin = 140 + verticalMargin
|
||||
|
||||
const outTextLength = 10 * textLength
|
||||
const x = 10 * (leftMargin + 0.5 * textLength + horizPadding)
|
||||
|
||||
let renderedText = ''
|
||||
if (shadow) {
|
||||
renderedText = `<text 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>`
|
||||
|
||||
return {
|
||||
renderedText,
|
||||
width: textLength,
|
||||
}
|
||||
}
|
||||
|
||||
function renderLinks({
|
||||
links: [leftLink, rightLink] = [],
|
||||
labelWidth,
|
||||
messageWidth,
|
||||
height,
|
||||
}) {
|
||||
leftLink = escapeXml(leftLink)
|
||||
rightLink = escapeXml(rightLink)
|
||||
const hasLeftLink = leftLink && leftLink.length
|
||||
const hasRightLink = rightLink && rightLink.length
|
||||
const leftLinkWidth = hasRightLink ? labelWidth : labelWidth + messageWidth
|
||||
|
||||
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: labelWidth + messageWidth })
|
||||
: '') +
|
||||
(hasLeftLink ? render({ link: leftLink, width: leftLinkWidth }) : '')
|
||||
)
|
||||
}
|
||||
|
||||
function renderBadge({ links, leftWidth, rightWidth, height }, main) {
|
||||
const width = leftWidth + rightWidth
|
||||
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>`
|
||||
}
|
||||
|
||||
function stripXmlWhitespace(xml) {
|
||||
return xml
|
||||
.replace(/>\s+/g, '>')
|
||||
.replace(/<\s+/g, '<')
|
||||
.trim()
|
||||
}
|
||||
|
||||
class Badge {
|
||||
static get fontFamily() {
|
||||
throw new Error('Not implemented')
|
||||
}
|
||||
|
||||
static get height() {
|
||||
throw new Error('Not implemented')
|
||||
}
|
||||
|
||||
static get verticalMargin() {
|
||||
throw new Error('Not implemented')
|
||||
}
|
||||
|
||||
static get shadow() {
|
||||
throw new Error('Not implemented')
|
||||
}
|
||||
|
||||
constructor({
|
||||
label,
|
||||
message,
|
||||
links,
|
||||
logo,
|
||||
logoWidth,
|
||||
logoPadding,
|
||||
color = '#4c1',
|
||||
labelColor,
|
||||
}) {
|
||||
const horizPadding = 5
|
||||
const { hasLogo, totalLogoWidth, renderedLogo } = renderLogo({
|
||||
logo,
|
||||
badgeHeight: this.constructor.height,
|
||||
horizPadding,
|
||||
logoWidth,
|
||||
logoPadding,
|
||||
})
|
||||
const hasLabel = label.length || labelColor
|
||||
if (labelColor == null) {
|
||||
labelColor = '#555'
|
||||
}
|
||||
|
||||
labelColor = hasLabel || hasLogo ? labelColor : color
|
||||
labelColor = escapeXml(labelColor)
|
||||
color = escapeXml(color)
|
||||
|
||||
const labelMargin = totalLogoWidth + 1
|
||||
|
||||
const { renderedText: renderedLabel, width: labelWidth } = renderText({
|
||||
leftMargin: labelMargin,
|
||||
horizPadding,
|
||||
content: label,
|
||||
verticalMargin: this.constructor.verticalMargin,
|
||||
shadow: this.constructor.shadow,
|
||||
})
|
||||
|
||||
const leftWidth = hasLabel
|
||||
? labelWidth + 2 * horizPadding + totalLogoWidth
|
||||
: 0
|
||||
|
||||
let messageMargin = leftWidth - (message.length ? 1 : 0)
|
||||
if (!hasLabel) {
|
||||
if (hasLogo) {
|
||||
messageMargin = messageMargin + totalLogoWidth + horizPadding
|
||||
} else {
|
||||
messageMargin = messageMargin + 1
|
||||
}
|
||||
}
|
||||
|
||||
const { renderedText: renderedMessage, width: messageWidth } = renderText({
|
||||
leftMargin: messageMargin,
|
||||
horizPadding,
|
||||
content: message,
|
||||
verticalMargin: this.constructor.verticalMargin,
|
||||
shadow: this.constructor.shadow,
|
||||
})
|
||||
|
||||
let rightWidth = messageWidth + 2 * horizPadding
|
||||
if (hasLogo && !hasLabel) {
|
||||
rightWidth += totalLogoWidth + horizPadding - 1
|
||||
}
|
||||
|
||||
const width = leftWidth + rightWidth
|
||||
|
||||
this.links = links
|
||||
this.leftWidth = leftWidth
|
||||
this.rightWidth = rightWidth
|
||||
this.width = width
|
||||
this.labelColor = labelColor
|
||||
this.color = color
|
||||
this.renderedLogo = renderedLogo
|
||||
this.renderedLabel = renderedLabel
|
||||
this.renderedMessage = renderedMessage
|
||||
}
|
||||
|
||||
render() {
|
||||
throw new Error('Not implemented')
|
||||
}
|
||||
}
|
||||
|
||||
class Plastic extends Badge {
|
||||
static get fontFamily() {
|
||||
return fontFamily
|
||||
}
|
||||
|
||||
static get height() {
|
||||
return 18
|
||||
}
|
||||
|
||||
static get verticalMargin() {
|
||||
return -10
|
||||
}
|
||||
|
||||
static get shadow() {
|
||||
return true
|
||||
}
|
||||
|
||||
render() {
|
||||
return renderBadge(
|
||||
{
|
||||
links: this.links,
|
||||
leftWidth: this.leftWidth,
|
||||
rightWidth: this.rightWidth,
|
||||
height: this.constructor.height,
|
||||
},
|
||||
`
|
||||
<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="${this.width}" height="${this.constructor.height}" rx="4" fill="#fff"/>
|
||||
</clipPath>
|
||||
|
||||
<g clip-path="url(#r)">
|
||||
<rect width="${this.leftWidth}" height="${this.constructor.height}" fill="${this.labelColor}"/>
|
||||
<rect x="${this.leftWidth}" width="${this.rightWidth}" height="${this.constructor.height}" fill="${this.color}"/>
|
||||
<rect width="${this.width}" height="${this.constructor.height}" fill="url(#s)"/>
|
||||
</g>
|
||||
|
||||
<g fill="#fff" text-anchor="middle" ${this.constructor.fontFamily} font-size="110">
|
||||
${this.renderedLogo}
|
||||
${this.renderedLabel}
|
||||
${this.renderedMessage}
|
||||
</g>`
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
class Flat extends Badge {
|
||||
static get fontFamily() {
|
||||
return fontFamily
|
||||
}
|
||||
|
||||
static get height() {
|
||||
return 20
|
||||
}
|
||||
|
||||
static get verticalMargin() {
|
||||
return 0
|
||||
}
|
||||
|
||||
static get shadow() {
|
||||
return true
|
||||
}
|
||||
|
||||
render() {
|
||||
return renderBadge(
|
||||
{
|
||||
links: this.links,
|
||||
leftWidth: this.leftWidth,
|
||||
rightWidth: this.rightWidth,
|
||||
height: this.constructor.height,
|
||||
},
|
||||
`
|
||||
<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="${this.width}" height="${this.constructor.height}" rx="3" fill="#fff"/>
|
||||
</clipPath>
|
||||
|
||||
<g clip-path="url(#r)">
|
||||
<rect width="${this.leftWidth}" height="${this.constructor.height}" fill="${this.labelColor}"/>
|
||||
<rect x="${this.leftWidth}" width="${this.rightWidth}" height="${this.constructor.height}" fill="${this.color}"/>
|
||||
<rect width="${this.width}" height="${this.constructor.height}" fill="url(#s)"/>
|
||||
</g>
|
||||
|
||||
<g fill="#fff" text-anchor="middle" ${this.constructor.fontFamily} font-size="110">
|
||||
${this.renderedLogo}
|
||||
${this.renderedLabel}
|
||||
${this.renderedMessage}
|
||||
</g>`
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
class FlatSquare extends Badge {
|
||||
static get fontFamily() {
|
||||
return fontFamily
|
||||
}
|
||||
|
||||
static get height() {
|
||||
return 20
|
||||
}
|
||||
|
||||
static get verticalMargin() {
|
||||
return 0
|
||||
}
|
||||
|
||||
static get shadow() {
|
||||
return false
|
||||
}
|
||||
|
||||
render() {
|
||||
return renderBadge(
|
||||
{
|
||||
links: this.links,
|
||||
leftWidth: this.leftWidth,
|
||||
rightWidth: this.rightWidth,
|
||||
height: this.constructor.height,
|
||||
},
|
||||
`
|
||||
<g shape-rendering="crispEdges">
|
||||
<rect width="${this.leftWidth}" height="${this.constructor.height}" fill="${this.labelColor}"/>
|
||||
<rect x="${this.leftWidth}" width="${this.rightWidth}" height="${this.constructor.height}" fill="${this.color}"/>
|
||||
</g>
|
||||
|
||||
<g fill="#fff" text-anchor="middle" ${this.constructor.fontFamily} font-size="110">
|
||||
${this.renderedLogo}
|
||||
${this.renderedLabel}
|
||||
${this.renderedMessage}
|
||||
</g>`
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
function plastic(params) {
|
||||
const badge = new Plastic(params)
|
||||
if (params.minify) {
|
||||
return stripXmlWhitespace(badge.render())
|
||||
}
|
||||
return badge.render()
|
||||
}
|
||||
|
||||
function flat(params) {
|
||||
const badge = new Flat(params)
|
||||
if (params.minify) {
|
||||
return stripXmlWhitespace(badge.render())
|
||||
}
|
||||
return badge.render()
|
||||
}
|
||||
|
||||
function flatSquare(params) {
|
||||
const badge = new FlatSquare(params)
|
||||
if (params.minify) {
|
||||
return stripXmlWhitespace(badge.render())
|
||||
}
|
||||
return badge.render()
|
||||
}
|
||||
|
||||
function social({
|
||||
label,
|
||||
message,
|
||||
links = [],
|
||||
logo,
|
||||
logoWidth,
|
||||
logoPadding,
|
||||
color = '#4c1',
|
||||
labelColor = '#555',
|
||||
minify,
|
||||
}) {
|
||||
// Social label is styled with a leading capital. Convert to caps here so
|
||||
// width can be measured using the correct characters.
|
||||
label = capitalize(label)
|
||||
|
||||
const externalHeight = 20
|
||||
const internalHeight = 19
|
||||
const horizPadding = 5
|
||||
const { totalLogoWidth, renderedLogo } = renderLogo({
|
||||
logo,
|
||||
badgeHeight: externalHeight,
|
||||
horizPadding,
|
||||
logoWidth,
|
||||
logoPadding,
|
||||
})
|
||||
const hasMessage = message.length
|
||||
|
||||
let { labelWidth, messageWidth } = computeWidths({ label, message })
|
||||
labelWidth += 10 + totalLogoWidth
|
||||
messageWidth += 10
|
||||
messageWidth -= 4
|
||||
|
||||
const labelTextX = ((labelWidth + totalLogoWidth) / 2) * 10
|
||||
const labelTextLength = (labelWidth - (10 + totalLogoWidth)) * 10
|
||||
const escapedLabel = escapeXml(label)
|
||||
|
||||
let [leftLink, rightLink] = links
|
||||
leftLink = escapeXml(leftLink)
|
||||
rightLink = escapeXml(rightLink)
|
||||
const hasLeftLink = leftLink && leftLink.length
|
||||
const hasRightLink = rightLink && rightLink.length
|
||||
|
||||
function renderMessageBubble() {
|
||||
const messageBubbleMainX = labelWidth + 6.5
|
||||
const messageBubbleNotchX = labelWidth + 6
|
||||
return `
|
||||
<rect x="${messageBubbleMainX}" y="0.5" width="${messageWidth}" height="${internalHeight}" rx="2" fill="#fafafa"/>
|
||||
<rect x="${messageBubbleNotchX}" y="7.5" width="0.5" height="5" stroke="#fafafa"/>
|
||||
<path d="M${messageBubbleMainX} 6.5 l-3 3v1 l3 3" stroke="d5d5d5" fill="#fafafa"/>
|
||||
`
|
||||
}
|
||||
|
||||
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 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>
|
||||
`
|
||||
}
|
||||
return `
|
||||
${shadow}
|
||||
${text}
|
||||
`
|
||||
}
|
||||
|
||||
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: [],
|
||||
leftWidth: labelWidth + 1,
|
||||
rightWidth: hasMessage ? messageWidth + 6 : 0,
|
||||
height: externalHeight,
|
||||
},
|
||||
`
|
||||
<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="${labelWidth}" height="${internalHeight}" rx="2"/>
|
||||
${hasMessage ? renderMessageBubble() : ''}
|
||||
</g>
|
||||
${renderedLogo}
|
||||
<g fill="#333" text-anchor="middle" ${socialFontFamily} 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>
|
||||
${hasMessage ? renderMessageText() : ''}
|
||||
</g>
|
||||
${renderLeftLink()}
|
||||
`
|
||||
)
|
||||
|
||||
if (minify) {
|
||||
return stripXmlWhitespace(badge)
|
||||
}
|
||||
return badge
|
||||
}
|
||||
|
||||
function forTheBadge({
|
||||
label,
|
||||
message,
|
||||
links,
|
||||
logo,
|
||||
logoWidth,
|
||||
logoPadding,
|
||||
color = '#4c1',
|
||||
labelColor,
|
||||
minify,
|
||||
}) {
|
||||
// For the Badge is styled in all caps. Convert to caps here so widths can
|
||||
// be measured using the correct characters.
|
||||
label = label.toUpperCase()
|
||||
message = message.toUpperCase()
|
||||
|
||||
let { labelWidth, messageWidth } = computeWidths({ label, message })
|
||||
const height = 28
|
||||
const hasLabel = label.length || labelColor
|
||||
if (labelColor == null) {
|
||||
labelColor = '#555'
|
||||
}
|
||||
const horizPadding = 9
|
||||
const { hasLogo, totalLogoWidth, renderedLogo } = renderLogo({
|
||||
logo,
|
||||
badgeHeight: height,
|
||||
horizPadding,
|
||||
logoWidth,
|
||||
logoPadding,
|
||||
})
|
||||
|
||||
labelWidth += 10 + totalLogoWidth
|
||||
if (label.length) {
|
||||
labelWidth += 10 + label.length * 1.5
|
||||
} else if (hasLogo) {
|
||||
if (hasLabel) {
|
||||
labelWidth += 7
|
||||
} else {
|
||||
labelWidth -= 7
|
||||
}
|
||||
} else {
|
||||
labelWidth -= 11
|
||||
}
|
||||
|
||||
messageWidth += 10
|
||||
messageWidth += 10 + message.length * 2
|
||||
const leftWidth = hasLogo && !hasLabel ? 0 : labelWidth
|
||||
const rightWidth =
|
||||
hasLogo && !hasLabel ? messageWidth + labelWidth : messageWidth
|
||||
|
||||
labelColor = hasLabel || hasLogo ? labelColor : color
|
||||
|
||||
color = escapeXml(color)
|
||||
labelColor = escapeXml(labelColor)
|
||||
|
||||
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 badge = renderBadge(
|
||||
{
|
||||
links,
|
||||
leftWidth,
|
||||
rightWidth,
|
||||
height,
|
||||
},
|
||||
`
|
||||
<g shape-rendering="crispEdges">
|
||||
<rect width="${leftWidth}" height="${height}" fill="${labelColor}"/>
|
||||
<rect x="${leftWidth}" width="${rightWidth}" height="${height}" fill="${color}"/>
|
||||
</g>
|
||||
<g fill="#fff" text-anchor="middle" ${fontFamily} 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>
|
||||
</g>`
|
||||
)
|
||||
|
||||
if (minify) {
|
||||
return stripXmlWhitespace(badge)
|
||||
}
|
||||
return badge
|
||||
}
|
||||
|
||||
module.exports = { plastic, flat, flatSquare, social, forTheBadge }
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
const isCSSColor = require('is-css-color')
|
||||
|
||||
// When updating these, be sure also to update the list in `gh-badges/README.md`.
|
||||
// When updating these, be sure also to update the list in `badge-maker/README.md`.
|
||||
const namedColors = {
|
||||
brightgreen: '#4c1',
|
||||
green: '#97ca00',
|
||||
87
badge-maker/lib/index.js
Normal file
87
badge-maker/lib/index.js
Normal file
@@ -0,0 +1,87 @@
|
||||
'use strict'
|
||||
/**
|
||||
* @module badge-maker
|
||||
*/
|
||||
|
||||
const _makeBadge = require('./make-badge')
|
||||
|
||||
class ValidationError extends Error {}
|
||||
|
||||
function _validate(format) {
|
||||
if (format !== Object(format)) {
|
||||
throw new ValidationError('makeBadge takes an argument of type object')
|
||||
}
|
||||
|
||||
if (!('message' in format)) {
|
||||
throw new ValidationError('Field `message` is required')
|
||||
}
|
||||
|
||||
const stringFields = ['labelColor', 'color', 'message', 'label']
|
||||
stringFields.forEach(function(field) {
|
||||
if (field in format && typeof format[field] !== 'string') {
|
||||
throw new ValidationError(`Field \`${field}\` must be of type string`)
|
||||
}
|
||||
})
|
||||
|
||||
const styleValues = [
|
||||
'plastic',
|
||||
'flat',
|
||||
'flat-square',
|
||||
'for-the-badge',
|
||||
'social',
|
||||
]
|
||||
if ('style' in format && !styleValues.includes(format.style)) {
|
||||
throw new ValidationError(
|
||||
`Field \`style\` must be one of (${styleValues.toString()})`
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
function _clean(format) {
|
||||
const expectedKeys = ['label', 'message', 'labelColor', 'color', 'style']
|
||||
|
||||
const cleaned = {}
|
||||
Object.keys(format).forEach(key => {
|
||||
if (format[key] != null && expectedKeys.includes(key)) {
|
||||
cleaned[key] = format[key]
|
||||
} else {
|
||||
throw new ValidationError(
|
||||
`Unexpected field '${key}'. Allowed values are (${expectedKeys.toString()})`
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
// convert "public" format to "internal" format
|
||||
cleaned.text = [cleaned.label || '', cleaned.message]
|
||||
delete cleaned.label
|
||||
delete cleaned.message
|
||||
if ('style' in cleaned) {
|
||||
cleaned.template = cleaned.style
|
||||
delete cleaned.style
|
||||
}
|
||||
|
||||
return cleaned
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a badge
|
||||
*
|
||||
* @param {object} format Object specifying badge data
|
||||
* @param {string} format.label (Optional) Badge label (e.g: 'build')
|
||||
* @param {string} format.message (Required) Badge message (e.g: 'passing')
|
||||
* @param {string} format.labelColor (Optional) Label color
|
||||
* @param {string} format.color (Optional) Message color
|
||||
* @param {string} format.style (Optional) Visual style e.g: 'flat'
|
||||
* @returns {string} Badge in SVG or JSON format
|
||||
* @see https://github.com/badges/shields/tree/master/badge-maker/README.md
|
||||
*/
|
||||
function makeBadge(format) {
|
||||
_validate(format)
|
||||
const cleanedFormat = _clean(format)
|
||||
return _makeBadge(cleanedFormat)
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
makeBadge,
|
||||
ValidationError,
|
||||
}
|
||||
75
badge-maker/lib/index.spec.js
Normal file
75
badge-maker/lib/index.spec.js
Normal file
@@ -0,0 +1,75 @@
|
||||
'use strict'
|
||||
|
||||
const { expect } = require('chai')
|
||||
const isSvg = require('is-svg')
|
||||
const { makeBadge, ValidationError } = require('.')
|
||||
|
||||
describe('makeBadge function', function() {
|
||||
it('should produce badge with valid input', function() {
|
||||
expect(
|
||||
makeBadge({
|
||||
label: 'build',
|
||||
message: 'passed',
|
||||
})
|
||||
).to.satisfy(isSvg)
|
||||
expect(
|
||||
makeBadge({
|
||||
message: 'passed',
|
||||
})
|
||||
).to.satisfy(isSvg)
|
||||
expect(
|
||||
makeBadge({
|
||||
label: 'build',
|
||||
message: 'passed',
|
||||
color: 'green',
|
||||
style: 'flat',
|
||||
})
|
||||
).to.satisfy(isSvg)
|
||||
})
|
||||
|
||||
it('should throw a ValidationError with invalid inputs', function() {
|
||||
;[null, undefined, 7, 'foo', 4.25].forEach(x => {
|
||||
console.log(x)
|
||||
expect(() => makeBadge(x)).to.throw(
|
||||
ValidationError,
|
||||
'makeBadge takes an argument of type object'
|
||||
)
|
||||
})
|
||||
expect(() => makeBadge({})).to.throw(
|
||||
ValidationError,
|
||||
'Field `message` is required'
|
||||
)
|
||||
expect(() => makeBadge({ label: 'build' })).to.throw(
|
||||
ValidationError,
|
||||
'Field `message` is required'
|
||||
)
|
||||
expect(() =>
|
||||
makeBadge({ label: 'build', message: 'passed', labelColor: 7 })
|
||||
).to.throw(ValidationError, 'Field `labelColor` must be of type string')
|
||||
expect(() =>
|
||||
makeBadge({ label: 'build', message: 'passed', format: 'png' })
|
||||
).to.throw(ValidationError, "Unexpected field 'format'")
|
||||
expect(() =>
|
||||
makeBadge({ label: 'build', message: 'passed', template: 'flat' })
|
||||
).to.throw(ValidationError, "Unexpected field 'template'")
|
||||
expect(() =>
|
||||
makeBadge({ label: 'build', message: 'passed', foo: 'bar' })
|
||||
).to.throw(ValidationError, "Unexpected field 'foo'")
|
||||
expect(() =>
|
||||
makeBadge({
|
||||
label: 'build',
|
||||
message: 'passed',
|
||||
style: 'something else',
|
||||
})
|
||||
).to.throw(
|
||||
ValidationError,
|
||||
'Field `style` must be one of (plastic,flat,flat-square,for-the-badge,social)'
|
||||
)
|
||||
expect(() =>
|
||||
makeBadge({ label: 'build', message: 'passed', style: 'popout' })
|
||||
).to.throw(
|
||||
ValidationError,
|
||||
'Field `style` must be one of (plastic,flat,flat-square,for-the-badge,social)'
|
||||
)
|
||||
})
|
||||
})
|
||||
64
badge-maker/lib/make-badge.js
Normal file
64
badge-maker/lib/make-badge.js
Normal file
@@ -0,0 +1,64 @@
|
||||
'use strict'
|
||||
|
||||
const camelcase = require('camelcase')
|
||||
const { normalizeColor, toSvgColor } = require('./color')
|
||||
const badgeRenderers = require('./badge-renderers')
|
||||
|
||||
/*
|
||||
note: makeBadge() is fairly thinly wrapped so if we are making changes here
|
||||
it is likely this will impact on the package's public interface in index.js
|
||||
*/
|
||||
module.exports = function makeBadge({
|
||||
format,
|
||||
template = 'flat',
|
||||
text,
|
||||
color,
|
||||
labelColor,
|
||||
logo,
|
||||
logoPosition,
|
||||
logoWidth,
|
||||
links = ['', ''],
|
||||
}) {
|
||||
// String coercion and whitespace removal.
|
||||
text = text.map(value => `${value}`.trim())
|
||||
|
||||
const [label, message] = text
|
||||
|
||||
color = normalizeColor(color)
|
||||
labelColor = normalizeColor(labelColor)
|
||||
|
||||
// This ought to be the responsibility of the server, not `makeBadge`.
|
||||
if (format === 'json') {
|
||||
return JSON.stringify({
|
||||
label,
|
||||
message,
|
||||
logoWidth,
|
||||
color,
|
||||
labelColor,
|
||||
link: links,
|
||||
name: label,
|
||||
value: message,
|
||||
})
|
||||
}
|
||||
|
||||
const methodName = camelcase(template)
|
||||
if (!(methodName in badgeRenderers)) {
|
||||
throw new Error(`Unknown template: '${template}'`)
|
||||
}
|
||||
const render = badgeRenderers[methodName]
|
||||
|
||||
logoWidth = +logoWidth || (logo ? 14 : 0)
|
||||
|
||||
return render({
|
||||
label,
|
||||
message,
|
||||
links,
|
||||
logo,
|
||||
logoPosition,
|
||||
logoWidth,
|
||||
logoPadding: logo && label.length ? 3 : 0,
|
||||
color: toSvgColor(color),
|
||||
labelColor: toSvgColor(labelColor),
|
||||
minify: true,
|
||||
})
|
||||
}
|
||||
571
badge-maker/lib/make-badge.spec.js
Normal file
571
badge-maker/lib/make-badge.spec.js
Normal file
@@ -0,0 +1,571 @@
|
||||
'use strict'
|
||||
|
||||
const { test, given, forCases } = require('sazerac')
|
||||
const { expect } = require('chai')
|
||||
const snapshot = require('snap-shot-it')
|
||||
const isSvg = require('is-svg')
|
||||
const makeBadge = require('./make-badge')
|
||||
|
||||
function testColor(color = '', colorAttr = 'color') {
|
||||
return JSON.parse(
|
||||
makeBadge({
|
||||
text: ['name', 'Bob'],
|
||||
[colorAttr]: color,
|
||||
format: 'json',
|
||||
})
|
||||
).color
|
||||
}
|
||||
|
||||
describe('The badge generator', function() {
|
||||
describe('color test', function() {
|
||||
test(testColor, () => {
|
||||
// valid hex
|
||||
forCases([
|
||||
given('#4c1'),
|
||||
given('#4C1'),
|
||||
given('4C1'),
|
||||
given('4c1'),
|
||||
]).expect('#4c1')
|
||||
forCases([
|
||||
given('#abc123'),
|
||||
given('#ABC123'),
|
||||
given('abc123'),
|
||||
given('ABC123'),
|
||||
]).expect('#abc123')
|
||||
// valid rgb(a)
|
||||
given('rgb(0,128,255)').expect('rgb(0,128,255)')
|
||||
given('rgba(0,128,255,0)').expect('rgba(0,128,255,0)')
|
||||
// valid hsl(a)
|
||||
given('hsl(100, 56%, 10%)').expect('hsl(100, 56%, 10%)')
|
||||
given('hsla(25,20%,0%,0.1)').expect('hsla(25,20%,0%,0.1)')
|
||||
// CSS named color.
|
||||
given('papayawhip').expect('papayawhip')
|
||||
// Shields named color.
|
||||
given('red').expect('red')
|
||||
given('green').expect('green')
|
||||
given('blue').expect('blue')
|
||||
given('yellow').expect('yellow')
|
||||
// Semantic color alias
|
||||
given('success').expect('brightgreen')
|
||||
given('informational').expect('blue')
|
||||
|
||||
forCases(
|
||||
// invalid hex
|
||||
given('#123red'), // contains letter above F
|
||||
given('#red'), // contains letter above F
|
||||
// invalid rgb(a)
|
||||
given('rgb(220,128,255,0.5)'), // has alpha
|
||||
given('rgba(0,0,255)'), // no alpha
|
||||
// invalid hsl(a)
|
||||
given('hsl(360,50%,50%,0.5)'), // has alpha
|
||||
given('hsla(0,50%,101%)'), // no alpha
|
||||
// neither a css named color nor colorscheme
|
||||
given('notacolor'),
|
||||
given('bluish'),
|
||||
given('almostred'),
|
||||
given('brightmaroon'),
|
||||
given('cactus')
|
||||
).expect(undefined)
|
||||
})
|
||||
})
|
||||
|
||||
describe('color aliases', function() {
|
||||
test(testColor, () => {
|
||||
forCases([given('#4c1', 'color')]).expect('#4c1')
|
||||
})
|
||||
})
|
||||
|
||||
describe('SVG', function() {
|
||||
it('should produce SVG', function() {
|
||||
const svg = makeBadge({ text: ['cactus', 'grown'], format: 'svg' })
|
||||
expect(svg)
|
||||
.to.satisfy(isSvg)
|
||||
.and.to.include('cactus')
|
||||
.and.to.include('grown')
|
||||
})
|
||||
|
||||
it('should match snapshot', function() {
|
||||
const svg = makeBadge({ text: ['cactus', 'grown'], format: 'svg' })
|
||||
snapshot(svg)
|
||||
})
|
||||
})
|
||||
|
||||
describe('JSON', function() {
|
||||
it('should produce the expected JSON', function() {
|
||||
const json = makeBadge({
|
||||
text: ['cactus', 'grown'],
|
||||
format: 'json',
|
||||
links: ['https://example.com/', 'https://other.example.com/'],
|
||||
})
|
||||
expect(JSON.parse(json)).to.deep.equal({
|
||||
name: 'cactus',
|
||||
label: 'cactus',
|
||||
value: 'grown',
|
||||
message: 'grown',
|
||||
link: ['https://example.com/', 'https://other.example.com/'],
|
||||
})
|
||||
})
|
||||
|
||||
it('should replace undefined svg template with "flat"', function() {
|
||||
const jsonBadgeWithUnknownStyle = makeBadge({
|
||||
text: ['name', 'Bob'],
|
||||
format: 'svg',
|
||||
})
|
||||
const jsonBadgeWithDefaultStyle = makeBadge({
|
||||
text: ['name', 'Bob'],
|
||||
format: 'svg',
|
||||
template: 'flat',
|
||||
})
|
||||
expect(jsonBadgeWithUnknownStyle)
|
||||
.to.equal(jsonBadgeWithDefaultStyle)
|
||||
.and.to.satisfy(isSvg)
|
||||
})
|
||||
|
||||
it('should fail with unknown svg template', function() {
|
||||
expect(() =>
|
||||
makeBadge({
|
||||
text: ['name', 'Bob'],
|
||||
format: 'svg',
|
||||
template: 'unknown_style',
|
||||
})
|
||||
).to.throw(Error, "Unknown template: 'unknown_style'")
|
||||
})
|
||||
})
|
||||
|
||||
describe('"flat" template badge generation', function() {
|
||||
it('should match snapshots: message/label, no logo', function() {
|
||||
snapshot(
|
||||
makeBadge({
|
||||
text: ['cactus', 'grown'],
|
||||
format: 'svg',
|
||||
template: 'flat',
|
||||
color: '#b3e',
|
||||
labelColor: '#0f0',
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it('should match snapshots: message/label, with logo', function() {
|
||||
snapshot(
|
||||
makeBadge({
|
||||
text: ['cactus', 'grown'],
|
||||
format: 'svg',
|
||||
template: 'flat',
|
||||
color: '#b3e',
|
||||
labelColor: '#0f0',
|
||||
logo: 'data:image/svg+xml;base64,PHN2ZyB4bWxu',
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it('should match snapshots: message only, no logo', function() {
|
||||
snapshot(
|
||||
makeBadge({
|
||||
text: ['', 'grown'],
|
||||
format: 'svg',
|
||||
template: 'flat',
|
||||
color: '#b3e',
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it('should match snapshots: message only, with logo', function() {
|
||||
snapshot(
|
||||
makeBadge({
|
||||
text: ['', 'grown'],
|
||||
format: 'svg',
|
||||
template: 'flat',
|
||||
color: '#b3e',
|
||||
logo: 'data:image/svg+xml;base64,PHN2ZyB4bWxu',
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it('should match snapshots: message only, with logo and labelColor', function() {
|
||||
snapshot(
|
||||
makeBadge({
|
||||
text: ['', 'grown'],
|
||||
format: 'svg',
|
||||
template: 'flat',
|
||||
color: '#b3e',
|
||||
labelColor: '#0f0',
|
||||
logo: 'data:image/svg+xml;base64,PHN2ZyB4bWxu',
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it('should match snapshots: message/label, with links', function() {
|
||||
snapshot(
|
||||
makeBadge({
|
||||
text: ['cactus', 'grown'],
|
||||
format: 'svg',
|
||||
template: 'flat',
|
||||
color: '#b3e',
|
||||
labelColor: '#0f0',
|
||||
links: ['https://shields.io/', 'https://www.google.co.uk/'],
|
||||
})
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('"flat-square" template badge generation', function() {
|
||||
it('should match snapshots: message/label, no logo', function() {
|
||||
snapshot(
|
||||
makeBadge({
|
||||
text: ['cactus', 'grown'],
|
||||
format: 'svg',
|
||||
template: 'flat-square',
|
||||
color: '#b3e',
|
||||
labelColor: '#0f0',
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it('should match snapshots: message/label, with logo', function() {
|
||||
snapshot(
|
||||
makeBadge({
|
||||
text: ['cactus', 'grown'],
|
||||
format: 'svg',
|
||||
template: 'flat-square',
|
||||
color: '#b3e',
|
||||
labelColor: '#0f0',
|
||||
logo: 'data:image/svg+xml;base64,PHN2ZyB4bWxu',
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it('should match snapshots: message only, no logo', function() {
|
||||
snapshot(
|
||||
makeBadge({
|
||||
text: ['', 'grown'],
|
||||
format: 'svg',
|
||||
template: 'flat-square',
|
||||
color: '#b3e',
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it('should match snapshots: message only, with logo', function() {
|
||||
snapshot(
|
||||
makeBadge({
|
||||
text: ['', 'grown'],
|
||||
format: 'svg',
|
||||
template: 'flat-square',
|
||||
color: '#b3e',
|
||||
logo: 'data:image/svg+xml;base64,PHN2ZyB4bWxu',
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it('should match snapshots: message only, with logo and labelColor', function() {
|
||||
snapshot(
|
||||
makeBadge({
|
||||
text: ['', 'grown'],
|
||||
format: 'svg',
|
||||
template: 'flat-square',
|
||||
color: '#b3e',
|
||||
labelColor: '#0f0',
|
||||
logo: 'data:image/svg+xml;base64,PHN2ZyB4bWxu',
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it('should match snapshots: message/label, with links', function() {
|
||||
snapshot(
|
||||
makeBadge({
|
||||
text: ['cactus', 'grown'],
|
||||
format: 'svg',
|
||||
template: 'flat-square',
|
||||
color: '#b3e',
|
||||
labelColor: '#0f0',
|
||||
links: ['https://shields.io/', 'https://www.google.co.uk/'],
|
||||
})
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('"plastic" template badge generation', function() {
|
||||
it('should match snapshots: message/label, no logo', function() {
|
||||
snapshot(
|
||||
makeBadge({
|
||||
text: ['cactus', 'grown'],
|
||||
format: 'svg',
|
||||
template: 'plastic',
|
||||
color: '#b3e',
|
||||
labelColor: '#0f0',
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it('should match snapshots: message/label, with logo', function() {
|
||||
snapshot(
|
||||
makeBadge({
|
||||
text: ['cactus', 'grown'],
|
||||
format: 'svg',
|
||||
template: 'plastic',
|
||||
color: '#b3e',
|
||||
labelColor: '#0f0',
|
||||
logo: 'data:image/svg+xml;base64,PHN2ZyB4bWxu',
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it('should match snapshots: message only, no logo', function() {
|
||||
snapshot(
|
||||
makeBadge({
|
||||
text: ['', 'grown'],
|
||||
format: 'svg',
|
||||
template: 'plastic',
|
||||
color: '#b3e',
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it('should match snapshots: message only, with logo', function() {
|
||||
snapshot(
|
||||
makeBadge({
|
||||
text: ['', 'grown'],
|
||||
format: 'svg',
|
||||
template: 'plastic',
|
||||
color: '#b3e',
|
||||
logo: 'data:image/svg+xml;base64,PHN2ZyB4bWxu',
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it('should match snapshots: message only, with logo and labelColor', function() {
|
||||
snapshot(
|
||||
makeBadge({
|
||||
text: ['', 'grown'],
|
||||
format: 'svg',
|
||||
template: 'plastic',
|
||||
color: '#b3e',
|
||||
labelColor: '#0f0',
|
||||
logo: 'data:image/svg+xml;base64,PHN2ZyB4bWxu',
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it('should match snapshots: message/label, with links', function() {
|
||||
snapshot(
|
||||
makeBadge({
|
||||
text: ['cactus', 'grown'],
|
||||
format: 'svg',
|
||||
template: 'plastic',
|
||||
color: '#b3e',
|
||||
labelColor: '#0f0',
|
||||
links: ['https://shields.io/', 'https://www.google.co.uk/'],
|
||||
})
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('"for-the-badge" template badge generation', function() {
|
||||
// https://github.com/badges/shields/issues/1280
|
||||
it('numbers should produce a string', function() {
|
||||
const svg = makeBadge({
|
||||
text: [1998, 1999],
|
||||
format: 'svg',
|
||||
template: 'for-the-badge',
|
||||
})
|
||||
expect(svg)
|
||||
.to.include('1998')
|
||||
.and.to.include('1999')
|
||||
})
|
||||
|
||||
it('lowercase/mixedcase string should produce uppercase string', function() {
|
||||
const svg = makeBadge({
|
||||
text: ['Label', '1 string'],
|
||||
format: 'svg',
|
||||
template: 'for-the-badge',
|
||||
})
|
||||
expect(svg)
|
||||
.to.include('LABEL')
|
||||
.and.to.include('1 STRING')
|
||||
})
|
||||
|
||||
it('should match snapshots: message/label, no logo', function() {
|
||||
snapshot(
|
||||
makeBadge({
|
||||
text: ['cactus', 'grown'],
|
||||
format: 'svg',
|
||||
template: 'for-the-badge',
|
||||
color: '#b3e',
|
||||
labelColor: '#0f0',
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it('should match snapshots: message/label, with logo', function() {
|
||||
snapshot(
|
||||
makeBadge({
|
||||
text: ['cactus', 'grown'],
|
||||
format: 'svg',
|
||||
template: 'for-the-badge',
|
||||
color: '#b3e',
|
||||
labelColor: '#0f0',
|
||||
logo: 'data:image/svg+xml;base64,PHN2ZyB4bWxu',
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it('should match snapshots: message only, no logo', function() {
|
||||
snapshot(
|
||||
makeBadge({
|
||||
text: ['', 'grown'],
|
||||
format: 'svg',
|
||||
template: 'for-the-badge',
|
||||
color: '#b3e',
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it('should match snapshots: message only, with logo', function() {
|
||||
snapshot(
|
||||
makeBadge({
|
||||
text: ['', 'grown'],
|
||||
format: 'svg',
|
||||
template: 'for-the-badge',
|
||||
color: '#b3e',
|
||||
logo: 'data:image/svg+xml;base64,PHN2ZyB4bWxu',
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it('should match snapshots: message only, with logo and labelColor', function() {
|
||||
snapshot(
|
||||
makeBadge({
|
||||
text: ['', 'grown'],
|
||||
format: 'svg',
|
||||
template: 'for-the-badge',
|
||||
color: '#b3e',
|
||||
labelColor: '#0f0',
|
||||
logo: 'data:image/svg+xml;base64,PHN2ZyB4bWxu',
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it('should match snapshots: message/label, with links', function() {
|
||||
snapshot(
|
||||
makeBadge({
|
||||
text: ['cactus', 'grown'],
|
||||
format: 'svg',
|
||||
template: 'for-the-badge',
|
||||
color: '#b3e',
|
||||
labelColor: '#0f0',
|
||||
links: ['https://shields.io/', 'https://www.google.co.uk/'],
|
||||
})
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('"social" template badge generation', function() {
|
||||
it('should produce capitalized string for badge key', function() {
|
||||
const svg = makeBadge({
|
||||
text: ['some-key', 'some-value'],
|
||||
format: 'svg',
|
||||
template: 'social',
|
||||
})
|
||||
expect(svg)
|
||||
.to.include('Some-key')
|
||||
.and.to.include('some-value')
|
||||
})
|
||||
|
||||
// https://github.com/badges/shields/issues/1606
|
||||
it('should handle empty strings used as badge keys', function() {
|
||||
const svg = makeBadge({
|
||||
text: ['', 'some-value'],
|
||||
format: 'json',
|
||||
template: 'social',
|
||||
})
|
||||
expect(svg)
|
||||
.to.include('""')
|
||||
.and.to.include('some-value')
|
||||
})
|
||||
|
||||
it('should match snapshots: message/label, no logo', function() {
|
||||
snapshot(
|
||||
makeBadge({
|
||||
text: ['cactus', 'grown'],
|
||||
format: 'svg',
|
||||
template: 'social',
|
||||
color: '#b3e',
|
||||
labelColor: '#0f0',
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it('should match snapshots: message/label, with logo', function() {
|
||||
snapshot(
|
||||
makeBadge({
|
||||
text: ['cactus', 'grown'],
|
||||
format: 'svg',
|
||||
template: 'social',
|
||||
color: '#b3e',
|
||||
labelColor: '#0f0',
|
||||
logo: 'data:image/svg+xml;base64,PHN2ZyB4bWxu',
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it('should match snapshots: message only, no logo', function() {
|
||||
snapshot(
|
||||
makeBadge({
|
||||
text: ['', 'grown'],
|
||||
format: 'svg',
|
||||
template: 'social',
|
||||
color: '#b3e',
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it('should match snapshots: message only, with logo', function() {
|
||||
snapshot(
|
||||
makeBadge({
|
||||
text: ['', 'grown'],
|
||||
format: 'svg',
|
||||
template: 'social',
|
||||
color: '#b3e',
|
||||
logo: 'data:image/svg+xml;base64,PHN2ZyB4bWxu',
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it('should match snapshots: message only, with logo and labelColor', function() {
|
||||
snapshot(
|
||||
makeBadge({
|
||||
text: ['', 'grown'],
|
||||
format: 'svg',
|
||||
template: 'social',
|
||||
color: '#b3e',
|
||||
labelColor: '#0f0',
|
||||
logo: 'data:image/svg+xml;base64,PHN2ZyB4bWxu',
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it('should match snapshots: message/label, with links', function() {
|
||||
snapshot(
|
||||
makeBadge({
|
||||
text: ['cactus', 'grown'],
|
||||
format: 'svg',
|
||||
template: 'social',
|
||||
color: '#b3e',
|
||||
labelColor: '#0f0',
|
||||
links: ['https://shields.io/', 'https://www.google.co.uk/'],
|
||||
})
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('badges with logos should always produce the same badge', function() {
|
||||
it('badge with logo', function() {
|
||||
const svg = makeBadge({
|
||||
text: ['label', 'message'],
|
||||
format: 'svg',
|
||||
logo: 'data:image/svg+xml;base64,PHN2ZyB4bWxu',
|
||||
})
|
||||
snapshot(svg)
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "gh-badges",
|
||||
"version": "2.2.1",
|
||||
"name": "badge-maker",
|
||||
"version": "3.0.0-rc1",
|
||||
"description": "Shields.io badge library",
|
||||
"keywords": [
|
||||
"GitHub",
|
||||
@@ -13,7 +13,7 @@
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/badges/shields.git",
|
||||
"directory": "gh-badges"
|
||||
"directory": "badge-maker"
|
||||
},
|
||||
"author": "Thaddée Tyl <thaddee.tyl@gmail.com>",
|
||||
"license": "CC0-1.0",
|
||||
@@ -35,10 +35,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"anafanafo": "^1.0.0",
|
||||
"dot": "^1.1.2",
|
||||
"gm": "^1.23.0",
|
||||
"is-css-color": "^1.0.0",
|
||||
"svgo": "^1.1.1"
|
||||
"is-css-color": "^1.0.0"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "echo 'Run tests from parent dir'; false"
|
||||
2
core/badge-urls/make-badge-url.d.ts
vendored
2
core/badge-urls/make-badge-url.d.ts
vendored
@@ -38,6 +38,7 @@ export function staticBadgeUrl({
|
||||
baseUrl,
|
||||
label,
|
||||
message,
|
||||
labelColor,
|
||||
color,
|
||||
style,
|
||||
namedLogo,
|
||||
@@ -46,6 +47,7 @@ export function staticBadgeUrl({
|
||||
baseUrl?: string
|
||||
label: string
|
||||
message: string
|
||||
labelColor?: string
|
||||
color?: string
|
||||
style?: string
|
||||
namedLogo?: string
|
||||
|
||||
@@ -59,6 +59,7 @@ function staticBadgeUrl({
|
||||
baseUrl = '',
|
||||
label,
|
||||
message,
|
||||
labelColor,
|
||||
color = 'lightgray',
|
||||
style,
|
||||
namedLogo,
|
||||
@@ -66,6 +67,7 @@ function staticBadgeUrl({
|
||||
}) {
|
||||
const path = [label, message, color].map(encodeField).join('-')
|
||||
const outQueryString = queryString.stringify({
|
||||
labelColor,
|
||||
style,
|
||||
logo: namedLogo,
|
||||
})
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
'use strict'
|
||||
|
||||
const makeBadge = require('../../gh-badges/lib/make-badge')
|
||||
const makeBadge = require('../../badge-maker/lib/make-badge')
|
||||
const BaseService = require('./base')
|
||||
const { MetricHelper } = require('./metric-helper')
|
||||
const { setCacheHeaders } = require('./cache-headers')
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
'use strict'
|
||||
|
||||
const makeBadge = require('../../gh-badges/lib/make-badge')
|
||||
const makeBadge = require('../../badge-maker/lib/make-badge')
|
||||
const BaseService = require('./base')
|
||||
const {
|
||||
serverHasBeenUpSinceResourceCached,
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
const { expect } = require('chai')
|
||||
const sinon = require('sinon')
|
||||
const Joi = require('@hapi/joi')
|
||||
const makeBadge = require('../../gh-badges/lib/make-badge')
|
||||
const makeBadge = require('../../badge-maker/lib/make-badge')
|
||||
const BaseSvgScrapingService = require('./base-svg-scraping')
|
||||
|
||||
function makeExampleSvg({ label, message }) {
|
||||
|
||||
@@ -392,7 +392,7 @@ describe('BaseService', function() {
|
||||
expect(mockSendBadge).to.have.been.calledWith(expectedFormat, {
|
||||
text: ['cat', 'Hello namedParamA: bar with queryParamA: ?'],
|
||||
color: 'lightgrey',
|
||||
template: undefined,
|
||||
template: 'flat',
|
||||
namedLogo: undefined,
|
||||
logo: undefined,
|
||||
logoWidth: undefined,
|
||||
|
||||
@@ -104,7 +104,23 @@ module.exports = function coalesceBadge(
|
||||
labelColor: defaultLabelColor,
|
||||
} = defaultBadgeData
|
||||
|
||||
const style = coalesce(overrideStyle, serviceStyle)
|
||||
let style = coalesce(overrideStyle, serviceStyle)
|
||||
if (typeof style !== 'string') {
|
||||
style = 'flat'
|
||||
}
|
||||
if (style.startsWith('popout')) {
|
||||
style = style.replace('popout', 'flat')
|
||||
}
|
||||
const styleValues = [
|
||||
'plastic',
|
||||
'flat',
|
||||
'flat-square',
|
||||
'for-the-badge',
|
||||
'social',
|
||||
]
|
||||
if (!styleValues.includes(style)) {
|
||||
style = 'flat'
|
||||
}
|
||||
|
||||
let namedLogo, namedLogoColor, logoWidth, logoPosition, logoSvgBase64
|
||||
if (overrideLogo) {
|
||||
|
||||
@@ -278,8 +278,21 @@ describe('coalesceBadge', function() {
|
||||
})
|
||||
|
||||
describe('Style', function() {
|
||||
it('overrides the template', function() {
|
||||
expect(coalesceBadge({ style: 'pill' }, {}, {}).template).to.equal('pill')
|
||||
it('falls back to flat with invalid style', function() {
|
||||
expect(coalesceBadge({ style: 'pill' }, {}, {}).template).to.equal('flat')
|
||||
expect(coalesceBadge({ style: 7 }, {}, {}).template).to.equal('flat')
|
||||
expect(coalesceBadge({ style: undefined }, {}, {}).template).to.equal(
|
||||
'flat'
|
||||
)
|
||||
})
|
||||
|
||||
it('replaces legacy popout styles', function() {
|
||||
expect(coalesceBadge({ style: 'popout' }, {}, {}).template).to.equal(
|
||||
'flat'
|
||||
)
|
||||
expect(
|
||||
coalesceBadge({ style: 'popout-square' }, {}, {}).template
|
||||
).to.equal('flat-square')
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
const request = require('request')
|
||||
const queryString = require('query-string')
|
||||
const makeBadge = require('../../gh-badges/lib/make-badge')
|
||||
const makeBadge = require('../../badge-maker/lib/make-badge')
|
||||
const { setCacheHeaders } = require('./cache-headers')
|
||||
const {
|
||||
Inaccessible,
|
||||
|
||||
@@ -9,7 +9,7 @@ const { URL } = url
|
||||
const bytes = require('bytes')
|
||||
const Camp = require('camp')
|
||||
const originalJoi = require('@hapi/joi')
|
||||
const makeBadge = require('../../gh-badges/lib/make-badge')
|
||||
const makeBadge = require('../../badge-maker/lib/make-badge')
|
||||
const GithubConstellation = require('../../services/github/github-constellation')
|
||||
const suggest = require('../../services/suggest')
|
||||
const { loadServiceClasses } = require('../base-service/loader')
|
||||
|
||||
@@ -7,7 +7,7 @@ The Shields codebase is divided into several parts:
|
||||
1. The frontend (about 7% of the code)
|
||||
1. [`frontend`][frontend]
|
||||
2. The badge renderer (which is available as an npm package)
|
||||
1. [`gh-badges`][gh-badges]
|
||||
1. [`badge-maker`][badge-maker]
|
||||
3. The base service classes (about 8% of the code, and probably the most important
|
||||
code in the codebase)
|
||||
1. [`core/base-service`][base-service]
|
||||
@@ -24,7 +24,7 @@ The Shields codebase is divided into several parts:
|
||||
1. [`lib/suggest.js`][suggest]
|
||||
|
||||
[frontend]: https://github.com/badges/shields/tree/master/frontend
|
||||
[gh-badges]: https://github.com/badges/shields/tree/master/gh-badges
|
||||
[badge-maker]: https://github.com/badges/shields/tree/master/badge-maker
|
||||
[base-service]: https://github.com/badges/shields/tree/master/core/base-service
|
||||
[server]: https://github.com/badges/shields/tree/master/core/server
|
||||
[token-pooling]: https://github.com/badges/shields/tree/master/core/token-pooling
|
||||
@@ -36,7 +36,7 @@ The tests are also divided into several parts:
|
||||
1. Unit and functional tests of the frontend
|
||||
1. `frontend/**/*.spec.js`
|
||||
2. Unit and functional tests of the badge renderer
|
||||
1. `gh-badges/**/*.spec.js`
|
||||
1. `badge-maker/**/*.spec.js`
|
||||
3. Unit and functional tests of the core code
|
||||
1. `core/**/*.spec.js`
|
||||
4. Unit and functional tests of the service helper functions
|
||||
|
||||
@@ -78,7 +78,7 @@ $ docker run --rm -p 8080:80 --name shields shields
|
||||
# or if you have shields.env file, run the following instead
|
||||
$ docker run --rm -p 8080:80 --env-file shields.env --name shields shields
|
||||
|
||||
> gh-badges@1.1.2 start /usr/src/app
|
||||
> badge-maker@3.0.0 start /usr/src/app
|
||||
> node server.js
|
||||
|
||||
http://[::1]/
|
||||
|
||||
154
frontend/components/development/style-page.tsx
Normal file
154
frontend/components/development/style-page.tsx
Normal file
@@ -0,0 +1,154 @@
|
||||
import React, { Fragment } from 'react'
|
||||
import styled from 'styled-components'
|
||||
// @ts-ingnore
|
||||
import { staticBadgeUrl } from '../../../core/badge-urls/make-badge-url'
|
||||
import { baseUrl } from '../../constants'
|
||||
import Meta from '../meta'
|
||||
// @ts-ignore
|
||||
import Header from '../header'
|
||||
import { H3, Badge } from '../common'
|
||||
|
||||
const StyledTable = styled.table`
|
||||
border: 1px solid #ccc;
|
||||
border-collapse: collapse;
|
||||
|
||||
td {
|
||||
border: 1px solid #ccc;
|
||||
padding: 3px;
|
||||
text-align: left;
|
||||
}
|
||||
`
|
||||
|
||||
interface BadgeData {
|
||||
label: string
|
||||
message: string
|
||||
labelColor?: string
|
||||
color: string
|
||||
namedLogo?: string
|
||||
}
|
||||
|
||||
function Badges({
|
||||
baseUrl,
|
||||
style,
|
||||
badges,
|
||||
}: {
|
||||
baseUrl: string
|
||||
style: string
|
||||
badges: BadgeData[]
|
||||
}): JSX.Element {
|
||||
return (
|
||||
<>
|
||||
{badges.map(({ label, message, labelColor, color, namedLogo }) => (
|
||||
<Fragment key={`${label}-${message}-${color}-${namedLogo}`}>
|
||||
<Badge
|
||||
alt="build"
|
||||
src={staticBadgeUrl({
|
||||
baseUrl,
|
||||
label,
|
||||
message,
|
||||
labelColor,
|
||||
color,
|
||||
namedLogo,
|
||||
style,
|
||||
})}
|
||||
/>
|
||||
<br />
|
||||
</Fragment>
|
||||
))}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
interface StyleExamples {
|
||||
title: string
|
||||
badges: BadgeData[]
|
||||
}
|
||||
|
||||
const examples = [
|
||||
{
|
||||
title: 'Basic examples',
|
||||
badges: [
|
||||
{ label: 'build', message: 'passing', color: 'brightgreen' },
|
||||
{ label: 'tests', message: '5 passing, 1 failed', color: 'red' },
|
||||
{ label: 'python', message: '3.5 | 3.6 | 3.7', color: 'blue' },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Logo',
|
||||
badges: [
|
||||
{
|
||||
label: 'build',
|
||||
message: 'passing',
|
||||
color: 'brightgreen',
|
||||
namedLogo: 'appveyor',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'No left text',
|
||||
badges: [
|
||||
{ label: '', message: 'blueviolet', color: 'blueviolet' },
|
||||
{
|
||||
label: '',
|
||||
message: 'passing',
|
||||
color: 'brightgreen',
|
||||
namedLogo: 'appveyor',
|
||||
},
|
||||
{
|
||||
label: '',
|
||||
message: 'passing',
|
||||
color: 'brightgreen',
|
||||
labelColor: 'grey',
|
||||
namedLogo: 'appveyor',
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
|
||||
function StyleTable({ style }: { style: string }): JSX.Element {
|
||||
return (
|
||||
<StyledTable>
|
||||
<thead>
|
||||
<tr>
|
||||
<td>Description</td>
|
||||
<td>Badges (new)</td>
|
||||
<td>Badges (old)</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{examples.map(({ title, badges }) => (
|
||||
<tr key={title}>
|
||||
<td>{title}</td>
|
||||
<td>
|
||||
<Badges badges={badges} baseUrl={baseUrl} style={style} />
|
||||
</td>
|
||||
<td>
|
||||
<Badges
|
||||
badges={badges}
|
||||
baseUrl="http://img.shields.io"
|
||||
style={style}
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</StyledTable>
|
||||
)
|
||||
}
|
||||
|
||||
const styles = ['flat', 'flat-square', 'for-the-badge', 'social', 'plastic']
|
||||
|
||||
export default function StylePage(): JSX.Element {
|
||||
return (
|
||||
<div>
|
||||
<Meta />
|
||||
<Header />
|
||||
{styles.map(style => (
|
||||
<Fragment key={style}>
|
||||
<H3>{style}</H3>
|
||||
<StyleTable style={style} />
|
||||
</Fragment>
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -21,6 +21,12 @@ const { categories } = yaml.safeLoad(
|
||||
// https://www.gatsbyjs.org/docs/using-gatsby-without-graphql/#the-approach-fetch-data-and-use-gatsbys-createpages-api
|
||||
async function createPages({ actions: { createPage } }) {
|
||||
if (includeDevPages) {
|
||||
createPage({
|
||||
path: '/dev/styles',
|
||||
component: require.resolve(
|
||||
'./frontend/components/development/style-page.tsx'
|
||||
),
|
||||
})
|
||||
createPage({
|
||||
path: '/dev/logos',
|
||||
component: require.resolve(
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
'use strict'
|
||||
/**
|
||||
* @module gh-badges
|
||||
*/
|
||||
|
||||
const makeBadge = require('./make-badge')
|
||||
|
||||
/**
|
||||
* BadgeFactory
|
||||
*/
|
||||
class BadgeFactory {
|
||||
constructor(options) {
|
||||
if (options !== undefined) {
|
||||
console.error(
|
||||
'BadgeFactory: Constructor options are deprecated and will be ignored'
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a badge
|
||||
*
|
||||
* @param {object} format Object specifying badge data
|
||||
* @param {string[]} format.text Badge text in an array e.g: ['build', 'passing']
|
||||
* @param {string} format.labelColor (Optional) Label color
|
||||
* @param {string} format.color (Optional) Message color
|
||||
* @param {string} format.colorA (Deprecated, Optional) alias for `labelColor`
|
||||
* @param {string} format.colorscheme (Deprecated, Optional) alias for `color`
|
||||
* @param {string} format.colorB (Deprecated, Optional) alias for `color`
|
||||
* @param {string} format.format (Optional) Output format: 'svg' or 'json'
|
||||
* @param {string} format.template (Optional) Visual template e.g: 'flat'
|
||||
* see {@link https://github.com/badges/shields/tree/master/gh-badges/templates}
|
||||
* @returns {string} Badge in SVG or JSON format
|
||||
* @see https://github.com/badges/shields/tree/master/gh-badges/README.md
|
||||
*/
|
||||
create(format) {
|
||||
return makeBadge(format)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
BadgeFactory,
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
'use strict'
|
||||
|
||||
const { expect } = require('chai')
|
||||
const isSvg = require('is-svg')
|
||||
const { BadgeFactory } = require('.')
|
||||
|
||||
const bf = new BadgeFactory()
|
||||
|
||||
describe('BadgeFactory class', function() {
|
||||
it('should produce badge with valid input', function() {
|
||||
expect(
|
||||
bf.create({
|
||||
text: ['build', 'passed'],
|
||||
format: 'svg',
|
||||
colorscheme: 'green',
|
||||
template: 'flat',
|
||||
})
|
||||
).to.satisfy(isSvg)
|
||||
})
|
||||
})
|
||||
@@ -1,185 +0,0 @@
|
||||
'use strict'
|
||||
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const SVGO = require('svgo')
|
||||
const dot = require('dot')
|
||||
const anafanafo = require('anafanafo')
|
||||
const { normalizeColor, toSvgColor } = require('./color')
|
||||
|
||||
// cache templates.
|
||||
const templates = {}
|
||||
const templateFiles = fs.readdirSync(path.join(__dirname, '..', 'templates'))
|
||||
dot.templateSettings.strip = false // Do not strip whitespace.
|
||||
templateFiles.forEach(async filename => {
|
||||
if (filename[0] === '.') {
|
||||
return
|
||||
}
|
||||
const templateData = fs
|
||||
.readFileSync(path.join(__dirname, '..', 'templates', filename))
|
||||
.toString()
|
||||
const extension = path.extname(filename).slice(1)
|
||||
const style = filename.slice(0, -`-template.${extension}`.length)
|
||||
// Compile the template. Necessary to always have a working template.
|
||||
templates[style] = dot.template(templateData)
|
||||
// Substitute dot code.
|
||||
const mapping = new Map()
|
||||
let mappingIndex = 1
|
||||
const untemplatedSvg = templateData.replace(/{{.*?}}/g, match => {
|
||||
// Weird substitution that currently works for all templates.
|
||||
const mapKey = `99999990${mappingIndex}.1`
|
||||
mappingIndex++
|
||||
mapping.set(mapKey, match)
|
||||
return mapKey
|
||||
})
|
||||
|
||||
const svgo = new SVGO()
|
||||
const { data, error } = await svgo.optimize(untemplatedSvg)
|
||||
|
||||
if (error !== undefined) {
|
||||
console.error(
|
||||
`Template ${filename}: ${error}\n` +
|
||||
' Generated untemplated SVG:\n' +
|
||||
`---\n${untemplatedSvg}---\n`
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
// Substitute dot code back.
|
||||
let svg = data
|
||||
const unmappedKeys = []
|
||||
mapping.forEach((value, key) => {
|
||||
let keySubstituted = false
|
||||
svg = svg.replace(RegExp(key, 'g'), () => {
|
||||
keySubstituted = true
|
||||
return value
|
||||
})
|
||||
if (!keySubstituted) {
|
||||
unmappedKeys.push(key)
|
||||
}
|
||||
})
|
||||
if (unmappedKeys.length > 0) {
|
||||
console.error(
|
||||
`Template ${filename} has unmapped keys ` +
|
||||
`${unmappedKeys.join(', ')}.\n` +
|
||||
' Generated untemplated SVG:\n' +
|
||||
`---\n${untemplatedSvg}\n---\n` +
|
||||
' Generated template:\n' +
|
||||
`---\n${svg}\n---\n`
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
templates[style] = dot.template(svg)
|
||||
})
|
||||
|
||||
function escapeXml(s) {
|
||||
if (s === undefined || typeof s !== 'string') {
|
||||
return undefined
|
||||
} else {
|
||||
return s
|
||||
.replace(/&/g, '&')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>')
|
||||
.replace(/"/g, '"')
|
||||
.replace(/'/g, ''')
|
||||
}
|
||||
}
|
||||
|
||||
function capitalize(s) {
|
||||
return s.charAt(0).toUpperCase() + s.slice(1)
|
||||
}
|
||||
|
||||
/*
|
||||
note: makeBadge() is fairly thinly wrapped so if we are making changes here
|
||||
it is likely this will impact on the package's public interface in index.js
|
||||
*/
|
||||
module.exports = function makeBadge({
|
||||
format,
|
||||
template,
|
||||
text,
|
||||
colorscheme,
|
||||
color,
|
||||
colorA,
|
||||
colorB,
|
||||
labelColor,
|
||||
logo,
|
||||
logoPosition,
|
||||
logoWidth,
|
||||
links = ['', ''],
|
||||
}) {
|
||||
// String coercion and whitespace removal.
|
||||
text = text.map(value => `${value}`.trim())
|
||||
|
||||
let [left, right] = text
|
||||
|
||||
color = normalizeColor(color || colorB || colorscheme)
|
||||
labelColor = normalizeColor(labelColor || colorA)
|
||||
|
||||
// This ought to be the responsibility of the server, not `makeBadge`.
|
||||
if (format === 'json') {
|
||||
return JSON.stringify({
|
||||
label: left,
|
||||
message: right,
|
||||
logoWidth,
|
||||
color,
|
||||
labelColor,
|
||||
link: links,
|
||||
name: left,
|
||||
value: right,
|
||||
})
|
||||
}
|
||||
|
||||
if (!(template in templates)) {
|
||||
if (template === 'popout-square') {
|
||||
template = 'flat-square'
|
||||
} else {
|
||||
template = 'flat'
|
||||
}
|
||||
}
|
||||
if (template === 'social') {
|
||||
left = capitalize(left)
|
||||
} else if (template === 'for-the-badge') {
|
||||
left = left.toUpperCase()
|
||||
right = right.toUpperCase()
|
||||
}
|
||||
|
||||
let leftWidth = (anafanafo(left) / 10) | 0
|
||||
// Increase chances of pixel grid alignment.
|
||||
if (leftWidth % 2 === 0) {
|
||||
leftWidth++
|
||||
}
|
||||
let rightWidth = (anafanafo(right) / 10) | 0
|
||||
// Increase chances of pixel grid alignment.
|
||||
if (rightWidth % 2 === 0) {
|
||||
rightWidth++
|
||||
}
|
||||
|
||||
logoWidth = +logoWidth || (logo ? 14 : 0)
|
||||
|
||||
let logoPadding
|
||||
if (left.length === 0) {
|
||||
logoPadding = 0
|
||||
} else {
|
||||
logoPadding = logo ? 3 : 0
|
||||
}
|
||||
|
||||
const context = {
|
||||
text: [left, right],
|
||||
escapedText: [left, right].map(escapeXml),
|
||||
widths: [leftWidth + 10 + logoWidth + logoPadding, rightWidth + 10],
|
||||
links: links.map(escapeXml),
|
||||
logo: escapeXml(logo),
|
||||
logoPosition,
|
||||
logoWidth,
|
||||
logoPadding,
|
||||
colorA: toSvgColor(labelColor),
|
||||
colorB: toSvgColor(color),
|
||||
escapeXml,
|
||||
}
|
||||
|
||||
const templateFn = templates[template]
|
||||
|
||||
// The call to template() can raise an exception.
|
||||
return templateFn(context)
|
||||
}
|
||||
@@ -1,231 +0,0 @@
|
||||
'use strict'
|
||||
|
||||
const { test, given, forCases } = require('sazerac')
|
||||
const { expect } = require('chai')
|
||||
const snapshot = require('snap-shot-it')
|
||||
const isSvg = require('is-svg')
|
||||
const makeBadge = require('./make-badge')
|
||||
|
||||
function testColor(color = '', colorAttr = 'colorB') {
|
||||
return JSON.parse(
|
||||
makeBadge({
|
||||
text: ['name', 'Bob'],
|
||||
[colorAttr]: color,
|
||||
format: 'json',
|
||||
})
|
||||
).color
|
||||
}
|
||||
|
||||
describe('The badge generator', function() {
|
||||
describe('color test', function() {
|
||||
test(testColor, () => {
|
||||
// valid hex
|
||||
forCases([
|
||||
given('#4c1'),
|
||||
given('#4C1'),
|
||||
given('4C1'),
|
||||
given('4c1'),
|
||||
]).expect('#4c1')
|
||||
forCases([
|
||||
given('#abc123'),
|
||||
given('#ABC123'),
|
||||
given('abc123'),
|
||||
given('ABC123'),
|
||||
]).expect('#abc123')
|
||||
// valid rgb(a)
|
||||
given('rgb(0,128,255)').expect('rgb(0,128,255)')
|
||||
given('rgba(0,128,255,0)').expect('rgba(0,128,255,0)')
|
||||
// valid hsl(a)
|
||||
given('hsl(100, 56%, 10%)').expect('hsl(100, 56%, 10%)')
|
||||
given('hsla(25,20%,0%,0.1)').expect('hsla(25,20%,0%,0.1)')
|
||||
// CSS named color.
|
||||
given('papayawhip').expect('papayawhip')
|
||||
// Shields named color.
|
||||
given('red').expect('red')
|
||||
given('green').expect('green')
|
||||
given('blue').expect('blue')
|
||||
given('yellow').expect('yellow')
|
||||
|
||||
forCases(
|
||||
// invalid hex
|
||||
given('#123red'), // contains letter above F
|
||||
given('#red'), // contains letter above F
|
||||
// invalid rgb(a)
|
||||
given('rgb(220,128,255,0.5)'), // has alpha
|
||||
given('rgba(0,0,255)'), // no alpha
|
||||
// invalid hsl(a)
|
||||
given('hsl(360,50%,50%,0.5)'), // has alpha
|
||||
given('hsla(0,50%,101%)'), // no alpha
|
||||
// neither a css named color nor colorscheme
|
||||
given('notacolor'),
|
||||
given('bluish'),
|
||||
given('almostred'),
|
||||
given('brightmaroon'),
|
||||
given('cactus')
|
||||
).expect(undefined)
|
||||
})
|
||||
})
|
||||
|
||||
describe('color aliases', function() {
|
||||
test(testColor, () => {
|
||||
forCases([
|
||||
given('#4c1', 'color'),
|
||||
given('#4c1', 'colorB'),
|
||||
given('#4c1', 'colorscheme'),
|
||||
]).expect('#4c1')
|
||||
})
|
||||
})
|
||||
|
||||
describe('SVG', function() {
|
||||
it('should produce SVG', function() {
|
||||
const svg = makeBadge({ text: ['cactus', 'grown'], format: 'svg' })
|
||||
expect(svg)
|
||||
.to.satisfy(isSvg)
|
||||
.and.to.include('cactus')
|
||||
.and.to.include('grown')
|
||||
})
|
||||
|
||||
it('should always produce the same SVG (unless we have changed something!)', function() {
|
||||
const svg = makeBadge({ text: ['cactus', 'grown'], format: 'svg' })
|
||||
snapshot(svg)
|
||||
})
|
||||
})
|
||||
|
||||
describe('JSON', function() {
|
||||
it('should produce the expected JSON', function() {
|
||||
const json = makeBadge({
|
||||
text: ['cactus', 'grown'],
|
||||
format: 'json',
|
||||
links: ['https://example.com/', 'https://other.example.com/'],
|
||||
})
|
||||
expect(JSON.parse(json)).to.deep.equal({
|
||||
name: 'cactus',
|
||||
label: 'cactus',
|
||||
value: 'grown',
|
||||
message: 'grown',
|
||||
link: ['https://example.com/', 'https://other.example.com/'],
|
||||
})
|
||||
})
|
||||
|
||||
it('should replace unknown svg template with "flat"', function() {
|
||||
const jsonBadgeWithUnknownStyle = makeBadge({
|
||||
text: ['name', 'Bob'],
|
||||
format: 'svg',
|
||||
template: 'unknown_style',
|
||||
})
|
||||
const jsonBadgeWithDefaultStyle = makeBadge({
|
||||
text: ['name', 'Bob'],
|
||||
format: 'svg',
|
||||
template: 'flat',
|
||||
})
|
||||
expect(jsonBadgeWithUnknownStyle)
|
||||
.to.equal(jsonBadgeWithDefaultStyle)
|
||||
.and.to.satisfy(isSvg)
|
||||
})
|
||||
|
||||
it('should replace "popout-square" svg template with "flat-square"', function() {
|
||||
const jsonBadgeWithUnknownStyle = makeBadge({
|
||||
text: ['name', 'Bob'],
|
||||
format: 'svg',
|
||||
template: 'popout-square',
|
||||
})
|
||||
const jsonBadgeWithDefaultStyle = makeBadge({
|
||||
text: ['name', 'Bob'],
|
||||
format: 'svg',
|
||||
template: 'flat-square',
|
||||
})
|
||||
expect(jsonBadgeWithUnknownStyle)
|
||||
.to.equal(jsonBadgeWithDefaultStyle)
|
||||
.and.to.satisfy(isSvg)
|
||||
})
|
||||
})
|
||||
|
||||
describe('"for-the-badge" template badge generation', function() {
|
||||
// https://github.com/badges/shields/issues/1280
|
||||
it('numbers should produce a string', function() {
|
||||
const svg = makeBadge({
|
||||
text: [1998, 1999],
|
||||
format: 'svg',
|
||||
template: 'for-the-badge',
|
||||
})
|
||||
expect(svg)
|
||||
.to.include('1998')
|
||||
.and.to.include('1999')
|
||||
})
|
||||
|
||||
it('lowercase/mixedcase string should produce uppercase string', function() {
|
||||
const svg = makeBadge({
|
||||
text: ['Label', '1 string'],
|
||||
format: 'svg',
|
||||
template: 'for-the-badge',
|
||||
})
|
||||
expect(svg)
|
||||
.to.include('LABEL')
|
||||
.and.to.include('1 STRING')
|
||||
})
|
||||
})
|
||||
|
||||
describe('"social" template badge generation', function() {
|
||||
it('should produce capitalized string for badge key', function() {
|
||||
const svg = makeBadge({
|
||||
text: ['some-key', 'some-value'],
|
||||
format: 'svg',
|
||||
template: 'social',
|
||||
})
|
||||
expect(svg)
|
||||
.to.include('Some-key')
|
||||
.and.to.include('some-value')
|
||||
})
|
||||
|
||||
// https://github.com/badges/shields/issues/1606
|
||||
it('should handle empty strings used as badge keys', function() {
|
||||
const svg = makeBadge({
|
||||
text: ['', 'some-value'],
|
||||
format: 'json',
|
||||
template: 'social',
|
||||
})
|
||||
expect(svg)
|
||||
.to.include('""')
|
||||
.and.to.include('some-value')
|
||||
})
|
||||
})
|
||||
describe('badges with logos should always produce the same badge', function() {
|
||||
it('shields GitHub logo default color (#333333)', function() {
|
||||
const svg = makeBadge({
|
||||
text: ['label', 'message'],
|
||||
format: 'svg',
|
||||
logo: 'github',
|
||||
})
|
||||
snapshot(svg)
|
||||
})
|
||||
|
||||
it('shields GitHub logo custom color (whitesmoke)', function() {
|
||||
const svg = makeBadge({
|
||||
text: ['label', 'message'],
|
||||
format: 'svg',
|
||||
logo: 'github',
|
||||
logoColor: 'whitesmoke',
|
||||
})
|
||||
snapshot(svg)
|
||||
})
|
||||
|
||||
it('simple-icons javascript logo default color (#F7DF1E)', function() {
|
||||
const svg = makeBadge({
|
||||
text: ['label', 'message'],
|
||||
format: 'svg',
|
||||
logo: 'javascript',
|
||||
})
|
||||
snapshot(svg)
|
||||
})
|
||||
|
||||
it('simple-icons javascript logo custom color (rgba(46,204,113,0.8))', function() {
|
||||
const svg = makeBadge({
|
||||
text: ['label', 'message'],
|
||||
format: 'svg',
|
||||
logo: 'javascript',
|
||||
logoColor: 'rgba(46,204,113,0.8)',
|
||||
})
|
||||
snapshot(svg)
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,25 +0,0 @@
|
||||
'use strict'
|
||||
|
||||
const { promisify } = require('util')
|
||||
const gm = require('gm')
|
||||
|
||||
const imageMagick = gm.subClass({ imageMagick: true })
|
||||
|
||||
async function svgToImg(svg, format) {
|
||||
const svgBuffer = Buffer.from(
|
||||
`<?xml version="1.0" encoding="UTF-8" standalone="yes"?>${svg}`
|
||||
)
|
||||
|
||||
const chain = imageMagick(svgBuffer, `image.${format}`)
|
||||
.density(90)
|
||||
.background(format === 'jpg' ? '#FFFFFF' : 'none')
|
||||
.flatten()
|
||||
const toBuffer = chain.toBuffer.bind(chain)
|
||||
|
||||
return promisify(toBuffer)(format)
|
||||
}
|
||||
|
||||
module.exports = svgToImg
|
||||
|
||||
// To simplify testing.
|
||||
module.exports._imageMagick = imageMagick
|
||||
@@ -1,14 +0,0 @@
|
||||
'use strict'
|
||||
|
||||
const { expect } = require('chai')
|
||||
const isPng = require('is-png')
|
||||
const svg2img = require('./svg-to-img')
|
||||
const makeBadge = require('./make-badge')
|
||||
|
||||
describe('The rasterizer', function() {
|
||||
it('should produce PNG', async function() {
|
||||
const svg = makeBadge({ text: ['cactus', 'grown'], format: 'svg' })
|
||||
const data = await svg2img(svg, 'png')
|
||||
expect(data).to.satisfy(isPng)
|
||||
})
|
||||
})
|
||||
@@ -1,25 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="{{=(it.widths[0] -= it.text[0].length ? 0 : (it.logo ? (it.colorA ? 0 : 7) : 11))+it.widths[1]}}" height="20">
|
||||
<g shape-rendering="crispEdges">
|
||||
<rect width="{{=it.widths[0]}}" height="20" fill="{{=it.escapeXml(it.text[0].length || it.logo && it.colorA ? (it.colorA||"#555") : (it.colorB||"#4c1"))}}"/>
|
||||
<rect x="{{=it.widths[0]}}" width="{{=it.widths[1]}}" height="20" fill="{{=it.escapeXml(it.colorB||"#4c1")}}"/>
|
||||
</g>
|
||||
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="110">
|
||||
{{?it.logo}}
|
||||
<image x="5" y="3" width="{{=it.logoWidth}}" height="14" xlink:href="{{=it.logo}}"/>
|
||||
{{?}}
|
||||
{{?it.text[0].length}}
|
||||
<text x="{{=(((it.widths[0]+it.logoWidth+it.logoPadding)/2)+1)*10}}" y="140" transform="scale(0.1)" textLength="{{=(it.widths[0]-(10+it.logoWidth+it.logoPadding))*10}}" lengthAdjust="spacing">{{=it.escapedText[0]}}</text>
|
||||
{{?}}
|
||||
<text x="{{=(it.widths[0]+it.widths[1]/2-(it.text[0].length ? 1 : 0 ))*10}}" y="140" transform="scale(0.1)" textLength="{{=(it.widths[1]-10)*10}}" lengthAdjust="spacing">{{=it.escapedText[1]}}</text>
|
||||
</g>
|
||||
{{?(it.links[0] && it.links[0].length)}}
|
||||
<a target="_blank" xlink:href="{{=it.links[0]}}">
|
||||
<rect width="{{=it.widths[0]}}" height="20" fill="rgba(0,0,0,0)"/>
|
||||
</a>
|
||||
{{?}}
|
||||
{{?(it.links[0] && it.links[0].length || it.links[1] && it.links[1].length)}}
|
||||
<a target="_blank" xlink:href="{{=it.links[1] || it.links[0]}}">
|
||||
<rect x="{{=it.widths[0]}}" width="{{=it.widths[1]}}" height="20" fill="rgba(0,0,0,0)"/>
|
||||
</a>
|
||||
{{?}}
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.6 KiB |
@@ -1,39 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="{{=(it.widths[0] -= it.text[0].length ? 0 : (it.logo ? (it.colorA ? 0 : 7) : 11))+it.widths[1]}}" height="20">
|
||||
<linearGradient id="smooth" x2="0" y2="100%">
|
||||
<stop offset="0" stop-color="#bbb" stop-opacity=".1"/>
|
||||
<stop offset="1" stop-opacity=".1"/>
|
||||
</linearGradient>
|
||||
|
||||
<clipPath id="round">
|
||||
<rect width="{{=it.widths[0]+it.widths[1]}}" height="20" rx="3" fill="#fff"/>
|
||||
</clipPath>
|
||||
|
||||
<g clip-path="url(#round)">
|
||||
<rect width="{{=it.widths[0]}}" height="20" fill="{{=it.escapeXml(it.text[0].length || it.logo && it.colorA ? (it.colorA||"#555") : (it.colorB||"#4c1"))}}"/>
|
||||
<rect x="{{=it.widths[0]}}" width="{{=it.widths[1]}}" height="20" fill="{{=it.escapeXml(it.colorB||"#4c1")}}"/>
|
||||
<rect width="{{=it.widths[0]+it.widths[1]}}" height="20" fill="url(#smooth)"/>
|
||||
</g>
|
||||
|
||||
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="110">
|
||||
{{?it.logo}}
|
||||
<image x="5" y="3" width="{{=it.logoWidth}}" height="14" xlink:href="{{=it.logo}}"/>
|
||||
{{?}}
|
||||
{{?it.text[0].length}}
|
||||
<text x="{{=(((it.widths[0]+it.logoWidth+it.logoPadding)/2)+1)*10}}" y="150" fill="#010101" fill-opacity=".3" transform="scale(0.1)" textLength="{{=(it.widths[0]-(10+it.logoWidth+it.logoPadding))*10}}" lengthAdjust="spacing">{{=it.escapedText[0]}}</text>
|
||||
<text x="{{=(((it.widths[0]+it.logoWidth+it.logoPadding)/2)+1)*10}}" y="140" transform="scale(0.1)" textLength="{{=(it.widths[0]-(10+it.logoWidth+it.logoPadding))*10}}" lengthAdjust="spacing">{{=it.escapedText[0]}}</text>
|
||||
{{?}}
|
||||
<text x="{{=(it.widths[0]+it.widths[1]/2-(it.text[0].length ? 1 : 0 ))*10}}" y="150" fill="#010101" fill-opacity=".3" transform="scale(0.1)" textLength="{{=(it.widths[1]-10)*10}}" lengthAdjust="spacing">{{=it.escapedText[1]}}</text>
|
||||
<text x="{{=(it.widths[0]+it.widths[1]/2-(it.text[0].length ? 1 : 0 ))*10}}" y="140" transform="scale(0.1)" textLength="{{=(it.widths[1]-10)*10}}" lengthAdjust="spacing">{{=it.escapedText[1]}}</text>
|
||||
</g>
|
||||
|
||||
{{?(it.links[0] && it.links[0].length)}}
|
||||
<a target="_blank" xlink:href="{{=it.links[0]}}">
|
||||
<rect width="{{=it.widths[0]}}" height="20" fill="rgba(0,0,0,0)"/>
|
||||
</a>
|
||||
{{?}}
|
||||
{{?(it.links[0] && it.links[0].length || it.links[1] && it.links[1].length)}}
|
||||
<a target="_blank" xlink:href="{{=it.links[1] || it.links[0]}}">
|
||||
<rect x="{{=it.widths[0]}}" width="{{=it.widths[1]}}" height="20" fill="rgba(0,0,0,0)"/>
|
||||
</a>
|
||||
{{?}}
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 2.5 KiB |
@@ -1,25 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="{{=(it.widths[0] -= it.text[0].length ? -(10+(it.text[0].length*1.5)) : (it.logo ? (it.colorA ? -7 : 7) : 11))+(it.widths[1]+=(10+(it.text[1].length*2)))}}" height="28">
|
||||
<g shape-rendering="crispEdges">
|
||||
<rect width="{{=it.widths[0]}}" height="28" fill="{{=it.escapeXml(it.text[0].length || it.logo && it.colorA ? (it.colorA||"#555") : (it.colorB||"#4c1"))}}"/>
|
||||
<rect x="{{=it.widths[0]}}" width="{{=it.widths[1]}}" height="28" fill="{{=it.escapeXml(it.colorB||"#4c1")}}"/>
|
||||
</g>
|
||||
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="100">
|
||||
{{?it.logo}}
|
||||
<image x="9" y="7" width="{{=it.logoWidth}}" height="14" xlink:href="{{=it.logo}}"/>
|
||||
{{?}}
|
||||
{{?it.text[0].length}}
|
||||
<text x="{{=((it.widths[0]+it.logoWidth+it.logoPadding)/2)*10}}" y="175" transform="scale(0.1)" textLength="{{=(it.widths[0]-(24+it.logoWidth+it.logoPadding))*10}}" lengthAdjust="spacing">{{=it.escapedText[0]}}</text>
|
||||
{{?}}
|
||||
<text x="{{=(it.widths[0]+it.widths[1]/2)*10}}" y="175" font-weight="bold" transform="scale(0.1)" textLength="{{=(it.widths[1]-24)*10}}" lengthAdjust="spacing">{{=it.escapedText[1]}}</text>
|
||||
</g>
|
||||
{{?(it.text[0].length && it.links[0] && it.links[0].length)}}
|
||||
<a target="_blank" xlink:href="{{=it.links[0]}}">
|
||||
<rect width="{{=it.widths[0]}}" height="28" fill="rgba(0,0,0,0)"/>
|
||||
</a>
|
||||
{{?}}
|
||||
{{?(it.links[0] && it.links[0].length || it.links[1] && it.links[1].length)}}
|
||||
<a target="_blank" xlink:href="{{=it.links[1] || it.links[0]}}">
|
||||
<rect x="{{=it.widths[0]}}" width="{{=it.widths[1]}}" height="28" fill="rgba(0,0,0,0)"/>
|
||||
</a>
|
||||
{{?}}
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.7 KiB |
@@ -1,41 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="{{=(it.widths[0] -= it.text[0].length ? 0 : (it.logo ? (it.colorA ? 0 : 7) : 11))+it.widths[1]}}" height="18">
|
||||
<linearGradient id="smooth" 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="round">
|
||||
<rect width="{{=it.widths[0]+it.widths[1]}}" height="18" rx="4" fill="#fff"/>
|
||||
</clipPath>
|
||||
|
||||
<g clip-path="url(#round)">
|
||||
<rect width="{{=it.widths[0]}}" height="18" fill="{{=it.escapeXml(it.text[0].length || it.logo && it.colorA ? (it.colorA||"#555") : (it.colorB||"#4c1"))}}"/>
|
||||
<rect x="{{=it.widths[0]}}" width="{{=it.widths[1]}}" height="18" fill="{{=it.escapeXml(it.colorB||"#4c1")}}"/>
|
||||
<rect width="{{=it.widths[0]+it.widths[1]}}" height="18" fill="url(#smooth)"/>
|
||||
</g>
|
||||
|
||||
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="110">
|
||||
{{?it.logo}}
|
||||
<image x="5" y="3" width="{{=it.logoWidth}}" height="14" xlink:href="{{=it.logo}}"/>
|
||||
{{?}}
|
||||
{{?it.text[0].length}}
|
||||
<text x="{{=(((it.widths[0]+it.logoWidth+it.logoPadding)/2)+1)*10}}" y="140" fill="#010101" fill-opacity=".3" transform="scale(0.1)" textLength="{{=(it.widths[0]-(10+it.logoWidth+it.logoPadding))*10}}" lengthAdjust="spacing">{{=it.escapedText[0]}}</text>
|
||||
<text x="{{=(((it.widths[0]+it.logoWidth+it.logoPadding)/2)+1)*10}}" y="130" transform="scale(0.1)" textLength="{{=(it.widths[0]-(10+it.logoWidth+it.logoPadding))*10}}" lengthAdjust="spacing">{{=it.escapedText[0]}}</text>
|
||||
{{?}}
|
||||
<text x="{{=(it.widths[0]+it.widths[1]/2-(it.text[0].length ? 1 : 0))*10}}" y="140" fill="#010101" fill-opacity=".3" transform="scale(0.1)" textLength="{{=(it.widths[1]-10)*10}}" lengthAdjust="spacing">{{=it.escapedText[1]}}</text>
|
||||
<text x="{{=(it.widths[0]+it.widths[1]/2-(it.text[0].length ? 1 : 0))*10}}" y="130" transform="scale(0.1)" textLength="{{=(it.widths[1]-10)*10}}" lengthAdjust="spacing">{{=it.escapedText[1]}}</text>
|
||||
</g>
|
||||
|
||||
{{?(it.links[0] && it.links[0].length)}}
|
||||
<a target="_blank" xlink:href="{{=it.links[0]}}">
|
||||
<rect width="{{=it.widths[0]}}" height="18" fill="rgba(0,0,0,0)"/>
|
||||
</a>
|
||||
{{?}}
|
||||
{{?(it.links[0] && it.links[0].length || it.links[1] && it.links[1].length)}}
|
||||
<a target="_blank" xlink:href="{{=it.links[1] || it.links[0]}}">
|
||||
<rect x="{{=it.widths[0]}}" width="{{=it.widths[1]}}" height="18" fill="rgba(0,0,0,0)"/>
|
||||
</a>
|
||||
{{?}}
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 2.6 KiB |
@@ -1,39 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="{{=it.widths[0]+1 + (it.text[1] && it.text[1].length > 0 ? it.widths[1]+2 : 0)}}" height="20">
|
||||
{{it.widths[1]-=4;}}
|
||||
<style type="text/css"><![CDATA[
|
||||
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="{{=it.widths[0]}}" height="19" rx="2"/>
|
||||
{{?(it.text[1] && it.text[1].length)}}
|
||||
<rect y="0.5" x="{{=it.widths[0]+6.5}}" width="{{=it.widths[1]}}" height="19" rx="2" fill="#fafafa"/>
|
||||
<rect x="{{=it.widths[0]+6}}" y="7.5" width="0.5" height="5" stroke="#fafafa"/>
|
||||
<path d="M{{=it.widths[0]+6.5}} 6.5 l-3 3v1 l3 3" stroke="d5d5d5" fill="#fafafa"/>
|
||||
{{?}}
|
||||
</g>
|
||||
{{?it.logo}}
|
||||
<image x="5" y="3" width="{{=it.logoWidth}}" height="14" xlink:href="{{=it.logo}}"/>
|
||||
{{?}}
|
||||
<g fill="#333" text-anchor="middle" font-family="Helvetica Neue,Helvetica,Arial,sans-serif" font-weight="700" font-size="110px" line-height="14px">
|
||||
<text x="{{=((it.widths[0]+it.logoWidth+it.logoPadding)/2)*10}}" y="150" fill="#fff" transform="scale(0.1)" textLength="{{=(it.widths[0]-(10+it.logoWidth+it.logoPadding))*10}}" lengthAdjust="spacing">{{=it.escapedText[0]}}</text>
|
||||
<text x="{{=((it.widths[0]+it.logoWidth+it.logoPadding)/2)*10}}" y="140" transform="scale(0.1)" textLength="{{=(it.widths[0]-(10+it.logoWidth+it.logoPadding))*10}}" lengthAdjust="spacing">{{=it.escapedText[0]}}</text>
|
||||
{{?(it.text[1] && it.text[1].length)}}
|
||||
<text x="{{=(it.widths[0]+it.widths[1]/2+6)*10}}" y="150" fill="#fff" transform="scale(0.1)" textLength="{{=(it.widths[1]-8)*10}}" lengthAdjust="spacing">{{=it.escapedText[1]}}</text>
|
||||
{{?(it.links[0] && it.links[0].length || it.links[1] && it.links[1].length)}}<a target="_blank" xlink:href="{{=it.links[1] || it.links[0]}}">{{?}}
|
||||
<text id="rlink" x="{{=(it.widths[0]+it.widths[1]/2+6)*10}}" y="140" transform="scale(0.1)" textLength="{{=(it.widths[1]-8)*10}}" lengthAdjust="spacing">{{=it.escapedText[1]}}</text>
|
||||
{{?(it.links[0] && it.links[0].length || it.links[1] && it.links[1].length)}}</a>{{?}}
|
||||
{{?}}
|
||||
</g>
|
||||
{{?(it.links[0] && it.links[0].length)}}<a target="_blank" xlink:href="{{=it.links[0]}}">{{?}}
|
||||
<rect id="llink" stroke="#d5d5d5" fill="url(#a)" x="0.5" y="0.5" width="{{=it.widths[0]}}" height="19" rx="2"/>
|
||||
{{?(it.links[0] && it.links[0].length)}}</a>{{?}}
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 2.7 KiB |
@@ -1,7 +1,7 @@
|
||||
'use strict'
|
||||
|
||||
const Joi = require('@hapi/joi')
|
||||
const { toSvgColor } = require('../gh-badges/lib/color')
|
||||
const { toSvgColor } = require('../badge-maker/lib/color')
|
||||
const coalesce = require('../core/base-service/coalesce')
|
||||
const { svg2base64 } = require('./svg-helpers')
|
||||
const logos = require('./load-logos')()
|
||||
|
||||
179
package-lock.json
generated
179
package-lock.json
generated
@@ -3259,7 +3259,8 @@
|
||||
"@hapi/address": {
|
||||
"version": "2.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@hapi/address/-/address-2.1.4.tgz",
|
||||
"integrity": "sha512-QD1PhQk+s31P1ixsX0H0Suoupp3VMXzIVMSwobR3F3MSUO2YCV0B7xqLcUw/Bh8yuvd3LhpyqLQWTNcRmp6IdQ=="
|
||||
"integrity": "sha512-QD1PhQk+s31P1ixsX0H0Suoupp3VMXzIVMSwobR3F3MSUO2YCV0B7xqLcUw/Bh8yuvd3LhpyqLQWTNcRmp6IdQ==",
|
||||
"dev": true
|
||||
},
|
||||
"@hapi/bourne": {
|
||||
"version": "1.3.2",
|
||||
@@ -4920,6 +4921,14 @@
|
||||
"integrity": "sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM=",
|
||||
"dev": true
|
||||
},
|
||||
"anafanafo": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/anafanafo/-/anafanafo-1.0.0.tgz",
|
||||
"integrity": "sha512-pDPbI7SFRHu0byMXHAf+v74+LCcHSxnLYkcbfiV91XRlE+NSLpFCpEQdVUy9ZxZw/LuhTrOin4r8wlR3OFrKBA==",
|
||||
"requires": {
|
||||
"char-width-table-consumer": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"ansi-align": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.0.tgz",
|
||||
@@ -5111,22 +5120,12 @@
|
||||
"integrity": "sha1-iKK6tz0c97zVwbEYoAP2b2ZfpmI=",
|
||||
"dev": true
|
||||
},
|
||||
"array-parallel": {
|
||||
"version": "0.1.3",
|
||||
"resolved": "https://registry.npmjs.org/array-parallel/-/array-parallel-0.1.3.tgz",
|
||||
"integrity": "sha1-j3hTCJJu1apHjEfmTRszS2wMlH0="
|
||||
},
|
||||
"array-reduce": {
|
||||
"version": "0.0.0",
|
||||
"resolved": "https://registry.npmjs.org/array-reduce/-/array-reduce-0.0.0.tgz",
|
||||
"integrity": "sha1-FziZ0//Rx9k4PkR5Ul2+J4yrXys=",
|
||||
"dev": true
|
||||
},
|
||||
"array-series": {
|
||||
"version": "0.1.5",
|
||||
"resolved": "https://registry.npmjs.org/array-series/-/array-series-0.1.5.tgz",
|
||||
"integrity": "sha1-3103v8XC7wdV4qpPkv6ufUtaly8="
|
||||
},
|
||||
"array-union": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
|
||||
@@ -6697,6 +6696,13 @@
|
||||
"resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz",
|
||||
"integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc="
|
||||
},
|
||||
"badge-maker": {
|
||||
"version": "file:badge-maker",
|
||||
"requires": {
|
||||
"anafanafo": "^1.0.0",
|
||||
"is-css-color": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"balanced-match": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
|
||||
@@ -6827,6 +6833,11 @@
|
||||
"integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==",
|
||||
"dev": true
|
||||
},
|
||||
"binary-search": {
|
||||
"version": "1.3.6",
|
||||
"resolved": "https://registry.npmjs.org/binary-search/-/binary-search-1.3.6.tgz",
|
||||
"integrity": "sha512-nbE1WxOTTrUWIfsfZ4aHGYu5DOuNkbxGokjV6Z2kxfJK3uaAb8zNK1muzOeipoLHZjInT4Br88BHpzevc681xA=="
|
||||
},
|
||||
"bindings": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
|
||||
@@ -6910,7 +6921,8 @@
|
||||
"boolbase": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
|
||||
"integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24="
|
||||
"integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=",
|
||||
"dev": true
|
||||
},
|
||||
"boxen": {
|
||||
"version": "4.2.0",
|
||||
@@ -7851,6 +7863,14 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"char-width-table-consumer": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/char-width-table-consumer/-/char-width-table-consumer-1.0.0.tgz",
|
||||
"integrity": "sha512-Fz4UD0LBpxPgL9i29CJ5O4KANwaMnX/OhhbxzvNa332h+9+nRKyeuLw4wA51lt/ex67+/AdsoBQJF3kgX2feYQ==",
|
||||
"requires": {
|
||||
"binary-search": "^1.3.5"
|
||||
}
|
||||
},
|
||||
"chardet": {
|
||||
"version": "0.7.0",
|
||||
"resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz",
|
||||
@@ -8514,6 +8534,7 @@
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/coa/-/coa-2.0.1.tgz",
|
||||
"integrity": "sha512-5wfTTO8E2/ja4jFSxePXlG5nRu5bBtL/r1HCIpJW/lzT6yDtKl0u0Z4o/Vpz32IpKmBn7HerheEZQgA9N2DarQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"q": "^1.1.2"
|
||||
}
|
||||
@@ -8583,7 +8604,8 @@
|
||||
"colors": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz",
|
||||
"integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM="
|
||||
"integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=",
|
||||
"dev": true
|
||||
},
|
||||
"combined-stream": {
|
||||
"version": "1.0.6",
|
||||
@@ -9195,6 +9217,7 @@
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-4.0.2.tgz",
|
||||
"integrity": "sha1-e5JHYhwjrf3ThWAEqCPL45dCTUE=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"lru-cache": "^4.0.1",
|
||||
"which": "^1.2.9"
|
||||
@@ -9339,7 +9362,8 @@
|
||||
"css-select-base-adapter": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/css-select-base-adapter/-/css-select-base-adapter-0.1.0.tgz",
|
||||
"integrity": "sha1-AQKz0UYw34bD65+p9UVicBBs+ZA="
|
||||
"integrity": "sha1-AQKz0UYw34bD65+p9UVicBBs+ZA=",
|
||||
"dev": true
|
||||
},
|
||||
"css-selector-tokenizer": {
|
||||
"version": "0.7.2",
|
||||
@@ -9367,6 +9391,7 @@
|
||||
"version": "1.0.0-alpha.28",
|
||||
"resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.28.tgz",
|
||||
"integrity": "sha512-joNNW1gCp3qFFzj4St6zk+Wh/NBv0vM5YbEreZk0SD4S23S+1xBKb6cLDg2uj4P4k/GUMlIm6cKIDqIG+vdt0w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"mdn-data": "~1.1.0",
|
||||
"source-map": "^0.5.3"
|
||||
@@ -9375,12 +9400,14 @@
|
||||
"css-url-regex": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/css-url-regex/-/css-url-regex-1.1.0.tgz",
|
||||
"integrity": "sha1-g4NCMMyfdMRX3lnuvRVD/uuDt+w="
|
||||
"integrity": "sha1-g4NCMMyfdMRX3lnuvRVD/uuDt+w=",
|
||||
"dev": true
|
||||
},
|
||||
"css-what": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.0.tgz",
|
||||
"integrity": "sha1-lGfQMsOM+u+58teVASUwYvh/ob0="
|
||||
"integrity": "sha1-lGfQMsOM+u+58teVASUwYvh/ob0=",
|
||||
"dev": true
|
||||
},
|
||||
"cssesc": {
|
||||
"version": "3.0.0",
|
||||
@@ -9469,6 +9496,7 @@
|
||||
"version": "3.5.1",
|
||||
"resolved": "https://registry.npmjs.org/csso/-/csso-3.5.1.tgz",
|
||||
"integrity": "sha512-vrqULLffYU1Q2tLdJvaCYbONStnfkfimRxXNaGjxMldI0C7JPBC4rB1RyjhfdZ4m1frm8pM9uRPKH3d2knZ8gg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"css-tree": "1.0.0-alpha.29"
|
||||
},
|
||||
@@ -9477,6 +9505,7 @@
|
||||
"version": "1.0.0-alpha.29",
|
||||
"resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.29.tgz",
|
||||
"integrity": "sha512-sRNb1XydwkW9IOci6iB2xmy8IGCj6r/fr+JWitvJ2JxQRPzN3T4AGGVWCMlVmVwM1gtgALJRmGIlWv5ppnGGkg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"mdn-data": "~1.1.0",
|
||||
"source-map": "^0.5.3"
|
||||
@@ -10325,6 +10354,7 @@
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz",
|
||||
"integrity": "sha1-BzxpdUbOB4DOI75KKOKT5AvDDII=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"domelementtype": "~1.1.1",
|
||||
"entities": "~1.1.1"
|
||||
@@ -10333,7 +10363,8 @@
|
||||
"domelementtype": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz",
|
||||
"integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs="
|
||||
"integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs=",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -10352,7 +10383,8 @@
|
||||
"domelementtype": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz",
|
||||
"integrity": "sha1-sXrtguirWeUt2cGbF1bg/BhyBMI="
|
||||
"integrity": "sha1-sXrtguirWeUt2cGbF1bg/BhyBMI=",
|
||||
"dev": true
|
||||
},
|
||||
"domhandler": {
|
||||
"version": "2.3.0",
|
||||
@@ -10373,11 +10405,6 @@
|
||||
"domelementtype": "1"
|
||||
}
|
||||
},
|
||||
"dot": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/dot/-/dot-1.1.2.tgz",
|
||||
"integrity": "sha1-xzdwGfxOVQeYkosrmv62ar+h8vk="
|
||||
},
|
||||
"dot-prop": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz",
|
||||
@@ -10662,7 +10689,8 @@
|
||||
"entities": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz",
|
||||
"integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA="
|
||||
"integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA=",
|
||||
"dev": true
|
||||
},
|
||||
"envinfo": {
|
||||
"version": "7.5.0",
|
||||
@@ -16118,48 +16146,6 @@
|
||||
"assert-plus": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"gh-badges": {
|
||||
"version": "file:gh-badges",
|
||||
"requires": {
|
||||
"anafanafo": "^1.0.0",
|
||||
"dot": "^1.1.2",
|
||||
"gm": "^1.23.0",
|
||||
"is-css-color": "^1.0.0",
|
||||
"svgo": "^1.1.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@hapi/joi": {
|
||||
"version": "15.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@hapi/joi/-/joi-15.0.3.tgz",
|
||||
"integrity": "sha512-z6CesJ2YBwgVCi+ci8SI8zixoj8bGFn/vZb9MBPbSyoxsS2PnWYjHcyTM17VLK6tx64YVK38SDIh10hJypB+ig==",
|
||||
"requires": {
|
||||
"@hapi/address": "2.x.x",
|
||||
"@hapi/topo": "3.x.x"
|
||||
}
|
||||
},
|
||||
"anafanafo": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/anafanafo/-/anafanafo-1.0.0.tgz",
|
||||
"integrity": "sha512-pDPbI7SFRHu0byMXHAf+v74+LCcHSxnLYkcbfiV91XRlE+NSLpFCpEQdVUy9ZxZw/LuhTrOin4r8wlR3OFrKBA==",
|
||||
"requires": {
|
||||
"char-width-table-consumer": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"binary-search": {
|
||||
"version": "1.3.5",
|
||||
"resolved": "https://registry.npmjs.org/binary-search/-/binary-search-1.3.5.tgz",
|
||||
"integrity": "sha512-RHFP0AdU6KAB0CCZsRMU2CJTk2EpL8GLURT+4gilpjr1f/7M91FgUMnXuQLmf3OKLet34gjuNFwO7e4agdX5pw=="
|
||||
},
|
||||
"char-width-table-consumer": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/char-width-table-consumer/-/char-width-table-consumer-1.0.0.tgz",
|
||||
"integrity": "sha512-Fz4UD0LBpxPgL9i29CJ5O4KANwaMnX/OhhbxzvNa332h+9+nRKyeuLw4wA51lt/ex67+/AdsoBQJF3kgX2feYQ==",
|
||||
"requires": {
|
||||
"binary-search": "^1.3.5"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"git-config-path": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/git-config-path/-/git-config-path-1.0.1.tgz",
|
||||
@@ -16422,32 +16408,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"gm": {
|
||||
"version": "1.23.1",
|
||||
"resolved": "https://registry.npmjs.org/gm/-/gm-1.23.1.tgz",
|
||||
"integrity": "sha1-Lt7rlYCE0PjqeYjl2ZWxx9/BR3c=",
|
||||
"requires": {
|
||||
"array-parallel": "~0.1.3",
|
||||
"array-series": "~0.1.5",
|
||||
"cross-spawn": "^4.0.0",
|
||||
"debug": "^3.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"debug": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
|
||||
"integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
|
||||
"requires": {
|
||||
"ms": "2.0.0"
|
||||
}
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
|
||||
}
|
||||
}
|
||||
},
|
||||
"got": {
|
||||
"version": "9.6.0",
|
||||
"resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz",
|
||||
@@ -20436,6 +20396,7 @@
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz",
|
||||
"integrity": "sha512-q4spe4KTfsAS1SUHLO0wz8Qiyf1+vMIAgpRYioFYDMNqKfHQbg+AVDH3i4fvpl71/P1L0dBl+fQi+P37UYf0ew==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"pseudomap": "^1.0.2",
|
||||
"yallist": "^2.1.2"
|
||||
@@ -20605,7 +20566,8 @@
|
||||
"mdn-data": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-1.1.4.tgz",
|
||||
"integrity": "sha512-FSYbp3lyKjyj3E7fMl6rYvUdX0FBXaluGqlFoYESWQlyUTq8R+wp0rkFxoYFqZlHCvsUXGjyJmLQSnXToYhOSA=="
|
||||
"integrity": "sha512-FSYbp3lyKjyj3E7fMl6rYvUdX0FBXaluGqlFoYESWQlyUTq8R+wp0rkFxoYFqZlHCvsUXGjyJmLQSnXToYhOSA==",
|
||||
"dev": true
|
||||
},
|
||||
"mdurl": {
|
||||
"version": "1.0.1",
|
||||
@@ -20621,7 +20583,7 @@
|
||||
},
|
||||
"media-typer": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "http://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
|
||||
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
|
||||
"integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=",
|
||||
"dev": true
|
||||
},
|
||||
@@ -22289,6 +22251,7 @@
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.1.tgz",
|
||||
"integrity": "sha1-mSms32KPwsQQmN6rgqxYDPFJquQ=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"boolbase": "~1.0.0"
|
||||
}
|
||||
@@ -22871,6 +22834,7 @@
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz",
|
||||
"integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"define-properties": "^1.1.2",
|
||||
"es-abstract": "^1.5.1"
|
||||
@@ -22897,6 +22861,7 @@
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/object.values/-/object.values-1.0.4.tgz",
|
||||
"integrity": "sha1-5STaCbT2b/Bd9FdUbscqyZ8TBpo=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"define-properties": "^1.1.2",
|
||||
"es-abstract": "^1.6.1",
|
||||
@@ -24768,7 +24733,8 @@
|
||||
"pseudomap": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
|
||||
"integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM="
|
||||
"integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=",
|
||||
"dev": true
|
||||
},
|
||||
"psl": {
|
||||
"version": "1.1.29",
|
||||
@@ -24854,7 +24820,8 @@
|
||||
"q": {
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz",
|
||||
"integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc="
|
||||
"integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=",
|
||||
"dev": true
|
||||
},
|
||||
"qs": {
|
||||
"version": "6.5.2",
|
||||
@@ -26453,7 +26420,8 @@
|
||||
"sax": {
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
|
||||
"integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw=="
|
||||
"integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==",
|
||||
"dev": true
|
||||
},
|
||||
"sazerac": {
|
||||
"version": "1.1.0",
|
||||
@@ -27711,7 +27679,8 @@
|
||||
"stable": {
|
||||
"version": "0.1.8",
|
||||
"resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz",
|
||||
"integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w=="
|
||||
"integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==",
|
||||
"dev": true
|
||||
},
|
||||
"stack-trace": {
|
||||
"version": "0.0.10",
|
||||
@@ -28866,6 +28835,7 @@
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/svgo/-/svgo-1.1.1.tgz",
|
||||
"integrity": "sha512-GBkJbnTuFpM4jFbiERHDWhZc/S/kpHToqmZag3aEBjPYK44JAN2QBjvrGIxLOoCyMZjuFQIfTO2eJd8uwLY/9g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"coa": "~2.0.1",
|
||||
"colors": "~1.1.2",
|
||||
@@ -28887,6 +28857,7 @@
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/css-select/-/css-select-2.0.0.tgz",
|
||||
"integrity": "sha512-MGhoq1S9EyPgZIGnts8Yz5WwUOyHmPMdlqeifsYs/xFX7AAm3hY0RJe1dqVlXtYPI66Nsk39R/sa5/ree6L2qg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"boolbase": "^1.0.0",
|
||||
"css-what": "2.1",
|
||||
@@ -28898,6 +28869,7 @@
|
||||
"version": "1.7.0",
|
||||
"resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz",
|
||||
"integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"dom-serializer": "0",
|
||||
"domelementtype": "1"
|
||||
@@ -28906,12 +28878,14 @@
|
||||
"minimist": {
|
||||
"version": "0.0.8",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
|
||||
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="
|
||||
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
|
||||
"dev": true
|
||||
},
|
||||
"mkdirp": {
|
||||
"version": "0.5.1",
|
||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
|
||||
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"minimist": "0.0.8"
|
||||
}
|
||||
@@ -29691,7 +29665,8 @@
|
||||
"unquote": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/unquote/-/unquote-1.1.1.tgz",
|
||||
"integrity": "sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ="
|
||||
"integrity": "sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ=",
|
||||
"dev": true
|
||||
},
|
||||
"unset-value": {
|
||||
"version": "1.0.0",
|
||||
@@ -30009,6 +29984,7 @@
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.0.tgz",
|
||||
"integrity": "sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"define-properties": "^1.1.2",
|
||||
"object.getownpropertydescriptors": "^2.0.3"
|
||||
@@ -30928,7 +30904,8 @@
|
||||
"yallist": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
|
||||
"integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI="
|
||||
"integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=",
|
||||
"dev": true
|
||||
},
|
||||
"yaml": {
|
||||
"version": "1.7.2",
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
"escape-string-regexp": "^2.0.0",
|
||||
"fast-xml-parser": "^3.16.0",
|
||||
"fsos": "^1.1.6",
|
||||
"gh-badges": "file:gh-badges",
|
||||
"badge-maker": "file:badge-maker",
|
||||
"glob": "^7.1.6",
|
||||
"graphql": "^14.6.0",
|
||||
"graphql-tag": "^2.10.3",
|
||||
@@ -84,7 +84,7 @@
|
||||
"test:frontend": "cross-env NODE_ENV=test ts-mocha --config .mocharc-frontend.yml \"frontend/**/*.spec.@(js|ts|tsx)\"",
|
||||
"test:e2e": "cypress run",
|
||||
"test:core": "cross-env NODE_CONFIG_ENV=test mocha \"core/**/*.spec.js\" \"lib/**/*.spec.js\" \"services/**/*.spec.js\"",
|
||||
"test:package": "mocha \"gh-badges/**/*.spec.js\"",
|
||||
"test:package": "mocha \"badge-maker/**/*.spec.js\"",
|
||||
"test:entrypoint": "cross-env NODE_CONFIG_ENV=test mocha entrypoint.spec.js",
|
||||
"test:integration": "cross-env NODE_CONFIG_ENV=test mocha \"core/**/*.integration.js\" \"services/**/*.integration.js\"",
|
||||
"test:services": "cross-env NODE_CONFIG_ENV=test mocha --delay core/service-test-runner/cli.js",
|
||||
|
||||
@@ -27,7 +27,7 @@ module.exports = class SnykVulnerabilityGitHub extends SynkVulnerabilityBase {
|
||||
namedParams: {
|
||||
user: 'badges',
|
||||
repo: 'shields',
|
||||
manifestFilePath: 'gh-badges/package.json',
|
||||
manifestFilePath: 'badge-maker/package.json',
|
||||
},
|
||||
staticPreview: this.render({ vulnerabilities: '0' }),
|
||||
documentation: `
|
||||
|
||||
@@ -32,7 +32,7 @@ t.create('valid target manifest path')
|
||||
})
|
||||
|
||||
t.create('invalid target manifest path')
|
||||
.get('/badges/shields/gh-badges/requirements.txt.json')
|
||||
.get('/badges/shields/badge-maker/requirements.txt.json')
|
||||
.timeout(20000)
|
||||
.expectBadge({
|
||||
label: 'vulnerabilities',
|
||||
@@ -66,12 +66,12 @@ t.create('repo has vulnerabilities')
|
||||
})
|
||||
|
||||
t.create('target manifest file has no vulnerabilities')
|
||||
.get('/badges/shields/gh-badges/package.json.json')
|
||||
.get('/badges/shields/badge-maker/package.json.json')
|
||||
.intercept(nock =>
|
||||
nock('https://snyk.io/test/github/badges/shields')
|
||||
.get('/badge.svg')
|
||||
.query({
|
||||
targetFile: 'gh-badges/package.json',
|
||||
targetFile: 'badge-maker/package.json',
|
||||
})
|
||||
.reply(200, zeroVulnerabilitiesSvg)
|
||||
)
|
||||
@@ -82,12 +82,12 @@ t.create('target manifest file has no vulnerabilities')
|
||||
})
|
||||
|
||||
t.create('target manifest file has vulnerabilities')
|
||||
.get('/badges/shields/gh-badges/package.json.json')
|
||||
.get('/badges/shields/badge-maker/package.json.json')
|
||||
.intercept(nock =>
|
||||
nock('https://snyk.io/test/github/badges/shields')
|
||||
.get('/badge.svg')
|
||||
.query({
|
||||
targetFile: 'gh-badges/package.json',
|
||||
targetFile: 'badge-maker/package.json',
|
||||
})
|
||||
.reply(200, twoVulnerabilitiesSvg)
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user