feat(editor): add alt text support for images (#2097)

* feat(editor): add alt text support for images
* feat:  extend alt text support to videos and diagrams

---------
Co-authored-by: Philipinho <16838612+Philipinho@users.noreply.github.com>
This commit is contained in:
Olivier Lambert
2026-05-20 16:45:59 +01:00
committed by GitHub
co-authored by Philipinho
parent 66a754c9eb
commit 1c166c4736
12 changed files with 315 additions and 17 deletions
@@ -5,6 +5,13 @@ import { getBasename } from './basename';
// CJS/ESM interop: .default exists in Vite, not in NestJS
const TurndownService = (_TurndownService as any).default || _TurndownService;
function sanitizeMdLinkText(value: string): string {
return value
.replace(/\\/g, '\\\\')
.replace(/([\[\]!])/g, '\\$1')
.replace(/[\r\n]+/g, ' ');
}
export function htmlToMarkdown(html: string): string {
const turndownService = new TurndownService({
headingStyle: 'atx',
@@ -25,6 +32,7 @@ export function htmlToMarkdown(html: string): string {
mathInline,
mathBlock,
iframeEmbed,
image,
video,
]);
return turndownService.turndown(html).replaceAll('<br>', ' ');
@@ -181,6 +189,20 @@ function iframeEmbed(turndownService: _TurndownService) {
});
}
function image(turndownService: _TurndownService) {
turndownService.addRule('image', {
filter: 'img',
replacement: function (_content: string, node: HTMLInputElement) {
const src = node.getAttribute('src') || '';
if (!src) return '';
const alt = sanitizeMdLinkText(node.getAttribute('alt') || '');
const title = node.getAttribute('title') || '';
const titlePart = title ? ' "' + title.replace(/"/g, '\\"') + '"' : '';
return '![' + alt + '](' + src + titlePart + ')';
},
});
}
function video(turndownService: _TurndownService) {
turndownService.addRule('video', {
filter: function (node: HTMLInputElement) {
@@ -188,7 +210,10 @@ function video(turndownService: _TurndownService) {
},
replacement: function (_content: string, node: HTMLInputElement) {
const src = node.getAttribute('src') || '';
const name = getBasename(src) || src;
const ariaLabel = node.getAttribute('aria-label');
const name = sanitizeMdLinkText(
ariaLabel || getBasename(src) || src,
);
return '[' + name + '](' + src + ')';
},
});