Skip to content

Commit c77aaec

Browse files
feat: support equals sign and surrounding whitespace in \htmlData attribute values (#4112)
* Support data attributes containing equals signs * Fix linter nits * Fix third linter nit * Code cleanup, more tests, and stop trimming value * Another test improvement --------- Co-authored-by: Erik Demaine <edemaine@mit.edu>
1 parent 9151d5e commit c77aaec

2 files changed

Lines changed: 51 additions & 5 deletions

File tree

src/functions/html.js

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,12 +52,15 @@ defineFunction({
5252
case "\\htmlData": {
5353
const data = value.split(",");
5454
for (let i = 0; i < data.length; i++) {
55-
const keyVal = data[i].split("=");
56-
if (keyVal.length !== 2) {
57-
throw new ParseError(
58-
"Error parsing key-value for \\htmlData");
55+
const item = data[i];
56+
const firstEquals = item.indexOf("=");
57+
if (firstEquals < 0) {
58+
throw new ParseError(`\\htmlData key/value '${item}'` +
59+
` missing equals sign`);
5960
}
60-
attributes["data-" + keyVal[0].trim()] = keyVal[1].trim();
61+
const key = item.slice(0, firstEquals);
62+
const value = item.slice(firstEquals + 1);
63+
attributes["data-" + key.trim()] = value;
6164
}
6265

6366
trustContext = {

test/katex-spec.js

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2217,6 +2217,49 @@ describe("An HTML extension builder", function() {
22172217
});
22182218
});
22192219

2220+
describe("The \\htmlData macro", function() {
2221+
const trustNonStrictSettings = new Settings({trust: true, strict: false});
2222+
it("should not fail if an argument contains a single equals sign", () => {
2223+
expect("\\htmlData{foo=a}{x}").toBuild(trustNonStrictSettings);
2224+
});
2225+
2226+
it("should allow equals signs in value", () => {
2227+
const built = getBuilt(
2228+
"\\htmlData{foo=a=b}{x}", trustNonStrictSettings);
2229+
expect(built[0].attributes["data-foo"]).toEqual("a=b");
2230+
});
2231+
2232+
it("should accept empty values", () => {
2233+
expect("\\htmlData{foo=}{x}").toBuild(trustNonStrictSettings);
2234+
});
2235+
2236+
it("should accept empty keys", () => {
2237+
expect("\\htmlData{=a}{x}").toBuild(trustNonStrictSettings);
2238+
});
2239+
2240+
it("should preserve spaces in value", () => {
2241+
const built = getBuilt(
2242+
"\\htmlData{foo= bar }{x}", trustNonStrictSettings);
2243+
expect(built[0].attributes["data-foo"]).toEqual(" bar ");
2244+
});
2245+
2246+
it("should throw Error if an argument contains no equals signs", () => {
2247+
try {
2248+
katex.renderToString(
2249+
"\\htmlData{foo}{x}", trustNonStrictSettings);
2250+
2251+
// Render is expected to throw, so this should not be called.
2252+
expect(true).toBe(false);
2253+
} catch (error) {
2254+
expect(error).toBeInstanceOf(ParseError);
2255+
const message =
2256+
"\\htmlData key/value 'foo' missing equals sign";
2257+
expect(error.message).toBe(`KaTeX parse error: ${message}`);
2258+
expect(error.rawMessage).toBe(message);
2259+
}
2260+
});
2261+
});
2262+
22202263
describe("A bin builder", function() {
22212264
it("should create mbins normally", function() {
22222265
const built = getBuilt`x + y`;

0 commit comments

Comments
 (0)