From 15441ccb653d07b3bfe45a263a36faaf005703b4 Mon Sep 17 00:00:00 2001 From: "Jan T. Sott" Date: Sun, 11 Jan 2026 22:01:53 +0100 Subject: [PATCH 1/4] chore: install markdown-it plugin for gfm alerts --- webui/package.json | 7 +-- webui/yarn.lock | 117 +++++++++++++++++++++++++++------------------ 2 files changed, 74 insertions(+), 50 deletions(-) diff --git a/webui/package.json b/webui/package.json index c1e58f159..ab5356525 100644 --- a/webui/package.json +++ b/webui/package.json @@ -38,6 +38,7 @@ "dependencies": { "@emotion/react": "^11.11.1", "@emotion/styled": "^11.11.0", + "@mdit/plugin-alert": "^0.22.3", "@mui/base": "^5.0.0-beta.9", "@mui/icons-material": "^5.13.7", "@mui/material": "^5.13.7", @@ -46,8 +47,8 @@ "dompurify": "^3.0.4", "fetch-retry": "^5.0.6", "lodash": "^4.17.21", - "markdown-it": "^13.0.1", - "markdown-it-anchor": "^8.6.7", + "markdown-it": "^14.1.0", + "markdown-it-anchor": "^9.2.0", "prop-types": "^15.8.1", "punycode": "^2.3.0", "react": "^18.2.0", @@ -74,7 +75,7 @@ "@types/dompurify": "^3.0.2", "@types/express": "^4.17.21", "@types/lodash": "^4.14.195", - "@types/markdown-it": "^13.0.1", + "@types/markdown-it": "^14", "@types/mocha": "^10.0.9", "@types/node": "^20.4.0", "@types/prop-types": "^15.7.5", diff --git a/webui/yarn.lock b/webui/yarn.lock index feb379f7d..8108b31c0 100644 --- a/webui/yarn.lock +++ b/webui/yarn.lock @@ -752,6 +752,20 @@ __metadata: languageName: node linkType: hard +"@mdit/plugin-alert@npm:^0.22.3": + version: 0.22.3 + resolution: "@mdit/plugin-alert@npm:0.22.3" + dependencies: + "@types/markdown-it": "npm:^14.1.2" + peerDependencies: + markdown-it: ^14.1.0 + peerDependenciesMeta: + markdown-it: + optional: true + checksum: 10/59215807519c878d56cfdf09a86153b25702dfb08da89489ecdfc23b6dceec864a30f772588e14cb40c439fc18d3fad3fdc13e4a28ae8137859eca8ad7d032b6 + languageName: node + linkType: hard + "@mui/base@npm:5.0.0-beta.40": version: 5.0.0-beta.40 resolution: "@mui/base@npm:5.0.0-beta.40" @@ -1225,10 +1239,10 @@ __metadata: languageName: node linkType: hard -"@types/linkify-it@npm:^3": - version: 3.0.5 - resolution: "@types/linkify-it@npm:3.0.5" - checksum: 10/fac28f41a6e576282300a459d70ea0d33aab70dbb77c3d09582bb0335bb00d862b6de69585792a4d590aae4173fbab0bf28861e2d90ca7b2b1439b52688e9ff6 +"@types/linkify-it@npm:^5": + version: 5.0.0 + resolution: "@types/linkify-it@npm:5.0.0" + checksum: 10/c3919044d4876f9d71d037e861745cd2485c95ac8c36a4fa67b132d4e60eb1d067e123cc7965c9cf5110eea351517d767f0d306af5e9147d6d0af87bc374ddcf languageName: node linkType: hard @@ -1239,20 +1253,20 @@ __metadata: languageName: node linkType: hard -"@types/markdown-it@npm:^13.0.1": - version: 13.0.8 - resolution: "@types/markdown-it@npm:13.0.8" +"@types/markdown-it@npm:^14, @types/markdown-it@npm:^14.1.2": + version: 14.1.2 + resolution: "@types/markdown-it@npm:14.1.2" dependencies: - "@types/linkify-it": "npm:^3" - "@types/mdurl": "npm:^1" - checksum: 10/0e1d2ac44bb6dda78707dcec2eb1bf617a37f1654a4710aef3ae92295db7689349b51900ff76f0ce307c1485eecad52971dfc0ec71fc8b125fc0ddcf05584691 + "@types/linkify-it": "npm:^5" + "@types/mdurl": "npm:^2" + checksum: 10/ca2f239c8d59610b9f936fd40261a6ccf2fa1ae27a21816c031e5712542dcf9ee01e2fe29b31118df90716e11ade54e47d92a498e9b6488800e77ca8827255a2 languageName: node linkType: hard -"@types/mdurl@npm:^1": - version: 1.0.5 - resolution: "@types/mdurl@npm:1.0.5" - checksum: 10/e8e872e8da8f517a9c748b06cec61c947cb73fd3069e8aeb0926670ec5dfac5d30549b3d0f1634950401633e812f9b7263f2d5dbe7e98fce12bcb2c659aa4b21 +"@types/mdurl@npm:^2": + version: 2.0.0 + resolution: "@types/mdurl@npm:2.0.0" + checksum: 10/78746e96c655ceed63db06382da466fd52c7e9dc54d60b12973dfdd110cae06b9439c4b90e17bb8d4461109184b3ea9f3e9f96b3e4bf4aa9fe18b6ac35f283c8 languageName: node linkType: hard @@ -2829,10 +2843,10 @@ __metadata: languageName: node linkType: hard -"entities@npm:~3.0.1": - version: 3.0.1 - resolution: "entities@npm:3.0.1" - checksum: 10/3706e0292ea3f3679720b3d3b1ed6290b164aaeb11116691a922a3acea144503871e0de2170b47671c3b735549b8b7f4741d0d3c2987e8f985ccaa0dd3762eba +"entities@npm:^4.4.0": + version: 4.5.0 + resolution: "entities@npm:4.5.0" + checksum: 10/ede2a35c9bce1aeccd055a1b445d41c75a14a2bb1cd22e242f20cf04d236cdcd7f9c859eb83f76885327bfae0c25bf03303665ee1ce3d47c5927b98b0e3e3d48 languageName: node linkType: hard @@ -4475,12 +4489,12 @@ __metadata: languageName: node linkType: hard -"linkify-it@npm:^4.0.1": - version: 4.0.1 - resolution: "linkify-it@npm:4.0.1" +"linkify-it@npm:^5.0.0": + version: 5.0.0 + resolution: "linkify-it@npm:5.0.0" dependencies: - uc.micro: "npm:^1.0.1" - checksum: 10/d0a786d2e3f02f46b6f4a9b466af9eb936fb68e86b7cd305933d5457b12fdc53a4d0e0b697b02dc2e7d84a51d2425d719598bb7b47af7e01911e492e07a97957 + uc.micro: "npm:^2.0.0" + checksum: 10/ef3b7609dda6ec0c0be8a7b879cea195f0d36387b0011660cd6711bba0ad82137f59b458b7e703ec74f11d88e7c1328e2ad9b855a8500c0ded67461a8c4519e6 languageName: node linkType: hard @@ -4610,28 +4624,29 @@ __metadata: languageName: node linkType: hard -"markdown-it-anchor@npm:^8.6.7": - version: 8.6.7 - resolution: "markdown-it-anchor@npm:8.6.7" +"markdown-it-anchor@npm:^9.2.0": + version: 9.2.0 + resolution: "markdown-it-anchor@npm:9.2.0" peerDependencies: "@types/markdown-it": "*" markdown-it: "*" - checksum: 10/1b061e9c8fb093dab6040725f9f3cedae7da1160a14ee8f29d144534be7ee5c788f02a4de4019f55eb8514cae5f12d350baaa7d08732c26a62abc60e5e66c7f7 + checksum: 10/ececb857a621946be9da08a9abdec98b954fa2f14493261293bf1868146f840d419042be7028317851940ecb7f6d2db318916d13bd38c9d398507c7802d6f70f languageName: node linkType: hard -"markdown-it@npm:^13.0.1": - version: 13.0.2 - resolution: "markdown-it@npm:13.0.2" +"markdown-it@npm:^14.1.0": + version: 14.1.0 + resolution: "markdown-it@npm:14.1.0" dependencies: argparse: "npm:^2.0.1" - entities: "npm:~3.0.1" - linkify-it: "npm:^4.0.1" - mdurl: "npm:^1.0.1" - uc.micro: "npm:^1.0.5" + entities: "npm:^4.4.0" + linkify-it: "npm:^5.0.0" + mdurl: "npm:^2.0.0" + punycode.js: "npm:^2.3.1" + uc.micro: "npm:^2.1.0" bin: - markdown-it: bin/markdown-it.js - checksum: 10/4f48271bbd44d16502efd4148d7c05ca1fb4b50719a07d34c91e8d16f8d065c558fed0fafe07cd13ca5958096bfe295b37cd4f042add7ec49f73c70154e75f58 + markdown-it: bin/markdown-it.mjs + checksum: 10/f34f921be178ed0607ba9e3e27c733642be445e9bb6b1dba88da7aafe8ba1bc5d2f1c3aa8f3fc33b49a902da4e4c08c2feadfafb290b8c7dda766208bb6483a9 languageName: node linkType: hard @@ -4642,10 +4657,10 @@ __metadata: languageName: node linkType: hard -"mdurl@npm:^1.0.1": - version: 1.0.1 - resolution: "mdurl@npm:1.0.1" - checksum: 10/ada367d01c9e81d07328101f187d5bd8641b71f33eab075df4caed935a24fa679e625f07108801d8250a5e4a99e5cd4be7679957a11424a3aa3e740d2bb2d5cb +"mdurl@npm:^2.0.0": + version: 2.0.0 + resolution: "mdurl@npm:2.0.0" + checksum: 10/1720349d4a53e401aa993241368e35c0ad13d816ad0b28388928c58ca9faa0cf755fa45f18ccbf64f4ce54a845a50ddce5c84e4016897b513096a68dac4b0158 languageName: node linkType: hard @@ -5068,6 +5083,7 @@ __metadata: "@emotion/styled": "npm:^11.11.0" "@eslint/eslintrc": "npm:^3.2.0" "@eslint/js": "npm:^9.15.0" + "@mdit/plugin-alert": "npm:^0.22.3" "@mui/base": "npm:^5.0.0-beta.9" "@mui/icons-material": "npm:^5.13.7" "@mui/material": "npm:^5.13.7" @@ -5078,7 +5094,7 @@ __metadata: "@types/dompurify": "npm:^3.0.2" "@types/express": "npm:^4.17.21" "@types/lodash": "npm:^4.14.195" - "@types/markdown-it": "npm:^13.0.1" + "@types/markdown-it": "npm:^14" "@types/mocha": "npm:^10.0.9" "@types/node": "npm:^20.4.0" "@types/prop-types": "npm:^15.7.5" @@ -5102,8 +5118,8 @@ __metadata: express-rate-limit: "npm:^7.4.0" fetch-retry: "npm:^5.0.6" lodash: "npm:^4.17.21" - markdown-it: "npm:^13.0.1" - markdown-it-anchor: "npm:^8.6.7" + markdown-it: "npm:^14.1.0" + markdown-it-anchor: "npm:^9.2.0" mocha: "npm:^11.7.5" prop-types: "npm:^15.8.1" punycode: "npm:^2.3.0" @@ -5481,6 +5497,13 @@ __metadata: languageName: node linkType: hard +"punycode.js@npm:^2.3.1": + version: 2.3.1 + resolution: "punycode.js@npm:2.3.1" + checksum: 10/f0e946d1edf063f9e3d30a32ca86d8ff90ed13ca40dad9c75d37510a04473340cfc98db23a905cc1e517b1e9deb0f6021dce6f422ace235c60d3c9ac47c5a16a + languageName: node + linkType: hard + "punycode@npm:^2.1.0, punycode@npm:^2.3.0": version: 2.3.1 resolution: "punycode@npm:2.3.1" @@ -6607,10 +6630,10 @@ __metadata: languageName: node linkType: hard -"uc.micro@npm:^1.0.1, uc.micro@npm:^1.0.5": - version: 1.0.6 - resolution: "uc.micro@npm:1.0.6" - checksum: 10/6898bb556319a38e9cf175e3628689347bd26fec15fc6b29fa38e0045af63075ff3fea4cf1fdba9db46c9f0cbf07f2348cd8844889dd31ebd288c29fe0d27e7a +"uc.micro@npm:^2.0.0, uc.micro@npm:^2.1.0": + version: 2.1.0 + resolution: "uc.micro@npm:2.1.0" + checksum: 10/37197358242eb9afe367502d4638ac8c5838b78792ab218eafe48287b0ed28aaca268ec0392cc5729f6c90266744de32c06ae938549aee041fc93b0f9672d6b2 languageName: node linkType: hard From a75e9769a46b02e78d42319dddd422c2925f923f Mon Sep 17 00:00:00 2001 From: "Jan T. Sott" Date: Sun, 11 Jan 2026 22:03:56 +0100 Subject: [PATCH 2/4] feat: initialize alert plugin --- webui/src/components/sanitized-markdown.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/webui/src/components/sanitized-markdown.tsx b/webui/src/components/sanitized-markdown.tsx index 9f1796a2b..8e7c0f7f3 100644 --- a/webui/src/components/sanitized-markdown.tsx +++ b/webui/src/components/sanitized-markdown.tsx @@ -9,8 +9,9 @@ ********************************************************************************/ import React, { FunctionComponent, useEffect } from 'react'; -import * as MarkdownIt from 'markdown-it'; +import MarkdownIt from 'markdown-it'; import * as MarkdownItAnchor from 'markdown-it-anchor'; +import { alert } from '@mdit/plugin-alert'; import DOMPurify from 'dompurify'; import { Theme, styled } from '@mui/material/styles'; import linkIcon from './link-icon'; @@ -85,6 +86,9 @@ export const SanitizedMarkdown: FunctionComponent = ({ c linkify: true, typographer: true }); + + markdownIt.use(alert); + if (linkify === undefined || linkify) { const anchor = MarkdownItAnchor.default; markdownIt.use(anchor, { From a2b0d1cbfb947038f522fe554331904d68bb2eb8 Mon Sep 17 00:00:00 2001 From: "Jan T. Sott" Date: Sun, 11 Jan 2026 22:04:13 +0100 Subject: [PATCH 3/4] feat: add styling for alerts --- webui/src/components/sanitized-markdown.tsx | 55 +++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/webui/src/components/sanitized-markdown.tsx b/webui/src/components/sanitized-markdown.tsx index 8e7c0f7f3..0e5bbdd7d 100644 --- a/webui/src/components/sanitized-markdown.tsx +++ b/webui/src/components/sanitized-markdown.tsx @@ -76,6 +76,61 @@ const Markdown = styled('div')(({ theme }: { theme: Theme }) => ({ textAlign: 'start', background: theme.palette.neutral.dark } + }, + '& .markdown-alert': { + padding: '8px 16px', + marginBottom: 16, + borderLeft: '4px solid', + borderRadius: 4, + '& .markdown-alert-title': { + display: 'flex', + alignItems: 'center', + fontWeight: 600, + marginBottom: 4, + '& svg': { + marginRight: 8, + width: 16, + height: 16 + } + }, + '& p': { + margin: 0 + } + }, + '& .markdown-alert-note': { + borderColor: '#2f81f7', + backgroundColor: 'rgba(47, 129, 247, 0.1)', + '& .markdown-alert-title': { + color: '#2f81f7' + } + }, + '& .markdown-alert-tip': { + borderColor: '#3fb950', + backgroundColor: 'rgba(63, 185, 80, 0.1)', + '& .markdown-alert-title': { + color: '#3fb950' + } + }, + '& .markdown-alert-important': { + borderColor: '#a371f7', + backgroundColor: 'rgba(163, 113, 247, 0.1)', + '& .markdown-alert-title': { + color: '#a371f7' + } + }, + '& .markdown-alert-warning': { + borderColor: '#d29922', + backgroundColor: 'rgba(210, 153, 34, 0.1)', + '& .markdown-alert-title': { + color: '#d29922' + } + }, + '& .markdown-alert-caution': { + borderColor: '#f85149', + backgroundColor: 'rgba(248, 81, 73, 0.1)', + '& .markdown-alert-title': { + color: '#f85149' + } } })); From 031d1aee461ec4b56524bb27397ad7e778fbe919 Mon Sep 17 00:00:00 2001 From: Thomas Neidhart Date: Mon, 12 Jan 2026 10:32:24 +0100 Subject: [PATCH 4/4] add changelog entry and add icons to alerts --- webui/CHANGELOG.md | 1 + webui/src/components/sanitized-markdown.tsx | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/webui/CHANGELOG.md b/webui/CHANGELOG.md index 61da2a17a..be42dd450 100644 --- a/webui/CHANGELOG.md +++ b/webui/CHANGELOG.md @@ -7,6 +7,7 @@ This change log covers only the frontend library (webui) of Open VSX. ### Added - Support removing reviews by admins ([#1403](https://github.com/eclipse/openvsx/pull/1403)) +- Support for GitHub flavored markdown alerts ([#1535](https://github.com/eclipse/openvsx/pull/1535)) ## [v0.17.1] (Jan. 2026) diff --git a/webui/src/components/sanitized-markdown.tsx b/webui/src/components/sanitized-markdown.tsx index 0e5bbdd7d..7d2e07de3 100644 --- a/webui/src/components/sanitized-markdown.tsx +++ b/webui/src/components/sanitized-markdown.tsx @@ -93,6 +93,12 @@ const Markdown = styled('div')(({ theme }: { theme: Theme }) => ({ height: 16 } }, + '& .markdown-alert-title:before': { + content: " ", + width: '16px', + height: '16px', + marginRight: '8px', + }, '& p': { margin: 0 } @@ -102,6 +108,9 @@ const Markdown = styled('div')(({ theme }: { theme: Theme }) => ({ backgroundColor: 'rgba(47, 129, 247, 0.1)', '& .markdown-alert-title': { color: '#2f81f7' + }, + '& .markdown-alert-title::before': { + content: `url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill='%232f81f7' d='M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8Zm8-6.5a6.5 6.5 0 1 0 0 13 6.5 6.5 0 0 0 0-13ZM6.5 7.75A.75.75 0 0 1 7.25 7h1a.75.75 0 0 1 .75.75v2.75h.25a.75.75 0 0 1 0 1.5h-2a.75.75 0 0 1 0-1.5h.25v-2h-.25a.75.75 0 0 1-.75-.75ZM8 6a1 1 0 1 1 0-2 1 1 0 0 1 0 2Z'/%3E%3C/svg%3E")` } }, '& .markdown-alert-tip': { @@ -109,6 +118,9 @@ const Markdown = styled('div')(({ theme }: { theme: Theme }) => ({ backgroundColor: 'rgba(63, 185, 80, 0.1)', '& .markdown-alert-title': { color: '#3fb950' + }, + '& .markdown-alert-title::before': { + content: `url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill='%233fb950' d='M8 1.5c-2.363 0-4 1.69-4 3.75 0 .984.424 1.625.984 2.304l.214.253c.223.264.47.556.673.848.284.411.537.896.621 1.49a.75.75 0 0 1-1.484.211c-.04-.282-.163-.547-.37-.847a8.456 8.456 0 0 0-.542-.68c-.084-.1-.173-.205-.268-.32C3.201 7.75 2.5 6.766 2.5 5.25 2.5 2.31 4.863 0 8 0s5.5 2.31 5.5 5.25c0 1.516-.701 2.5-1.328 3.259-.095.115-.184.22-.268.319-.207.245-.383.453-.541.681-.208.3-.33.565-.37.847a.751.751 0 0 1-1.485-.212c.084-.593.337-1.078.621-1.489.203-.292.45-.584.673-.848.075-.088.147-.173.213-.253.561-.679.985-1.32.985-2.304 0-2.06-1.637-3.75-4-3.75ZM5.75 12h4.5a.75.75 0 0 1 0 1.5h-4.5a.75.75 0 0 1 0-1.5ZM6 15.25a.75.75 0 0 1 .75-.75h2.5a.75.75 0 0 1 0 1.5h-2.5a.75.75 0 0 1-.75-.75Z'/%3E%3C/svg%3E")` } }, '& .markdown-alert-important': { @@ -116,6 +128,9 @@ const Markdown = styled('div')(({ theme }: { theme: Theme }) => ({ backgroundColor: 'rgba(163, 113, 247, 0.1)', '& .markdown-alert-title': { color: '#a371f7' + }, + '& .markdown-alert-title::before': { + content: `url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill='%23a371f7' d='M0 1.75C0 .784.784 0 1.75 0h12.5C15.216 0 16 .784 16 1.75v9.5A1.75 1.75 0 0 1 14.25 13H8.06l-2.573 2.573A1.458 1.458 0 0 1 3 14.543V13H1.75A1.75 1.75 0 0 1 0 11.25Zm1.75-.25a.25.25 0 0 0-.25.25v9.5c0 .138.112.25.25.25h2a.75.75 0 0 1 .75.75v2.19l2.72-2.72a.749.749 0 0 1 .53-.22h6.5a.25.25 0 0 0 .25-.25v-9.5a.25.25 0 0 0-.25-.25Zm7 2.25v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 9a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z'/%3E%3C/svg%3E ")` } }, '& .markdown-alert-warning': { @@ -123,6 +138,9 @@ const Markdown = styled('div')(({ theme }: { theme: Theme }) => ({ backgroundColor: 'rgba(210, 153, 34, 0.1)', '& .markdown-alert-title': { color: '#d29922' + }, + '& .markdown-alert-title::before': { + content: `url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill='%23d29922' d='M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z'/%3E%3C/svg%3E")` } }, '& .markdown-alert-caution': { @@ -130,6 +148,9 @@ const Markdown = styled('div')(({ theme }: { theme: Theme }) => ({ backgroundColor: 'rgba(248, 81, 73, 0.1)', '& .markdown-alert-title': { color: '#f85149' + }, + '& .markdown-alert-title::before': { + content: `url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill='%23f85149' d='M4.47.22A.749.749 0 0 1 5 0h6c.199 0 .389.079.53.22l4.25 4.25c.141.14.22.331.22.53v6a.749.749 0 0 1-.22.53l-4.25 4.25A.749.749 0 0 1 11 16H5a.749.749 0 0 1-.53-.22L.22 11.53A.749.749 0 0 1 0 11V5c0-.199.079-.389.22-.53Zm.84 1.28L1.5 5.31v5.38l3.81 3.81h5.38l3.81-3.81V5.31L10.69 1.5ZM8 4a.75.75 0 0 1 .75.75v3.5a.75.75 0 0 1-1.5 0v-3.5A.75.75 0 0 1 8 4Zm0 8a1 1 0 1 1 0-2 1 1 0 0 1 0 2Z'/%3E%3C/svg%3E")` } } }));