@@ -23,29 +23,61 @@ export class CssLabel {
2323 private _customOpacity : number | undefined = undefined
2424 private _shouldBeShown = false
2525 private _text : string | number = ''
26+ /**
27+ * Tracks whether content was set via `dangerouslySetHtml` (`true`) or `setText` (`false`).
28+ * Needed so that switching mode with the same string (e.g. `setText` then `dangerouslySetHtml`) still updates the DOM.
29+ */
30+ private _contentIsHtml = false
2631 private _customPadding : Padding | undefined = undefined
2732
2833 private _customPointerEvents : Options [ 'pointerEvents' ] | undefined
2934 private _customStyle : string | undefined
3035 private _customClassName : string | undefined
3136
32- public constructor ( container : HTMLDivElement , text ?: string | number , dontInjectStyles ?: boolean ) {
37+ /**
38+ * @param container - The parent element for the label.
39+ * @param text - Initial label content (plain text or, if dangerousHtml is true, HTML).
40+ * @param dontInjectStyles - When true, global styles are not injected.
41+ * @param dangerousHtml - When true, text is set via innerHTML (XSS risk). Only use with trusted/sanitized content.
42+ */
43+ public constructor ( container : HTMLDivElement , text ?: string | number , dontInjectStyles ?: boolean , dangerousHtml ?: boolean ) {
3344 if ( ! dontInjectStyles && ! globalCssLabelStyles ) globalCssLabelStyles = injectStyles ( cssLabelStyles )
3445 this . _container = container
3546 this . _updateClasses ( )
36- if ( text !== undefined ) this . setText ( text )
47+ if ( text !== undefined ) {
48+ if ( dangerousHtml ) {
49+ this . dangerouslySetHtml ( text )
50+ } else {
51+ this . setText ( text )
52+ }
53+ }
3754 this . resetFontSize ( )
3855 this . resetPadding ( )
3956 }
4057
4158 /**
42- * Sets the text of the element.
59+ * Sets the text of the element using textContent (safe from XSS) .
4360 * @param text - The text to set.
4461 */
4562 public setText ( text : string | number ) : void {
46- if ( this . _text !== text ) {
63+ if ( this . _text !== text || this . _contentIsHtml ) {
4764 this . _text = text
48- this . element . innerHTML = typeof text === 'number' ? String ( text ) : text
65+ this . _contentIsHtml = false
66+ this . element . textContent = typeof text === 'number' ? String ( text ) : text
67+ this . _needsMeasureUpdate = true
68+ }
69+ }
70+
71+ /**
72+ * Sets the inner HTML of the element. Only use with trusted or sanitized content.
73+ * WARNING: XSS risk — do not pass user-provided or unsanitized HTML.
74+ * @param html - The HTML to set (string or number; numbers are converted to string).
75+ */
76+ public dangerouslySetHtml ( html : string | number ) : void {
77+ if ( this . _text !== html || ! this . _contentIsHtml ) {
78+ this . _text = html
79+ this . _contentIsHtml = true
80+ this . element . innerHTML = typeof html === 'number' ? String ( html ) : html
4981 this . _needsMeasureUpdate = true
5082 }
5183 }
0 commit comments