Skip to content

Commit 0e942bc

Browse files
djbarnwalnishantmonu51
authored andcommitted
fix: field formatter sanitizer for vega formatter (#9390)
* fix: field formatter sanitizer for vega formatter * use exact name in assertion
1 parent d36811e commit 0e942bc

2 files changed

Lines changed: 58 additions & 6 deletions

File tree

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import { describe, expect, it } from "vitest";
2+
import { parseExpression } from "vega-expression";
3+
import { sanitizeFieldName } from "./util";
4+
5+
describe("sanitizeFieldName", () => {
6+
it("keeps simple field names readable", () => {
7+
expect(sanitizeFieldName("total_sales")).toBe("rill_total_sales");
8+
});
9+
10+
it("returns a valid Vega expression function name for measure names with operators", () => {
11+
const measureNames: [string, string][] = [
12+
["Total Sample Revenue", "rill_Total_u20_Sample_u20_Revenue"],
13+
["Sample Rate* Lift", "rill_Sample_u20_Rate_u2a__u20_Lift"],
14+
[
15+
"Share(%) | Variant A",
16+
"rill_Share_u28__u25__u29__u20__u7c__u20_Variant_u20_A",
17+
],
18+
[
19+
"Share(%) | Baseline",
20+
"rill_Share_u28__u25__u29__u20__u7c__u20_Baseline",
21+
],
22+
[
23+
"Avg Sample Value | Variant A",
24+
"rill_Avg_u20_Sample_u20_Value_u20__u7c__u20_Variant_u20_A",
25+
],
26+
[
27+
"Avg Sample Value | Baseline",
28+
"rill_Avg_u20_Sample_u20_Value_u20__u7c__u20_Baseline",
29+
],
30+
[
31+
"Success Rate | Variant A",
32+
"rill_Success_u20_Rate_u20__u7c__u20_Variant_u20_A",
33+
],
34+
[
35+
"Success Rate | Baseline",
36+
"rill_Success_u20_Rate_u20__u7c__u20_Baseline",
37+
],
38+
["Success Rate | Delta", "rill_Success_u20_Rate_u20__u7c__u20_Delta"],
39+
];
40+
41+
for (const [measureName, expectedFormatType] of measureNames) {
42+
const formatType = sanitizeFieldName(measureName);
43+
44+
expect(formatType).toBe(expectedFormatType);
45+
expect(() => parseExpression(`${formatType}(datum.value)`)).not.toThrow();
46+
}
47+
});
48+
});

web-common/src/components/vega/util.ts

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,17 @@ export function sanitizeValuesForSpec(values: unknown[]) {
3131
}
3232

3333
export function sanitizeFieldName(fieldName: string) {
34-
const specialCharactersRemoved = sanitizeValueForVega(fieldName);
35-
const sanitizedFieldName = specialCharactersRemoved.replace(" ", "__");
34+
const sanitizedFieldName = Array.from(fieldName)
35+
.map((char) => {
36+
if (/[a-zA-Z0-9_$]/.test(char)) return char;
37+
return `_u${char.codePointAt(0)?.toString(16) ?? "0"}_`;
38+
})
39+
.join("");
3640

3741
/**
38-
* Add a prefix to the beginning of the field
39-
* name to avoid variables starting with a special
40-
* character or number.
42+
* Vega-Lite compiles custom formatType values as expression function calls.
43+
* Keep this value to a JavaScript/Vega identifier-safe subset so measure
44+
* names with spaces or operators can still be used as formatter names.
4145
*/
42-
return `rill_${sanitizedFieldName}`;
46+
return `rill_${sanitizedFieldName || "field"}`;
4347
}

0 commit comments

Comments
 (0)