badgepy 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- badgepy/__init__.py +252 -0
- badgepy/__main__.py +209 -0
- badgepy/badge-template-full.svg +80 -0
- badgepy/default-widths.json +11925 -0
- badgepy/pil_text_measurer.py +40 -0
- badgepy/precalculate_text.py +205 -0
- badgepy/precalculated_text_measurer.py +97 -0
- badgepy/py.typed +0 -0
- badgepy/text_measurer.py +25 -0
- badgepy/version.py +15 -0
- badgepy-1.0.0.dist-info/METADATA +225 -0
- badgepy-1.0.0.dist-info/RECORD +33 -0
- badgepy-1.0.0.dist-info/WHEEL +5 -0
- badgepy-1.0.0.dist-info/licenses/LICENSE +202 -0
- badgepy-1.0.0.dist-info/top_level.txt +1 -0
- pybadger/__init__.py +252 -0
- pybadger/__main__.py +209 -0
- pybadger/pil_text_measurer.py +40 -0
- pybadger/precalculate_text.py +205 -0
- pybadger/precalculated_text_measurer.py +97 -0
- pybadger/py.typed +0 -0
- pybadger/text_measurer.py +25 -0
- pybadger/version.py +15 -0
- pybadges/__init__.py +252 -0
- pybadges/__main__.py +209 -0
- pybadges/badge-template-full.svg +80 -0
- pybadges/default-widths.json +11925 -0
- pybadges/pil_text_measurer.py +40 -0
- pybadges/precalculate_text.py +205 -0
- pybadges/precalculated_text_measurer.py +97 -0
- pybadges/py.typed +0 -0
- pybadges/text_measurer.py +25 -0
- pybadges/version.py +15 -0
badgepy/__init__.py
ADDED
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
# Copyright 2018 The pybadge Authors
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# https://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
"""Creates a github-style badge as a SVG image.
|
|
15
|
+
|
|
16
|
+
This package seeks to generate semantically-identical output to the JavaScript
|
|
17
|
+
gh-badges library
|
|
18
|
+
(https://github.com/badges/shields/blob/master/doc/gh-badges.md)
|
|
19
|
+
|
|
20
|
+
>>> badge(left_text='coverage', right_text='23%', right_color='red')
|
|
21
|
+
'<svg...</svg>'
|
|
22
|
+
>>> badge(left_text='build', right_text='green', right_color='green',
|
|
23
|
+
... whole_link="http://www.example.com/")
|
|
24
|
+
'<svg...</svg>'
|
|
25
|
+
>>> # base64-encoded PNG image
|
|
26
|
+
>>> image_data = 'iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAIAAAD91JpzAAAAD0lEQVQI12P4zwAD/xkYAA/+Af8iHnLUAAAAAElFTkSuQmCC'
|
|
27
|
+
>>> badge(left_text='build', right_text='green', right_color='green',
|
|
28
|
+
... logo="data:image/png;base64," + image_data)
|
|
29
|
+
'<svg...</svg>'
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
import base64
|
|
33
|
+
import mimetypes
|
|
34
|
+
from typing import Optional
|
|
35
|
+
import urllib.parse
|
|
36
|
+
from xml.dom import minidom
|
|
37
|
+
|
|
38
|
+
import filetype
|
|
39
|
+
import jinja2
|
|
40
|
+
import requests
|
|
41
|
+
|
|
42
|
+
from badgepy import text_measurer
|
|
43
|
+
from badgepy import precalculated_text_measurer
|
|
44
|
+
from badgepy.version import __version__
|
|
45
|
+
|
|
46
|
+
_JINJA2_ENVIRONMENT = jinja2.Environment(
|
|
47
|
+
trim_blocks=True,
|
|
48
|
+
lstrip_blocks=True,
|
|
49
|
+
loader=jinja2.PackageLoader('badgepy', '.'),
|
|
50
|
+
autoescape=jinja2.select_autoescape(['svg']))
|
|
51
|
+
|
|
52
|
+
# Use the same color scheme as describe in:
|
|
53
|
+
# https://github.com/badges/shields/blob/master/lib/colorscheme.json
|
|
54
|
+
|
|
55
|
+
_NAME_TO_COLOR = {
|
|
56
|
+
'brightgreen': '#4c1',
|
|
57
|
+
'green': '#97CA00',
|
|
58
|
+
'yellow': '#dfb317',
|
|
59
|
+
'yellowgreen': '#a4a61d',
|
|
60
|
+
'orange': '#fe7d37',
|
|
61
|
+
'red': '#e05d44',
|
|
62
|
+
'blue': '#007ec6',
|
|
63
|
+
'grey': '#555',
|
|
64
|
+
'gray': '#555',
|
|
65
|
+
'lightgrey': '#9f9f9f',
|
|
66
|
+
'lightgray': '#9f9f9f',
|
|
67
|
+
'critical': '#e05d44',
|
|
68
|
+
'important': '#fe7d37',
|
|
69
|
+
'success': '#4c1',
|
|
70
|
+
'informational': '#007ec6',
|
|
71
|
+
'inactive': '#9f9f9f',
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def _remove_blanks(node):
|
|
76
|
+
for x in node.childNodes:
|
|
77
|
+
if x.nodeType == minidom.Node.TEXT_NODE:
|
|
78
|
+
if x.nodeValue:
|
|
79
|
+
x.nodeValue = x.nodeValue.strip()
|
|
80
|
+
elif x.nodeType == minidom.Node.ELEMENT_NODE:
|
|
81
|
+
_remove_blanks(x)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def _embed_image(url: str) -> str:
|
|
85
|
+
parsed_url = urllib.parse.urlparse(url)
|
|
86
|
+
|
|
87
|
+
if parsed_url.scheme == 'data':
|
|
88
|
+
return url
|
|
89
|
+
elif parsed_url.scheme.startswith('http'):
|
|
90
|
+
r = requests.get(url)
|
|
91
|
+
r.raise_for_status()
|
|
92
|
+
content_type = r.headers.get('content-type')
|
|
93
|
+
if content_type is None:
|
|
94
|
+
raise ValueError('no "Content-Type" header')
|
|
95
|
+
content_type, image_type = content_type.split('/')
|
|
96
|
+
if content_type != 'image':
|
|
97
|
+
raise ValueError(
|
|
98
|
+
'expected an image, got "{0}"'.format(content_type))
|
|
99
|
+
image_data = r.content
|
|
100
|
+
elif parsed_url.scheme:
|
|
101
|
+
raise ValueError('unsupported scheme "{0}"'.format(parsed_url.scheme))
|
|
102
|
+
else:
|
|
103
|
+
with open(url, 'rb') as f:
|
|
104
|
+
image_data = f.read()
|
|
105
|
+
kind = filetype.guess(image_data)
|
|
106
|
+
image_type = kind.extension if kind is not None else None
|
|
107
|
+
if not image_type:
|
|
108
|
+
mime_type, _ = mimetypes.guess_type(url, strict=False)
|
|
109
|
+
if not mime_type:
|
|
110
|
+
raise ValueError('not able to determine file type')
|
|
111
|
+
else:
|
|
112
|
+
content_type, image_type = mime_type.split('/')
|
|
113
|
+
if content_type != 'image':
|
|
114
|
+
raise ValueError('expected an image, got "{0}"'.format(
|
|
115
|
+
content_type or 'unknown'))
|
|
116
|
+
|
|
117
|
+
encoded_image = base64.b64encode(image_data).decode('ascii')
|
|
118
|
+
return 'data:image/{};base64,{}'.format(image_type, encoded_image)
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def badge(
|
|
122
|
+
left_text: str,
|
|
123
|
+
right_text: Optional[str] = None,
|
|
124
|
+
left_link: Optional[str] = None,
|
|
125
|
+
right_link: Optional[str] = None,
|
|
126
|
+
center_link: Optional[str] = None,
|
|
127
|
+
whole_link: Optional[str] = None,
|
|
128
|
+
logo: Optional[str] = None,
|
|
129
|
+
left_color: str = '#555',
|
|
130
|
+
right_color: str = '#007ec6',
|
|
131
|
+
center_color: Optional[str] = None,
|
|
132
|
+
measurer: Optional[text_measurer.TextMeasurer] = None,
|
|
133
|
+
left_title: Optional[str] = None,
|
|
134
|
+
right_title: Optional[str] = None,
|
|
135
|
+
center_title: Optional[str] = None,
|
|
136
|
+
whole_title: Optional[str] = None,
|
|
137
|
+
right_image: Optional[str] = None,
|
|
138
|
+
center_image: Optional[str] = None,
|
|
139
|
+
embed_logo: bool = False,
|
|
140
|
+
embed_right_image: bool = False,
|
|
141
|
+
embed_center_image: bool = False,
|
|
142
|
+
id_suffix: str = '',
|
|
143
|
+
) -> str:
|
|
144
|
+
"""Creates a github-style badge as an SVG image.
|
|
145
|
+
|
|
146
|
+
>>> badge(left_text='coverage', right_text='23%', right_color='red')
|
|
147
|
+
'<svg...</svg>'
|
|
148
|
+
>>> badge(left_text='build', right_text='green', right_color='green',
|
|
149
|
+
... whole_link="http://www.example.com/")
|
|
150
|
+
'<svg...</svg>'
|
|
151
|
+
|
|
152
|
+
Args:
|
|
153
|
+
left_text: The text that should appear on the left-hand-side of the
|
|
154
|
+
badge e.g. "coverage".
|
|
155
|
+
right_text: The text that should appear on the right-hand-side of the
|
|
156
|
+
badge e.g. "23%".
|
|
157
|
+
left_link: The URL that should be redirected to when the left-hand text
|
|
158
|
+
is selected.
|
|
159
|
+
right_link: The URL that should be redirected to when the right-hand
|
|
160
|
+
text is selected.
|
|
161
|
+
whole_link: The link that should be redirected to when the badge is
|
|
162
|
+
selected. If set then left_link and right_right may not be set.
|
|
163
|
+
logo: A url representing a logo that will be displayed inside the
|
|
164
|
+
badge. Can be a data URL e.g. "data:image/svg+xml;utf8,<svg..."
|
|
165
|
+
left_color: The color of the part of the badge containing the left-hand
|
|
166
|
+
text. Can be an valid CSS color
|
|
167
|
+
(see https://developer.mozilla.org/en-US/docs/Web/CSS/color) or a
|
|
168
|
+
color name defined here:
|
|
169
|
+
https://github.com/badges/shields/blob/master/badge-maker/lib/color.js
|
|
170
|
+
right_color: The color of the part of the badge containing the
|
|
171
|
+
right-hand text. Can be an valid CSS color
|
|
172
|
+
(see https://developer.mozilla.org/en-US/docs/Web/CSS/color) or a
|
|
173
|
+
color name defined here:
|
|
174
|
+
https://github.com/badges/shields/blob/master/badge-maker/lib/color.js
|
|
175
|
+
measurer: A text_measurer.TextMeasurer that can be used to measure the
|
|
176
|
+
width of left_text and right_text.
|
|
177
|
+
embed_logo: If True then embed the logo image directly in the badge.
|
|
178
|
+
This can prevent an HTTP request and some browsers will not render
|
|
179
|
+
external image referenced. When True, `logo` must be a HTTP/HTTPS
|
|
180
|
+
URI or a filesystem path. Also, the `badge` call may raise an
|
|
181
|
+
exception if the logo cannot be loaded, is not an image, etc.
|
|
182
|
+
whole_title: The title attribute to associate with the entire badge.
|
|
183
|
+
See https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title.
|
|
184
|
+
left_title: The title attribute to associate with the left part of the
|
|
185
|
+
badge.
|
|
186
|
+
See https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title.
|
|
187
|
+
right_title: The title attribute to associate with the right part of
|
|
188
|
+
the badge.
|
|
189
|
+
See https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title.
|
|
190
|
+
id_suffix: The suffix of the id attributes used in the SVG's elements.
|
|
191
|
+
Use to prevent duplicate ids if several badges are embedded on the
|
|
192
|
+
same page.
|
|
193
|
+
"""
|
|
194
|
+
if measurer is None:
|
|
195
|
+
measurer = (
|
|
196
|
+
precalculated_text_measurer.PrecalculatedTextMeasurer.default())
|
|
197
|
+
|
|
198
|
+
if (left_link or right_link or center_link) and whole_link:
|
|
199
|
+
raise ValueError(
|
|
200
|
+
'whole_link may not bet set with left_link, right_link, or center_link'
|
|
201
|
+
)
|
|
202
|
+
|
|
203
|
+
if center_image and not (right_image or right_text):
|
|
204
|
+
raise ValueError('cannot have a center_image without a right element')
|
|
205
|
+
|
|
206
|
+
if (center_image and not center_color) or (not center_image and
|
|
207
|
+
center_color):
|
|
208
|
+
raise ValueError('must have both a center_image and a center_color')
|
|
209
|
+
|
|
210
|
+
if logo and embed_logo:
|
|
211
|
+
logo = _embed_image(logo)
|
|
212
|
+
|
|
213
|
+
if right_image and embed_right_image:
|
|
214
|
+
right_image = _embed_image(right_image)
|
|
215
|
+
|
|
216
|
+
if center_image and embed_center_image:
|
|
217
|
+
center_image = _embed_image(center_image)
|
|
218
|
+
|
|
219
|
+
if center_color:
|
|
220
|
+
center_color = _NAME_TO_COLOR.get(center_color, center_color)
|
|
221
|
+
|
|
222
|
+
right_text_width = None
|
|
223
|
+
if right_text:
|
|
224
|
+
right_text_width = measurer.text_width(right_text) / 10.0
|
|
225
|
+
|
|
226
|
+
template = _JINJA2_ENVIRONMENT.get_template('badge-template-full.svg')
|
|
227
|
+
|
|
228
|
+
svg = template.render(
|
|
229
|
+
left_text=left_text,
|
|
230
|
+
right_text=right_text,
|
|
231
|
+
left_text_width=measurer.text_width(left_text) / 10.0,
|
|
232
|
+
right_text_width=right_text_width,
|
|
233
|
+
left_link=left_link,
|
|
234
|
+
right_link=right_link,
|
|
235
|
+
whole_link=whole_link,
|
|
236
|
+
center_link=center_link,
|
|
237
|
+
logo=logo,
|
|
238
|
+
left_color=_NAME_TO_COLOR.get(left_color, left_color),
|
|
239
|
+
right_color=_NAME_TO_COLOR.get(right_color, right_color),
|
|
240
|
+
center_color=center_color,
|
|
241
|
+
left_title=left_title,
|
|
242
|
+
right_title=right_title,
|
|
243
|
+
center_title=center_title,
|
|
244
|
+
whole_title=whole_title,
|
|
245
|
+
right_image=right_image,
|
|
246
|
+
center_image=center_image,
|
|
247
|
+
id_suffix=id_suffix,
|
|
248
|
+
)
|
|
249
|
+
xml = minidom.parseString(svg)
|
|
250
|
+
_remove_blanks(xml)
|
|
251
|
+
xml.normalize()
|
|
252
|
+
return xml.documentElement.toxml()
|
badgepy/__main__.py
ADDED
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
# Copyright 2018 The pybadge Authors
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# https://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
"""Output a github-style badge as an SVG image given some text and colors.
|
|
15
|
+
|
|
16
|
+
For more information, run:
|
|
17
|
+
$ python3 -m badgepy --help
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
import argparse
|
|
21
|
+
import sys
|
|
22
|
+
import tempfile
|
|
23
|
+
import webbrowser
|
|
24
|
+
|
|
25
|
+
sys.path.append('/home/nick/git/badgepy/')
|
|
26
|
+
import badgepy
|
|
27
|
+
from badgepy.version import __version__
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def main():
|
|
31
|
+
parser = argparse.ArgumentParser(
|
|
32
|
+
'badgepy',
|
|
33
|
+
description='generate a github-style badge given some text and colors')
|
|
34
|
+
|
|
35
|
+
parser.add_argument(
|
|
36
|
+
'--left-text',
|
|
37
|
+
default='license',
|
|
38
|
+
help='the text to show on the left-hand-side of the badge')
|
|
39
|
+
parser.add_argument(
|
|
40
|
+
'--right-text',
|
|
41
|
+
default=None,
|
|
42
|
+
help='the text to show on the right-hand-side of the badge')
|
|
43
|
+
parser.add_argument(
|
|
44
|
+
'--left-link',
|
|
45
|
+
default=None,
|
|
46
|
+
help='the url to redirect to when the left-hand of the badge is ' +
|
|
47
|
+
'clicked')
|
|
48
|
+
parser.add_argument(
|
|
49
|
+
'--right-link',
|
|
50
|
+
default=None,
|
|
51
|
+
help='the url to redirect to when the right-hand of the badge is ' +
|
|
52
|
+
'clicked')
|
|
53
|
+
parser.add_argument(
|
|
54
|
+
'--center-link',
|
|
55
|
+
default=None,
|
|
56
|
+
help='the url to redirect to when the center of the badge is ' +
|
|
57
|
+
'clicked')
|
|
58
|
+
parser.add_argument('--whole-link',
|
|
59
|
+
default=None,
|
|
60
|
+
help='the url to redirect to when the badge is clicked')
|
|
61
|
+
parser.add_argument(
|
|
62
|
+
'--logo',
|
|
63
|
+
default=None,
|
|
64
|
+
help='a URI reference to a logo to display in the badge')
|
|
65
|
+
parser.add_argument(
|
|
66
|
+
'--left-color',
|
|
67
|
+
default='#555',
|
|
68
|
+
help='the background color of the left-hand-side of the badge')
|
|
69
|
+
parser.add_argument(
|
|
70
|
+
'--right-color',
|
|
71
|
+
default='#007ec6',
|
|
72
|
+
help='the background color of the right-hand-side of the badge')
|
|
73
|
+
parser.add_argument(
|
|
74
|
+
'--center-color',
|
|
75
|
+
default=None,
|
|
76
|
+
help='the background color of the right-hand-side of the badge')
|
|
77
|
+
parser.add_argument('--browser',
|
|
78
|
+
action='store_true',
|
|
79
|
+
default=False,
|
|
80
|
+
help='display the badge in a browser tab')
|
|
81
|
+
parser.add_argument(
|
|
82
|
+
'--use-pil-text-measurer',
|
|
83
|
+
action='store_true',
|
|
84
|
+
default=False,
|
|
85
|
+
help='use the PilMeasurer to measure the length of text (kerning may '
|
|
86
|
+
'be more precise for non-Western languages. ' +
|
|
87
|
+
'--deja-vu-sans-path must also be set.')
|
|
88
|
+
parser.add_argument(
|
|
89
|
+
'--deja-vu-sans-path',
|
|
90
|
+
default=None,
|
|
91
|
+
help='the path to the ttf font file containing DejaVu Sans. If not ' +
|
|
92
|
+
'present on your system, you can download it from ' +
|
|
93
|
+
'https://www.fontsquirrel.com/fonts/dejavu-sans')
|
|
94
|
+
parser.add_argument(
|
|
95
|
+
'--left-title',
|
|
96
|
+
default=None,
|
|
97
|
+
help='the title to associate with the left part of the badge. See '
|
|
98
|
+
'https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title')
|
|
99
|
+
parser.add_argument(
|
|
100
|
+
'--right-title',
|
|
101
|
+
default=None,
|
|
102
|
+
help='the title to associate with the right part of the badge. See '
|
|
103
|
+
'https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title')
|
|
104
|
+
parser.add_argument(
|
|
105
|
+
'--center-title',
|
|
106
|
+
default=None,
|
|
107
|
+
help='the title to associate with the center part of the badge. See '
|
|
108
|
+
'https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title')
|
|
109
|
+
parser.add_argument(
|
|
110
|
+
'--whole-title',
|
|
111
|
+
default=None,
|
|
112
|
+
help='the title to associate with the entire badge. See '
|
|
113
|
+
'https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title')
|
|
114
|
+
parser.add_argument(
|
|
115
|
+
'--right-image',
|
|
116
|
+
default=None,
|
|
117
|
+
help='the image to associate with the right-hand side of the badge')
|
|
118
|
+
parser.add_argument(
|
|
119
|
+
'--center-image',
|
|
120
|
+
default=None,
|
|
121
|
+
help='the image to associate with the center of the badge')
|
|
122
|
+
parser.add_argument(
|
|
123
|
+
'--embed-logo',
|
|
124
|
+
nargs='?',
|
|
125
|
+
type=lambda x: x.lower() in ['y', 'yes', 't', 'true', '1', ''],
|
|
126
|
+
const='yes',
|
|
127
|
+
default='no',
|
|
128
|
+
help='if the logo is specified then include the image data directly in '
|
|
129
|
+
'the badge (this will prevent a URL fetch and may work around the '
|
|
130
|
+
'fact that some browsers do not fetch external image references); '
|
|
131
|
+
'only works if --logo is a HTTP/HTTPS URI or a file path')
|
|
132
|
+
parser.add_argument(
|
|
133
|
+
'--embed-right-image',
|
|
134
|
+
nargs='?',
|
|
135
|
+
type=lambda x: x.lower() in ['y', 'yes', 't', 'true', '1', ''],
|
|
136
|
+
const='yes',
|
|
137
|
+
default='no',
|
|
138
|
+
help=
|
|
139
|
+
'if the right image is specified then include the image data directly in '
|
|
140
|
+
'the badge (this will prevent a URL fetch and may work around the '
|
|
141
|
+
'fact that some browsers do not fetch external image references); '
|
|
142
|
+
'only works if --logo is a HTTP/HTTPS URI or a file path')
|
|
143
|
+
parser.add_argument(
|
|
144
|
+
'--embed-center-image',
|
|
145
|
+
nargs='?',
|
|
146
|
+
type=lambda x: x.lower() in ['y', 'yes', 't', 'true', '1', ''],
|
|
147
|
+
const='yes',
|
|
148
|
+
default='no',
|
|
149
|
+
help=
|
|
150
|
+
'if the center image is specified then include the image data directly in '
|
|
151
|
+
'the badge (this will prevent a URL fetch and may work around the '
|
|
152
|
+
'fact that some browsers do not fetch external image references); '
|
|
153
|
+
'only works if --logo is a HTTP/HTTPS URI or a file path')
|
|
154
|
+
parser.add_argument(
|
|
155
|
+
'-v',
|
|
156
|
+
'--version',
|
|
157
|
+
action='version',
|
|
158
|
+
version='%(prog)s {version}'.format(version=__version__))
|
|
159
|
+
args = parser.parse_args()
|
|
160
|
+
|
|
161
|
+
if (args.left_link or args.right_link or
|
|
162
|
+
args.center_link) and args.whole_link:
|
|
163
|
+
print('argument --whole-link: cannot be set with ' +
|
|
164
|
+
'--left-link, --right-link, or --center_link',
|
|
165
|
+
file=sys.stderr)
|
|
166
|
+
sys.exit(1)
|
|
167
|
+
|
|
168
|
+
measurer = None
|
|
169
|
+
if args.use_pil_text_measurer:
|
|
170
|
+
if args.deja_vu_sans_path is None:
|
|
171
|
+
print('argument --use-pil-text-measurer: must also set ' +
|
|
172
|
+
'--deja-vu-sans-path',
|
|
173
|
+
file=sys.stderr)
|
|
174
|
+
sys.exit(1)
|
|
175
|
+
from badgepy import pil_text_measurer
|
|
176
|
+
measurer = pil_text_measurer.PilMeasurer(args.deja_vu_sans_path)
|
|
177
|
+
|
|
178
|
+
badge = badgepy.badge(left_text=args.left_text,
|
|
179
|
+
right_text=args.right_text,
|
|
180
|
+
left_link=args.left_link,
|
|
181
|
+
right_link=args.right_link,
|
|
182
|
+
center_link=args.center_link,
|
|
183
|
+
whole_link=args.whole_link,
|
|
184
|
+
logo=args.logo,
|
|
185
|
+
left_color=args.left_color,
|
|
186
|
+
right_color=args.right_color,
|
|
187
|
+
center_color=args.center_color,
|
|
188
|
+
measurer=measurer,
|
|
189
|
+
left_title=args.left_title,
|
|
190
|
+
right_title=args.right_title,
|
|
191
|
+
center_title=args.center_title,
|
|
192
|
+
whole_title=args.whole_title,
|
|
193
|
+
right_image=args.right_image,
|
|
194
|
+
center_image=args.center_image,
|
|
195
|
+
embed_logo=args.embed_logo,
|
|
196
|
+
embed_right_image=args.embed_right_image,
|
|
197
|
+
embed_center_image=args.embed_center_image)
|
|
198
|
+
|
|
199
|
+
if args.browser:
|
|
200
|
+
_, badge_path = tempfile.mkstemp(suffix='.svg')
|
|
201
|
+
with open(badge_path, 'w') as f:
|
|
202
|
+
f.write(badge)
|
|
203
|
+
|
|
204
|
+
webbrowser.open_new_tab('file://' + badge_path)
|
|
205
|
+
else:
|
|
206
|
+
print(badge, end='')
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
main()
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
{% set logo_width = 14 if logo else 0 %}
|
|
2
|
+
{% set logo_padding = 3 if (logo and left_text) else 0 %}
|
|
3
|
+
{% set image_width = 107 if center_image else 0 %}
|
|
4
|
+
{% set left_width = left_text_width + 10 + logo_width + logo_padding %}
|
|
5
|
+
{% set center_width = image_width + 10 if center_image else 0 %}
|
|
6
|
+
{% set right_width = center_width + right_text_width + 10 if right_text else 0 %}
|
|
7
|
+
{% set id_smooth = 'smooth' + id_suffix %}
|
|
8
|
+
{% set id_round = 'round' + id_suffix %}
|
|
9
|
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="{{ left_width + right_width }}" height="20">
|
|
10
|
+
{% if whole_title %}
|
|
11
|
+
<title>{{ whole_title }}</title>
|
|
12
|
+
{% endif %}
|
|
13
|
+
<linearGradient id="{{ id_smooth }}" x2="0" y2="100%">
|
|
14
|
+
<stop offset="0" stop-color="#bbb" stop-opacity=".1"/>
|
|
15
|
+
<stop offset="1" stop-opacity=".1"/>
|
|
16
|
+
</linearGradient>
|
|
17
|
+
|
|
18
|
+
<clipPath id="{{ id_round }}">
|
|
19
|
+
<rect width="{{ left_width + right_width }}" height="20" rx="3" fill="#fff"/>
|
|
20
|
+
</clipPath>
|
|
21
|
+
|
|
22
|
+
<g clip-path="url(#{{ id_round }})">
|
|
23
|
+
|
|
24
|
+
<rect width="{{ left_width }}" height="20" fill="{{ left_color }}">
|
|
25
|
+
{% if left_title %}
|
|
26
|
+
<title>{{ left_title }}</title>
|
|
27
|
+
{% endif %}
|
|
28
|
+
</rect>
|
|
29
|
+
|
|
30
|
+
{% if center_image %}
|
|
31
|
+
<rect x="{{ left_width }}" width="{{ center_width }}" height="20" fill="{{ center_color }}">
|
|
32
|
+
{% if center_title %}
|
|
33
|
+
<title>{{ center_title }}</title>
|
|
34
|
+
{% endif %}
|
|
35
|
+
</rect>
|
|
36
|
+
{% endif %}
|
|
37
|
+
|
|
38
|
+
<rect x="{{ left_width + center_width }}" width="{{ right_width }}" height="20" fill="{{ right_color }}">
|
|
39
|
+
{% if right_title %}
|
|
40
|
+
<title>{{ right_title }}</title>
|
|
41
|
+
{% endif %}
|
|
42
|
+
</rect>
|
|
43
|
+
|
|
44
|
+
<rect width="{{ left_width + right_width }}" height="20" fill="url(#{{ id_smooth }})"/>
|
|
45
|
+
</g>
|
|
46
|
+
|
|
47
|
+
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="110">
|
|
48
|
+
{% if logo %}
|
|
49
|
+
<image x="5" y="3" width="{{ logo_width }}" height="14" xlink:href="{{ logo}}"/>
|
|
50
|
+
{% endif %}
|
|
51
|
+
<text x="{{ (((left_width+logo_width+logo_padding)/2)+1)*10 }}" y="150" fill="#010101" fill-opacity=".3" transform="scale(0.1)" textLength="{{ (left_width-(10+logo_width+logo_padding))*10 }}" lengthAdjust="spacing">{{ left_text }}</text>
|
|
52
|
+
<text x="{{ (((left_width+logo_width+logo_padding)/2)+1)*10 }}" y="140" transform="scale(0.1)" textLength="{{ (left_width-(10+logo_width+logo_padding))*10 }}" lengthAdjust="spacing">{{ left_text }}</text>
|
|
53
|
+
{% if center_image %}
|
|
54
|
+
<image x="{{ left_width }}" y="3" width="{{ center_width }}" height="14" xlink:href="{{ center_image }}"/>
|
|
55
|
+
{% endif %}
|
|
56
|
+
{% if right_image %}
|
|
57
|
+
<image x="{{ left_width + center_width }}" y="3" width="{{ right_width }}" height="14" xlink:href="{{ right_image }}"/>
|
|
58
|
+
{% endif %}
|
|
59
|
+
{% if right_text %}
|
|
60
|
+
<text x="{{ (left_width+center_width/2+right_width/2-1)*10 }}" y="150" fill="#010101" fill-opacity=".3" transform="scale(0.1)" textLength="{{ (right_width-center_width-10)*10 }}" lengthAdjust="spacing">{{ right_text }}</text>
|
|
61
|
+
<text x="{{ (left_width+center_width/2+right_width/2-1)*10 }}" y="140" transform="scale(0.1)" textLength="{{ (right_width-center_width-10)*10 }}" lengthAdjust="spacing">{{ right_text }}</text>
|
|
62
|
+
{% endif %}
|
|
63
|
+
|
|
64
|
+
{% if left_link or whole_link %}
|
|
65
|
+
<a xlink:href="{{ left_link or whole_link }}">
|
|
66
|
+
<rect width="{{ left_width }}" height="20" fill="rgba(0,0,0,0)"/>
|
|
67
|
+
</a>
|
|
68
|
+
{% endif %}
|
|
69
|
+
{% if center_image and (center_width or whole_link) %}
|
|
70
|
+
<a xlink:href="{{ center_link or whole_link }}">
|
|
71
|
+
<rect x="{{ left_width }}" width="{{ center_width }}" height="20" fill="rgba(0,0,0,0)"/>
|
|
72
|
+
</a>
|
|
73
|
+
{% endif %}
|
|
74
|
+
{% if right_link or whole_link %}
|
|
75
|
+
<a xlink:href="{{ right_link or whole_link }}">
|
|
76
|
+
<rect x="{{ left_width + center_width }}" width="{{ right_width }}" height="20" fill="rgba(0,0,0,0)"/>
|
|
77
|
+
</a>
|
|
78
|
+
{% endif %}
|
|
79
|
+
</g>
|
|
80
|
+
</svg>
|