From cb55632a3e853cd75c68ecc8703d1aba41a9d12a Mon Sep 17 00:00:00 2001 From: HugoDF Date: Mon, 21 Oct 2024 21:01:15 +0100 Subject: [PATCH 1/6] support interpolation of object --- html-esc.js | 3 +++ html-esc.test.js | 10 ++++++++++ 2 files changed, 13 insertions(+) diff --git a/html-esc.js b/html-esc.js index 20a8268..21f1f2e 100644 --- a/html-esc.js +++ b/html-esc.js @@ -12,6 +12,9 @@ const markSafe = (str) => function htmlSanitize(rawText = "") { if (rawText?.__html_sanitized) return rawText; + if (typeof rawText !== "string") { + rawText = JSON.stringify(rawText); + } return markSafe(esc(rawText)); } diff --git a/html-esc.test.js b/html-esc.test.js index ad0f5fc..2b42af9 100644 --- a/html-esc.test.js +++ b/html-esc.test.js @@ -42,6 +42,16 @@ test("html - supports interpolation of lists of tagged items", (t) => { `, ); }); +test("html - interpolation of objects", (t) => { + t.assert.strictEqual( + html`
+      ${{ hello: "world " }}
+    
`.valueOf(), + `
+      {"hello":"world <img src='some-url'>"}
+    
`, + ); +}); test("html - doesn't break on bad payloads", (t) => { const badPayload = `">`; From 269ef39d3ce97285eee6f8c47254c80f5d419faf Mon Sep 17 00:00:00 2001 From: HugoDF Date: Mon, 21 Oct 2024 21:06:52 +0100 Subject: [PATCH 2/6] get formatter and tester happy with each other --- html-esc.test.js | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/html-esc.test.js b/html-esc.test.js index 2b42af9..66d8a85 100644 --- a/html-esc.test.js +++ b/html-esc.test.js @@ -44,12 +44,8 @@ test("html - supports interpolation of lists of tagged items", (t) => { }); test("html - interpolation of objects", (t) => { t.assert.strictEqual( - html`
-      ${{ hello: "world " }}
-    
`.valueOf(), - `
-      {"hello":"world <img src='some-url'>"}
-    
`, + html`
${{ hello: "world " }}
`.valueOf(), + `
{"hello":"world <img src='some-url'>"}
`, ); }); test("html - doesn't break on bad payloads", (t) => { From 5e237c00e27b13d48cc50222ae073c9445f85875 Mon Sep 17 00:00:00 2001 From: HugoDF Date: Mon, 21 Oct 2024 21:07:55 +0100 Subject: [PATCH 3/6] lint command shouldn't fix the file --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b9bc6e8..5fa2299 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "scripts": { "dev": "node serve.js", "test": "node --test --experimental-test-coverage", - "lint": "npm run format -- -c", + "lint": "npm run format -- -c --no-write", "format": "prettier --write './**/*.{js,json,yml,md,html}'" }, "homepage": "https://github.com/HugoDF/html-esc", From bd55ff313c318651e9bb4b3b5aa731440bb6871c Mon Sep 17 00:00:00 2001 From: HugoDF Date: Mon, 21 Oct 2024 21:09:49 +0100 Subject: [PATCH 4/6] add comment --- html-esc.js | 1 + 1 file changed, 1 insertion(+) diff --git a/html-esc.js b/html-esc.js index 21f1f2e..6b504c2 100644 --- a/html-esc.js +++ b/html-esc.js @@ -13,6 +13,7 @@ const markSafe = (str) => function htmlSanitize(rawText = "") { if (rawText?.__html_sanitized) return rawText; if (typeof rawText !== "string") { + // not doing `&& !(rawText instanceof String)` since it would fall into if (..__html_sanitized) rawText = JSON.stringify(rawText); } return markSafe(esc(rawText)); From 1d5b01763f474f541dc6ae3f93825fd28a4baeff Mon Sep 17 00:00:00 2001 From: HugoDF Date: Mon, 21 Oct 2024 21:22:35 +0100 Subject: [PATCH 5/6] switch to throwing on bad input --- html-esc.js | 7 ++++++- html-esc.test.js | 13 +++++++++---- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/html-esc.js b/html-esc.js index 6b504c2..5a03a60 100644 --- a/html-esc.js +++ b/html-esc.js @@ -14,7 +14,12 @@ function htmlSanitize(rawText = "") { if (rawText?.__html_sanitized) return rawText; if (typeof rawText !== "string") { // not doing `&& !(rawText instanceof String)` since it would fall into if (..__html_sanitized) - rawText = JSON.stringify(rawText); + throw Object.assign( + new Error( + `Bad interpolated value, expected type "string" received type "${typeof rawText}". Try serializing the value.`, + ), + { value: rawText }, + ); } return markSafe(esc(rawText)); } diff --git a/html-esc.test.js b/html-esc.test.js index 66d8a85..130cd67 100644 --- a/html-esc.test.js +++ b/html-esc.test.js @@ -42,10 +42,15 @@ test("html - supports interpolation of lists of tagged items", (t) => { `, ); }); -test("html - interpolation of objects", (t) => { - t.assert.strictEqual( - html`
${{ hello: "world " }}
`.valueOf(), - `
{"hello":"world <img src='some-url'>"}
`, +test("html - interpolation of objects is forbidden, throws", (t) => { + t.assert.throws( + () => html`
${{ hello: "world " }}
`, + { + name: 'Error', + message: + 'Bad interpolated value, expected type "string" received type "object". Try serializing the value.', + value: { hello: "world " }, + }, ); }); test("html - doesn't break on bad payloads", (t) => { From eb772e4a3dba06acfa524866eb7888a045535138 Mon Sep 17 00:00:00 2001 From: HugoDF Date: Mon, 21 Oct 2024 21:36:15 +0100 Subject: [PATCH 6/6] console.error include the bad value, continue without crashing --- html-esc.js | 10 ++++------ html-esc.test.js | 21 +++++++++++++-------- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/html-esc.js b/html-esc.js index 5a03a60..b824b67 100644 --- a/html-esc.js +++ b/html-esc.js @@ -13,13 +13,11 @@ const markSafe = (str) => function htmlSanitize(rawText = "") { if (rawText?.__html_sanitized) return rawText; if (typeof rawText !== "string") { - // not doing `&& !(rawText instanceof String)` since it would fall into if (..__html_sanitized) - throw Object.assign( - new Error( - `Bad interpolated value, expected type "string" received type "${typeof rawText}". Try serializing the value.`, - ), - { value: rawText }, + console.error( + `Bad interpolated value, expected type "string" received type "${typeof rawText}". Try serializing the value:`, + rawText, ); + rawText = ""; } return markSafe(esc(rawText)); } diff --git a/html-esc.test.js b/html-esc.test.js index 130cd67..3f5380f 100644 --- a/html-esc.test.js +++ b/html-esc.test.js @@ -42,16 +42,21 @@ test("html - supports interpolation of lists of tagged items", (t) => { `, ); }); -test("html - interpolation of objects is forbidden, throws", (t) => { - t.assert.throws( - () => html`
${{ hello: "world " }}
`, +test("html - interpolation of objects is forbidden, console.error but doesn't crash", (t) => { + const mockConsoleError = t.mock.method(console, "error", () => {}); + t.assert.strictEqual( + html`
${{ hello: "world " }}
`.valueOf(), + `
`,
+  );
+  t.assert.strictEqual(mockConsoleError.mock.callCount(), 1);
+  t.assert.deepStrictEqual(mockConsoleError.mock.calls[0].arguments, [
+    'Bad interpolated value, expected type "string" received type "object". Try serializing the value:',
     {
-      name: 'Error',
-      message:
-        'Bad interpolated value, expected type "string" received type "object". Try serializing the value.',
-      value: { hello: "world " },
+      hello: "world ",
     },
-  );
+  ]);
+
+  t.mock.reset();
 });
 test("html - doesn't break on bad payloads", (t) => {
   const badPayload = `">`;