From 8a0ee14a031e93931ed4c7802da350a675d52477 Mon Sep 17 00:00:00 2001 From: Benoit Richter Date: Tue, 21 Oct 2025 16:26:12 +0200 Subject: [PATCH 1/4] feat(MarkdownText): Support images --- .../stories/MarkdownText.stories.tsx | 13 +++++++++++++ .../src/components/MarkdownText/MarkdownText.svelte | 1 + 2 files changed, 14 insertions(+) diff --git a/packages/visualizations-react/stories/MarkdownText.stories.tsx b/packages/visualizations-react/stories/MarkdownText.stories.tsx index 3ef9a017..ee175c8e 100644 --- a/packages/visualizations-react/stories/MarkdownText.stories.tsx +++ b/packages/visualizations-react/stories/MarkdownText.stories.tsx @@ -59,3 +59,16 @@ Link.args = { }, options: {}, }; + +export const Image = Template.bind({}); +Image.args = { + data: { + value: ` + I'd like to show an image: + ![My image](https://hub.huwise.com/static/ods/imgv4/huwise-black.svg "Huwise logo") + + Thanks! + `, + }, + options: {}, +}; \ No newline at end of file diff --git a/packages/visualizations/src/components/MarkdownText/MarkdownText.svelte b/packages/visualizations/src/components/MarkdownText/MarkdownText.svelte index f23ebaf5..93e4999c 100644 --- a/packages/visualizations/src/components/MarkdownText/MarkdownText.svelte +++ b/packages/visualizations/src/components/MarkdownText/MarkdownText.svelte @@ -43,6 +43,7 @@ }) .enable([ 'hr', + 'image', 'list', 'heading', 'emphasis', // bold & italic From 0c567f78efb2e1eabff97d6e0e154316f7c1c589 Mon Sep 17 00:00:00 2001 From: Benoit Richter Date: Tue, 21 Oct 2025 16:41:43 +0200 Subject: [PATCH 2/4] chore(MarkdownText): Upgrade MarkdownIt --- package-lock.json | 92 +++++++++++++++++----------- packages/visualizations/package.json | 2 +- 2 files changed, 56 insertions(+), 38 deletions(-) diff --git a/package-lock.json b/package-lock.json index 881a282f..bc8c2dad 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3797,7 +3797,6 @@ "arm64" ], "dev": true, - "license": "MIT", "optional": true, "os": [ "darwin" @@ -3809,11 +3808,12 @@ }, "node_modules/@nrwl/devkit/node_modules/@nx/nx-darwin-x64": { "version": "18.3.5", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-18.3.5.tgz", + "integrity": "sha512-Drn6jOG237AD/s6OWPt06bsMj0coGKA5Ce1y5gfLhptOGk4S4UPE/Ay5YCjq+/yhTo1gDHzCHxH0uW2X9MN9Fg==", "cpu": [ "x64" ], "dev": true, - "license": "MIT", "optional": true, "os": [ "darwin" @@ -3831,7 +3831,6 @@ "x64" ], "dev": true, - "license": "MIT", "optional": true, "os": [ "freebsd" @@ -3849,7 +3848,6 @@ "arm" ], "dev": true, - "license": "MIT", "optional": true, "os": [ "linux" @@ -3867,7 +3865,6 @@ "arm64" ], "dev": true, - "license": "MIT", "optional": true, "os": [ "linux" @@ -3885,7 +3882,6 @@ "arm64" ], "dev": true, - "license": "MIT", "optional": true, "os": [ "linux" @@ -3903,7 +3899,6 @@ "x64" ], "dev": true, - "license": "MIT", "optional": true, "os": [ "linux" @@ -3921,7 +3916,6 @@ "x64" ], "dev": true, - "license": "MIT", "optional": true, "os": [ "linux" @@ -3939,7 +3933,6 @@ "arm64" ], "dev": true, - "license": "MIT", "optional": true, "os": [ "win32" @@ -3957,7 +3950,6 @@ "x64" ], "dev": true, - "license": "MIT", "optional": true, "os": [ "win32" @@ -3968,9 +3960,10 @@ } }, "node_modules/@nrwl/devkit/node_modules/brace-expansion": { - "version": "2.0.1", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "dev": true, - "license": "MIT", "peer": true, "dependencies": { "balanced-match": "^1.0.0" @@ -3978,8 +3971,9 @@ }, "node_modules/@nrwl/devkit/node_modules/cliui": { "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", "dev": true, - "license": "ISC", "peer": true, "dependencies": { "string-width": "^4.2.0", @@ -3992,8 +3986,9 @@ }, "node_modules/@nrwl/devkit/node_modules/json5": { "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true, - "license": "MIT", "peer": true, "bin": { "json5": "lib/cli.js" @@ -4004,8 +3999,9 @@ }, "node_modules/@nrwl/devkit/node_modules/lines-and-columns": { "version": "2.0.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-2.0.4.tgz", + "integrity": "sha512-wM1+Z03eypVAVUCE7QdSqpVIvelbOakn1M0bPDoA4SGWPx3sNDVUiMo3L6To6WWGClB7VyXnhQ4Sn7gxiJbE6A==", "dev": true, - "license": "MIT", "peer": true, "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" @@ -4013,8 +4009,9 @@ }, "node_modules/@nrwl/devkit/node_modules/minimatch": { "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", "dev": true, - "license": "ISC", "peer": true, "dependencies": { "brace-expansion": "^2.0.1" @@ -4028,9 +4025,10 @@ }, "node_modules/@nrwl/devkit/node_modules/nx": { "version": "18.3.5", + "resolved": "https://registry.npmjs.org/nx/-/nx-18.3.5.tgz", + "integrity": "sha512-wWcvwoTgiT5okdrG0RIWm1tepC17bDmSpw+MrOxnjfBjARQNTURkiq4U6cxjCVsCxNHxCrlAaBSQLZeBgJZTzQ==", "dev": true, "hasInstallScript": true, - "license": "MIT", "peer": true, "dependencies": { "@nrwl/tao": "18.3.5", @@ -4099,8 +4097,9 @@ }, "node_modules/@nrwl/devkit/node_modules/ora": { "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.3.0.tgz", + "integrity": "sha512-zAKMgGXUim0Jyd6CXK9lraBnD3H5yPGBPPOkC23a2BG6hsm4Zu6OQSjQuEtV0BHDf4aKHcUFvJiGRrFuW3MG8g==", "dev": true, - "license": "MIT", "peer": true, "dependencies": { "bl": "^4.0.3", @@ -4121,8 +4120,9 @@ }, "node_modules/@nrwl/devkit/node_modules/strip-bom": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", "dev": true, - "license": "MIT", "peer": true, "engines": { "node": ">=4" @@ -4138,8 +4138,9 @@ }, "node_modules/@nrwl/devkit/node_modules/tsconfig-paths": { "version": "4.2.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", + "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==", "dev": true, - "license": "MIT", "peer": true, "dependencies": { "json5": "^2.2.2", @@ -17834,10 +17835,11 @@ "license": "MIT" }, "node_modules/linkify-it": { - "version": "3.0.3", - "license": "MIT", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", "dependencies": { - "uc.micro": "^1.0.1" + "uc.micro": "^2.0.0" } }, "node_modules/listr": { @@ -18507,17 +18509,19 @@ } }, "node_modules/markdown-it": { - "version": "12.3.2", - "license": "MIT", + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", + "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", "dependencies": { "argparse": "^2.0.1", - "entities": "~2.1.0", - "linkify-it": "^3.0.1", - "mdurl": "^1.0.1", - "uc.micro": "^1.0.5" + "entities": "^4.4.0", + "linkify-it": "^5.0.0", + "mdurl": "^2.0.0", + "punycode.js": "^2.3.1", + "uc.micro": "^2.1.0" }, "bin": { - "markdown-it": "bin/markdown-it.js" + "markdown-it": "bin/markdown-it.mjs" } }, "node_modules/markdown-it-link-attributes": { @@ -18529,8 +18533,12 @@ "license": "MIT" }, "node_modules/markdown-it/node_modules/entities": { - "version": "2.1.0", - "license": "BSD-2-Clause", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "engines": { + "node": ">=0.12" + }, "funding": { "url": "https://github.com/fb55/entities?sponsor=1" } @@ -18625,8 +18633,9 @@ "license": "CC0-1.0" }, "node_modules/mdurl": { - "version": "1.0.1", - "license": "MIT" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==" }, "node_modules/media-typer": { "version": "0.3.0", @@ -22129,6 +22138,14 @@ "node": ">=6" } }, + "node_modules/punycode.js": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", + "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", + "engines": { + "node": ">=6" + } + }, "node_modules/puppeteer-core": { "version": "2.1.1", "dev": true, @@ -25714,8 +25731,9 @@ "license": "MIT" }, "node_modules/uc.micro": { - "version": "1.0.6", - "license": "MIT" + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", + "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==" }, "node_modules/ufo": { "version": "1.4.0", @@ -27104,7 +27122,7 @@ "lodash": "^4.17.21", "luxon": "^2.5.0", "maplibre-gl": "^3.6.2", - "markdown-it": "^12.0.4", + "markdown-it": "14.1.0", "markdown-it-link-attributes": "^3.0.0", "markdown-it-mark": "^3.0.1", "sass": "^1.70.0", diff --git a/packages/visualizations/package.json b/packages/visualizations/package.json index 780ebf67..2b323e2a 100644 --- a/packages/visualizations/package.json +++ b/packages/visualizations/package.json @@ -103,7 +103,7 @@ "lodash": "^4.17.21", "luxon": "^2.5.0", "maplibre-gl": "^3.6.2", - "markdown-it": "^12.0.4", + "markdown-it": "14.1.0", "markdown-it-link-attributes": "^3.0.0", "markdown-it-mark": "^3.0.1", "sass": "^1.70.0", From 7522995713448972c1eed8677217aba5bbf35a61 Mon Sep 17 00:00:00 2001 From: Benoit Richter Date: Tue, 21 Oct 2025 17:05:47 +0200 Subject: [PATCH 3/4] chore(MarkdownText): Update tests --- .../test/MarkdownText.test.tsx | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/visualizations-react/test/MarkdownText.test.tsx b/packages/visualizations-react/test/MarkdownText.test.tsx index 5048700e..08b35263 100644 --- a/packages/visualizations-react/test/MarkdownText.test.tsx +++ b/packages/visualizations-react/test/MarkdownText.test.tsx @@ -10,19 +10,22 @@ describe('MarkdownText', () => { }); it('renders markdown supported syntax', () => { - const { getByText, queryByText } = render( - + const { getByText, queryByText, getByRole } = render( + ); + // Bold getByText('Bold'); expect(queryByText('**Bold**')).not.toBeInTheDocument(); + + // Image + getByRole('img', { name: 'alt text' }); + expect(queryByText('[alt text]')).not.toBeInTheDocument(); }); it("doesn't transform unsupported syntax", () => { - const value = - 'Hello bold\n\n```code```\n\n`inline`\n\n' + - '![alt text](image.jpg)\n\n~~strikethrough~~'; - const { getByText, getByRole } = render(); + const value = 'Hello bold\n\n```code```\n\n`inline`\n\n~~strikethrough~~'; + const { getByText } = render(); // HTML should be kept as-is (and encoded) getByText('Hello bold'); @@ -31,9 +34,6 @@ describe('MarkdownText', () => { getByText('```code```'); getByText('`inline`'); - // Image (should be parsed as a link, not as an image tag) - getByRole('link', { name: 'alt text' }); - // Strikethrough getByText('~~strikethrough~~'); }); From 295ec6f0ee742dfe60a955cb76e9669e167bcf94 Mon Sep 17 00:00:00 2001 From: Benoit Richter Date: Wed, 22 Oct 2025 09:45:25 +0200 Subject: [PATCH 4/4] Update vector tiles URL for stories --- packages/visualizations-react/stories/Map/data.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/visualizations-react/stories/Map/data.ts b/packages/visualizations-react/stories/Map/data.ts index ae2e5cc6..ccfca415 100644 --- a/packages/visualizations-react/stories/Map/data.ts +++ b/packages/visualizations-react/stories/Map/data.ts @@ -22,8 +22,8 @@ export const dataReg: ChoroplethDataValue[] = [ ]; export const shapesTiles: ChoroplethShapeVectorTilesValue = { - url: 'https://static.opendatasoft.com/vector-tiles/fr_40_region_2021/{z}/{x}/{y}.pbf', - layer: 'fr_40_region_2021', + url: 'https://static.opendatasoft.com/vector-tiles/fr_40_region_2024/{z}/{x}/{y}.pbf', + layer: 'fr_40_region_2024', key: 'reg_code', label: 'reg_code', };