@flux-ui/statistics 3.0.0-next.72 → 3.0.0-next.73

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.
package/dist/index.js CHANGED
@@ -130,13 +130,39 @@ function deepResolveCssVars(value, root) {
130
130
  return changed ? out : value;
131
131
  }
132
132
  //#endregion
133
+ //#region src/util/html.ts
134
+ var HTML_ESCAPES = {
135
+ "&": "&",
136
+ "<": "&lt;",
137
+ ">": "&gt;",
138
+ "\"": "&quot;",
139
+ "'": "&#39;"
140
+ };
141
+ var HTML_PATTERN = /[&<>"']/g;
142
+ var ATTR_PATTERN = /[&<>"]/g;
143
+ /**
144
+ * Escapes a value for safe interpolation into HTML text content.
145
+ */
146
+ function escapeHtml(value) {
147
+ return String(value ?? "").replace(HTML_PATTERN, (char) => HTML_ESCAPES[char]);
148
+ }
149
+ /**
150
+ * Escapes a value for safe interpolation into a double-quoted HTML attribute
151
+ * or inline style value. Prevents attribute breakout from untrusted input.
152
+ */
153
+ function escapeAttr(value) {
154
+ return String(value ?? "").replace(ATTR_PATTERN, (char) => HTML_ESCAPES[char]);
155
+ }
156
+ //#endregion
133
157
  //#region src/util/icons.ts
134
158
  function renderIconSvg(name, color, size = 14) {
135
159
  if (!name) return "";
136
160
  const icon = iconRegistry[name];
137
161
  if (!icon) return "";
138
162
  const [width, height, , , pathData] = icon;
139
- return `<svg viewBox="0 0 ${width} ${height}" width="${size}" height="${size}" focusable="false" aria-hidden="true">${(Array.isArray(pathData) ? pathData : [pathData]).map((d) => `<path d="${d}" fill="${color}"/>`).join("")}</svg>`;
163
+ const paths = Array.isArray(pathData) ? pathData : [pathData];
164
+ const safeColor = escapeAttr(color);
165
+ return `<svg viewBox="0 0 ${width} ${height}" width="${size}" height="${size}" focusable="false" aria-hidden="true">${paths.map((d) => `<path d="${escapeAttr(d)}" fill="${safeColor}"/>`).join("")}</svg>`;
140
166
  }
141
167
  //#endregion
142
168
  //#region src/util/series/chartColors.ts
@@ -6822,17 +6848,18 @@ function K(e, t, n) {
6822
6848
  //#region src/util/tooltips/render.ts
6823
6849
  function renderTooltip(t, styles, title, items, activeIndex = -1, valueFormatter) {
6824
6850
  if (items.length === 0) return "";
6825
- const titleHtml = title ? `<div class="${styles.statisticsChartTooltipTitle}">${title}</div>` : "";
6851
+ const titleHtml = title ? `<div class="${styles.statisticsChartTooltipTitle}">${escapeHtml(title)}</div>` : "";
6826
6852
  const hasActive = activeIndex !== -1;
6827
6853
  const body = items.map((item, idx) => {
6828
6854
  const activeClass = !hasActive || idx === activeIndex ? ` ${styles.isActive}` : "";
6829
6855
  const translatedName = item.name ? t(String(item.name)) : "";
6830
- const marker = item.icon ? `<div class="${styles.statisticsChartTooltipSeriesIcon}${activeClass}" style="color: ${item.color}">${renderIconSvg(item.icon, item.color, 14)}</div>` : `<div class="${styles.statisticsChartTooltipSeriesColor}${activeClass}" style="background: ${item.color}"></div>`;
6856
+ const safeColor = escapeAttr(item.color);
6857
+ const marker = item.icon ? `<div class="${styles.statisticsChartTooltipSeriesIcon}${activeClass}" style="color: ${safeColor}">${renderIconSvg(item.icon, item.color, 14)}</div>` : `<div class="${styles.statisticsChartTooltipSeriesColor}${activeClass}" style="background: ${safeColor}"></div>`;
6831
6858
  const display = valueFormatter ? valueFormatter(item.value, item) : formatValue(item.value);
6832
6859
  return `
6833
6860
  ${marker}
6834
- <div class="${styles.statisticsChartTooltipSeriesName}${activeClass}">${translatedName}</div>
6835
- <div class="${styles.statisticsChartTooltipSeriesValue}${activeClass}">${display}</div>
6861
+ <div class="${styles.statisticsChartTooltipSeriesName}${activeClass}">${escapeHtml(translatedName)}</div>
6862
+ <div class="${styles.statisticsChartTooltipSeriesValue}${activeClass}">${escapeHtml(display)}</div>
6836
6863
  `;
6837
6864
  }).join("");
6838
6865
  return `<div class="${styles.statisticsChartTooltip}">${titleHtml}<div class="${styles.statisticsChartTooltipBody}">${body}</div></div>`;