@beinformed/ui 1.33.0-beta.2 → 1.33.0-beta.3

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/CHANGELOG.md CHANGED
@@ -2,6 +2,13 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [commit-and-tag-version](https://github.com/absolute-version/commit-and-tag-version) for commit guidelines.
4
4
 
5
+ ## [1.33.0-beta.3](https://git.beinformed.com/public/nl.beinformed.bi.layout.lib.ui/compare/v1.33.0-beta.2...v1.33.0-beta.3) (2023-08-28)
6
+
7
+
8
+ ### Bug Fixes
9
+
10
+ * **sanitize-html:** improve encoding of html entities to numerical entities ([45c3c56](https://git.beinformed.com/public/nl.beinformed.bi.layout.lib.ui/commit/45c3c56c8e04ca36b898efb5651fd87cbc9eea9f))
11
+
5
12
  ## [1.33.0-beta.2](https://git.beinformed.com/public/nl.beinformed.bi.layout.lib.ui/compare/v1.33.0-beta.1...v1.33.0-beta.2) (2023-08-24)
6
13
 
7
14
 
@@ -5,13 +5,15 @@ import { IllegalArgumentException } from "../../exceptions";
5
5
  * When path is only one deep better use optional chaining
6
6
  */
7
7
  const properEntityEncoding = html => {
8
- const escapedGt = html.replace(/</g, "[");
9
- const escapedLt = escapedGt.replace(/>/g, "]");
10
- const properEntities = he.encode(he.decode(escapedLt), {
11
- decimal: true
8
+ const htmlDecoded = he.decode(html, {
9
+ decimal: true,
10
+ allowUnsafeSymbols: true
12
11
  });
13
- const unescapedGt = properEntities.replace(/\[/g, "<");
14
- return unescapedGt.replace(/]/g, ">");
12
+ const htmlEncoded = he.encode(htmlDecoded, {
13
+ decimal: true,
14
+ allowUnsafeSymbols: true
15
+ });
16
+ return htmlEncoded;
15
17
  };
16
18
 
17
19
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"sanitizeHtml.js","names":["he","IllegalArgumentException","properEntityEncoding","html","escapedGt","replace","escapedLt","properEntities","encode","decode","decimal","unescapedGt","removeUnwantedHtml","options","arguments","length","undefined","allowedTags","correctEntityHtml","htmlWithoutAttributes","htmlWithCorrectBR","Array","isArray","join","pattern","regex","RegExp"],"sources":["../../../src/utils/helpers/sanitizeHtml.js"],"sourcesContent":["// @flow\nimport he from \"he\";\n\nimport { IllegalArgumentException } from \"../../exceptions\";\n\ntype removeUnwantedHtmlOptions = {\n allowedTags?: Array<string>,\n};\n\n/**\n * Translates html entities to their correct decimal equivalent\n * When path is only one deep better use optional chaining\n */\nconst properEntityEncoding = (html: string) => {\n const escapedGt = html.replace(/</g, \"[\");\n const escapedLt = escapedGt.replace(/>/g, \"]\");\n\n const properEntities = he.encode(he.decode(escapedLt), {\n decimal: true,\n });\n\n const unescapedGt = properEntities.replace(/\\[/g, \"<\");\n\n return unescapedGt.replace(/]/g, \">\");\n};\n\n/**\n * removes unwanted html, this might result in incorrect html, as it removes all html that we don't except,\n * like <b style=\"font-weight: 400\">bold</b> will result in bold</b>\n */\nconst removeUnwantedHtml = (\n html: string,\n options: removeUnwantedHtmlOptions = {\n allowedTags: [\"p\", \"br\", \"b\", \"i\", \"u\", \"strike\"],\n },\n): string => {\n if (typeof html !== \"string\") {\n throw new IllegalArgumentException(\"sanitizeHTML method expects a string\");\n }\n\n const correctEntityHtml = properEntityEncoding(html);\n\n // remove attributes from html elements\n const htmlWithoutAttributes = correctEntityHtml.replace(\n /<(\\w+)(.|[\\r\\n])*?>/gi,\n \"<$1>\",\n );\n\n const htmlWithCorrectBR = htmlWithoutAttributes.replace(\n /<br\\s*>/gi,\n \"<br />\",\n );\n\n // remove not allowed tags\n const allowedTags = Array.isArray(options.allowedTags)\n ? options.allowedTags.join(\"|\")\n : \"\";\n const pattern = `<(?!\\\\/?(${allowedTags})(>|\\\\s\\\\/))[^<]+?>`;\n const regex = new RegExp(pattern, \"gi\");\n\n return htmlWithCorrectBR.replace(regex, \"\");\n};\n\nexport { removeUnwantedHtml };\n"],"mappings":"AACA,OAAOA,EAAE,MAAM,IAAI;AAEnB,SAASC,wBAAwB,QAAQ,kBAAkB;AAM3D;AACA;AACA;AACA;AACA,MAAMC,oBAAoB,GAAIC,IAAY,IAAK;EAC7C,MAAMC,SAAS,GAAGD,IAAI,CAACE,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC;EACzC,MAAMC,SAAS,GAAGF,SAAS,CAACC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC;EAE9C,MAAME,cAAc,GAAGP,EAAE,CAACQ,MAAM,CAACR,EAAE,CAACS,MAAM,CAACH,SAAS,CAAC,EAAE;IACrDI,OAAO,EAAE;EACX,CAAC,CAAC;EAEF,MAAMC,WAAW,GAAGJ,cAAc,CAACF,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;EAEtD,OAAOM,WAAW,CAACN,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC;AACvC,CAAC;;AAED;AACA;AACA;AACA;AACA,MAAMO,kBAAkB,GAAG,SAAAA,CACzBT,IAAY,EAID;EAAA,IAHXU,OAAkC,GAAAC,SAAA,CAAAC,MAAA,QAAAD,SAAA,QAAAE,SAAA,GAAAF,SAAA,MAAG;IACnCG,WAAW,EAAE,CAAC,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,QAAQ;EAClD,CAAC;EAED,IAAI,OAAOd,IAAI,KAAK,QAAQ,EAAE;IAC5B,MAAM,IAAIF,wBAAwB,CAAC,sCAAsC,CAAC;EAC5E;EAEA,MAAMiB,iBAAiB,GAAGhB,oBAAoB,CAACC,IAAI,CAAC;;EAEpD;EACA,MAAMgB,qBAAqB,GAAGD,iBAAiB,CAACb,OAAO,CACrD,uBAAuB,EACvB,MACF,CAAC;EAED,MAAMe,iBAAiB,GAAGD,qBAAqB,CAACd,OAAO,CACrD,WAAW,EACX,QACF,CAAC;;EAED;EACA,MAAMY,WAAW,GAAGI,KAAK,CAACC,OAAO,CAACT,OAAO,CAACI,WAAW,CAAC,GAClDJ,OAAO,CAACI,WAAW,CAACM,IAAI,CAAC,GAAG,CAAC,GAC7B,EAAE;EACN,MAAMC,OAAO,GAAI,YAAWP,WAAY,qBAAoB;EAC5D,MAAMQ,KAAK,GAAG,IAAIC,MAAM,CAACF,OAAO,EAAE,IAAI,CAAC;EAEvC,OAAOJ,iBAAiB,CAACf,OAAO,CAACoB,KAAK,EAAE,EAAE,CAAC;AAC7C,CAAC;AAED,SAASb,kBAAkB"}
1
+ {"version":3,"file":"sanitizeHtml.js","names":["he","IllegalArgumentException","properEntityEncoding","html","htmlDecoded","decode","decimal","allowUnsafeSymbols","htmlEncoded","encode","removeUnwantedHtml","options","arguments","length","undefined","allowedTags","correctEntityHtml","htmlWithoutAttributes","replace","htmlWithCorrectBR","Array","isArray","join","pattern","regex","RegExp"],"sources":["../../../src/utils/helpers/sanitizeHtml.js"],"sourcesContent":["// @flow\nimport he from \"he\";\n\nimport { IllegalArgumentException } from \"../../exceptions\";\n\ntype removeUnwantedHtmlOptions = {\n allowedTags?: Array<string>,\n};\n\n/**\n * Translates html entities to their correct decimal equivalent\n * When path is only one deep better use optional chaining\n */\nconst properEntityEncoding = (html: string) => {\n const htmlDecoded = he.decode(html, {\n decimal: true,\n allowUnsafeSymbols: true,\n });\n\n const htmlEncoded = he.encode(htmlDecoded, {\n decimal: true,\n allowUnsafeSymbols: true,\n });\n\n return htmlEncoded;\n};\n\n/**\n * removes unwanted html, this might result in incorrect html, as it removes all html that we don't except,\n * like <b style=\"font-weight: 400\">bold</b> will result in bold</b>\n */\nconst removeUnwantedHtml = (\n html: string,\n options: removeUnwantedHtmlOptions = {\n allowedTags: [\"p\", \"br\", \"b\", \"i\", \"u\", \"strike\"],\n },\n): string => {\n if (typeof html !== \"string\") {\n throw new IllegalArgumentException(\"sanitizeHTML method expects a string\");\n }\n\n const correctEntityHtml = properEntityEncoding(html);\n\n // remove attributes from html elements\n const htmlWithoutAttributes = correctEntityHtml.replace(\n /<(\\w+)(.|[\\r\\n])*?>/gi,\n \"<$1>\",\n );\n\n const htmlWithCorrectBR = htmlWithoutAttributes.replace(\n /<br\\s*>/gi,\n \"<br />\",\n );\n\n // remove not allowed tags\n const allowedTags = Array.isArray(options.allowedTags)\n ? options.allowedTags.join(\"|\")\n : \"\";\n const pattern = `<(?!\\\\/?(${allowedTags})(>|\\\\s\\\\/))[^<]+?>`;\n const regex = new RegExp(pattern, \"gi\");\n\n return htmlWithCorrectBR.replace(regex, \"\");\n};\n\nexport { removeUnwantedHtml };\n"],"mappings":"AACA,OAAOA,EAAE,MAAM,IAAI;AAEnB,SAASC,wBAAwB,QAAQ,kBAAkB;AAM3D;AACA;AACA;AACA;AACA,MAAMC,oBAAoB,GAAIC,IAAY,IAAK;EAC7C,MAAMC,WAAW,GAAGJ,EAAE,CAACK,MAAM,CAACF,IAAI,EAAE;IAClCG,OAAO,EAAE,IAAI;IACbC,kBAAkB,EAAE;EACtB,CAAC,CAAC;EAEF,MAAMC,WAAW,GAAGR,EAAE,CAACS,MAAM,CAACL,WAAW,EAAE;IACzCE,OAAO,EAAE,IAAI;IACbC,kBAAkB,EAAE;EACtB,CAAC,CAAC;EAEF,OAAOC,WAAW;AACpB,CAAC;;AAED;AACA;AACA;AACA;AACA,MAAME,kBAAkB,GAAG,SAAAA,CACzBP,IAAY,EAID;EAAA,IAHXQ,OAAkC,GAAAC,SAAA,CAAAC,MAAA,QAAAD,SAAA,QAAAE,SAAA,GAAAF,SAAA,MAAG;IACnCG,WAAW,EAAE,CAAC,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,QAAQ;EAClD,CAAC;EAED,IAAI,OAAOZ,IAAI,KAAK,QAAQ,EAAE;IAC5B,MAAM,IAAIF,wBAAwB,CAAC,sCAAsC,CAAC;EAC5E;EAEA,MAAMe,iBAAiB,GAAGd,oBAAoB,CAACC,IAAI,CAAC;;EAEpD;EACA,MAAMc,qBAAqB,GAAGD,iBAAiB,CAACE,OAAO,CACrD,uBAAuB,EACvB,MACF,CAAC;EAED,MAAMC,iBAAiB,GAAGF,qBAAqB,CAACC,OAAO,CACrD,WAAW,EACX,QACF,CAAC;;EAED;EACA,MAAMH,WAAW,GAAGK,KAAK,CAACC,OAAO,CAACV,OAAO,CAACI,WAAW,CAAC,GAClDJ,OAAO,CAACI,WAAW,CAACO,IAAI,CAAC,GAAG,CAAC,GAC7B,EAAE;EACN,MAAMC,OAAO,GAAI,YAAWR,WAAY,qBAAoB;EAC5D,MAAMS,KAAK,GAAG,IAAIC,MAAM,CAACF,OAAO,EAAE,IAAI,CAAC;EAEvC,OAAOJ,iBAAiB,CAACD,OAAO,CAACM,KAAK,EAAE,EAAE,CAAC;AAC7C,CAAC;AAED,SAASd,kBAAkB"}
@@ -12,7 +12,7 @@ describe("sanitizeHTML", () => {
12
12
 
13
13
  expect(
14
14
  removeUnwantedHtml(
15
- "<p>String with <b>allowed <i>html</i></b><br /> and <strong>NOT</strong> allowed html</p>",
15
+ "<p>String with <b>allowed <i>html</i></b><br /> and <blink>NOT</blink> allowed html</p>",
16
16
  ),
17
17
  ).toBe(
18
18
  "<p>String with <b>allowed <i>html</i></b><br /> and NOT allowed html</p>",
@@ -28,4 +28,38 @@ describe("sanitizeHTML", () => {
28
28
  ),
29
29
  ).toBe("<p>String <b>not allowed attribute</b> string</p>");
30
30
  });
31
+
32
+ it("Can convert html entities to numerical entities", () => {
33
+ expect(
34
+ removeUnwantedHtml("f&ouml;o &hearts; b&aring;r &#x1D306; baz"),
35
+ ).toBe("f&#246;o &#9829; b&#229;r &#119558; baz");
36
+ });
37
+
38
+ it("Can encode special charcaters to numerical characters", () => {
39
+ expect(removeUnwantedHtml("<p>foo © bar ≠ baz 𝌆 qux bla</p>")).toBe(
40
+ "<p>foo &#169; bar &#8800; baz &#119558; qux bla</p>",
41
+ );
42
+
43
+ expect(
44
+ removeUnwantedHtml(
45
+ "<p>foo &#169; bar &#8800; baz &#119558; qux &#160; bla</p>",
46
+ ),
47
+ ).toBe("<p>foo &#169; bar &#8800; baz &#119558; qux &#160; bla</p>");
48
+ });
49
+
50
+ it("Keeps brackets", () => {
51
+ expect(
52
+ removeUnwantedHtml(
53
+ "The list of children [ Peter, Steven, Susan ] is up to date.",
54
+ ),
55
+ ).toBe("The list of children [ Peter, Steven, Susan ] is up to date.");
56
+ });
57
+
58
+ it("Keeps curly brackets", () => {
59
+ expect(
60
+ removeUnwantedHtml(
61
+ "The list of children { Peter, Steven, Susan } is up to date.",
62
+ ),
63
+ ).toBe("The list of children { Peter, Steven, Susan } is up to date.");
64
+ });
31
65
  });
@@ -12,13 +12,15 @@ var _exceptions = require("../../exceptions");
12
12
  * When path is only one deep better use optional chaining
13
13
  */
14
14
  const properEntityEncoding = html => {
15
- const escapedGt = html.replace(/</g, "[");
16
- const escapedLt = escapedGt.replace(/>/g, "]");
17
- const properEntities = _he.default.encode(_he.default.decode(escapedLt), {
18
- decimal: true
15
+ const htmlDecoded = _he.default.decode(html, {
16
+ decimal: true,
17
+ allowUnsafeSymbols: true
19
18
  });
20
- const unescapedGt = properEntities.replace(/\[/g, "<");
21
- return unescapedGt.replace(/]/g, ">");
19
+ const htmlEncoded = _he.default.encode(htmlDecoded, {
20
+ decimal: true,
21
+ allowUnsafeSymbols: true
22
+ });
23
+ return htmlEncoded;
22
24
  };
23
25
 
24
26
  /**
@@ -12,16 +12,17 @@ type removeUnwantedHtmlOptions = {
12
12
  * When path is only one deep better use optional chaining
13
13
  */
14
14
  const properEntityEncoding = (html: string) => {
15
- const escapedGt = html.replace(/</g, "[");
16
- const escapedLt = escapedGt.replace(/>/g, "]");
17
-
18
- const properEntities = he.encode(he.decode(escapedLt), {
15
+ const htmlDecoded = he.decode(html, {
19
16
  decimal: true,
17
+ allowUnsafeSymbols: true,
20
18
  });
21
19
 
22
- const unescapedGt = properEntities.replace(/\[/g, "<");
20
+ const htmlEncoded = he.encode(htmlDecoded, {
21
+ decimal: true,
22
+ allowUnsafeSymbols: true,
23
+ });
23
24
 
24
- return unescapedGt.replace(/]/g, ">");
25
+ return htmlEncoded;
25
26
  };
26
27
 
27
28
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"sanitizeHtml.js","names":["_he","_interopRequireDefault","require","_exceptions","properEntityEncoding","html","escapedGt","replace","escapedLt","properEntities","he","encode","decode","decimal","unescapedGt","removeUnwantedHtml","options","arguments","length","undefined","allowedTags","IllegalArgumentException","correctEntityHtml","htmlWithoutAttributes","htmlWithCorrectBR","Array","isArray","join","pattern","regex","RegExp","exports"],"sources":["../../../src/utils/helpers/sanitizeHtml.js"],"sourcesContent":["// @flow\nimport he from \"he\";\n\nimport { IllegalArgumentException } from \"../../exceptions\";\n\ntype removeUnwantedHtmlOptions = {\n allowedTags?: Array<string>,\n};\n\n/**\n * Translates html entities to their correct decimal equivalent\n * When path is only one deep better use optional chaining\n */\nconst properEntityEncoding = (html: string) => {\n const escapedGt = html.replace(/</g, \"[\");\n const escapedLt = escapedGt.replace(/>/g, \"]\");\n\n const properEntities = he.encode(he.decode(escapedLt), {\n decimal: true,\n });\n\n const unescapedGt = properEntities.replace(/\\[/g, \"<\");\n\n return unescapedGt.replace(/]/g, \">\");\n};\n\n/**\n * removes unwanted html, this might result in incorrect html, as it removes all html that we don't except,\n * like <b style=\"font-weight: 400\">bold</b> will result in bold</b>\n */\nconst removeUnwantedHtml = (\n html: string,\n options: removeUnwantedHtmlOptions = {\n allowedTags: [\"p\", \"br\", \"b\", \"i\", \"u\", \"strike\"],\n },\n): string => {\n if (typeof html !== \"string\") {\n throw new IllegalArgumentException(\"sanitizeHTML method expects a string\");\n }\n\n const correctEntityHtml = properEntityEncoding(html);\n\n // remove attributes from html elements\n const htmlWithoutAttributes = correctEntityHtml.replace(\n /<(\\w+)(.|[\\r\\n])*?>/gi,\n \"<$1>\",\n );\n\n const htmlWithCorrectBR = htmlWithoutAttributes.replace(\n /<br\\s*>/gi,\n \"<br />\",\n );\n\n // remove not allowed tags\n const allowedTags = Array.isArray(options.allowedTags)\n ? options.allowedTags.join(\"|\")\n : \"\";\n const pattern = `<(?!\\\\/?(${allowedTags})(>|\\\\s\\\\/))[^<]+?>`;\n const regex = new RegExp(pattern, \"gi\");\n\n return htmlWithCorrectBR.replace(regex, \"\");\n};\n\nexport { removeUnwantedHtml };\n"],"mappings":";;;;;;;AACA,IAAAA,GAAA,GAAAC,sBAAA,CAAAC,OAAA;AAEA,IAAAC,WAAA,GAAAD,OAAA;AAMA;AACA;AACA;AACA;AACA,MAAME,oBAAoB,GAAIC,IAAY,IAAK;EAC7C,MAAMC,SAAS,GAAGD,IAAI,CAACE,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC;EACzC,MAAMC,SAAS,GAAGF,SAAS,CAACC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC;EAE9C,MAAME,cAAc,GAAGC,WAAE,CAACC,MAAM,CAACD,WAAE,CAACE,MAAM,CAACJ,SAAS,CAAC,EAAE;IACrDK,OAAO,EAAE;EACX,CAAC,CAAC;EAEF,MAAMC,WAAW,GAAGL,cAAc,CAACF,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;EAEtD,OAAOO,WAAW,CAACP,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC;AACvC,CAAC;;AAED;AACA;AACA;AACA;AACA,MAAMQ,kBAAkB,GAAG,SAAAA,CACzBV,IAAY,EAID;EAAA,IAHXW,OAAkC,GAAAC,SAAA,CAAAC,MAAA,QAAAD,SAAA,QAAAE,SAAA,GAAAF,SAAA,MAAG;IACnCG,WAAW,EAAE,CAAC,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,QAAQ;EAClD,CAAC;EAED,IAAI,OAAOf,IAAI,KAAK,QAAQ,EAAE;IAC5B,MAAM,IAAIgB,oCAAwB,CAAC,sCAAsC,CAAC;EAC5E;EAEA,MAAMC,iBAAiB,GAAGlB,oBAAoB,CAACC,IAAI,CAAC;;EAEpD;EACA,MAAMkB,qBAAqB,GAAGD,iBAAiB,CAACf,OAAO,CACrD,uBAAuB,EACvB,MACF,CAAC;EAED,MAAMiB,iBAAiB,GAAGD,qBAAqB,CAAChB,OAAO,CACrD,WAAW,EACX,QACF,CAAC;;EAED;EACA,MAAMa,WAAW,GAAGK,KAAK,CAACC,OAAO,CAACV,OAAO,CAACI,WAAW,CAAC,GAClDJ,OAAO,CAACI,WAAW,CAACO,IAAI,CAAC,GAAG,CAAC,GAC7B,EAAE;EACN,MAAMC,OAAO,GAAI,YAAWR,WAAY,qBAAoB;EAC5D,MAAMS,KAAK,GAAG,IAAIC,MAAM,CAACF,OAAO,EAAE,IAAI,CAAC;EAEvC,OAAOJ,iBAAiB,CAACjB,OAAO,CAACsB,KAAK,EAAE,EAAE,CAAC;AAC7C,CAAC;AAACE,OAAA,CAAAhB,kBAAA,GAAAA,kBAAA"}
1
+ {"version":3,"file":"sanitizeHtml.js","names":["_he","_interopRequireDefault","require","_exceptions","properEntityEncoding","html","htmlDecoded","he","decode","decimal","allowUnsafeSymbols","htmlEncoded","encode","removeUnwantedHtml","options","arguments","length","undefined","allowedTags","IllegalArgumentException","correctEntityHtml","htmlWithoutAttributes","replace","htmlWithCorrectBR","Array","isArray","join","pattern","regex","RegExp","exports"],"sources":["../../../src/utils/helpers/sanitizeHtml.js"],"sourcesContent":["// @flow\nimport he from \"he\";\n\nimport { IllegalArgumentException } from \"../../exceptions\";\n\ntype removeUnwantedHtmlOptions = {\n allowedTags?: Array<string>,\n};\n\n/**\n * Translates html entities to their correct decimal equivalent\n * When path is only one deep better use optional chaining\n */\nconst properEntityEncoding = (html: string) => {\n const htmlDecoded = he.decode(html, {\n decimal: true,\n allowUnsafeSymbols: true,\n });\n\n const htmlEncoded = he.encode(htmlDecoded, {\n decimal: true,\n allowUnsafeSymbols: true,\n });\n\n return htmlEncoded;\n};\n\n/**\n * removes unwanted html, this might result in incorrect html, as it removes all html that we don't except,\n * like <b style=\"font-weight: 400\">bold</b> will result in bold</b>\n */\nconst removeUnwantedHtml = (\n html: string,\n options: removeUnwantedHtmlOptions = {\n allowedTags: [\"p\", \"br\", \"b\", \"i\", \"u\", \"strike\"],\n },\n): string => {\n if (typeof html !== \"string\") {\n throw new IllegalArgumentException(\"sanitizeHTML method expects a string\");\n }\n\n const correctEntityHtml = properEntityEncoding(html);\n\n // remove attributes from html elements\n const htmlWithoutAttributes = correctEntityHtml.replace(\n /<(\\w+)(.|[\\r\\n])*?>/gi,\n \"<$1>\",\n );\n\n const htmlWithCorrectBR = htmlWithoutAttributes.replace(\n /<br\\s*>/gi,\n \"<br />\",\n );\n\n // remove not allowed tags\n const allowedTags = Array.isArray(options.allowedTags)\n ? options.allowedTags.join(\"|\")\n : \"\";\n const pattern = `<(?!\\\\/?(${allowedTags})(>|\\\\s\\\\/))[^<]+?>`;\n const regex = new RegExp(pattern, \"gi\");\n\n return htmlWithCorrectBR.replace(regex, \"\");\n};\n\nexport { removeUnwantedHtml };\n"],"mappings":";;;;;;;AACA,IAAAA,GAAA,GAAAC,sBAAA,CAAAC,OAAA;AAEA,IAAAC,WAAA,GAAAD,OAAA;AAMA;AACA;AACA;AACA;AACA,MAAME,oBAAoB,GAAIC,IAAY,IAAK;EAC7C,MAAMC,WAAW,GAAGC,WAAE,CAACC,MAAM,CAACH,IAAI,EAAE;IAClCI,OAAO,EAAE,IAAI;IACbC,kBAAkB,EAAE;EACtB,CAAC,CAAC;EAEF,MAAMC,WAAW,GAAGJ,WAAE,CAACK,MAAM,CAACN,WAAW,EAAE;IACzCG,OAAO,EAAE,IAAI;IACbC,kBAAkB,EAAE;EACtB,CAAC,CAAC;EAEF,OAAOC,WAAW;AACpB,CAAC;;AAED;AACA;AACA;AACA;AACA,MAAME,kBAAkB,GAAG,SAAAA,CACzBR,IAAY,EAID;EAAA,IAHXS,OAAkC,GAAAC,SAAA,CAAAC,MAAA,QAAAD,SAAA,QAAAE,SAAA,GAAAF,SAAA,MAAG;IACnCG,WAAW,EAAE,CAAC,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,QAAQ;EAClD,CAAC;EAED,IAAI,OAAOb,IAAI,KAAK,QAAQ,EAAE;IAC5B,MAAM,IAAIc,oCAAwB,CAAC,sCAAsC,CAAC;EAC5E;EAEA,MAAMC,iBAAiB,GAAGhB,oBAAoB,CAACC,IAAI,CAAC;;EAEpD;EACA,MAAMgB,qBAAqB,GAAGD,iBAAiB,CAACE,OAAO,CACrD,uBAAuB,EACvB,MACF,CAAC;EAED,MAAMC,iBAAiB,GAAGF,qBAAqB,CAACC,OAAO,CACrD,WAAW,EACX,QACF,CAAC;;EAED;EACA,MAAMJ,WAAW,GAAGM,KAAK,CAACC,OAAO,CAACX,OAAO,CAACI,WAAW,CAAC,GAClDJ,OAAO,CAACI,WAAW,CAACQ,IAAI,CAAC,GAAG,CAAC,GAC7B,EAAE;EACN,MAAMC,OAAO,GAAI,YAAWT,WAAY,qBAAoB;EAC5D,MAAMU,KAAK,GAAG,IAAIC,MAAM,CAACF,OAAO,EAAE,IAAI,CAAC;EAEvC,OAAOJ,iBAAiB,CAACD,OAAO,CAACM,KAAK,EAAE,EAAE,CAAC;AAC7C,CAAC;AAACE,OAAA,CAAAjB,kBAAA,GAAAA,kBAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@beinformed/ui",
3
- "version": "1.33.0-beta.2",
3
+ "version": "1.33.0-beta.3",
4
4
  "description": "Toolbox for be informed javascript layouts",
5
5
  "license": "SEE LICENSE IN LICENSE.md",
6
6
  "bugs": "http://support.beinformed.com",
@@ -12,7 +12,7 @@ describe("sanitizeHTML", () => {
12
12
 
13
13
  expect(
14
14
  removeUnwantedHtml(
15
- "<p>String with <b>allowed <i>html</i></b><br /> and <strong>NOT</strong> allowed html</p>",
15
+ "<p>String with <b>allowed <i>html</i></b><br /> and <blink>NOT</blink> allowed html</p>",
16
16
  ),
17
17
  ).toBe(
18
18
  "<p>String with <b>allowed <i>html</i></b><br /> and NOT allowed html</p>",
@@ -28,4 +28,38 @@ describe("sanitizeHTML", () => {
28
28
  ),
29
29
  ).toBe("<p>String <b>not allowed attribute</b> string</p>");
30
30
  });
31
+
32
+ it("Can convert html entities to numerical entities", () => {
33
+ expect(
34
+ removeUnwantedHtml("f&ouml;o &hearts; b&aring;r &#x1D306; baz"),
35
+ ).toBe("f&#246;o &#9829; b&#229;r &#119558; baz");
36
+ });
37
+
38
+ it("Can encode special charcaters to numerical characters", () => {
39
+ expect(removeUnwantedHtml("<p>foo © bar ≠ baz 𝌆 qux bla</p>")).toBe(
40
+ "<p>foo &#169; bar &#8800; baz &#119558; qux bla</p>",
41
+ );
42
+
43
+ expect(
44
+ removeUnwantedHtml(
45
+ "<p>foo &#169; bar &#8800; baz &#119558; qux &#160; bla</p>",
46
+ ),
47
+ ).toBe("<p>foo &#169; bar &#8800; baz &#119558; qux &#160; bla</p>");
48
+ });
49
+
50
+ it("Keeps brackets", () => {
51
+ expect(
52
+ removeUnwantedHtml(
53
+ "The list of children [ Peter, Steven, Susan ] is up to date.",
54
+ ),
55
+ ).toBe("The list of children [ Peter, Steven, Susan ] is up to date.");
56
+ });
57
+
58
+ it("Keeps curly brackets", () => {
59
+ expect(
60
+ removeUnwantedHtml(
61
+ "The list of children { Peter, Steven, Susan } is up to date.",
62
+ ),
63
+ ).toBe("The list of children { Peter, Steven, Susan } is up to date.");
64
+ });
31
65
  });
@@ -12,16 +12,17 @@ type removeUnwantedHtmlOptions = {
12
12
  * When path is only one deep better use optional chaining
13
13
  */
14
14
  const properEntityEncoding = (html: string) => {
15
- const escapedGt = html.replace(/</g, "[");
16
- const escapedLt = escapedGt.replace(/>/g, "]");
17
-
18
- const properEntities = he.encode(he.decode(escapedLt), {
15
+ const htmlDecoded = he.decode(html, {
19
16
  decimal: true,
17
+ allowUnsafeSymbols: true,
20
18
  });
21
19
 
22
- const unescapedGt = properEntities.replace(/\[/g, "<");
20
+ const htmlEncoded = he.encode(htmlDecoded, {
21
+ decimal: true,
22
+ allowUnsafeSymbols: true,
23
+ });
23
24
 
24
- return unescapedGt.replace(/]/g, ">");
25
+ return htmlEncoded;
25
26
  };
26
27
 
27
28
  /**