badge_maker/
lib.rs

1//! # Badge-Maker
2//!
3//! A fast and accurate badge maker for services like [shields.io](https://shields.io/). Verified to
4//! match [badge-maker](https://www.npmjs.com/package/badge-maker) 1-to-1 with side by rendering tests*.
5//!
6//! <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="84" height="20" role="img" aria-label="example: flat"><title>example: flat</title><linearGradient id="bms-6df9790b166df7b8" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="bmr-6df9790b166df7b8"><rect width="84" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#bmr-6df9790b166df7b8)"><rect width="57" height="20" fill="#555"/><rect x="57" width="27" height="20" fill="#ff5b5a"/><rect width="84" height="20" fill="url(#bms-6df9790b166df7b8)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text aria-hidden="true" x="295" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="470">example</text><text x="295" y="140" transform="scale(.1)" fill="#fff" textLength="470">example</text><text aria-hidden="true" x="695" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="170">flat</text><text x="695" y="140" transform="scale(.1)" fill="#fff" textLength="170">flat</text></g></svg>
7//!
8//! <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="102" height="18" role="img" aria-label="example: plastic"><title>example: plastic</title><linearGradient id="bms-673fc3b0d46c7e6f" 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="bmr-673fc3b0d46c7e6f"><rect width="102" height="18" rx="4" fill="#fff"/></clipPath><g clip-path="url(#bmr-673fc3b0d46c7e6f)"><rect width="57" height="18" fill="#555"/><rect x="57" width="45" height="18" fill="#ffb932"/><rect width="102" height="18" fill="url(#bms-673fc3b0d46c7e6f)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text aria-hidden="true" x="295" y="140" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="470">example</text><text x="295" y="130" transform="scale(.1)" fill="#fff" textLength="470">example</text><text aria-hidden="true" x="785" y="140" fill="#ccc" fill-opacity=".3" transform="scale(.1)" textLength="350">plastic</text><text x="785" y="130" transform="scale(.1)" fill="#333" textLength="350">plastic</text></g></svg>
9//!
10//! <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="122" height="20" role="img" aria-label="example: flatsquare"><title>example: flatsquare</title><g shape-rendering="crispEdges"><rect width="57" height="20" fill="#555"/><rect x="57" width="65" height="20" fill="#fffe27"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text x="295" y="140" transform="scale(.1)" fill="#fff" textLength="470">example</text><text x="885" y="140" transform="scale(.1)" fill="#333" textLength="550">flatsquare</text></g></svg>
11//!
12//! <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="88" height="20" role="img" aria-label="badge: maker"><title>badge: maker</title><linearGradient id="bms-65d9c12cf1a1b6af" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="bmr-65d9c12cf1a1b6af"><rect width="88" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#bmr-65d9c12cf1a1b6af)"><rect width="43" height="20" fill="#555"/><rect x="43" width="45" height="20" fill="#33b5e5"/><rect width="88" height="20" fill="url(#bms-65d9c12cf1a1b6af)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text aria-hidden="true" x="225" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="330">badge</text><text x="225" y="140" transform="scale(.1)" fill="#fff" textLength="330">badge</text><text aria-hidden="true" x="645" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="350">maker</text><text x="645" y="140" transform="scale(.1)" fill="#fff" textLength="350">maker</text></g></svg>
13//!
14//! <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="94" height="20" role="img" aria-label="color: example"><title>color: example</title><linearGradient id="bms-e0307dea9033836d" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="bmr-e0307dea9033836d"><rect width="94" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#bmr-e0307dea9033836d)"><rect width="37" height="20" fill="#555"/><rect x="37" width="57" height="20" fill="#0ac832"/><rect width="94" height="20" fill="url(#bms-e0307dea9033836d)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text aria-hidden="true" x="195" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="270">color</text><text x="195" y="140" transform="scale(.1)" fill="#fff" textLength="270">color</text><text aria-hidden="true" x="645" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="470">example</text><text x="645" y="140" transform="scale(.1)" fill="#fff" textLength="470">example</text></g></svg>
15//!
16//! <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="100" height="20" role="img" aria-label="example: badge"><title>example: badge</title><linearGradient id="bms-058ad8d642fc4c85" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="bmr-058ad8d642fc4c85"><rect width="100" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#bmr-058ad8d642fc4c85)"><rect width="57" height="20" fill="#555"/><rect x="57" width="43" height="20" fill="#4c1"/><rect width="100" height="20" fill="url(#bms-058ad8d642fc4c85)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text aria-hidden="true" x="295" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="470">example</text><text x="295" y="140" transform="scale(.1)" fill="#fff" textLength="470">example</text><text aria-hidden="true" x="775" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="330">badge</text><text x="775" y="140" transform="scale(.1)" fill="#fff" textLength="330">badge</text></g></svg>
17//!
18//! *_This library differs in that it generates unique IDs for the svg so it can be directly
19//!  embedded in websites (such as in this doc_svgs). So a diff between the outputs will not match. We
20//! only claim the visual outputs match which is whats important._
21//!
22//! ## About
23//!
24//! This library is meant to be the Rust version of
25//! [badge-maker](https://www.npmjs.com/package/badge-maker).
26//! The use cases for this library are two-fold:
27//!  * **Rusty** badge maker for any rust-based [shields.io](https://shields.io/) clones
28//!  * **WASM** based npm package for a speed increase over the node based version (numbers coming when
29//! optimizations are finished)
30//!
31//! **Current todos**
32//!  1. Better code coverage
33//!  2. Optimize text formatters
34//!  3. Fix errors. The output is ugly.
35//!  4. Other badge styles (requires a custom renderer)
36//!
37//! ### Example
38//! <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="88" height="20" role="img" aria-label="badge: maker"><title>badge: maker</title><linearGradient id="bms-badgemaker55533b5e5" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="bmr-badgemaker55533b5e5"><rect width="88" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#bmr-badgemaker55533b5e5)"><rect width="43" height="20" fill="#555"/><rect x="43" width="45" height="20" fill="#33b5e5"/><rect width="88" height="20" fill="url(#bms-badgemaker55533b5e5)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text aria-hidden="true" x="225" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="330">badge</text><text x="225" y="140" transform="scale(.1)" fill="#fff" textLength="330">badge</text><text aria-hidden="true" x="645" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="350">maker</text><text x="645" y="140" transform="scale(.1)" fill="#fff" textLength="350">maker</text></g></svg>
39//! ```rust
40//! use badge_maker::BadgeBuilder;
41//!
42//! let svg = BadgeBuilder::new()
43//!       .label("badge")
44//!       .message("maker")
45//!       .color_parse("#33B5E5")
46//!       .build()?
47//!       .svg();
48//!
49//! println!("{}", svg);
50//!
51//! # Ok::<(), badge_maker::error::Error>(())
52//! ```
53//!
54//! ## Features
55//! > This library is still in its infancy. Tests and documentation are being added whenever
56//! possible. If you are interested in contributing then check out the [repository](https://github.com/cgburgess/badge-maker).
57//! The API is likely to change. If you see something you think would work better than
58//! the way I've done it open an issue, I'd love to hear your suggestions.
59//!
60//! We support different [styles](Style), [colors](color::Color), [logos](Logo), and [links](Links). The
61//! [badge builder](BadgeBuilder) accepts all of these options with the `field()` and an
62//! alternate method of `field_parse()` which accepts a string and will attempt parse the text as
63//! a valid field.
64//!
65//! #### CLI
66//!
67//! This is a library but you can use it with a simple cli tool as well.
68//!
69//! <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="100" height="20" role="img" aria-label="example: badge"><title>example: badge</title><linearGradient id="bms-141813996f263f24" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="bmr-141813996f263f24"><rect width="100" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#bmr-141813996f263f24)"><rect width="57" height="20" fill="#282828"/><rect x="57" width="43" height="20" fill="#007ec6"/><rect width="100" height="20" fill="url(#bms-141813996f263f24)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text aria-hidden="true" x="295" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="470">example</text><text x="295" y="140" transform="scale(.1)" fill="#fff" textLength="470">example</text><text aria-hidden="true" x="775" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="330">badge</text><text x="775" y="140" transform="scale(.1)" fill="#fff" textLength="330">badge</text></g></svg>
70//!
71//! install
72//! ```bash
73//! cargo install badge-maker --features cli
74//! ```
75//! use
76//! ```bash
77//! badge-maker example badge -c informational -l #282828 -s flat
78//! ```
79//!
80//!
81//! ### [Colors](Color)
82//!
83//! We currently support hex colors 3 and 6 chars long, [named colors](color::NamedColor)
84//! and their [alias's](color::AliasColor), and [RGB](color::Color::Rgb) color inputs. These can be constructed
85//! with their enum variants or using the `...parse()` methods.
86//!
87//! <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="94" height="20" role="img" aria-label="color: example"><title>color: example</title><linearGradient id="bms-e0307dea9033836d" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="bmr-e0307dea9033836d"><rect width="94" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#bmr-e0307dea9033836d)"><rect width="37" height="20" fill="#555"/><rect x="37" width="57" height="20" fill="#0ac832"/><rect width="94" height="20" fill="url(#bms-e0307dea9033836d)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text aria-hidden="true" x="195" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="270">color</text><text x="195" y="140" transform="scale(.1)" fill="#fff" textLength="270">color</text><text aria-hidden="true" x="645" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="470">example</text><text x="645" y="140" transform="scale(.1)" fill="#fff" textLength="470">example</text></g></svg>
88//! ```rust
89//! use badge_maker::BadgeBuilder;
90//! use badge_maker::color::{Color, AliasColor, NamedColor};
91//!
92//! let svg = BadgeBuilder::new()
93//!     .label("color")
94//!     .message("example")
95//!     // by enums
96//!     .color(Color::Named(NamedColor::BrightGreen))
97//!     .color(Color::Alias(AliasColor::Success))
98//!     .color(Color::Rgb(10, 200, 50))
99//!     // or parsing
100//!     .color_parse("brightgreen")
101//!     .color_parse("success")
102//!     .color_parse("rgb(10, 200, 50)")
103//!     .build()?
104//!     .svg();
105//!
106//! # Ok::<(), badge_maker::error::Error>(())
107//! ```
108//!
109//!
110//! ### [Styles](Style)
111//! **Supported**. Others coming soon. See [Style](Style) enum for choices when
112//! building or use the string literals.
113//!
114//!  - **Flat** <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="84" height="20" role="img" aria-label="example: flat"><title>example: flat</title><linearGradient id="bms-exampleflat555ff5b5a" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="bmr-exampleflat555ff5b5a"><rect width="84" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#bmr-exampleflat555ff5b5a)"><rect width="57" height="20" fill="#555"/><rect x="57" width="27" height="20" fill="#ff5b5a"/><rect width="84" height="20" fill="url(#bms-exampleflat555ff5b5a)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text aria-hidden="true" x="295" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="470">example</text><text x="295" y="140" transform="scale(.1)" fill="#fff" textLength="470">example</text><text aria-hidden="true" x="695" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="170">flat</text><text x="695" y="140" transform="scale(.1)" fill="#fff" textLength="170">flat</text></g></svg>
115//!  - **Plastic** <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="102" height="18" role="img" aria-label="example: plastic"><title>example: plastic</title><linearGradient id="bms-673fc3b0d46c7e6f" 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="bmr-673fc3b0d46c7e6f"><rect width="102" height="18" rx="4" fill="#fff"/></clipPath><g clip-path="url(#bmr-673fc3b0d46c7e6f)"><rect width="57" height="18" fill="#555"/><rect x="57" width="45" height="18" fill="#ffb932"/><rect width="102" height="18" fill="url(#bms-673fc3b0d46c7e6f)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text aria-hidden="true" x="295" y="140" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="470">example</text><text x="295" y="130" transform="scale(.1)" fill="#fff" textLength="470">example</text><text aria-hidden="true" x="785" y="140" fill="#ccc" fill-opacity=".3" transform="scale(.1)" textLength="350">plastic</text><text x="785" y="130" transform="scale(.1)" fill="#333" textLength="350">plastic</text></g></svg>
116//!  - **FlatSquare** <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="122" height="20" role="img" aria-label="example: flatsquare"><title>example: flatsquare</title><g shape-rendering="crispEdges"><rect width="57" height="20" fill="#555"/><rect x="57" width="65" height="20" fill="#fffe27"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text x="295" y="140" transform="scale(.1)" fill="#fff" textLength="470">example</text><text x="885" y="140" transform="scale(.1)" fill="#333" textLength="550">flatsquare</text></g></svg>
117//!  - ForTheBadge
118//!  - Social
119//!
120//! ```rust
121//! use badge_maker::{BadgeBuilder, Style};
122//!
123//! let svg = BadgeBuilder::new()
124//!   .label("example")
125//!   .message("plastic")
126//!   .color_parse("#FFB932")
127//!   .style(Style::Plastic) // example of using typed input
128//!   .style_parse("plastic") // example of parsing to derive
129//!   .build()?
130//!   .svg();
131//!
132//! println!("{}", svg);
133//!
134//! # Ok::<(), badge_maker::error::Error>(())
135//! ```
136//!
137//! ### [Links](Links) & [Logos](Logo)
138//! Adding links to the natively rendered badge supported. This is great if you need
139//! to embed the svg directly. However, on a website like the rust docs they may show
140//! the underline. To solve this, your third-party api that renders the badges should
141//! wrap the svg in markdown `[![name for readers](link to api endpoint)](link when clicked)`.
142//!
143//!
144//! <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="81" height="20" ><a target="_blank" xlink:href="https://www.rust-lang.org/"><g shape-rendering="crispEdges"><rect width="50" height="20" fill="#555"/><rect x="50" width="31" height="20" fill="#f5f5f5"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><image x="5" y="3" width="14" height="14" xlink:href="https://upload.wikimedia.org/wikipedia/commons/thumb/d/d5/Rust_programming_language_black_logo.svg/1024px-Rust_programming_language_black_logo.svg.png"/><text x="345" y="140" transform="scale(.1)" fill="#fff" textLength="230">lang</text><text x="645" y="140" transform="scale(.1)" fill="#333" textLength="210">rust</text></g></a></svg>
145//! ```rust
146//! use badge_maker::BadgeBuilder;
147//!
148//! let logo_url = "https://upload.wikimedia.org/wikipedia/commons/\
149//!   thumb/d/d5/Rust_programming_language_black_logo.svg/\
150//!   1024px-Rust_programming_language_black_logo.svg.png";
151//!
152//! let svg = BadgeBuilder::new()
153//!   .label("lang")
154//!   .message("rust")
155//!   .color_parse("#F5F5F5")
156//!   .link("https://www.rust-lang.org/")
157//!   .logo_url(logo_url)
158//!   .style_parse("flatsquare")
159//!   .build()?
160//!   .svg();
161//!
162//! # Ok::<(), badge_maker::error::Error>(())
163//! ```
164
165pub use badge::color;
166pub use badge::{Badge, BadgeBuilder, Links, Logo, Style};
167
168pub mod error;
169
170mod badge;
171mod render;