fix(theme): preserve alt overrides for themed images (#5457)

pull/5463/head
lllleolin-max 1 week ago committed by GitHub
parent 23361e2493
commit 61c0cbbefe
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,38 @@
describe('themeable image alt overrides', () => {
beforeEach(async () => {
await goto('/theme-image/')
})
test.each(['light', 'dark'])('uses the alt prop in %s mode', async (mode) => {
await page.evaluate((mode) => {
document.documentElement.classList.toggle('dark', mode === 'dark')
}, mode)
expect(
await page.locator('.image-override img:visible').getAttribute('alt')
).toBe('Override description')
expect(
await page.locator('.image-decorative img:visible').getAttribute('alt')
).toBe('')
expect(
await page.locator('.image-fallback img:visible').getAttribute('alt')
).toBe('Image description')
})
test('updates both images when the alt prop changes', async () => {
const descriptions = () =>
page
.locator('.image-override img')
.evaluateAll((images) =>
images.map((image) => image.getAttribute('alt'))
)
await page.getByRole('button', { name: 'Update description' }).click()
await expect
.poll(descriptions)
.toEqual(['Updated description', 'Updated description'])
await page.getByRole('button', { name: 'Clear description' }).click()
await expect.poll(descriptions).toEqual(['', ''])
})
})

@ -0,0 +1,28 @@
<script setup>
import { ref } from 'vue'
import { VPImage } from 'vitepress/theme'
const description = ref('Override description')
const image = {
light: '/pwa_light.svg',
dark: '/pwa_dark.svg',
alt: 'Image description'
}
</script>
# Themeable image descriptions
<div class="image-override">
<VPImage :image :alt="description" />
</div>
<div class="image-decorative">
<VPImage :image alt="" />
</div>
<div class="image-fallback">
<VPImage :image />
</div>
<button @click="description = 'Updated description'">Update description</button>
<button @click="description = ''">Clear description</button>

@ -0,0 +1,41 @@
// @ts-expect-error the unit typecheck uses tsc; Vite compiles this SFC at runtime
import VPImage from 'client/theme-default/components/VPImage.vue'
import { createSSRApp } from 'vue'
import { renderToString } from 'vue/server-renderer'
vi.mock('vitepress', () => ({ withBase: (path: string) => path }))
const images = [
{ name: 'string', image: 'logo.svg', fallback: '', count: 1 },
{
name: 'single source',
image: { src: 'logo.svg', alt: 'Image description' },
fallback: 'Image description',
count: 1
},
{
name: 'themed sources',
image: { light: 'light.svg', dark: 'dark.svg', alt: 'Image description' },
fallback: 'Image description',
count: 2
},
{
name: 'themed sources without alt',
image: { light: 'light.svg', dark: 'dark.svg' },
fallback: '',
count: 2
}
]
describe.each(images)('VPImage with $name', ({ image, fallback, count }) => {
test.each(['Override description', '', undefined])(
'respects the alt prop %j',
async (alt) => {
const html = await renderToString(createSSRApp(VPImage, { image, alt }))
const descriptions = [...html.matchAll(/ alt(?:="([^"]*)")?/g)].map(
([, value]) => value ?? ''
)
expect(descriptions).toEqual(Array(count).fill(alt ?? fallback))
}
)
})

@ -23,13 +23,13 @@ defineOptions({ inheritAttrs: false })
<VPImage <VPImage
class="dark" class="dark"
:image="image.dark" :image="image.dark"
:alt="image.alt" :alt="alt ?? image.alt"
v-bind="$attrs" v-bind="$attrs"
/> />
<VPImage <VPImage
class="light" class="light"
:image="image.light" :image="image.light"
:alt="image.alt" :alt="alt ?? image.alt"
v-bind="$attrs" v-bind="$attrs"
/> />
</template> </template>

Loading…
Cancel
Save