feat: add custom container stylings

pull/639/head
Kia King Ishii 3 years ago
parent 68ebd43664
commit e51d2a8c49

@ -52,7 +52,11 @@ function sidebarGuide() {
return [
{
text: 'Introduction',
items: [{ text: 'What is VitePress?', link: '/guide/what-is-vitepress' }]
items: [
{ text: 'What is VitePress?', link: '/guide/what-is-vitepress' },
{ text: 'Markdown Extensions', link: '/guide/markdown-extensions' },
{ text: 'Frontmatter', link: '/guide/frontmatter' }
]
},
{
text: 'Migrations',

@ -52,6 +52,30 @@ description: VitePress
---
```
### head
- Type: `Head[]`
Specify extra head tags to be injected:
```yaml
---
head:
- - meta
- name: description
content: hello
- - meta
- name: keywords
content: super duper SEO
---
```
```ts
type Head =
| [string, Record<string, string>]
| [string, Record<string, string>, string]
```
## layout
- Type: `doc | home | page`

@ -0,0 +1,38 @@
# Frontmatter
Any Markdown file that contains a YAML frontmatter block will be processed by [gray-matter](https://github.com/jonschlinkert/gray-matter). The frontmatter must be at the top of the Markdown file, and must take the form of valid YAML set between triple-dashed lines. Example:
```md
---
title: Docs with VitePress
editLink: true
---
```
Between the triple-dashed lines, you can set [predefined variables](../config/frontmatter-configs), or even create custom ones of your own. These variables can be used via the special <code>$frontmatter</code> variable.
Heres an example of how you could use it in your Markdown file:
```md
---
title: Docs with VitePress
editLink: true
---
# {{ $frontmatter.title }}
Guide content
```
## Alternative frontmatter Formats
VitePress also supports JSON frontmatter syntax, starting and ending in curly braces:
```json
---
{
"title": "Blogging Like a Hacker",
"editLink": true
}
---
```

@ -0,0 +1,413 @@
# Markdown Extensions
VitePress comes with built in Markdown Extensions.
## Header Anchors
Headers automatically get anchor links applied. Rendering of anchors can be configured using the `markdown.anchor` option.
## Links
Both internal and external links gets special treatments.
### Internal Links
Internal links are converted to router link for SPA navigation. Also, every `index.md` contained in each sub-directory will automatically be converted to `index.html`, with corresponding URL `/`.
For example, given the following directory structure:
```
.
├─ index.md
├─ foo
│ ├─ index.md
│ ├─ one.md
│ └─ two.md
└─ bar
├─ index.md
├─ three.md
└─ four.md
```
And providing you are in `foo/one.md`:
```md
[Home](/) <!-- sends the user to the root index.md -->
[foo](/foo/) <!-- sends the user to index.html of directory foo -->
[foo heading](./#heading) <!-- anchors user to a heading in the foo index file -->
[bar - three](../bar/three) <!-- you can omit extention -->
[bar - three](../bar/three.md) <!-- you can append .md -->
[bar - four](../bar/four.html) <!-- or you can append .html -->
```
### Page Suffix
Pages and internal links get generated with the `.html` suffix by default.
### External Links
Outbound links automatically get `target="_blank" rel="noopener noreferrer"`:
- [vuejs.org](https://vuejs.org)
- [VitePress on GitHub](https://github.com/vuejs/vitepress)
## Frontmatter
[YAML frontmatter](https://jekyllrb.com/docs/front-matter/) is supported out of the box:
```yaml
---
title: Blogging Like a Hacker
lang: en-US
---
```
This data will be available to the rest of the page, along with all custom and theming components.
For more details, see [Frontmatter](./frontmatter).
## GitHub-Style Tables
**Input**
```
| Tables | Are | Cool |
| ------------- |:-------------:| -----:|
| col 3 is | right-aligned | $1600 |
| col 2 is | centered | $12 |
| zebra stripes | are neat | $1 |
```
**Output**
| Tables | Are | Cool |
| ------------- | :-----------: | -----: |
| col 3 is | right-aligned | \$1600 |
| col 2 is | centered | \$12 |
| zebra stripes | are neat | \$1 |
## Emoji :tada:
**Input**
```
:tada: :100:
```
**Output**
:tada: :100:
A [list of all emojis](https://github.com/markdown-it/markdown-it-emoji/blob/master/lib/data/full.json) is available.
## Table of Contents
**Input**
```
[[toc]]
```
**Output**
[[toc]]
Rendering of the TOC can be configured using the `markdown.toc` option.
## Custom Containers
Custom containers can be defined by their types, titles, and contents.
### Default Title
**Input**
```md
::: info
This is an info box.
:::
::: tip
This is a tip.
:::
::: warning
This is a warning.
:::
::: danger
This is a dangerous warning.
:::
::: details
This is a details block.
:::
```
**Output**
::: info
This is an info box.
:::
::: tip
This is a tip.
:::
::: warning
This is a dangerous warning.
:::
::: danger
This is a dangerous warning.
:::
::: details
This is a details block.
:::
### Custom Title
You may set custom title by appending the text right after the "type" of the container.
**Input**
````md
::: danger STOP
Danger zone, do not proceed
:::
::: details Click me to view the code
```js
console.log('Hello, VitePress!')
```
:::
````
**Output**
::: danger STOP
Danger zone, do not proceed
:::
::: details Click me to view the code
```js
console.log('Hello, VitePress!')
```
:::
## Syntax Highlighting in Code Blocks
VitePress uses [Prism](https://prismjs.com) to highlight language syntax in Markdown code blocks, using coloured text. Prism supports a wide variety of programming languages. All you need to do is append a valid language alias to the beginning backticks for the code block:
**Input**
````
```js
export default {
name: 'MyComponent',
// ...
}
```
````
**Output**
```js
export default {
name: 'MyComponent'
// ...
}
```
**Input**
````
```html
<ul>
<li v-for="todo in todos" :key="todo.id">
{{ todo.text }}
</li>
</ul>
```
````
**Output**
```html
<ul>
<li v-for="todo in todos" :key="todo.id">{{ todo.text }}</li>
</ul>
```
A [list of valid languages](https://prismjs.com/#languages-list) is available on Prisms site.
## Line Highlighting in Code Blocks
**Input**
````
```js{4}
export default {
data () {
return {
msg: 'Highlighted!'
}
}
}
```
````
**Output**
```js{4}
export default {
data () {
return {
msg: 'Highlighted!'
}
}
}
```
In addition to a single line, you can also specify multiple single lines, ranges, or both:
- Line ranges: for example `{5-8}`, `{3-10}`, `{10-17}`
- Multiple single lines: for example `{4,7,9}`
- Line ranges and single lines: for example `{4,7-13,16,23-27,40}`
**Input**
````
```js{1,4,6-7}
export default { // Highlighted
data () {
return {
msg: `Highlighted!
This line isn't highlighted,
but this and the next 2 are.`,
motd: 'VitePress is awesome',
lorem: 'ipsum',
}
}
}
```
````
**Output**
```js{1,4,6-8}
export default { // Highlighted
data () {
return {
msg: `Highlighted!
This line isn't highlighted,
but this and the next 2 are.`,
motd: 'VitePress is awesome',
lorem: 'ipsum',
}
}
}
```
## Line Numbers
You can enable line numbers for each code blocks via config:
```js
module.exports = {
markdown: {
lineNumbers: true
}
}
```
## Import Code Snippets
You can import code snippets from existing files via following syntax:
```md
<<< @/filepath
```
It also supports [line highlighting](#line-highlighting-in-code-blocks):
```md
<<< @/filepath{highlightLines}
```
**Input**
```md
<<< @/snippets/snippet.js{2}
```
**Code file**
<!--lint disable strong-marker-->
<<< @/snippets/snippet.js
<!--lint enable strong-marker-->
**Output**
<!--lint disable strong-marker-->
<<< @/snippets/snippet.js{2}
<!--lint enable strong-marker-->
::: tip
The value of `@` corresponds to the source root. By default it's the VitePress project root, unless `srcDir` is configured.
:::
You can also use a [VS Code region](https://code.visualstudio.com/docs/editor/codebasics#_folding) to only include the corresponding part of the code file. You can provide a custom region name after a `#` following the filepath (`snippet` by default):
**Input**
```md
<<< @/snippets/snippet-with-region.js{1}
```
**Code file**
<!--lint disable strong-marker-->
<<< @/snippets/snippet-with-region.js
<!--lint enable strong-marker-->
**Output**
<!--lint disable strong-marker-->
<<< @/snippets/snippet-with-region.js#snippet{1}
<!--lint enable strong-marker-->
## 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`:
```js
const anchor = require('markdown-it-anchor')
module.exports = {
markdown: {
// options for markdown-it-anchor
// https://github.com/valeriangalliat/markdown-it-anchor#permalinks
anchor: {
permalink: anchor.permalink.headerLink()
},
// options for markdown-it-table-of-contents
toc: { includeLevel: [1, 2] },
config: (md) => {
// use more markdown-it plugins!
md.use(require('markdown-it-xxx'))
}
}
}
```

@ -0,0 +1,7 @@
// #region snippet
function foo() {
// ..
}
// #endregion snippet
export default foo

@ -0,0 +1,3 @@
export default function () {
// ..
}

@ -2,8 +2,9 @@ import './styles/fonts.css'
import './styles/vars.css'
import './styles/base.css'
import './styles/utils.css'
import './styles/vp-doc.css'
import './styles/vp-sponsor.css'
import './styles/components/custom-block.css'
import './styles/components/vp-doc.css'
import './styles/components/vp-sponsor.css'
import { Theme } from 'vitepress'
import Layout from './Layout.vue'

@ -0,0 +1,66 @@
.custom-block {
border: 1px solid transparent;
border-radius: 8px;
padding: 16px 16px 8px;
line-height: 20px;
font-size: 14px;
color: var(--vp-c-text-2);
}
.custom-block.info {
border-color: var(--vp-custom-block-info-border);
color: var(--vp-custom-block-info-text);
background-color: var(--vp-custom-block-info-bg);
}
.custom-block.tip {
border-color: var(--vp-custom-block-tip-border);
color: var(--vp-custom-block-tip-text);
background-color: var(--vp-custom-block-tip-bg);
}
.custom-block.warning {
border-color: var(--vp-custom-block-warning-border);
color: var(--vp-custom-block-warning-text);
background-color: var(--vp-custom-block-warning-bg);
}
.custom-block.danger {
border-color: var(--vp-custom-block-danger-border);
color: var(--vp-custom-block-danger-text);
background-color: var(--vp-custom-block-danger-bg);
}
.custom-block.details {
border-color: var(--vp-custom-block-details-border);
color: var(--vp-custom-block-details-text);
background-color: var(--vp-custom-block-details-bg);
}
.custom-block-title {
font-weight: 700;
}
.custom-block p + p {
margin: 8px 0;
}
.custom-block.details summary {
margin: 0 0 8px;
font-weight: 700;
}
.custom-block.details summary + p {
margin: 8px 0;
}
.custom-block a {
color: inherit;
font-weight: 600;
text-decoration: underline;
transition: opacity .25s;
}
.custom-block a:hover {
opacity: 0.6;
}

@ -115,18 +115,27 @@
.vp-doc ul,
.vp-doc ol {
padding-left: 1.25rem;
margin: 16px 0;
}
.vp-doc ul {
padding-left: 1.25rem;
list-style: disc;
}
.vp-doc ol {
list-style: decimal;
}
.vp-doc li + li {
margin-top: 8px;
}
.vp-doc li > ol,
.vp-doc li > ul {
margin: 8px 0 0;
}
/**
* Table
* -------------------------------------------------------------------------- */
@ -177,6 +186,38 @@
border-top: 1px solid var(--vp-c-divider-light);
}
/**
* Custom Block
* -------------------------------------------------------------------------- */
.vp-doc .custom-block {
margin: 16px 0;
}
.vp-doc .custom-block p {
margin: 8px 0;
line-height: 24px;
}
.vp-doc .custom-block p:first-child {
margin: 0;
}
.vp-doc .custom-block a {
color: inherit;
font-weight: 600;
text-decoration: underline;
transition: opacity .25s;
}
.vp-doc .custom-block a:hover {
opacity: 0.6;
}
.vp-doc .custom-block div[class*='language-'] {
margin: 8px 0;
}
/**
* Code
* -------------------------------------------------------------------------- */

@ -43,12 +43,6 @@
--vp-c-text-dark-3: rgba(235, 235, 235, 0.38);
--vp-c-text-dark-4: rgba(235, 235, 235, 0.18);
--vp-c-green: #42b883;
--vp-c-green-light: #42d392;
--vp-c-green-lighter: #35eb9a;
--vp-c-green-dark: #33a06f;
--vp-c-green-darker: #155f3e;
--vp-c-indigo: #213547;
--vp-c-indigo-soft: #476582;
--vp-c-indigo-light: #aac8e4;
@ -56,29 +50,26 @@
--vp-c-indigo-dark: #1d2f3f;
--vp-c-indigo-darker: #14212e;
--vp-c-blue: #3b8eed;
--vp-c-blue-light: #549ced;
--vp-c-blue-lighter: #50a2ff;
--vp-c-blue-dark: #3468a3;
--vp-c-blue-darker: #255489;
--vp-c-green: #42b883;
--vp-c-green-light: #42d392;
--vp-c-green-lighter: #35eb9a;
--vp-c-green-dark: #33a06f;
--vp-c-green-darker: #155f3e;
--vp-c-green-dimm: rgba(66, 184, 131, 0.08);
--vp-c-yellow: #ffc517;
--vp-c-yellow-light: #ffe417;
--vp-c-yellow-lighter: #ffff17;
--vp-c-yellow-dark: #e0ad15;
--vp-c-yellow-darker: #bc9112;
--vp-c-yellow-darker: #ad850e;
--vp-c-yellow-dimm: rgba(255, 197, 23, 0.08);
--vp-c-red: #ed3c50;
--vp-c-red-light: #f43771;
--vp-c-red-lighter: #fd1d7c;
--vp-c-red-dark: #cd2d3f;
--vp-c-red-darker: #ab2131;
--vp-c-purple: #de41e0;
--vp-c-purple-light: #e936eb;
--vp-c-purple-lighter: #f616f8;
--vp-c-purple-dark: #823c83;
--vp-c-purple-darker: #602960;
--vp-c-red-dimm: rgba(237, 60, 80, 0.08);
}
/**
@ -188,30 +179,6 @@
--vp-layout-max-width: 1376px;
}
/**
* Component: Nav
* -------------------------------------------------------------------------- */
:root {
--vp-nav-height: var(--vp-nav-height-mobile);
--vp-nav-height-mobile: 56px;
--vp-nav-height-desktop: 72px;
}
@media (min-width: 960px) {
:root {
--vp-nav-height: var(--vp-nav-height-desktop);
}
}
/**
* Component: Sidebar
* -------------------------------------------------------------------------- */
:root {
--vp-sidebar-width: 272px;
}
/**
* Component: Code
* -------------------------------------------------------------------------- */
@ -289,6 +256,67 @@
--vp-button-sponsor-text: var(--vp-c-text-dark-2);
}
/**
* Component: Custom Block
* -------------------------------------------------------------------------- */
:root {
--vp-custom-block-info-border: var(--vp-c-divider-light);
--vp-custom-block-info-text: var(--vp-c-text-2);
--vp-custom-block-info-bg: var(--vp-c-white-soft);
--vp-custom-block-tip-border: var(--vp-c-green);
--vp-custom-block-tip-text: var(--vp-c-green-darker);
--vp-custom-block-tip-bg: var(--vp-c-green-dimm);
--vp-custom-block-warning-border: var(--vp-c-yellow);
--vp-custom-block-warning-text: var(--vp-c-yellow-darker);
--vp-custom-block-warning-bg: var(--vp-c-yellow-dimm);
--vp-custom-block-danger-border: var(--vp-c-red);
--vp-custom-block-danger-text: var(--vp-c-red-darker);
--vp-custom-block-danger-bg: var(--vp-c-red-dimm);
--vp-custom-block-details-border: var(--vp-custom-block-info-border);
--vp-custom-block-details-text: var(--vp-custom-block-info-text);
--vp-custom-block-details-bg: var(--vp-custom-block-info-bg);
}
.dark {
--vp-custom-block-info-border: var(--vp-c-divider-light);
--vp-custom-block-info-bg: var(--vp-c-black-mute);
--vp-custom-block-tip-text: var(--vp-c-green);
--vp-custom-block-warning-text: var(--vp-c-yellow);
--vp-custom-block-danger-text: var(--vp-c-red);
}
/**
* Component: Nav
* -------------------------------------------------------------------------- */
:root {
--vp-nav-height: var(--vp-nav-height-mobile);
--vp-nav-height-mobile: 56px;
--vp-nav-height-desktop: 72px;
}
@media (min-width: 960px) {
:root {
--vp-nav-height: var(--vp-nav-height-desktop);
}
}
/**
* Component: Sidebar
* -------------------------------------------------------------------------- */
:root {
--vp-sidebar-width: 272px;
}
/**
* Component: Home
* -------------------------------------------------------------------------- */

@ -6,7 +6,7 @@ export const containerPlugin = (md: MarkdownIt) => {
md.use(...createContainer('tip', 'TIP'))
.use(...createContainer('info', 'INFO'))
.use(...createContainer('warning', 'WARNING'))
.use(...createContainer('danger', 'WARNING'))
.use(...createContainer('danger', 'DANGER'))
.use(...createContainer('details', 'Details'))
// explicitly escape Vue syntax
.use(container, 'v-pre', {
@ -34,7 +34,7 @@ function createContainer(klass: string, defaultTitle: string): ContainerArgs {
if (token.nesting === 1) {
if (klass === 'details') {
return `<details class="${klass} custom-block">${
info ? `<summary>${info}</summary>` : ''
info ? `<summary>${info}</summary>` : `<summary>Details</summary>`
}\n`
}
return `<div class="${klass} custom-block"><p class="custom-block-title">${

Loading…
Cancel
Save