feat(theme): allow adding images as icons in features section (#1738)

Co-authored-by: Divyansh Singh <40380293+brc-dd@users.noreply.github.com>
pull/1747/head
Joaquín Sánchez 2 years ago committed by GitHub
parent ce9467e389
commit 9df598f36e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -0,0 +1,21 @@
# Lorem Ipsum
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
## What is Lorem Ipsum?
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
## Where does it come from?
Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old. Richard McClintock, a Latin professor at Hampden-Sydney College in Virginia, looked up one of the more obscure Latin words, consectetur, from a Lorem Ipsum passage, and going through the cites of the word in classical literature, discovered the undoubtable source. Lorem Ipsum comes from sections 1.10.32 and 1.10.33 of "de Finibus Bonorum et Malorum" (The Extremes of Good and Evil) by Cicero, written in 45 BC. This book is a treatise on the theory of ethics, very popular during the Renaissance. The first line of Lorem Ipsum, "Lorem ipsum dolor sit amet..", comes from a line in section 1.10.32.
The standard chunk of Lorem Ipsum used since the 1500s is reproduced below for those interested. Sections 1.10.32 and 1.10.33 from "de Finibus Bonorum et Malorum" by Cicero are also reproduced in their exact original form, accompanied by English versions from the 1914 translation by H. Rackham.
## Why do we use it?
It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using 'Content here, content here', making it look like readable English. Many desktop publishing packages and web page editors now use Lorem Ipsum as their default model text, and a search for 'lorem ipsum' will uncover many web sites still in their infancy. Various versions have evolved over the years, sometimes by accident, sometimes on purpose (injected humour and the like).
## Where can I get some?
There are many variations of passages of Lorem Ipsum available, but the majority have suffered alteration in some form, by injected humour, or randomised words which don't look even slightly believable. If you are going to use a passage of Lorem Ipsum, you need to be sure there isn't anything embarrassing hidden in the middle of text. All the Lorem Ipsum generators on the Internet tend to repeat predefined chunks as necessary, making this the first true generator on the Internet. It uses a dictionary of over 200 Latin words, combined with a handful of model sentence structures, to generate Lorem Ipsum which looks reasonable. The generated Lorem Ipsum is therefore always free from repetition, injected humour, or non-characteristic words etc.

@ -1,6 +1,6 @@
describe('render correct content', async () => {
beforeAll(async () => {
await goto('/')
await goto('/home')
})
test('main content', async () => {

@ -1,21 +1,36 @@
# Lorem Ipsum
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
## What is Lorem Ipsum?
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
## Where does it come from?
Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old. Richard McClintock, a Latin professor at Hampden-Sydney College in Virginia, looked up one of the more obscure Latin words, consectetur, from a Lorem Ipsum passage, and going through the cites of the word in classical literature, discovered the undoubtable source. Lorem Ipsum comes from sections 1.10.32 and 1.10.33 of "de Finibus Bonorum et Malorum" (The Extremes of Good and Evil) by Cicero, written in 45 BC. This book is a treatise on the theory of ethics, very popular during the Renaissance. The first line of Lorem Ipsum, "Lorem ipsum dolor sit amet..", comes from a line in section 1.10.32.
The standard chunk of Lorem Ipsum used since the 1500s is reproduced below for those interested. Sections 1.10.32 and 1.10.33 from "de Finibus Bonorum et Malorum" by Cicero are also reproduced in their exact original form, accompanied by English versions from the 1914 translation by H. Rackham.
## Why do we use it?
It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using 'Content here, content here', making it look like readable English. Many desktop publishing packages and web page editors now use Lorem Ipsum as their default model text, and a search for 'lorem ipsum' will uncover many web sites still in their infancy. Various versions have evolved over the years, sometimes by accident, sometimes on purpose (injected humour and the like).
## Where can I get some?
There are many variations of passages of Lorem Ipsum available, but the majority have suffered alteration in some form, by injected humour, or randomised words which don't look even slightly believable. If you are going to use a passage of Lorem Ipsum, you need to be sure there isn't anything embarrassing hidden in the middle of text. All the Lorem Ipsum generators on the Internet tend to repeat predefined chunks as necessary, making this the first true generator on the Internet. It uses a dictionary of over 200 Latin words, combined with a handful of model sentence structures, to generate Lorem Ipsum which looks reasonable. The generated Lorem Ipsum is therefore always free from repetition, injected humour, or non-characteristic words etc.
---
layout: home
title: VitePress
hero:
name: VitePress
text: Vite & Vue Powered Static Site Generator
actions:
- theme: brand
text: Examples
link: /home
features:
- title: Emoji
details: Emoji on features section
icon: ⚡️
- title: SVG
details: SVG on features section
icon:
src: /vitepress.svg
alt: VitePress Logo
- title: PNG
details: PNG on features section
icon:
src: /vitepress.png
width: 48
height: 48
alt: VitePress Logo
- title: Dark/Light SVG
details: Dark/Light SVG on features section
icon:
dark: /pwa_dark.svg
light: /pwa_light.svg
alt: Vite PWA Logo
---

@ -1,5 +1,6 @@
{
"private": true,
"type": "module",
"devDependencies": {
"vitepress": "workspace:*"
}

@ -0,0 +1,5 @@
<svg width="48" height="48" viewBox="0 0 155 155" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M50.6853 104.345C48.3909 100.398 46.0047 96.3602 43.7103 92.4138C43.5268 92.1385 43.435 91.8632 43.5267 91.4043C45.8211 84.4293 48.1155 77.3626 50.4099 70.3876C50.4099 70.2959 50.5017 70.1123 50.5935 69.837C53.255 75.0682 55.8247 80.2076 58.4862 85.4389C58.6697 85.0717 58.7615 84.7964 58.8533 84.5211C62.4326 73.508 66.0118 62.5867 69.5911 51.5736C69.7746 51.1147 69.9582 50.9312 70.417 51.0229C73.6292 51.0229 76.8414 51.0229 80.1453 51.0229C80.6959 51.0229 80.8795 51.2065 81.063 51.6654C84.367 62.5867 87.6709 73.4162 90.9748 84.3375C91.0666 84.6129 91.1584 84.98 91.3419 85.4389C91.8008 84.5211 92.1679 83.6033 92.4432 82.7774C96.9402 72.3149 101.345 61.9443 105.842 51.4818C105.934 51.2065 106.026 51.0229 106.393 51.0229C110.982 51.0229 115.571 51.0229 120.068 51.0229C120.068 51.0229 120.16 51.0229 120.251 51.0229C119.701 52.3078 119.242 53.5009 118.783 54.7857C112.175 71.0301 105.659 87.3661 99.0511 103.61C98.9593 103.794 98.7757 103.978 98.8675 104.253C94.0952 104.253 89.3229 104.253 84.5505 104.253C84.6423 104.069 84.5505 103.794 84.4587 103.61C84.0916 102.417 83.7245 101.224 83.3574 100.031C80.6042 91.3125 77.9426 82.6856 75.1894 73.9669C75.1894 73.7833 75.1894 73.5998 74.9141 73.508C71.5184 83.6951 68.2144 93.974 64.8187 104.161C60.0464 104.345 55.3658 104.345 50.6853 104.345Z" fill="#4AA6C0"/>
<path d="M7 104.345C7 86.8155 7 69.2863 7 51.7571C7 51.2065 7.09178 51.0229 7.73421 51.0229C15.168 51.0229 22.6019 51.0229 30.0357 51.0229C34.1656 51.0229 38.0202 51.9407 41.3241 54.5104C42.7008 55.5199 43.8938 56.8048 44.9034 58.2732C45.0869 58.5485 45.0869 58.7321 44.9952 59.0074C42.2419 67.5426 39.3968 76.1695 36.6436 84.7046C36.5518 85.0717 36.3682 85.1635 36.0011 85.2553C34.0738 85.7142 32.0548 85.9895 30.0357 85.9895C27.0071 85.9895 24.0703 85.9895 21.0417 85.9895C20.6746 85.9895 20.5828 85.9895 20.5828 86.4484C20.5828 92.322 20.5828 98.2874 20.5828 104.161V104.253C16.0858 104.345 11.497 104.345 7 104.345ZM20.5828 68.4603C20.5828 70.6629 20.5828 72.8656 20.5828 75.16C20.5828 75.6188 20.6746 75.7106 21.1335 75.7106C22.2348 75.7106 23.4279 75.7106 24.5292 75.7106C26.0894 75.7106 27.6495 75.7106 29.2097 75.3435C30.5864 74.9764 31.8712 74.5175 32.6972 73.3244C34.441 70.8465 34.6245 68.0932 33.5232 65.34C32.6054 62.862 30.4946 61.8525 28.0166 61.5771C25.7223 61.3018 23.4279 61.4854 21.1335 61.3936C20.6746 61.3936 20.5828 61.5771 20.5828 61.9442C20.5828 64.1469 20.5828 66.3495 20.5828 68.4603Z" fill="#EEEEEE"/>
<path d="M128.167 92.3636H114L133.833 44V71.6364H148L128.167 120V92.3636Z" fill="#F7D94B"/>
</svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

@ -0,0 +1,5 @@
<svg width="48" height="48" viewBox="0 0 155 155" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M50.6853 104.345C48.3909 100.398 46.0047 96.3602 43.7103 92.4138C43.5268 92.1385 43.435 91.8632 43.5267 91.4043C45.8211 84.4293 48.1155 77.3626 50.4099 70.3876C50.4099 70.2959 50.5017 70.1123 50.5935 69.837C53.255 75.0682 55.8247 80.2076 58.4862 85.4389C58.6697 85.0717 58.7615 84.7964 58.8533 84.5211C62.4326 73.508 66.0118 62.5867 69.5911 51.5736C69.7746 51.1147 69.9582 50.9312 70.417 51.0229C73.6292 51.0229 76.8413 51.0229 80.1453 51.0229C80.6959 51.0229 80.8795 51.2065 81.063 51.6654C84.367 62.5867 87.6709 73.4162 90.9748 84.3375C91.0666 84.6129 91.1584 84.98 91.3419 85.4389C91.8008 84.5211 92.1679 83.6033 92.4432 82.7774C96.9402 72.3149 101.345 61.9443 105.842 51.4818C105.934 51.2065 106.026 51.0229 106.393 51.0229C110.982 51.0229 115.571 51.0229 120.068 51.0229C120.068 51.0229 120.16 51.0229 120.251 51.0229C119.701 52.3078 119.242 53.5009 118.783 54.7857C112.175 71.0301 105.659 87.3661 99.0511 103.61C98.9593 103.794 98.7757 103.978 98.8675 104.253C94.0952 104.253 89.3229 104.253 84.5505 104.253C84.6423 104.069 84.5505 103.794 84.4587 103.61C84.0916 102.417 83.7245 101.224 83.3574 100.031C80.6042 91.3125 77.9426 82.6856 75.1894 73.9669C75.1894 73.7833 75.1894 73.5998 74.9141 73.508C71.5184 83.6951 68.2144 93.974 64.8187 104.161C60.0464 104.345 55.3658 104.345 50.6853 104.345Z" fill="#35849A"/>
<path d="M7 104.345C7 86.8155 7 69.2863 7 51.7571C7 51.2065 7.09178 51.0229 7.73421 51.0229C15.168 51.0229 22.6019 51.0229 30.0357 51.0229C34.1656 51.0229 38.0202 51.9407 41.3241 54.5104C42.7008 55.5199 43.8938 56.8048 44.9034 58.2732C45.0869 58.5485 45.0869 58.7321 44.9952 59.0074C42.2419 67.5426 39.3968 76.1695 36.6436 84.7046C36.5518 85.0717 36.3682 85.1635 36.0011 85.2553C34.0738 85.7142 32.0548 85.9895 30.0357 85.9895C27.0071 85.9895 24.0703 85.9895 21.0417 85.9895C20.6746 85.9895 20.5828 85.9895 20.5828 86.4484C20.5828 92.322 20.5828 98.2874 20.5828 104.161V104.253C16.0858 104.345 11.497 104.345 7 104.345ZM20.5828 68.4603C20.5828 70.6629 20.5828 72.8656 20.5828 75.16C20.5828 75.6188 20.6746 75.7106 21.1335 75.7106C22.2348 75.7106 23.4279 75.7106 24.5292 75.7106C26.0894 75.7106 27.6495 75.7106 29.2097 75.3435C30.5864 74.9764 31.8712 74.5175 32.6972 73.3244C34.441 70.8465 34.6245 68.0932 33.5232 65.34C32.6054 62.862 30.4946 61.8525 28.0166 61.5771C25.7223 61.3018 23.4279 61.4854 21.1335 61.3936C20.6746 61.3936 20.5828 61.5771 20.5828 61.9442C20.5828 64.1469 20.5828 66.3495 20.5828 68.4603Z" fill="#3E3E3E"/>
<path d="M128.167 92.3636H114L133.833 44V71.6364H148L128.167 120V92.3636Z" fill="#efcd0a"/>
</svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 70 KiB

@ -169,49 +169,6 @@ This option only takes effect when `layout` is set to `home`.
It defines items to display in features section.
```yaml
---
layout: home
features:
- icon: ⚡️
title: Vite, The DX that can't be beat
details: Lorem ipsum...
- icon: 🖖
title: Power of Vue meets Markdown
details: Lorem ipsum...
- icon: 🛠️
title: Simple and minimal, always
details: Lorem ipsum...
---
```
```ts
interface Feature {
// Show icon on each feature box. Currently, only emojis
// are supported.
icon?: string
// Title of the feature.
title: string
// Details of the feature.
details: string
// Link when clicked on feature component. The link can
// be both internal or external.
//
// e.g. `guide/theme-home-page` or `htttps://example.com`
link?: string
// Link text to be shown inside feature component. Best
// used with `link` option.
//
// e.g. `Learn more`, `Visit page`, etc.
linkText?: string
}
```
You may learn more about it in [Theme: Home Page](../guide/theme-home-page).
## aside

@ -34,8 +34,10 @@ export default {
```
```ts
type Image = string | { src: string; alt?: string }
type ThemeableImage = Image | { light: Image; dark: Image }
type ThemeableImage =
| string
| { src: string; alt?: string }
| { light: string; dark: string; alt?: string }
```
## siteTitle

@ -87,28 +87,32 @@ Also you may customize it further by combining `--vp-home-hero-name-background`
In Features section, you can list any number of features you would like to show right after the Hero section. To configure it, pass `features` option to the frontmatter.
You can provide an icon for each feature, which can be an emoji or any type of image. When the configured icon is an image (svg, png, jpeg...), you must provide the icon with the proper width and height; you can also provide the description, its intrinsic size as well as its variants for dark and light theme when required.
```yaml
---
layout: home
features:
- icon: ⚡️
title: Vite, The DX that can't be beat
details: Lorem ipsum...
- icon: 🖖
title: Power of Vue meets Markdown
details: Lorem ipsum...
- icon: 🛠️
title: Simple and minimal, always
details: Lorem ipsum...
- icon:
src: /cool-feature-icon.svg
title: Another cool feature
details: Lorem ipsum...
- icon:
dark: /dark-feature-icon.svg
light: /light-feature-icon.svg
title: Another cool feature
details: Lorem ipsum...
---
```
```ts
interface Feature {
// Show icon on each feature box. Currently, only emojis
// are supported.
icon?: string
// Show icon on each feature box.
icon?: FeatureIcon
// Title of the feature.
title: string
@ -128,4 +132,15 @@ interface Feature {
// e.g. `Learn more`, `Visit page`, etc.
linkText?: string
}
type FeatureIcon =
| string
| { src: string; alt?: string; width?: string; height: string }
| {
light: string
dark: string
alt?: string
width?: string
height: string
}
```

@ -68,6 +68,7 @@
"test-build": "VITE_TEST_BUILD=1 pnpm test-preview",
"debug-preview": "DEBUG=1 vitest -r __tests__/e2e",
"debug-build": "VITE_TEST_BUILD=1 pnpm debug-preview",
"e2e-dev": "wait-on -d 100 dist/node/cli.js && node ./bin/vitepress dev __tests__/e2e",
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s",
"release": "node scripts/release.js",
"docs": "run-p dev docs-dev",

@ -1,9 +1,11 @@
<script setup lang="ts">
import type { DefaultTheme } from 'vitepress/theme'
import VPImage from './VPImage.vue'
import VPLink from './VPLink.vue'
import VPIconArrowRight from './icons/VPIconArrowRight.vue'
defineProps<{
icon?: string
icon?: DefaultTheme.FeatureIcon
title: string
details: string
link?: string
@ -14,7 +16,14 @@ defineProps<{
<template>
<VPLink class="VPFeature" :href="link" :no-icon="true">
<article class="box">
<div v-if="icon" class="icon">{{ icon }}</div>
<VPImage
v-if="typeof icon === 'object'"
:image="icon"
:alt="icon.alt"
:height="icon.height"
:width="icon.width"
/>
<div v-else-if="icon" class="icon">{{ icon }}</div>
<h2 class="title">{{ title }}</h2>
<p class="details">{{ details }}</p>
@ -53,6 +62,11 @@ defineProps<{
height: 100%;
}
.VPFeature:deep(.VPImage) {
width: fit-content;
margin-bottom: 20px;
}
.icon {
display: flex;
justify-content: center;

@ -1,9 +1,10 @@
<script setup lang="ts">
import type { DefaultTheme } from 'vitepress/theme'
import { computed } from 'vue'
import VPFeature from './VPFeature.vue'
export interface Feature {
icon?: string
icon?: DefaultTheme.FeatureIcon
title: string
details: string
link?: string
@ -35,7 +36,12 @@ const grid = computed(() => {
<div v-if="features" class="VPFeatures">
<div class="container">
<div class="items">
<div v-for="feature in features" :key="feature.title" class="item" :class="[grid]">
<div
v-for="feature in features"
:key="feature.title"
class="item"
:class="[grid]"
>
<VPFeature
:icon="feature.icon"
:title="feature.title"

@ -27,21 +27,13 @@ export default {
<VPImage
class="dark"
:image="image.dark"
:alt="
typeof image.dark === 'string'
? image.alt
: image.dark.alt || image.alt
"
:alt="image.alt"
v-bind="$attrs"
/>
<VPImage
class="light"
:image="image.light"
:alt="
typeof image.light === 'string'
? image.alt
: image.light.alt || image.alt
"
:alt="image.alt"
v-bind="$attrs"
/>
</template>

@ -114,12 +114,23 @@ export namespace DefaultTheme {
activeMatch?: string
}
// image -----------------------------------------------------------------------
// image ---------------------------------------------------------------------
export type ThemeableImage =
| Image
| { light: Image; dark: Image; alt?: string }
export type Image = string | { src: string; alt?: string }
| string
| { src: string; alt?: string }
| { light: string; dark: string; alt?: string }
export type FeatureIcon =
| string
| { src: string; alt?: string; width?: string; height: string }
| {
light: string
dark: string
alt?: string
width?: string
height: string
}
// sidebar -------------------------------------------------------------------
@ -239,7 +250,7 @@ export namespace DefaultTheme {
link: string
}
// algolia ------------------------------------------------------------------
// algolia -------------------------------------------------------------------
/**
* The Algolia search options. Partially copied from

Loading…
Cancel
Save