From 3931631c07d08056f3ac6ec200238d9b2e351deb Mon Sep 17 00:00:00 2001 From: zonemeen Date: Sat, 16 Dec 2023 15:28:10 +0800 Subject: [PATCH] feat: support custom image lazy loading --- __tests__/e2e/.vitepress/config.ts | 3 +++ __tests__/e2e/markdown-extensions/index.md | 4 ++++ .../markdown-extensions/markdown-extensions.test.ts | 9 ++++++++- docs/guide/markdown.md | 13 +++++++++++++ src/node/markdown/markdown.ts | 7 ++++++- src/node/markdown/plugins/image.ts | 5 ++++- 6 files changed, 38 insertions(+), 3 deletions(-) diff --git a/__tests__/e2e/.vitepress/config.ts b/__tests__/e2e/.vitepress/config.ts index 84fc64f2..9c02cc26 100644 --- a/__tests__/e2e/.vitepress/config.ts +++ b/__tests__/e2e/.vitepress/config.ts @@ -86,6 +86,9 @@ const sidebar: DefaultTheme.Config['sidebar'] = { export default defineConfig({ title: 'Example', description: 'An example app using VitePress.', + markdown: { + lazyLoading: true + }, themeConfig: { sidebar, search: { diff --git a/__tests__/e2e/markdown-extensions/index.md b/__tests__/e2e/markdown-extensions/index.md index 36d6c028..47246c18 100644 --- a/__tests__/e2e/markdown-extensions/index.md +++ b/__tests__/e2e/markdown-extensions/index.md @@ -196,3 +196,7 @@ export default config ## Markdown File Inclusion with Range without End + +## Image Lazy Loading + +![vitepress logo](/vitepress.png) \ No newline at end of file diff --git a/__tests__/e2e/markdown-extensions/markdown-extensions.test.ts b/__tests__/e2e/markdown-extensions/markdown-extensions.test.ts index 42a89891..23b8b1a0 100644 --- a/__tests__/e2e/markdown-extensions/markdown-extensions.test.ts +++ b/__tests__/e2e/markdown-extensions/markdown-extensions.test.ts @@ -65,7 +65,7 @@ describe('Table of Contents', () => { test('render toc', async () => { const items = page.locator('#table-of-contents + nav ul li') const count = await items.count() - expect(count).toBe(35) + expect(count).toBe(36) }) }) @@ -280,3 +280,10 @@ describe('Markdown File Inclusion', () => { expect(await p.textContent()).not.toContain('title') }) }) + +describe('Image Lazy Loading', () => { + test('render loading="lazy" in the tag', async () => { + const img = page.locator('#image-lazy-loading + p img') + expect(await img.getAttribute('loading')).toBe('lazy') + }) +}) diff --git a/docs/guide/markdown.md b/docs/guide/markdown.md index c7fcbd47..132432b2 100644 --- a/docs/guide/markdown.md +++ b/docs/guide/markdown.md @@ -847,6 +847,19 @@ $$ x = {-b \pm \sqrt{b^2-4ac} \over 2a} $$ | $\nabla \times \vec{\mathbf{E}}\, +\, \frac1c\, \frac{\partial\vec{\mathbf{B}}}{\partial t} = \vec{\mathbf{0}}$ | curl of $\vec{\mathbf{E}}$ is proportional to the rate of change of $\vec{\mathbf{B}}$ | | $\nabla \times \vec{\mathbf{B}} -\, \frac1c\, \frac{\partial\vec{\mathbf{E}}}{\partial t} = \frac{4\pi}{c}\vec{\mathbf{j}} \nabla \cdot \vec{\mathbf{E}} = 4 \pi \rho$ | _wha?_ | +## Image Lazy Loading + +You can enable lazy loading for each image tag in the content via config: + +```js +// image lazy loading is disabled by default +export default { + markdown: { + lazyLoading: true + } +} +``` + ## Advanced Configuration VitePress uses [markdown-it](https://github.com/markdown-it/markdown-it) as the Markdown renderer. A lot of the extensions above are implemented via custom plugins. You can further customize the `markdown-it` instance using the `markdown` option in `.vitepress/config.js`: diff --git a/src/node/markdown/markdown.ts b/src/node/markdown/markdown.ts index c549901d..e1fbf058 100644 --- a/src/node/markdown/markdown.ts +++ b/src/node/markdown/markdown.ts @@ -165,6 +165,11 @@ export interface MarkdownOptions extends MarkdownIt.Options { * @see https://vitepress.dev/guide/markdown#math-equations */ math?: boolean | any + /** + * Support native lazy loading for the tag. + * @default false + */ + lazyLoading?: boolean } export type MarkdownRenderer = MarkdownIt @@ -197,7 +202,7 @@ export const createMarkdownRenderer = async ( .use(preWrapperPlugin, { hasSingleTheme }) .use(snippetPlugin, srcDir) .use(containerPlugin, { hasSingleTheme }, options.container) - .use(imagePlugin) + .use(imagePlugin, options?.lazyLoading) .use( linkPlugin, { target: '_blank', rel: 'noreferrer', ...options.externalLinks }, diff --git a/src/node/markdown/plugins/image.ts b/src/node/markdown/plugins/image.ts index 06d1a360..7fcd8bcd 100644 --- a/src/node/markdown/plugins/image.ts +++ b/src/node/markdown/plugins/image.ts @@ -3,7 +3,7 @@ import type MarkdownIt from 'markdown-it' import { EXTERNAL_URL_RE } from '../../shared' -export const imagePlugin = (md: MarkdownIt) => { +export const imagePlugin = (md: MarkdownIt, lazyLoading: boolean) => { const imageRule = md.renderer.rules.image! md.renderer.rules.image = (tokens, idx, options, env, self) => { const token = tokens[idx] @@ -12,6 +12,9 @@ export const imagePlugin = (md: MarkdownIt) => { if (!/^\.?\//.test(url)) url = './' + url token.attrSet('src', decodeURIComponent(url)) } + if (lazyLoading) { + token.attrSet('loading', 'lazy') + } return imageRule(tokens, idx, options, env, self) } }