fix: Fix label and value escaping

Fix label and value escaping by defaulting to html escaping them.
Provide Python and CLI args to allow reverting to old behavior of
not escaping.

Fixes #91
This commit is contained in:
Jon Grace-Cox
2025-01-06 20:12:27 -05:00
parent 67af6673fc
commit c20d66fe0a
3 changed files with 49 additions and 2 deletions

View File

@@ -351,6 +351,19 @@ Each threshold entry is used to define the upper bounds of the threshold. If you
upper bound for your version number threshold you will need to provide an extreme upper bound -
in this example it is `999.0.0`.
### Escaping
Badges are generated as .svg files, which utilize an XML-based markup language. Consequently,
any HTML characters present in badge labels or values must be escaped to ensure proper
representation. If you need to disable escaping, the following options are available:
- Python API
- `escape_label=False`
- `escape_value=False`
- CLI
- `--no-escape-label`
- `--no-escape-value`
### Examples
#### Pylint using template

View File

@@ -2,6 +2,7 @@ import os
from collections import OrderedDict
from pathlib import Path
from typing import Dict, Type, Optional, Union
import html
from . import config
from .colors import Color
@@ -122,6 +123,8 @@ class Badge:
value_format: Optional[str] = None,
text_color: Optional[str] = None,
semver: Optional[bool] = False,
escape_label: Optional[bool] = True,
escape_value: Optional[bool] = True,
):
"""Constructor for Badge class."""
# Set defaults if values were not passed
@@ -209,6 +212,9 @@ class Badge:
self.use_max_when_value_exceeds = use_max_when_value_exceeds
self.mask_str = self.__class__._get_next_mask_str()
self.escape_label = escape_label
self.escape_value = escape_value
def __repr__(self) -> str:
"""Return a representation of the Badge object instance.
@@ -333,6 +339,20 @@ class Badge:
else:
return self.template
@property
def encoded_label(self) -> str:
if self.escape_label:
return html.escape(self.label)
else:
return self.label
@property
def encoded_value(self) -> str:
if self.escape_value:
return html.escape(self.value_text)
else:
return self.value_text
@property
def semver_version(self) -> Version:
"""The semantic version represented by the value string.
@@ -638,8 +658,8 @@ class Badge:
badge_text.replace("{{ badge width }}", str(self.badge_width))
.replace("{{ font name }}", self.font_name)
.replace("{{ font size }}", str(self.font_size))
.replace("{{ label }}", self.label)
.replace("{{ value }}", self.value_text)
.replace("{{ label }}", self.encoded_label)
.replace("{{ value }}", self.encoded_value)
.replace("{{ label anchor }}", str(self.label_anchor))
.replace("{{ label anchor shadow }}", str(self.label_anchor_shadow))
.replace("{{ value anchor }}", str(self.value_anchor))

View File

@@ -155,6 +155,18 @@ examples:
default=False,
help="Treat value and thresholds as semantic versions.",
)
parser.add_argument(
"--no-escape-label",
action="store_true",
default=False,
help="Do not escape the label text.",
)
parser.add_argument(
"--no-escape-value",
action="store_true",
default=False,
help="Do not escape the value text.",
)
parser.add_argument(
"args",
nargs=argparse.REMAINDER,
@@ -217,6 +229,8 @@ def main(args=None):
value_format=args.value_format,
text_color=args.text_color,
semver=args.semver,
escape_label=not args.no_escape_label,
escape_value=not args.no_escape_value,
)
if args.file: