diff --git a/packages/gitbook/src/lib/markdownPage.test.ts b/packages/gitbook/src/lib/markdownPage.test.ts
index f7eb9d9559..45a6ca6423 100644
--- a/packages/gitbook/src/lib/markdownPage.test.ts
+++ b/packages/gitbook/src/lib/markdownPage.test.ts
@@ -1,8 +1,11 @@
-import { describe, expect, it } from 'bun:test';
+import { describe, expect, it, mock } from 'bun:test';
+
+mock.module('server-only', () => ({}));
import type { GitBookAnyContext } from './context';
import { createLinker, linkerWithDirectPagePaths, linkerWithMarkdownPages } from './links';
-import { fromPageMarkdown, toPageMarkdown } from './markdownPage';
+
+const { fromPageMarkdown, toPageMarkdown } = await import('./markdownPage');
const page = {
id: 'designer',
@@ -56,3 +59,57 @@ describe('HTML links in page markdown', () => {
);
});
});
+
+it('rewrites stable file references inside HTML images', async () => {
+ const fileId = 'WNXq6RcD2e4WTRcZEz4f';
+
+ const contextWithFile = {
+ ...context,
+ revision: {
+ pages: [page],
+ files: [
+ {
+ id: fileId,
+ name: 'options-menu.svg',
+ downloadURL: 'https://cdn.example.com/options-menu.svg',
+ },
+ ],
+ },
+ } as unknown as GitBookAnyContext;
+
+ const markdown = `
\n`;
+
+ const tree = await fromPageMarkdown(contextWithFile, {
+ markdown,
+ pagePath: 'workflows',
+ });
+
+ expect(toPageMarkdown(tree)).toContain('src="https://cdn.example.com/options-menu.svg"');
+});
+
+it('rewrites stable file references inside HTML image srcsets', async () => {
+ const fileId = 'WNXq6RcD2e4WTRcZEz4f';
+
+ const contextWithFile = {
+ ...context,
+ revision: {
+ pages: [page],
+ files: [
+ {
+ id: fileId,
+ name: 'options-menu.svg',
+ downloadURL: 'https://cdn.example.com/options-menu.svg',
+ },
+ ],
+ },
+ } as unknown as GitBookAnyContext;
+
+ const markdown = `\n`;
+
+ const tree = await fromPageMarkdown(contextWithFile, {
+ markdown,
+ pagePath: 'workflows',
+ });
+
+ expect(toPageMarkdown(tree)).toContain('srcset="https://cdn.example.com/options-menu.svg"');
+});
diff --git a/packages/gitbook/src/lib/markdownPage.ts b/packages/gitbook/src/lib/markdownPage.ts
index 75590995e7..b0ac514a2b 100644
--- a/packages/gitbook/src/lib/markdownPage.ts
+++ b/packages/gitbook/src/lib/markdownPage.ts
@@ -32,6 +32,7 @@ import { getMarkdownForPagesTree } from '@/routes/llms';
const HTML_ANCHOR_RE = /]*?)href="([^"]*)"([^>]*)>([\s\S]*?)<\/a>/g;
const HTML_ANCHOR_OPEN_RE = /]*?)href="([^"]*)"([^>]*)>/g;
const HTML_SRC_RE = /\bsrc="([^"]*)"/g;
+const HTML_SRCSET_RE = /\bsrcset="([^"]*)"/g;
/**
* Generate a markdown version of a page.
@@ -377,6 +378,12 @@ async function rewriteHTMLRefs(context: GitBookAnyContext, node: Html): Promise<
const resolved = await resolveRefURL(context, src);
return resolved ? `src="${escapeHTML(resolved.url)}"` : full;
});
+
+ node.value = await replaceAsync(node.value, HTML_SRCSET_RE, async (match) => {
+ const [full, srcset = ''] = match;
+ const resolved = await resolveRefURL(context, srcset);
+ return resolved ? `srcset="${escapeHTML(resolved.url)}"` : full;
+ });
}
async function replaceAsync(