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 - upper bound for your version number threshold you will need to provide an extreme upper bound -
in this example it is `999.0.0`. 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 ### Examples
#### Pylint using template #### Pylint using template

View File

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

View File

@@ -155,6 +155,18 @@ examples:
default=False, default=False,
help="Treat value and thresholds as semantic versions.", 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( parser.add_argument(
"args", "args",
nargs=argparse.REMAINDER, nargs=argparse.REMAINDER,
@@ -217,6 +229,8 @@ def main(args=None):
value_format=args.value_format, value_format=args.value_format,
text_color=args.text_color, text_color=args.text_color,
semver=args.semver, semver=args.semver,
escape_label=not args.no_escape_label,
escape_value=not args.no_escape_value,
) )
if args.file: if args.file: