Fix padding issues (#38)

* Set default padding chars to 0.5.
* Split num_padding_chars into num_label_padding_chars and num_value_padding_chars
  to allow better control. Retain num_padding_chars as an input parameter, but
  internally it is dropped.
* Remove padding multipliers.
* Add measurements image for developers. Helps show what each of the internal
  measurements are.
* Add script to build example badges.
* Update example badges.

Reliability
=======

* Raise a value error if an invalid font is passed.
* Handle labels that are not passed as str.
* Raise a value error if an invalid color name is passed.

Testing
=======

* Expand doctests to increase test coverage.
* Add Arial size 11 font and extra font sizes (mainly for testing).
* Make parse_args and main more testable by taking args as an input parameter.
* Use useful badge text in unittest badges.
* Add template svg file for testing.
* Add HTML coverage generation to travis yaml.
This commit is contained in:
Jon Grace-Cox
2020-03-15 12:51:34 -04:00
committed by GitHub
parent c6af09f82b
commit aeedfbb93d
28 changed files with 450 additions and 227 deletions

View File

@@ -8,7 +8,7 @@ python:
install:
- pip install -U setuptools pip -r build-requirements.txt
script:
- pytest --doctest-modules --cov=anybadge anybadge.py tests
- pytest --doctest-modules --cov=anybadge --cov-report html:htmlcov anybadge.py tests
before_deploy:
- sed -i "s/^version = .*/version = __version__ = \"$TRAVIS_TAG\"/" anybadge.py
deploy:

View File

@@ -163,10 +163,10 @@ This table was generated with the following code:
print("""| Color Name | Hex Code | Example |
| ---------- | -------- | ------- |""")
for color, hex in sorted(anybadge.COLORS.items()):
file = 'https://cdn.rawgit.com/jongracecox/anybadge/master/examples/color_' + color + '.svg'
file = 'examples/color_' + color + '.svg'
url = 'https://cdn.rawgit.com/jongracecox/anybadge/master/' + file
anybadge.Badge(label='Color', value=color, default_color=color).write_badge(file, overwrite=True)
print("| {color} | {hex} | ![]({file}) |".format(color=color, hex=hex.upper(), file=file))
print("| {color} | {hex} | ![]({url}) |".format(color=color, hex=hex.upper(), url=url))
```
### Examples

View File

@@ -5,9 +5,11 @@ anybadge
A Python module for generating badges for your projects, with a focus on
simplicity and flexibility.
"""
import sys
import os
import re
import argparse
import textwrap
# Package information
version = __version__ = "0.0.0"
@@ -20,7 +22,7 @@ __uri__ = "https://github.com/jongracecox/anybadge"
# Set some defaults
DEFAULT_FONT = 'DejaVu Sans,Verdana,Geneva,sans-serif'
DEFAULT_FONT_SIZE = 11
NUM_PADDING_CHARS = 0
NUM_PADDING_CHARS = 0.5
DEFAULT_COLOR = '#4c1'
DEFAULT_TEXT_COLOR = '#fff'
MASK_ID_PREFIX = 'anybadge_'
@@ -29,8 +31,13 @@ MASK_ID_PREFIX = 'anybadge_'
# supported fonts and font sizes.
FONT_WIDTHS = {
'DejaVu Sans,Verdana,Geneva,sans-serif': {
11: 10
}
10: 9,
11: 10,
12: 11,
},
'Arial, Helvetica, sans-serif': {
11: 8,
},
}
# Create a dictionary of colors to make selections
@@ -111,6 +118,10 @@ class Badge(object):
font_size(int, optional): Font size.
num_padding_chars(float, optional): Number of padding characters to use to give extra
space around text.
num_label_padding_chars(float, optional): Number of padding characters to use to give extra
space around label text.
num_value_padding_chars(float, optional): Number of padding characters to use to give extra
space around value text.
template(str, optional): String containing the SVG template. This should be valid SVG
file content with place holders for variables to be populated during rendering.
value_prefix(str, optional): Prefix to be placed before value.
@@ -178,18 +189,26 @@ class Badge(object):
"""
def __init__(self, label, value, font_name=None, font_size=None,
num_padding_chars=None, template=None,
num_padding_chars=None, num_label_padding_chars=None,
num_value_padding_chars=None, template=None,
value_prefix='', value_suffix='', thresholds=None, default_color=None,
use_max_when_value_exceeds=True, value_format=None, text_color=None):
"""Constructor for Badge class."""
# Set defaults if values were not passed
if not font_name:
font_name = DEFAULT_FONT
if not font_size:
font_size = DEFAULT_FONT_SIZE
if num_padding_chars is None:
num_padding_chars = NUM_PADDING_CHARS
if num_label_padding_chars is None:
if num_padding_chars is None:
num_label_padding_chars = NUM_PADDING_CHARS
else:
num_label_padding_chars = num_padding_chars
if num_value_padding_chars is None:
if num_padding_chars is None:
num_value_padding_chars = NUM_PADDING_CHARS
else:
num_value_padding_chars = num_padding_chars
if not template:
template = TEMPLATE_SVG
if not default_color:
@@ -207,9 +226,13 @@ class Badge(object):
self.value_prefix = value_prefix
self.value_suffix = value_suffix
self.value_text = value_prefix + value_text + value_suffix
if font_name not in FONT_WIDTHS:
raise ValueError('Font name "%s" not found. Available fonts: %s' % (font_name, ', '.join(FONT_WIDTHS.keys())))
self.font_name = font_name
self.font_size = font_size
self.num_padding_chars = num_padding_chars
self.num_label_padding_chars = num_label_padding_chars
self.num_value_padding_chars = num_value_padding_chars
self.template = template
self.thresholds = thresholds
self.default_color = default_color
@@ -244,14 +267,34 @@ class Badge(object):
>>> repr(badge)
"Badge('example', '123.456', value_suffix='TB', text_color='#111111')"
>>> badge = Badge('example', '123', num_padding_chars=5)
>>> repr(badge)
"Badge('example', '123', num_padding_chars=5)"
>>> badge = Badge('example', '123', num_label_padding_chars=5)
>>> repr(badge)
"Badge('example', '123', num_label_padding_chars=5)"
>>> badge = Badge('example', '123', num_label_padding_chars=5, num_value_padding_chars=6,
... template='template.svg', value_prefix='$', thresholds={10: 'green', 30: 'red'},
... default_color='red', use_max_when_value_exceeds=False, value_format="%s m/s")
>>> repr(badge)
"Badge('example', '123', num_label_padding_chars=5, num_value_padding_chars=6, template='template.svg', value_prefix='$', thresholds={10: 'green', 30: 'red'}, default_color='red', use_max_when_value_exceeds=False, value_format='%s m/s')"
"""
optional_args = ""
if self.font_name != DEFAULT_FONT:
optional_args += ", font_name=%s" % repr(self.font_name)
if self.font_size != DEFAULT_FONT_SIZE:
optional_args += ", font_size=%s" % repr(self.font_size)
if self.num_padding_chars != NUM_PADDING_CHARS:
optional_args += ", num_padding_chars=%s" % repr(self.num_padding_chars)
if self.num_label_padding_chars == self.num_value_padding_chars:
if self.num_label_padding_chars != NUM_PADDING_CHARS:
optional_args += ", num_padding_chars=%s" % repr(self.num_label_padding_chars)
else:
if self.num_label_padding_chars != NUM_PADDING_CHARS:
optional_args += ", num_label_padding_chars=%s" % repr(self.num_label_padding_chars)
if self.num_value_padding_chars != NUM_PADDING_CHARS:
optional_args += ", num_value_padding_chars=%s" % repr(self.num_value_padding_chars)
if self.template != TEMPLATE_SVG:
optional_args += ", template=%s" % repr(self.template)
if self.value_prefix != '':
@@ -351,7 +394,7 @@ class Badge(object):
Returns: int
"""
return int(self.get_text_width(self.label) + (2.0 * self.num_padding_chars * self.font_width))
return int(self.get_text_width(str(self.label)) + (2.0 * self.num_label_padding_chars * self.font_width))
@property
def value_width(self):
@@ -359,7 +402,7 @@ class Badge(object):
Returns: int
"""
return int(self.get_text_width(str(self.value_text)) + (self.num_padding_chars * self.font_width))
return int(self.get_text_width(str(self.value_text)) + (2.0 * self.num_value_padding_chars * self.font_width))
@property
def font_width(self):
@@ -381,8 +424,7 @@ class Badge(object):
Returns: int
"""
return int(self.font_width + self.label_width +
float(self.font_width) * float(self.num_padding_chars))
return self.badge_width - self.value_width
@property
def label_anchor(self):
@@ -426,11 +468,9 @@ class Badge(object):
>>> badge = Badge('pylint', '5')
>>> badge.badge_width
53
61
"""
padding_char_width = self.get_text_width(' ')
padding = int(padding_char_width * (self.num_padding_chars + 3))
return padding + self.label_width + self.value_width
return self.label_width + self.value_width
@property
def badge_svg_text(self):
@@ -459,7 +499,7 @@ class Badge(object):
.replace('{{ label text color }}', self.label_text_color) \
.replace('{{ value text color }}', self.value_text_color) \
.replace('{{ color split x }}', str(self.color_split_position)) \
.replace('{{ value width }}', str(self.badge_width - self.color_split_position))\
.replace('{{ value width }}', str(self.value_width))\
.replace('{{ mask id }}', self.mask_id)
def __str__(self):
@@ -531,18 +571,24 @@ class Badge(object):
"""Return the color code for the badge.
Returns: str
Raises: ValueError when an invalid badge color is set.
"""
color = self.badge_color
if color[0] == '#':
return color
return COLORS[color]
try:
return COLORS[color]
except KeyError:
raise ValueError('Invalid color code "%s". Valid color codes are: %s', (color, ", ".join(COLORS.keys())))
def write_badge(self, file_path, overwrite=False):
"""Write badge to file."""
# Validate path (part 1)
if file_path.endswith('/'):
raise Exception('File location may not be a directory.')
raise ValueError('File location may not be a directory.')
# Get absolute filepath
path = os.path.abspath(file_path)
@@ -551,7 +597,7 @@ class Badge(object):
# Validate path (part 2)
if not overwrite and os.path.exists(path):
raise Exception('File "{}" already exists.'.format(path))
raise RuntimeError('File "{}" already exists.'.format(path))
with open(path, mode='w') as file_handle:
file_handle.write(self.badge_svg_text)
@@ -664,10 +710,8 @@ def _get_approx_string_width(text, font_width, fixed_width=False):
# for group in char_width_groups}
def parse_args():
def parse_args(args):
"""Parse the command line arguments."""
import argparse
import textwrap
parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter,
description=textwrap.dedent('''\
Command line utility to generate .svg badges.
@@ -741,13 +785,13 @@ examples:
parser.add_argument('args', nargs=argparse.REMAINDER, help='Pairs of <upper>=<color>. '
'For example 2=red 4=orange 6=yellow 8=good. '
'Read this as "Less than 2 = red, less than 4 = orange...".')
return parser.parse_args()
return parser.parse_args(args)
def main():
def main(args):
"""Generate a badge based on command line arguments."""
# Parse command line arguments
args = parse_args()
args = parse_args(args)
label = args.label
threshold_text = args.args
@@ -786,4 +830,4 @@ def main():
if __name__ == '__main__':
main()
main(sys.argv[1:])

15
build_examples.py Normal file
View File

@@ -0,0 +1,15 @@
import anybadge
if __name__ == '__main__':
print("""| Color Name | Hex Code | Example |
| ---------- | -------- | ------- |""")
for color, hex in sorted(anybadge.COLORS.items()):
file = 'examples/color_' + color + '.svg'
url = 'https://cdn.rawgit.com/jongracecox/anybadge/master/' + file
anybadge.Badge(label='Color', value=color, default_color=color).write_badge(file, overwrite=True)
print("| {color} | {hex} | ![]({url}) |".format(color=color, hex=hex.upper(), url=url))

View File

@@ -1,23 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="71" height="20">
<svg xmlns="http://www.w3.org/2000/svg" width="79" 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>
<mask id="anybadge_1">
<rect width="71" height="20" rx="3" fill="#fff"/>
<rect width="79" height="20" rx="3" fill="#fff"/>
</mask>
<g mask="url(#anybadge_1)">
<path fill="#555" d="M0 0h41v20H0z"/>
<path fill="#00FFFF" d="M41 0h30v20H41z"/>
<path fill="url(#b)" d="M0 0h71v20H0z"/>
<path fill="#00FFFF" d="M41 0h38v20H41z"/>
<path fill="url(#b)" d="M0 0h79v20H0z"/>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="21" y="15" fill="#010101" fill-opacity=".3">Color</text>
<text x="20" y="14">Color</text>
<text x="21.5" y="15" fill="#010101" fill-opacity=".3">Color</text>
<text x="20.5" y="14">Color</text>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="57" y="15" fill="#010101" fill-opacity=".3">aqua</text>
<text x="56" y="14">aqua</text>
<text x="61.0" y="15" fill="#010101" fill-opacity=".3">aqua</text>
<text x="60.0" y="14">aqua</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -1,23 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="75" height="20">
<svg xmlns="http://www.w3.org/2000/svg" width="83" 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>
<mask id="anybadge_2">
<rect width="75" height="20" rx="3" fill="#fff"/>
<rect width="83" height="20" rx="3" fill="#fff"/>
</mask>
<g mask="url(#anybadge_2)">
<path fill="#555" d="M0 0h41v20H0z"/>
<path fill="#000000" d="M41 0h34v20H41z"/>
<path fill="url(#b)" d="M0 0h75v20H0z"/>
<path fill="#000000" d="M41 0h42v20H41z"/>
<path fill="url(#b)" d="M0 0h83v20H0z"/>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="21" y="15" fill="#010101" fill-opacity=".3">Color</text>
<text x="20" y="14">Color</text>
<text x="21.5" y="15" fill="#010101" fill-opacity=".3">Color</text>
<text x="20.5" y="14">Color</text>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="59" y="15" fill="#010101" fill-opacity=".3">black</text>
<text x="58" y="14">black</text>
<text x="63.0" y="15" fill="#010101" fill-opacity=".3">black</text>
<text x="62.0" y="14">black</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -1,23 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="68" height="20">
<svg xmlns="http://www.w3.org/2000/svg" width="76" 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>
<mask id="anybadge_3">
<rect width="68" height="20" rx="3" fill="#fff"/>
<rect width="76" height="20" rx="3" fill="#fff"/>
</mask>
<g mask="url(#anybadge_3)">
<path fill="#555" d="M0 0h41v20H0z"/>
<path fill="#0000FF" d="M41 0h27v20H41z"/>
<path fill="url(#b)" d="M0 0h68v20H0z"/>
<path fill="#0000FF" d="M41 0h35v20H41z"/>
<path fill="url(#b)" d="M0 0h76v20H0z"/>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="21" y="15" fill="#010101" fill-opacity=".3">Color</text>
<text x="20" y="14">Color</text>
<text x="21.5" y="15" fill="#010101" fill-opacity=".3">Color</text>
<text x="20.5" y="14">Color</text>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="55" y="15" fill="#010101" fill-opacity=".3">blue</text>
<text x="54" y="14">blue</text>
<text x="59.5" y="15" fill="#010101" fill-opacity=".3">blue</text>
<text x="58.5" y="14">blue</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -1,23 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="99" height="20">
<svg xmlns="http://www.w3.org/2000/svg" width="107" 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>
<mask id="anybadge_4">
<rect width="99" height="20" rx="3" fill="#fff"/>
<rect width="107" height="20" rx="3" fill="#fff"/>
</mask>
<g mask="url(#anybadge_4)">
<path fill="#555" d="M0 0h41v20H0z"/>
<path fill="#FF0000" d="M41 0h58v20H41z"/>
<path fill="url(#b)" d="M0 0h99v20H0z"/>
<path fill="#FF0000" d="M41 0h66v20H41z"/>
<path fill="url(#b)" d="M0 0h107v20H0z"/>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="21" y="15" fill="#010101" fill-opacity=".3">Color</text>
<text x="20" y="14">Color</text>
<text x="21.5" y="15" fill="#010101" fill-opacity=".3">Color</text>
<text x="20.5" y="14">Color</text>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="71" y="15" fill="#010101" fill-opacity=".3">brightred</text>
<text x="70" y="14">brightred</text>
<text x="75.0" y="15" fill="#010101" fill-opacity=".3">brightred</text>
<text x="74.0" y="14">brightred</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -1,23 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="115" height="20">
<svg xmlns="http://www.w3.org/2000/svg" width="123" 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>
<mask id="anybadge_5">
<rect width="115" height="20" rx="3" fill="#fff"/>
<rect width="123" height="20" rx="3" fill="#fff"/>
</mask>
<g mask="url(#anybadge_5)">
<path fill="#555" d="M0 0h41v20H0z"/>
<path fill="#FFFF00" d="M41 0h74v20H41z"/>
<path fill="url(#b)" d="M0 0h115v20H0z"/>
<path fill="#FFFF00" d="M41 0h82v20H41z"/>
<path fill="url(#b)" d="M0 0h123v20H0z"/>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="21" y="15" fill="#010101" fill-opacity=".3">Color</text>
<text x="20" y="14">Color</text>
<text x="21.5" y="15" fill="#010101" fill-opacity=".3">Color</text>
<text x="20.5" y="14">Color</text>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="79" y="15" fill="#010101" fill-opacity=".3">brightyellow</text>
<text x="78" y="14">brightyellow</text>
<text x="83.0" y="15" fill="#010101" fill-opacity=".3">brightyellow</text>
<text x="82.0" y="14">brightyellow</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -1,23 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="87" height="20">
<svg xmlns="http://www.w3.org/2000/svg" width="95" 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>
<mask id="anybadge_6">
<rect width="87" height="20" rx="3" fill="#fff"/>
<rect width="95" height="20" rx="3" fill="#fff"/>
</mask>
<g mask="url(#anybadge_6)">
<path fill="#555" d="M0 0h41v20H0z"/>
<path fill="#FF00FF" d="M41 0h46v20H41z"/>
<path fill="url(#b)" d="M0 0h87v20H0z"/>
<path fill="#FF00FF" d="M41 0h54v20H41z"/>
<path fill="url(#b)" d="M0 0h95v20H0z"/>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="21" y="15" fill="#010101" fill-opacity=".3">Color</text>
<text x="20" y="14">Color</text>
<text x="21.5" y="15" fill="#010101" fill-opacity=".3">Color</text>
<text x="20.5" y="14">Color</text>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="65" y="15" fill="#010101" fill-opacity=".3">fuchsia</text>
<text x="64" y="14">fuchsia</text>
<text x="69.0" y="15" fill="#010101" fill-opacity=".3">fuchsia</text>
<text x="68.0" y="14">fuchsia</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -1,23 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="70" height="20">
<svg xmlns="http://www.w3.org/2000/svg" width="78" 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>
<mask id="anybadge_7">
<rect width="70" height="20" rx="3" fill="#fff"/>
<rect width="78" height="20" rx="3" fill="#fff"/>
</mask>
<g mask="url(#anybadge_7)">
<path fill="#555" d="M0 0h41v20H0z"/>
<path fill="#808080" d="M41 0h29v20H41z"/>
<path fill="url(#b)" d="M0 0h70v20H0z"/>
<path fill="#808080" d="M41 0h37v20H41z"/>
<path fill="url(#b)" d="M0 0h78v20H0z"/>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="21" y="15" fill="#010101" fill-opacity=".3">Color</text>
<text x="20" y="14">Color</text>
<text x="21.5" y="15" fill="#010101" fill-opacity=".3">Color</text>
<text x="20.5" y="14">Color</text>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="56" y="15" fill="#010101" fill-opacity=".3">gray</text>
<text x="55" y="14">gray</text>
<text x="60.5" y="15" fill="#010101" fill-opacity=".3">gray</text>
<text x="59.5" y="14">gray</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -1,23 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="77" height="20">
<svg xmlns="http://www.w3.org/2000/svg" width="85" 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>
<mask id="anybadge_8">
<rect width="77" height="20" rx="3" fill="#fff"/>
<rect width="85" height="20" rx="3" fill="#fff"/>
</mask>
<g mask="url(#anybadge_8)">
<path fill="#555" d="M0 0h41v20H0z"/>
<path fill="#4c1" d="M41 0h36v20H41z"/>
<path fill="url(#b)" d="M0 0h77v20H0z"/>
<path fill="#4c1" d="M41 0h44v20H41z"/>
<path fill="url(#b)" d="M0 0h85v20H0z"/>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="21" y="15" fill="#010101" fill-opacity=".3">Color</text>
<text x="20" y="14">Color</text>
<text x="21.5" y="15" fill="#010101" fill-opacity=".3">Color</text>
<text x="20.5" y="14">Color</text>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="60" y="15" fill="#010101" fill-opacity=".3">green</text>
<text x="59" y="14">green</text>
<text x="64.0" y="15" fill="#010101" fill-opacity=".3">green</text>
<text x="63.0" y="14">green</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -1,23 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="97" height="20">
<svg xmlns="http://www.w3.org/2000/svg" width="105" 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>
<mask id="anybadge_9">
<rect width="97" height="20" rx="3" fill="#fff"/>
<rect width="105" height="20" rx="3" fill="#fff"/>
</mask>
<g mask="url(#anybadge_9)">
<path fill="#555" d="M0 0h41v20H0z"/>
<path fill="#9f9f9f" d="M41 0h56v20H41z"/>
<path fill="url(#b)" d="M0 0h97v20H0z"/>
<path fill="#9f9f9f" d="M41 0h64v20H41z"/>
<path fill="url(#b)" d="M0 0h105v20H0z"/>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="21" y="15" fill="#010101" fill-opacity=".3">Color</text>
<text x="20" y="14">Color</text>
<text x="21.5" y="15" fill="#010101" fill-opacity=".3">Color</text>
<text x="20.5" y="14">Color</text>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="70" y="15" fill="#010101" fill-opacity=".3">lightgrey</text>
<text x="69" y="14">lightgrey</text>
<text x="74.0" y="15" fill="#010101" fill-opacity=".3">lightgrey</text>
<text x="73.0" y="14">lightgrey</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -1,23 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="68" height="20">
<svg xmlns="http://www.w3.org/2000/svg" width="76" 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>
<mask id="anybadge_10">
<rect width="68" height="20" rx="3" fill="#fff"/>
<rect width="76" height="20" rx="3" fill="#fff"/>
</mask>
<g mask="url(#anybadge_10)">
<path fill="#555" d="M0 0h41v20H0z"/>
<path fill="#00FF00" d="M41 0h27v20H41z"/>
<path fill="url(#b)" d="M0 0h68v20H0z"/>
<path fill="#00FF00" d="M41 0h35v20H41z"/>
<path fill="url(#b)" d="M0 0h76v20H0z"/>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="21" y="15" fill="#010101" fill-opacity=".3">Color</text>
<text x="20" y="14">Color</text>
<text x="21.5" y="15" fill="#010101" fill-opacity=".3">Color</text>
<text x="20.5" y="14">Color</text>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="55" y="15" fill="#010101" fill-opacity=".3">lime</text>
<text x="54" y="14">lime</text>
<text x="59.5" y="15" fill="#010101" fill-opacity=".3">lime</text>
<text x="58.5" y="14">lime</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -1,23 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="87" height="20">
<svg xmlns="http://www.w3.org/2000/svg" width="95" 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>
<mask id="anybadge_11">
<rect width="87" height="20" rx="3" fill="#fff"/>
<rect width="95" height="20" rx="3" fill="#fff"/>
</mask>
<g mask="url(#anybadge_11)">
<path fill="#555" d="M0 0h41v20H0z"/>
<path fill="#800000" d="M41 0h46v20H41z"/>
<path fill="url(#b)" d="M0 0h87v20H0z"/>
<path fill="#800000" d="M41 0h54v20H41z"/>
<path fill="url(#b)" d="M0 0h95v20H0z"/>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="21" y="15" fill="#010101" fill-opacity=".3">Color</text>
<text x="20" y="14">Color</text>
<text x="21.5" y="15" fill="#010101" fill-opacity=".3">Color</text>
<text x="20.5" y="14">Color</text>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="65" y="15" fill="#010101" fill-opacity=".3">maroon</text>
<text x="64" y="14">maroon</text>
<text x="69.0" y="15" fill="#010101" fill-opacity=".3">maroon</text>
<text x="68.0" y="14">maroon</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -1,23 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="71" height="20">
<svg xmlns="http://www.w3.org/2000/svg" width="79" 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>
<mask id="anybadge_12">
<rect width="71" height="20" rx="3" fill="#fff"/>
<rect width="79" height="20" rx="3" fill="#fff"/>
</mask>
<g mask="url(#anybadge_12)">
<path fill="#555" d="M0 0h41v20H0z"/>
<path fill="#000080" d="M41 0h30v20H41z"/>
<path fill="url(#b)" d="M0 0h71v20H0z"/>
<path fill="#000080" d="M41 0h38v20H41z"/>
<path fill="url(#b)" d="M0 0h79v20H0z"/>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="21" y="15" fill="#010101" fill-opacity=".3">Color</text>
<text x="20" y="14">Color</text>
<text x="21.5" y="15" fill="#010101" fill-opacity=".3">Color</text>
<text x="20.5" y="14">Color</text>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="57" y="15" fill="#010101" fill-opacity=".3">navy</text>
<text x="56" y="14">navy</text>
<text x="61.0" y="15" fill="#010101" fill-opacity=".3">navy</text>
<text x="60.0" y="14">navy</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -1,23 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="72" height="20">
<svg xmlns="http://www.w3.org/2000/svg" width="80" 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>
<mask id="anybadge_13">
<rect width="72" height="20" rx="3" fill="#fff"/>
<rect width="80" height="20" rx="3" fill="#fff"/>
</mask>
<g mask="url(#anybadge_13)">
<path fill="#555" d="M0 0h41v20H0z"/>
<path fill="#808000" d="M41 0h31v20H41z"/>
<path fill="url(#b)" d="M0 0h72v20H0z"/>
<path fill="#808000" d="M41 0h39v20H41z"/>
<path fill="url(#b)" d="M0 0h80v20H0z"/>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="21" y="15" fill="#010101" fill-opacity=".3">Color</text>
<text x="20" y="14">Color</text>
<text x="21.5" y="15" fill="#010101" fill-opacity=".3">Color</text>
<text x="20.5" y="14">Color</text>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="57" y="15" fill="#010101" fill-opacity=".3">olive</text>
<text x="56" y="14">olive</text>
<text x="61.5" y="15" fill="#010101" fill-opacity=".3">olive</text>
<text x="60.5" y="14">olive</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -1,23 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="84" height="20">
<svg xmlns="http://www.w3.org/2000/svg" width="92" 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>
<mask id="anybadge_14">
<rect width="84" height="20" rx="3" fill="#fff"/>
<rect width="92" height="20" rx="3" fill="#fff"/>
</mask>
<g mask="url(#anybadge_14)">
<path fill="#555" d="M0 0h41v20H0z"/>
<path fill="#fe7d37" d="M41 0h43v20H41z"/>
<path fill="url(#b)" d="M0 0h84v20H0z"/>
<path fill="#fe7d37" d="M41 0h51v20H41z"/>
<path fill="url(#b)" d="M0 0h92v20H0z"/>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="21" y="15" fill="#010101" fill-opacity=".3">Color</text>
<text x="20" y="14">Color</text>
<text x="21.5" y="15" fill="#010101" fill-opacity=".3">Color</text>
<text x="20.5" y="14">Color</text>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="63" y="15" fill="#010101" fill-opacity=".3">orange</text>
<text x="62" y="14">orange</text>
<text x="67.5" y="15" fill="#010101" fill-opacity=".3">orange</text>
<text x="66.5" y="14">orange</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -1,23 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="81" height="20">
<svg xmlns="http://www.w3.org/2000/svg" width="89" 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>
<mask id="anybadge_15">
<rect width="81" height="20" rx="3" fill="#fff"/>
<rect width="89" height="20" rx="3" fill="#fff"/>
</mask>
<g mask="url(#anybadge_15)">
<path fill="#555" d="M0 0h41v20H0z"/>
<path fill="#800080" d="M41 0h40v20H41z"/>
<path fill="url(#b)" d="M0 0h81v20H0z"/>
<path fill="#800080" d="M41 0h48v20H41z"/>
<path fill="url(#b)" d="M0 0h89v20H0z"/>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="21" y="15" fill="#010101" fill-opacity=".3">Color</text>
<text x="20" y="14">Color</text>
<text x="21.5" y="15" fill="#010101" fill-opacity=".3">Color</text>
<text x="20.5" y="14">Color</text>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="62" y="15" fill="#010101" fill-opacity=".3">purple</text>
<text x="61" y="14">purple</text>
<text x="66.0" y="15" fill="#010101" fill-opacity=".3">purple</text>
<text x="65.0" y="14">purple</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -1,23 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="63" height="20">
<svg xmlns="http://www.w3.org/2000/svg" width="71" 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>
<mask id="anybadge_16">
<rect width="63" height="20" rx="3" fill="#fff"/>
<rect width="71" height="20" rx="3" fill="#fff"/>
</mask>
<g mask="url(#anybadge_16)">
<path fill="#555" d="M0 0h41v20H0z"/>
<path fill="#e05d44" d="M41 0h22v20H41z"/>
<path fill="url(#b)" d="M0 0h63v20H0z"/>
<path fill="#e05d44" d="M41 0h30v20H41z"/>
<path fill="url(#b)" d="M0 0h71v20H0z"/>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="21" y="15" fill="#010101" fill-opacity=".3">Color</text>
<text x="20" y="14">Color</text>
<text x="21.5" y="15" fill="#010101" fill-opacity=".3">Color</text>
<text x="20.5" y="14">Color</text>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="53" y="15" fill="#010101" fill-opacity=".3">red</text>
<text x="52" y="14">red</text>
<text x="57.0" y="15" fill="#010101" fill-opacity=".3">red</text>
<text x="56.0" y="14">red</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -1,23 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="78" height="20">
<svg xmlns="http://www.w3.org/2000/svg" width="86" 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>
<mask id="anybadge_17">
<rect width="78" height="20" rx="3" fill="#fff"/>
<rect width="86" height="20" rx="3" fill="#fff"/>
</mask>
<g mask="url(#anybadge_17)">
<path fill="#555" d="M0 0h41v20H0z"/>
<path fill="#C0C0C0" d="M41 0h37v20H41z"/>
<path fill="url(#b)" d="M0 0h78v20H0z"/>
<path fill="#C0C0C0" d="M41 0h45v20H41z"/>
<path fill="url(#b)" d="M0 0h86v20H0z"/>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="21" y="15" fill="#010101" fill-opacity=".3">Color</text>
<text x="20" y="14">Color</text>
<text x="21.5" y="15" fill="#010101" fill-opacity=".3">Color</text>
<text x="20.5" y="14">Color</text>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="60" y="15" fill="#010101" fill-opacity=".3">silver</text>
<text x="59" y="14">silver</text>
<text x="64.5" y="15" fill="#010101" fill-opacity=".3">silver</text>
<text x="63.5" y="14">silver</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -1,23 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="66" height="20">
<svg xmlns="http://www.w3.org/2000/svg" width="74" 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>
<mask id="anybadge_18">
<rect width="66" height="20" rx="3" fill="#fff"/>
<rect width="74" height="20" rx="3" fill="#fff"/>
</mask>
<g mask="url(#anybadge_18)">
<path fill="#555" d="M0 0h41v20H0z"/>
<path fill="#008080" d="M41 0h25v20H41z"/>
<path fill="url(#b)" d="M0 0h66v20H0z"/>
<path fill="#008080" d="M41 0h33v20H41z"/>
<path fill="url(#b)" d="M0 0h74v20H0z"/>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="21" y="15" fill="#010101" fill-opacity=".3">Color</text>
<text x="20" y="14">Color</text>
<text x="21.5" y="15" fill="#010101" fill-opacity=".3">Color</text>
<text x="20.5" y="14">Color</text>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="54" y="15" fill="#010101" fill-opacity=".3">teal</text>
<text x="53" y="14">teal</text>
<text x="58.5" y="15" fill="#010101" fill-opacity=".3">teal</text>
<text x="57.5" y="14">teal</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -1,23 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="73" height="20">
<svg xmlns="http://www.w3.org/2000/svg" width="81" 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>
<mask id="anybadge_19">
<rect width="73" height="20" rx="3" fill="#fff"/>
<rect width="81" height="20" rx="3" fill="#fff"/>
</mask>
<g mask="url(#anybadge_19)">
<path fill="#555" d="M0 0h41v20H0z"/>
<path fill="#FFFFFF" d="M41 0h32v20H41z"/>
<path fill="url(#b)" d="M0 0h73v20H0z"/>
<path fill="#FFFFFF" d="M41 0h40v20H41z"/>
<path fill="url(#b)" d="M0 0h81v20H0z"/>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="21" y="15" fill="#010101" fill-opacity=".3">Color</text>
<text x="20" y="14">Color</text>
<text x="21.5" y="15" fill="#010101" fill-opacity=".3">Color</text>
<text x="20.5" y="14">Color</text>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="58" y="15" fill="#010101" fill-opacity=".3">white</text>
<text x="57" y="14">white</text>
<text x="62.0" y="15" fill="#010101" fill-opacity=".3">white</text>
<text x="61.0" y="14">white</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -1,23 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="79" height="20">
<svg xmlns="http://www.w3.org/2000/svg" width="87" 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>
<mask id="anybadge_20">
<rect width="79" height="20" rx="3" fill="#fff"/>
<rect width="87" height="20" rx="3" fill="#fff"/>
</mask>
<g mask="url(#anybadge_20)">
<path fill="#555" d="M0 0h41v20H0z"/>
<path fill="#dfb317" d="M41 0h38v20H41z"/>
<path fill="url(#b)" d="M0 0h79v20H0z"/>
<path fill="#dfb317" d="M41 0h46v20H41z"/>
<path fill="url(#b)" d="M0 0h87v20H0z"/>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="21" y="15" fill="#010101" fill-opacity=".3">Color</text>
<text x="20" y="14">Color</text>
<text x="21.5" y="15" fill="#010101" fill-opacity=".3">Color</text>
<text x="20.5" y="14">Color</text>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="61" y="15" fill="#010101" fill-opacity=".3">yellow</text>
<text x="60" y="14">yellow</text>
<text x="65.0" y="15" fill="#010101" fill-opacity=".3">yellow</text>
<text x="64.0" y="14">yellow</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -1,23 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="113" height="20">
<svg xmlns="http://www.w3.org/2000/svg" width="121" 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>
<mask id="anybadge_21">
<rect width="113" height="20" rx="3" fill="#fff"/>
<rect width="121" height="20" rx="3" fill="#fff"/>
</mask>
<g mask="url(#anybadge_21)">
<path fill="#555" d="M0 0h41v20H0z"/>
<path fill="#a4a61d" d="M41 0h72v20H41z"/>
<path fill="url(#b)" d="M0 0h113v20H0z"/>
<path fill="#a4a61d" d="M41 0h80v20H41z"/>
<path fill="url(#b)" d="M0 0h121v20H0z"/>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="21" y="15" fill="#010101" fill-opacity=".3">Color</text>
<text x="20" y="14">Color</text>
<text x="21.5" y="15" fill="#010101" fill-opacity=".3">Color</text>
<text x="20.5" y="14">Color</text>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="78" y="15" fill="#010101" fill-opacity=".3">yellowgreen</text>
<text x="77" y="14">yellowgreen</text>
<text x="82.0" y="15" fill="#010101" fill-opacity=".3">yellowgreen</text>
<text x="81.0" y="14">yellowgreen</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

BIN
measurements.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

23
tests/template.svg Normal file
View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="{{ badge width }}" 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>
<mask id="{{ mask id }}">
<rect width="{{ badge width }}" height="20" rx="3" fill="#fff"/>
</mask>
<g mask="url(#{{ mask id }})">
<path fill="#555" d="M0 0h{{ color split x }}v20H0z"/>
<path fill="{{ color }}" d="M{{ color split x }} 0h{{ value width }}v20H{{ color split x }}z"/>
<path fill="url(#b)" d="M0 0h{{ badge width }}v20H0z"/>
</g>
<g fill="{{ label text color }}" text-anchor="middle" font-family="{{ font name }}" font-size="{{ font size }}">
<text x="{{ label anchor shadow }}" y="15" fill="#010101" fill-opacity=".3">{{ label }}</text>
<text x="{{ label anchor }}" y="14">{{ label }}</text>
</g>
<g fill="{{ value text color }}" text-anchor="middle" font-family="{{ font name }}" font-size="{{ font size }}">
<text x="{{ value anchor shadow }}" y="15" fill="#010101" fill-opacity=".3">{{ value }}</text>
<text x="{{ value anchor }}" y="14">{{ value }}</text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -1,10 +1,28 @@
from unittest import TestCase
from anybadge import Badge
from anybadge import Badge, parse_args, main
class TestAnybadge(TestCase):
"""Test case class for anybadge package."""
def test_badge_equal_label_value_width(self):
"""Test that label and value widths are equal when text is the same."""
badge = Badge(label='a', value='a', num_padding_chars=0)
self.assertEqual(badge.label_width, badge.value_width)
def test_badge_equal_split(self):
"""Test that the color split is in the middle when label and value are equal width."""
badge = Badge(label='a', value='a')
self.assertEqual(int(badge.badge_width / 2), badge.color_split_position)
def test_badge_equal_split_no_padding(self):
"""Test that the color split is in the middle when label and value are equal width."""
badge = Badge(label='a', value='a', num_padding_chars=0)
self.assertEqual(int(badge.badge_width / 2), badge.color_split_position)
def test_badge_width_with_long_value_text(self):
"""Test the width of a badge generated with a long text value."""
@@ -35,21 +53,21 @@ class TestAnybadge(TestCase):
value='89.67%',
default_color='green')
badge.write_badge('test_badge_3.svg', overwrite=True)
badge.write_badge('test_badge_medium.svg', overwrite=True)
self.assertLessEqual(badge.badge_width, 138)
def test_badge_width_with_medium_value_text_zero_pad(self):
"""Test the width of a badge generated with a medium text value."""
badge = Badge(label='medium',
badge = Badge(label='medium no padding',
value='89.67%',
default_color='green',
num_padding_chars=0)
badge.write_badge('test_badge_4.svg', overwrite=True)
badge.write_badge('test_badge_medium_no_padding.svg', overwrite=True)
self.assertLessEqual(badge.badge_width, 118)
self.assertLessEqual(badge.badge_width, 156)
def test_badge_width_with_short_value_text(self):
"""Test the width of a badge generated with a short text value."""
@@ -58,21 +76,21 @@ class TestAnybadge(TestCase):
value='1',
default_color='green')
badge.write_badge('test_badge_5.svg', overwrite=True)
badge.write_badge('test_badge_short.svg', overwrite=True)
self.assertLessEqual(badge.badge_width, 101)
def test_badge_width_with_short_value_text_zero_pad(self):
"""Test the width of a badge generated with a short text value."""
badge = Badge(label='short',
badge = Badge(label='short value no padding',
value='1',
default_color='green',
num_padding_chars=0)
badge.write_badge('test_badge_6.svg', overwrite=True)
badge.write_badge('test_badge_short_no_padding.svg', overwrite=True)
self.assertLessEqual(badge.badge_width, 81)
self.assertLessEqual(badge.badge_width, 143)
def test_badge_width_with_tiny_value_text(self):
"""Test the width of a badge generated with a short text value."""
@@ -81,7 +99,19 @@ class TestAnybadge(TestCase):
value='1',
default_color='green')
badge.write_badge('test_badge_7.svg', overwrite=True)
badge.write_badge('test_badge_tiny_text_value.svg', overwrite=True)
self.assertLessEqual(badge.badge_width, 76)
def test_badge_width_with_tiny_value_text_no_padding(self):
"""Test the width of a badge generated with a short text value."""
badge = Badge(label='a',
value='1',
default_color='green',
num_padding_chars=0)
badge.write_badge('test_badge_tiny_text_value_no_padding.svg', overwrite=True)
self.assertLessEqual(badge.badge_width, 76)
@@ -91,58 +121,169 @@ class TestAnybadge(TestCase):
2: 'red', 4: 'orange', 6: 'green', 8: 'brightgreen'
}
badge = Badge('test', '2.22', value_suffix='%',
badge = Badge('thresholds', '2.22', value_suffix='%',
thresholds=thresholds)
badge.write_badge('test_badge_8.svg', overwrite=True)
badge.write_badge('test_badge_thresholds.svg', overwrite=True)
def test_badge_with_text_color(self):
"""Test generating a badge with alternate text_color."""
badge = Badge('test', '2.22', value_suffix='%',
badge = Badge('text color', '2.22', value_suffix='%',
text_color='#010101,#101010')
badge.write_badge('test_badge_9.svg', overwrite=True)
badge.write_badge('test_badge_text_color.svg', overwrite=True)
def test_multiple_badges_in_one_session(self):
badges = [
Badge('something', value='100', value_suffix='%', num_padding_chars=0),
Badge('coverage', value='1234567890'),
Badge('multiple 1', value='100', value_suffix='%', num_padding_chars=0),
Badge('multiple 2', value='1234567890'),
]
self.assertNotEqual(badges[0].badge_width, badges[1].badge_width)
def test_multiple_badges_get_different_mask_id(self):
badges = [
Badge('something', value='100', value_suffix='%', num_padding_chars=0),
Badge('coverage', value='1234567890'),
Badge('multiple 1', value='100', value_suffix='%', num_padding_chars=0),
Badge('multiple 2', value='1234567890'),
]
self.assertNotEqual(badges[0].mask_id, badges[1].mask_id)
def test_integer_value_is_handled_as_integer(self):
badge = Badge('test', value='1234')
def test_integer_str_value_is_handled_as_integer(self):
badge = Badge('integer', value='1234')
self.assertTrue(badge.value_is_int)
self.assertFalse(badge.value_is_float)
badge.write_badge('test_badge_int_str.svg', overwrite=True)
def test_integer_int_value_is_handled_as_integer(self):
badge = Badge('integer', value=1234)
self.assertTrue(badge.value_is_int)
self.assertFalse(badge.value_is_float)
badge.write_badge('test_badge_int.svg', overwrite=True)
def test_float_str_value_is_handled_as_float(self):
badge = Badge('float str', value='1234.1')
self.assertFalse(badge.value_is_int)
self.assertTrue(badge.value_is_float)
badge.write_badge('test_badge_float_str.svg', overwrite=True)
def test_float_value_is_handled_as_float(self):
badge = Badge('test', value='1234.1')
badge = Badge('float int', value=1234.1)
self.assertFalse(badge.value_is_int)
self.assertTrue(badge.value_is_float)
badge.write_badge('test_badge_float.svg', overwrite=True)
def test_float_value_with_zero_decimal(self):
badge = Badge('test', value='10.00')
badge = Badge('float with zeros', value='10.00')
self.assertFalse(badge.value_is_int)
self.assertTrue(badge.value_is_float)
badge.write_badge('test_badge_10.svg', overwrite=True)
badge.write_badge('test_badge_float_zeros.svg', overwrite=True)
def test_float_value_with_non_zero_decimal(self):
badge = Badge('test', value='10.01')
badge = Badge('float str no decimal', value='10.01')
self.assertFalse(badge.value_is_int)
self.assertTrue(badge.value_is_float)
badge.write_badge('test_badge_11.svg', overwrite=True)
badge.write_badge('test_badge_float-str-no-decimal.svg', overwrite=True)
def test_padding_label(self):
badge = Badge('label padding', value='10.01', num_label_padding_chars=2)
badge.write_badge('test_badge_padding_label.svg', overwrite=True)
def test_padding_value(self):
badge = Badge('value padding', value='10.01', num_value_padding_chars=2)
badge.write_badge('test_badge_padding_value.svg', overwrite=True)
def test_value_formatting(self):
badge = Badge('value formatting', value="10", value_format="%s hits/sec")
self.assertEqual("10 hits/sec", badge.value_text)
def test_font_name(self):
font = 'Arial, Helvetica, sans-serif'
badge = Badge('font', value=font, font_name=font)
badge.write_badge('test_badge_font.svg', overwrite=True)
badge_repr = repr(badge)
self.assertTrue("font_name='Arial, Helvetica, sans-serif'" in badge_repr)
def test_invalid_font_name(self):
font = 'Invalid font'
with self.assertRaises(ValueError):
_ = Badge('font', value=font, font_name=font)
def test_font_size(self):
for size in [10, 11, 12]:
badge = Badge('font size', value=size, font_size=size)
badge.write_badge('test_badge_font_size_%s.svg' % size, overwrite=True)
def test_font_size_repr(self):
badge = Badge('font size', value=10, font_size=10)
badge_repr = repr(badge)
self.assertTrue("font_size=10" in badge_repr)
def test_template_from_file(self):
file = "tests/template.svg"
badge = Badge('template from file', value=file, template=file)
_ = badge.badge_svg_text
def test_repr_svg(self):
badge = Badge('label', 'value')
self.assertEqual(badge.badge_svg_text, badge._repr_svg_())
def test_str_value_with_threshold_and_default(self):
badge = Badge('label', value='fred', thresholds={'pass': 'green', 'fail': 'red'}, default_color='orange')
self.assertTrue('orange', badge.badge_color)
def test_invalid_color(self):
with self.assertRaises(ValueError):
badge = Badge('label', value='fred', default_color='floberry')
_ = badge.badge_color_code
def test_invalid_write_path(self):
badge = Badge('label', 'value')
with self.assertRaisesRegexp(ValueError, r'File location may not be a directory\.'):
badge.write_badge('tests/')
with self.assertRaisesRegexp(RuntimeError, r'File ".*tests\/exists\.svg" already exists\.'):
badge.write_badge('tests/exists')
badge.write_badge('tests/exists')
def test_arg_parsing(self):
args = parse_args(['-l', 'label', '-v', 'value'])
self.assertEqual('label', args.label)
self.assertEqual('value', args.value)
def test_main_print(self):
main(['--label', 'label', '--value', 'value'])
def test_main_write_to_file(self):
main(['--label', 'label', '--value', 'value', '--file', 'test_badge_main.svg', '--overwrite'])
def test_main_thresholds(self):
main([
'--label', 'label',
'--value', 'value',
'--file', 'test_badge_main_threshold.svg',
'--overwrite',
'2=red', '4=orange'])
def test_named_threshold(self):
main([
'--value', 'value',
'--file', 'test_badge_main_named_threshold.svg',
'--overwrite',
'coverage'])
def test_main_missing_value(self):
with self.assertRaisesRegexp(ValueError, r'Label has not been set\. Please use --label argument\.'):
main(['--value', '123', '--file', 'test_badge_main.svg', '--overwrite'])