mirror of
https://github.com/immich-app/static-pages.git
synced 2026-09-30 13:23:05 +08:00
fix: markdown images (#798)
This commit is contained in:
@@ -98,6 +98,49 @@ describe(svelteMarkdownPreprocess.name, () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('svelte components', () => {
|
||||
const render = async (content: string) => {
|
||||
const result = await svelteMarkdownPreprocess().markup({ filename: 'test.md', content });
|
||||
return result?.code ?? '';
|
||||
};
|
||||
|
||||
it('should render a component that owns its line', async () => {
|
||||
await expect(render('<Markdown.Image src="a.webp" />')).resolves.toContain('<Markdown.Image src="a.webp" />');
|
||||
});
|
||||
|
||||
it('should render sibling components sharing a line', async () => {
|
||||
const code = await render('<Markdown.Image src="a.webp" /> <Markdown.Image src="b.webp" />');
|
||||
|
||||
expect(code).toContain('<Markdown.Image src="a.webp" />');
|
||||
expect(code).toContain('<Markdown.Image src="b.webp" />');
|
||||
expect(code).not.toContain('<');
|
||||
});
|
||||
|
||||
it('should render a component followed by prose on the same line', async () => {
|
||||
const code = await render('<Markdown.Image src="a.webp" />In order to use this');
|
||||
|
||||
expect(code).toContain('<Markdown.Image src="a.webp" />');
|
||||
expect(code).toContain('<Markdown.Paragraph>In order to use this</Markdown.Paragraph>');
|
||||
});
|
||||
|
||||
it('should render a component preceded by prose on the same line', async () => {
|
||||
await expect(render('Look at this <Markdown.Image src="a.webp" />')).resolves.toContain(
|
||||
'<Markdown.Paragraph>Look at this <Markdown.Image src="a.webp" /></Markdown.Paragraph>',
|
||||
);
|
||||
});
|
||||
|
||||
it('should import a relative source from a component sharing a line', async () => {
|
||||
const code = await render('Look at this <Markdown.Image src="./img/example.webp" />');
|
||||
|
||||
expect(code).toContain(`import __image_0 from './img/example.webp';`);
|
||||
expect(code).toContain('<Markdown.Image src={__image_0} />');
|
||||
});
|
||||
|
||||
it('should leave a component inside a code fence as code', async () => {
|
||||
await expect(render('```svelte\n<Markdown.Image src="a.webp" />\n```')).resolves.toContain('<Markdown.Code');
|
||||
});
|
||||
});
|
||||
|
||||
describe('images', () => {
|
||||
it('should import relative images so vite can optimize them', async () => {
|
||||
const result = await svelteMarkdownPreprocess().markup({
|
||||
|
||||
@@ -27,7 +27,8 @@ const renderAlert = (
|
||||
) => `<Markdown.Alert${createAttributes({ variant, title })}>${parser.parse(tokens)}</Markdown.Alert>\n`;
|
||||
|
||||
// Marked reads a dotted tag as text, so a component like `<Markdown.Image />` needs its own rule.
|
||||
const SVELTE_COMPONENT_REGEX = /^<[A-Z]\w*\.\w+\b[^>]*\/>[ \t]*(?:\n+|$)/;
|
||||
const SVELTE_COMPONENT_REGEX = /^<[A-Z]\w*\.\w+\b[^>]*\/>/;
|
||||
const SVELTE_COMPONENT_BLOCK_REGEX = new RegExp(String.raw`${SVELTE_COMPONENT_REGEX.source}[ \t]*\n?`);
|
||||
|
||||
const normalizeText = (text: string) => escapeHtml(emojify(text));
|
||||
|
||||
@@ -75,9 +76,16 @@ export const markedSvelte = (): MarkedExtension => ({
|
||||
},
|
||||
|
||||
html(src) {
|
||||
const match = SVELTE_COMPONENT_REGEX.exec(src);
|
||||
const match = SVELTE_COMPONENT_BLOCK_REGEX.exec(src);
|
||||
return match ? { type: 'html', raw: match[0], text: `${match[0].trim()}\n`, pre: false, block: true } : false;
|
||||
},
|
||||
|
||||
tag(src) {
|
||||
const match = SVELTE_COMPONENT_REGEX.exec(src);
|
||||
return match
|
||||
? { type: 'html', raw: match[0], text: match[0], inLink: false, inRawBlock: false, block: false }
|
||||
: false;
|
||||
},
|
||||
},
|
||||
|
||||
extensions: [
|
||||
|
||||
Reference in New Issue
Block a user