feat: ppst-vitepress-theme
commit
a329fd9116
@ -0,0 +1,11 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
@ -0,0 +1,10 @@
|
||||
/coverage
|
||||
/node_modules
|
||||
dist
|
||||
TODOs.md
|
||||
.DS_Store
|
||||
demo/.vitepress/cache
|
||||
demo/node_modules
|
||||
|
||||
demo/doc/.vitepress/cache
|
||||
demo/doc/node_modules
|
@ -0,0 +1,4 @@
|
||||
semi: false
|
||||
singleQuote: true
|
||||
printWidth: 80
|
||||
trailingComma: none
|
@ -0,0 +1,6 @@
|
||||
/coverage
|
||||
/node_modules
|
||||
dist
|
||||
TODOs.md
|
||||
.DS_Store
|
||||
demo/.vitepress/cache
|
@ -0,0 +1,12 @@
|
||||
import { CustomTheme } from 'ppst-vitepress-theme'
|
||||
// import { h } from 'vue'
|
||||
|
||||
import './override.css'
|
||||
|
||||
export default {
|
||||
...CustomTheme,
|
||||
// Layout() {
|
||||
// return h(CustomTheme.Layout, null, {
|
||||
// })
|
||||
// }
|
||||
}
|
@ -0,0 +1,97 @@
|
||||
:root {
|
||||
--c-main-color:#80adff;
|
||||
}
|
||||
|
||||
|
||||
/* card */
|
||||
|
||||
.news-box {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
margin: 0 auto;
|
||||
padding: 20px 0;
|
||||
}
|
||||
.news-box .card-item {
|
||||
flex-basis: 25%;
|
||||
padding: 15px;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
.news-box .card-item .item-box {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
border-radius: 15px;
|
||||
padding: 15px;
|
||||
margin-bottom: 140px;
|
||||
background: #f8f8fc;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
.news-box .card-item .item-box .icon {
|
||||
font-size: 48px;
|
||||
color: var(--c-main-color);
|
||||
}
|
||||
.news-box .card-item .item-box .title {
|
||||
font-size: 18px;
|
||||
line-height: 2;
|
||||
font-weight: 500;
|
||||
color: #020312;
|
||||
}
|
||||
.news-box .card-item .item-box .desc {
|
||||
font-size: 16px;
|
||||
line-height: 2;
|
||||
color: #717e96;
|
||||
overflow: hidden;
|
||||
}
|
||||
.news-box .card-item .item-box .desc {
|
||||
font-size: 16px;
|
||||
line-height: 2;
|
||||
color: #717e96;
|
||||
}
|
||||
.news-box .card-item:hover .item-box {
|
||||
background: var(--c-main-color);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
.news-box .card-item .item-box.active {
|
||||
background: var(--c-main-color);
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.news-box .card-item:hover .item-box .icon,
|
||||
.news-box .card-item:hover .item-box .title,
|
||||
.news-box .card-item:hover .item-box .desc,
|
||||
.news-box .card-item .item-box.active .icon,
|
||||
.news-box .card-item .item-box.active .title,
|
||||
.news-box .card-item .item-box.active .desc {
|
||||
color: #fff;
|
||||
}
|
||||
@media (max-width: 1200px) {
|
||||
.banner .banner-left {
|
||||
font-size: 14px;
|
||||
}
|
||||
.banner .banner-left .desc {
|
||||
font-size: 12px;
|
||||
}
|
||||
.note-box {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.note-box .note-item {
|
||||
flex-basis: 100%;
|
||||
}
|
||||
.news-box {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.news-box .card-item {
|
||||
flex-basis: 100%;
|
||||
}
|
||||
.news-box .card-item .item-box {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.news-box .card-item .item-box .title {
|
||||
font-size: 14px;
|
||||
}
|
||||
.news-box .card-item .item-box .desc {
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
@ -0,0 +1,95 @@
|
||||
---
|
||||
page: true
|
||||
date: 2021-06-30
|
||||
title: 自定义标题
|
||||
sidebar: false
|
||||
---
|
||||
<script setup>
|
||||
</script>
|
||||
<Home>
|
||||
|
||||
<template #banner>
|
||||
<img src="/img/page.png" />
|
||||
</template>
|
||||
|
||||
<template #description>
|
||||
<!-- 一些其他描述 -->
|
||||
</template>
|
||||
|
||||
<div class="card-header max-width">
|
||||
<div class="title">手册</div>
|
||||
<div class="desc">基础知识手册(学习基础笔记)</div>
|
||||
</div>
|
||||
<div class="note-box max-width">
|
||||
<div class="note-item">
|
||||
<div class="item-box">
|
||||
<div class="title">💡CSS手册</div>
|
||||
<div class="go">
|
||||
<span class="button-box"
|
||||
><a href="https://css.web.ppst.top/">💡CSS手册</a></span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="note-item">
|
||||
<div class="item-box">
|
||||
<div class="title">💡JS手册</div>
|
||||
<div class="go">
|
||||
<span class="button-box"><a href="https://js.web.ppst.top/">💡JS手册</a></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="note-item">
|
||||
<div class="item-box">
|
||||
<div class="title">💡博客</div>
|
||||
<div class="go">
|
||||
<span class="button-box"><a href="https://blog.web.ppst.top/">💡博客</a></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-header max-width">
|
||||
<div class="title">随笔</div>
|
||||
<div class="desc">最常用随笔分类</div>
|
||||
</div>
|
||||
|
||||
<div class="news-box max-width">
|
||||
<div class="card-item">
|
||||
<div class="item-box">
|
||||
<div class="icon">?</div>
|
||||
<div class="title">JS笔记</div>
|
||||
<div class="desc">
|
||||
我就是记录一些笔记,以及异常处理经验记录,工作中遇到问题记录解决方案
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-item">
|
||||
<div class="item-box active">
|
||||
<div class="icon">?</div>
|
||||
<div class="title">vue笔记</div>
|
||||
<div class="desc">
|
||||
我就是记录一些笔记,以及异常处理经验记录,工作中遇到问题记录解决方案
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-item">
|
||||
<div class="item-box">
|
||||
<div class="icon">?</div>
|
||||
<div class="title">服务器笔记</div>
|
||||
<div class="desc">
|
||||
我就是记录一些笔记,以及异常处理经验记录,工作中遇到问题记录解决方案
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-item">
|
||||
<div class="item-box active">
|
||||
<div class="icon">?</div>
|
||||
<div class="title">浏览器笔记</div>
|
||||
<div class="desc">
|
||||
我就是记录一些笔记,以及异常处理经验记录,工作中遇到问题记录解决方案
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Home>
|
@ -0,0 +1,19 @@
|
||||
{
|
||||
"name": "demo",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"dev": "vitepress dev --host 0.0.0.0",
|
||||
"build": "vitepress build "
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@types/node": "^18.15.11",
|
||||
"markdown-from-posts": "^1.0.4",
|
||||
"vitepress": "1.0.0-alpha.64",
|
||||
"ppst-vitepress-theme": "^1.0.1"
|
||||
}
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
---
|
||||
page: true
|
||||
title: Archive
|
||||
description: Archive
|
||||
sidebar: false
|
||||
---
|
||||
<Archives>
|
||||
|
||||
<template #banner>
|
||||
<img src="/img/banner.png" />
|
||||
</template>
|
||||
|
||||
</Archives>
|
@ -0,0 +1,13 @@
|
||||
---
|
||||
page: true
|
||||
title: 分类
|
||||
description: 分类
|
||||
sidebar: false
|
||||
---
|
||||
<CategoryPage title='分类' category='demo' description="分类">
|
||||
|
||||
<template #banner>
|
||||
<img src="/img/banner.png" />
|
||||
</template>
|
||||
|
||||
</CategoryPage>
|
@ -0,0 +1,13 @@
|
||||
---
|
||||
page: true
|
||||
title: 默认
|
||||
description: 默认
|
||||
sidebar: false
|
||||
---
|
||||
<DefaultPage title='默认' category='default' description="默认">
|
||||
<template #banner>
|
||||
<img src="/img/banner.png" />
|
||||
</template>
|
||||
|
||||
</DefaultPage>
|
||||
|
@ -0,0 +1,11 @@
|
||||
---
|
||||
page: true
|
||||
title: 搜索
|
||||
description: 全文检索
|
||||
sidebar: false
|
||||
---
|
||||
<Search>
|
||||
<template #banner>
|
||||
<img src="/img/banner.png" />
|
||||
</template>
|
||||
</Search>
|
@ -0,0 +1,63 @@
|
||||
---
|
||||
title: default
|
||||
date: 2018-09-14 13:57:02
|
||||
category: default
|
||||
tags:
|
||||
- default
|
||||
---
|
||||
# 主标题AAAA
|
||||
|
||||
## 副标题
|
||||
|
||||
我是内容
|
||||
|
||||
```js
|
||||
let a = '我是js代码'
|
||||
```
|
||||
|
||||
```css
|
||||
.default{
|
||||
color:red;
|
||||
}
|
||||
```
|
||||
|
||||
```shell
|
||||
npm install default
|
||||
```
|
||||
|
||||
### 副标题1
|
||||
|
||||
我是内容
|
||||
|
||||
```js
|
||||
let a = '我是js代码'
|
||||
```
|
||||
|
||||
```css
|
||||
.default{
|
||||
color:red;
|
||||
}
|
||||
```
|
||||
|
||||
```shell
|
||||
npm install default
|
||||
```
|
||||
|
||||
|
||||
#### 副标题111
|
||||
|
||||
我是内容
|
||||
|
||||
```js
|
||||
let a = '我是js代码'
|
||||
```
|
||||
|
||||
```css
|
||||
.default{
|
||||
color:red;
|
||||
}
|
||||
```
|
||||
|
||||
```shell
|
||||
npm install default
|
||||
```
|
@ -0,0 +1,63 @@
|
||||
---
|
||||
title: demo
|
||||
date: 2018-09-14 13:57:02
|
||||
category: demo
|
||||
tags:
|
||||
- demo
|
||||
---
|
||||
# 主标题BBBB
|
||||
|
||||
## 副标题
|
||||
|
||||
我是内容
|
||||
|
||||
```js
|
||||
let a = '我是js代码'
|
||||
```
|
||||
|
||||
```css
|
||||
.demo{
|
||||
color:red;
|
||||
}
|
||||
```
|
||||
|
||||
```shell
|
||||
npm install demo
|
||||
```
|
||||
|
||||
### 副标题1
|
||||
|
||||
我是内容
|
||||
|
||||
```js
|
||||
let a = '我是js代码'
|
||||
```
|
||||
|
||||
```css
|
||||
.demo{
|
||||
color:red;
|
||||
}
|
||||
```
|
||||
|
||||
```shell
|
||||
npm install demo
|
||||
```
|
||||
|
||||
|
||||
#### 副标题111
|
||||
|
||||
我是内容
|
||||
|
||||
```js
|
||||
let a = '我是js代码'
|
||||
```
|
||||
|
||||
```css
|
||||
.demo{
|
||||
color:red;
|
||||
}
|
||||
```
|
||||
|
||||
```shell
|
||||
npm install demo
|
||||
```
|
Binary file not shown.
After Width: | Height: | Size: 4.0 KiB |
Binary file not shown.
After Width: | Height: | Size: 60 KiB |
Binary file not shown.
After Width: | Height: | Size: 83 KiB |
@ -0,0 +1,47 @@
|
||||
{
|
||||
"name": "ppst-vitepress-theme",
|
||||
"version": "0.0.1",
|
||||
"description": "自定义vitepress主题",
|
||||
"main": "src/index.ts",
|
||||
"exports": {
|
||||
".": "./src/index.ts",
|
||||
"./config": {
|
||||
"types": "./src/vitepress/config/baseConfig.d.ts",
|
||||
"default": "./src/vitepress/config/baseConfig.js"
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"src",
|
||||
"types"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "http://git.ppst.top/pp/ppst-vitepress-theme"
|
||||
},
|
||||
"keywords": [
|
||||
"vue",
|
||||
"vitepress"
|
||||
],
|
||||
"author": "pp",
|
||||
"scripts": {
|
||||
"lint": "prettier --check --write --parser typescript \"{__tests__,docs,src,types}/**/*.ts\"",
|
||||
"lint:fail": "prettier --check --parser typescript \"{__tests__,docs,src,types}/**/*.ts\"",
|
||||
"type": "tsc --noEmit",
|
||||
"test": "npm run lint && npm run type",
|
||||
"demo": "cd demo && vitepress dev demo --host 0.0.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"markdown-from-posts": "^1.0.8",
|
||||
"normalize.css": "^8.0.1",
|
||||
"vitepress": "1.0.0-alpha.64"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^18.15.11",
|
||||
"prettier": "^2.7.1",
|
||||
"typescript": "^4.9.5",
|
||||
"vue": "^3.2.47"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"vitepress": "^1.0.0-alpha.64"
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1 @@
|
||||
export * from './vitepress'
|
@ -0,0 +1,12 @@
|
||||
declare module 'ppst-vitepress-theme' {
|
||||
const CustomTheme: Theme = {
|
||||
Layout: any
|
||||
}
|
||||
|
||||
export { CustomTheme }
|
||||
}
|
||||
declare module '*.vue' {
|
||||
import { ComponentOptions } from 'vue'
|
||||
const componentOptions: ComponentOptions
|
||||
export default componentOptions
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
<template>
|
||||
<div class="page-banner-box max-width">
|
||||
<div class="banner">
|
||||
<div class="banner-left">
|
||||
<slot name="banner"></slot>
|
||||
</div>
|
||||
<div class="banner-right">
|
||||
<div class="title">归档</div>
|
||||
<div class="desc">时间顺序进行归档</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="archives-box">
|
||||
<div v-for="(yearList, index) in data" :key="index">
|
||||
<div class="year">
|
||||
{{ yearList[0].frontMatter.date.split("-")[0] }}
|
||||
</div>
|
||||
<a
|
||||
:href="withBase(article.regularPath)"
|
||||
v-for="(article, index) in yearList"
|
||||
:key="index"
|
||||
class="article"
|
||||
>
|
||||
<div class="title">
|
||||
<div class="title-o"></div>
|
||||
{{ article.frontMatter.title }}
|
||||
</div>
|
||||
<div class="date">{{ article.frontMatter.date.slice(5) }}</div>
|
||||
</a>
|
||||
</div>
|
||||
<div class="body-bg"></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useData, withBase } from "vitepress";
|
||||
import { computed } from "vue";
|
||||
import { useYearSort } from "../composables/functions";
|
||||
const { theme } = useData();
|
||||
const data = computed(() => useYearSort(theme.value.posts));
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.year {
|
||||
padding: 16px 0 8px 0;
|
||||
font-size: 1.4rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
.archives-box {
|
||||
border-radius: 5px;
|
||||
background: #fbfafc;
|
||||
box-shadow: 0 1px 2px 0 #fbfafc;
|
||||
padding: 40px;
|
||||
}
|
||||
.dark .archives-box{
|
||||
background: rgb(0 0 0 / 10%);
|
||||
box-shadow: 0 1px 2px 0 rgb(0 0 0 / 10%);
|
||||
}
|
||||
.article {
|
||||
padding: 4px 0 4px 25px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.title {
|
||||
color: var(--title-color);
|
||||
font-size: 1rem;
|
||||
}
|
||||
.title:hover {
|
||||
color: var(--c-main-color);
|
||||
}
|
||||
.date {
|
||||
color: var(--date-color);
|
||||
}
|
||||
</style>
|
@ -0,0 +1,3 @@
|
||||
<template>
|
||||
<svg t="1656596007290" fill="#666666" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2433" width="32" height="32"><path d="M528.978185 161.824619c-4.505617-4.502547-10.610662-7.033184-16.981766-7.033184-6.369058 0-12.472056 2.52859-16.97358 7.033184L320.073294 336.772117c-9.376555 9.377578-9.376555 24.576745 0 33.952276 9.375531 9.375531 24.576745 9.378601 33.952276 0l157.971871-157.971871 157.972894 157.971871c4.688789 4.688789 10.831696 7.033184 16.977673 7.033184 6.142907 0 12.288884-2.344395 16.978696-7.033184 9.375531-9.376555 9.375531-24.576745 0-33.952276L528.975115 161.824619 528.978185 161.824619 528.978185 161.824619z" p-id="2434"></path><path d="M64.55783 607.030353 167.254793 607.030353 167.254793 869.208565 215.270367 869.208565 215.270367 607.030353 317.968353 607.030353 317.968353 559.016827 64.55783 559.016827 64.55783 607.030353Z" p-id="2435"></path><path d="M582.790788 559.016827l-127.19696 0c-15.358803 0-30.719652 5.860475-42.439578 17.579377-11.718903 11.719926-17.578354 27.079752-17.578354 42.437531l0 190.156898c0 15.361873 5.860475 30.720675 17.578354 42.439578 11.720949 11.720949 27.080775 17.579377 42.439578 17.579377l127.19696 0c15.356756 0 30.719652-5.859451 42.438555-17.579377 11.719926-11.719926 17.579377-27.079752 17.579377-42.439578L642.80872 619.033735c0-15.358803-5.862521-30.718629-17.579377-42.437531C613.509417 564.874231 598.146521 559.016827 582.790788 559.016827L582.790788 559.016827zM594.79417 809.190633c0 2.269693-0.61296 5.582135-3.515057 8.486278-2.908236 2.90619-6.223748 3.518127-8.489348 3.518127l-127.19696 0c-2.267647 0-5.581112-0.610914-8.485255-3.515057-2.90619-2.908236-3.518127-6.222725-3.518127-8.490372L443.589422 619.033735c0-2.267647 0.60989-5.581112 3.515057-8.485255 2.905166-2.90619 6.221702-3.518127 8.488325-3.518127l127.19696 0c2.267647 0 5.581112 0.61296 8.483208 3.515057 2.908236 2.907213 3.520173 6.223748 3.520173 8.488325L594.793146 809.190633 594.79417 809.190633z" p-id="2436"></path><path d="M941.860746 576.59518c-11.719926-11.720949-27.082822-17.579377-42.440601-17.579377L734.803947 559.015803l0 310.192761 48.015573 0L782.81952 733.158982l116.600625 0c15.360849 0 30.722722-5.860475 42.440601-17.579377 11.718903-11.720949 17.5804-27.081799 17.5804-42.439578l0-54.107315C959.441147 603.674932 953.579649 588.315106 941.860746 576.59518L941.860746 576.59518zM911.42762 673.14105c0 2.269693-0.61296 5.580089-3.514033 8.485255-2.90926 2.907213-6.223748 3.518127-8.490372 3.518127L782.81952 685.144432l0-78.113055 116.603695 0c2.26867 0 5.581112 0.61296 8.487302 3.515057 2.904143 2.907213 3.517103 6.223748 3.517103 8.488325L911.42762 673.14105 911.42762 673.14105z" p-id="2437"></path></svg>
|
||||
</template>
|
@ -0,0 +1,47 @@
|
||||
<template>
|
||||
<div class="page-banner-box max-width">
|
||||
<div class="banner">
|
||||
<div class="banner-left">
|
||||
<slot name="banner"></slot>
|
||||
</div>
|
||||
<div class="banner-right">
|
||||
<div class="title">{{ props.title ? props.title : '标题' }}</div>
|
||||
<div class="desc">
|
||||
{{ props.description ? props.description : props.title ? props.title : '' }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-box max-width">
|
||||
<div class="card-item" v-for="(article, index) in data.list" :key="index">
|
||||
<div class="item-box">
|
||||
<div class="title">
|
||||
{{ article.frontMatter.title }}
|
||||
</div>
|
||||
<div class="mark-box">
|
||||
<a class="mark" :href="withBase(article.regularPath)">{{ article.frontMatter.title }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive } from "vue";
|
||||
import { useData, withBase } from "vitepress";
|
||||
import { Article } from "../config/baseConfig";
|
||||
import { initLists } from "../composables/functions";
|
||||
const { theme } = useData();
|
||||
const data:{list:Array<Article>} = reactive({list:[]})
|
||||
const props = defineProps({
|
||||
title: String,
|
||||
category:String,
|
||||
description: String,
|
||||
});
|
||||
|
||||
data.list = initLists(theme.value.posts,props.category?props.category:'js');
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
@ -0,0 +1,62 @@
|
||||
<template>
|
||||
<div class="site-footer">
|
||||
Copyright ©
|
||||
<a href="http://beian.miit.gov.cn/" target="_blank" class="site"
|
||||
>{{ data.footer.copyright }}</a
|
||||
>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { reactive, onMounted } from "vue";
|
||||
import { useData } from "vitepress";
|
||||
import { FooterConfig } from "../config/baseConfig";
|
||||
const { theme } = useData();
|
||||
const data: { footer: FooterConfig } = reactive({
|
||||
footer: {
|
||||
copyright: "",
|
||||
},
|
||||
});
|
||||
onMounted(() => {
|
||||
data.footer = theme.value.footer;
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.site-footer {
|
||||
color: #171a2e;
|
||||
height: 60px;
|
||||
text-align: center;
|
||||
font-size: 14px;
|
||||
width: 100vw;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background-color: var(--c-bg-white);
|
||||
position: relative;
|
||||
bottom: -60px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
}
|
||||
.dark .site-footer {
|
||||
background-color: var(--c-bg-black);
|
||||
}
|
||||
.site {
|
||||
color: var(--c-text-color-light);
|
||||
}
|
||||
a :link,
|
||||
a:visited,
|
||||
a:hover,
|
||||
a:active {
|
||||
color: var(--c-text-color-light);
|
||||
|
||||
}
|
||||
.dark .site {
|
||||
color: var(--c-text-color-dark);
|
||||
}
|
||||
.dark a :link,
|
||||
.dark a:visited,
|
||||
.dark a:hover,
|
||||
.dark a:active {
|
||||
color: var(--c-text-color-dark);
|
||||
}
|
||||
</style>
|
@ -0,0 +1,71 @@
|
||||
<template>
|
||||
<div class="page-banner-box max-width">
|
||||
<div class="banner">
|
||||
<div class="banner-left">
|
||||
<slot name="banner"></slot>
|
||||
</div>
|
||||
<div class="banner-right">
|
||||
<div class="title">{{ props.title ? props.title : '标题' }}</div>
|
||||
<div class="desc">
|
||||
{{ props.description ? props.description : props.title ? props.title : '' }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-box max-width">
|
||||
<div class="card-item" v-for="(article, index) in data.list" :key="index">
|
||||
<div class="item-box">
|
||||
<div class="title">{{ article.frontMatter.title }} 【{{ article.frontMatter.date }}】【{{ article.frontMatter.tags.join(", ") }}】</div>
|
||||
<div class="desc">
|
||||
{{ article.frontMatter.title }} : {{ article.frontMatter.description }}
|
||||
</div>
|
||||
<div class="mark-box">
|
||||
<a class="mark" :href="getWithBase(article.regularPath)">前往详情</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive } from "vue";
|
||||
import { useData } from "vitepress";
|
||||
import { Article } from "../config/baseConfig";
|
||||
import { initLists,getWithBase } from "../composables/functions";
|
||||
const {theme} = useData();
|
||||
const data:{list:Array<Article>} = reactive({list:[]})
|
||||
const props = defineProps({
|
||||
title: String,
|
||||
category:String,
|
||||
description: String,
|
||||
});
|
||||
|
||||
data.list = initLists(theme.value.posts,props.category?props.category:'js');
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.card-box .card-item {
|
||||
flex-basis: 100%;
|
||||
}
|
||||
.card-box .card-item .item-box{
|
||||
justify-content: flex-start;
|
||||
align-items: flex-start;
|
||||
}
|
||||
.card-box .item-box:hover .mark-box,
|
||||
.card-box .item-box:hover .mark-box .mark {
|
||||
opacity: 0.8;
|
||||
color: #000;
|
||||
font-size: 12px;
|
||||
background-color: rgba(255, 255, 255, .6);
|
||||
}
|
||||
|
||||
.dark .card-box .item-box:hover .mark-box,
|
||||
.dark .card-box .item-box:hover .mark-box .mark {
|
||||
opacity: 0.8;
|
||||
color: #fff;
|
||||
font-size: 12px;
|
||||
background-color: rgba(0, 0, 0, .6);
|
||||
}
|
||||
</style>
|
@ -0,0 +1,83 @@
|
||||
<template>
|
||||
<div class="banner-box max-width">
|
||||
<div class="banner">
|
||||
<div class="banner-left">
|
||||
<div class="title">{{ data.config.headline }}<span class="hight">{{ data.config.headlineHeight }}</span></div>
|
||||
<div class="title"><span class="hight">{{ data.config.subheadingHeight }}</span>{{ data.config.subheading }}</div>
|
||||
<div class="desc">{{ data.config.description }}</div>
|
||||
</div>
|
||||
<div class="banner-right">
|
||||
<slot name="banner"></slot>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-header max-width">
|
||||
<slot name="description"></slot>
|
||||
</div>
|
||||
<slot></slot>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { reactive, onMounted } from "vue";
|
||||
import { useData } from "vitepress";
|
||||
import { HomeConfig } from "../config/baseConfig";
|
||||
const { theme } = useData();
|
||||
const data: { config: HomeConfig } = reactive({
|
||||
config: {
|
||||
headline: "", //大标题
|
||||
headlineHeight: "", //大标题高亮
|
||||
subheading: "", //小标题
|
||||
subheadingHeight: "", //小标题高亮
|
||||
description: "", //描述
|
||||
}
|
||||
});
|
||||
onMounted(() => {
|
||||
data.config = theme.value.homeConfig;
|
||||
});
|
||||
</script>
|
||||
<style scoped>
|
||||
.margin-header {
|
||||
margin-top: 40px;
|
||||
}
|
||||
.banner-box {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.banner {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.banner-left {
|
||||
flex-basis: 50%;
|
||||
font-size: 36px;
|
||||
line-height: 2;
|
||||
padding-left: 10%;
|
||||
}
|
||||
.banner-left .title {
|
||||
color: var(--c-main-color);
|
||||
}
|
||||
.banner-left .desc {
|
||||
font-size: 18px;
|
||||
color: #888296;
|
||||
}
|
||||
.banner-left .hight {
|
||||
color: var(--c-text-color-light);
|
||||
}
|
||||
.dark .banner-left .hight {
|
||||
color: var(--c-text-color-dark);
|
||||
}
|
||||
.banner-right {
|
||||
width: 500px;
|
||||
}
|
||||
.banner-right img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
@ -0,0 +1,87 @@
|
||||
<template>
|
||||
<div id="top" class="wrap">
|
||||
<HeaderNav></HeaderNav>
|
||||
<div class="layout-box max-width">
|
||||
<div class="resize-layout">
|
||||
<div class="resize-left" ref="left"> <Sidebar></Sidebar></div>
|
||||
<div class="resize-right" ref="right">
|
||||
<div class="right-box">
|
||||
<Content class="page-box" />
|
||||
<a href="#top" class="return-top"><BackPng class="return-img" /></a>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Copyright />
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts" >
|
||||
import Copyright from './Copyright.vue'
|
||||
import HeaderNav from './header/Index.vue'
|
||||
import Sidebar from './Sidebar.vue'
|
||||
import BackPng from './BackPng.vue'
|
||||
import { ref,watch } from 'vue';
|
||||
import { useRoute } from 'vitepress';
|
||||
let left = ref();
|
||||
let right = ref();
|
||||
const route = useRoute();
|
||||
|
||||
watch(() => route.data.frontmatter.sidebar, (newValue, _oldValue) => {
|
||||
if(newValue===undefined){
|
||||
showRightBox();
|
||||
}else{
|
||||
hideRightBox();
|
||||
}
|
||||
});
|
||||
|
||||
function showRightBox() {
|
||||
left.value.style.width = '30%';
|
||||
right.value.style.width = '70%';
|
||||
}
|
||||
function hideRightBox() {
|
||||
left.value.style.width = '0';
|
||||
right.value.style.width = '100%';
|
||||
}
|
||||
</script>
|
||||
<style scoped>
|
||||
.layout-box{
|
||||
display: flex;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.page-box{
|
||||
width: 100%;
|
||||
min-height: 90vh;
|
||||
}
|
||||
|
||||
.resize-layout {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.resize-left {
|
||||
width: 0;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
.resize-right {
|
||||
width: 100%; /*右侧初始化宽度*/
|
||||
}
|
||||
|
||||
.right-box {
|
||||
height: 100%;
|
||||
}
|
||||
@media (max-width: 1200px) {
|
||||
|
||||
.resize-right{
|
||||
width: 100% !important;
|
||||
}
|
||||
.resize-left{
|
||||
width: 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
</style>
|
@ -0,0 +1,120 @@
|
||||
import { h } from 'vue'
|
||||
import { useRoute, useData, Header } from 'vitepress'
|
||||
export const hashRE = /#.*$/
|
||||
export const extRE = /(index)?\.(md|html)$/
|
||||
export const endingSlashRE = /\/$/
|
||||
export const outboundRE = /^[a-z]+:/i
|
||||
export function normalize(path: string) {
|
||||
return decodeURI(path).replace(hashRE, '').replace(extRE, '')
|
||||
}
|
||||
export function isActive(
|
||||
route: { data: { relativePath: string } },
|
||||
path: string
|
||||
) {
|
||||
if (path === undefined) {
|
||||
return false
|
||||
}
|
||||
const routePath = normalize(`/${route.data.relativePath}`)
|
||||
const pagePath = normalize(path)
|
||||
|
||||
return routePath === pagePath
|
||||
}
|
||||
export function joinUrl(base: string, path: string) {
|
||||
const baseEndsWithSlash = base.endsWith('/')
|
||||
const pathStartsWithSlash = path.startsWith('/')
|
||||
if (baseEndsWithSlash && pathStartsWithSlash) {
|
||||
return base.slice(0, -1) + path
|
||||
}
|
||||
if (!baseEndsWithSlash && !pathStartsWithSlash) {
|
||||
return `${base}/${path}`
|
||||
}
|
||||
|
||||
return base + path
|
||||
}
|
||||
export const SideBarLink = (props: any) => {
|
||||
const route = useRoute()
|
||||
const { site, frontmatter } = useData()
|
||||
const depth = props.depth || 1
|
||||
const maxDepth = frontmatter.value.sidebarDepth || Infinity
|
||||
const headers = route.data.headers
|
||||
const text = props.item.text
|
||||
const link = resolveLink(site.value.base, props.item.link)
|
||||
const children = props.item.children
|
||||
const active = isActive(route, props.item.link)
|
||||
const childItems =
|
||||
depth < maxDepth
|
||||
? createChildren(active, children, headers, depth + 1)
|
||||
: null
|
||||
return h('li', { class: 'sidebar-link' }, [
|
||||
h(
|
||||
link ? 'a' : 'p',
|
||||
{
|
||||
class: { 'sidebar-link-item': true, active },
|
||||
href: link
|
||||
},
|
||||
text
|
||||
),
|
||||
childItems
|
||||
])
|
||||
}
|
||||
function resolveLink(base: string, path: string) {
|
||||
if (path === undefined) {
|
||||
return path
|
||||
}
|
||||
// keep relative hash to the same page
|
||||
if (path.startsWith('#')) {
|
||||
return path
|
||||
}
|
||||
return joinUrl(base, path)
|
||||
}
|
||||
function createChildren(
|
||||
active: boolean,
|
||||
children: any,
|
||||
headers: Array<Header> | undefined,
|
||||
depth = 1
|
||||
) {
|
||||
if (children && children.length > 0) {
|
||||
return h(
|
||||
'ul',
|
||||
{ class: 'sidebar-links' },
|
||||
children.map((c: any) => {
|
||||
return h(SideBarLink, { item: c, depth })
|
||||
})
|
||||
)
|
||||
}
|
||||
if (active && headers && Array.isArray(headers)) {
|
||||
// if(createChildren(false, resolveHeaders(headers), undefined, depth)) return createChildren(false, resolveHeaders(headers), undefined, depth);
|
||||
}
|
||||
return null
|
||||
}
|
||||
// function resolveHeaders(headers:any) {
|
||||
// return mapHeaders(groupHeaders(headers));
|
||||
// }
|
||||
// function groupHeaders(headers:Array<Header>) {
|
||||
// headers = headers.map((h:Header) => Object.assign({}, h));
|
||||
// let lastH2:any;
|
||||
// headers.forEach((h:Header) => {
|
||||
// if (h.level === 2) {
|
||||
// lastH2 = h;
|
||||
// }
|
||||
// else if (lastH2) {
|
||||
// ;
|
||||
// (lastH2.children || (lastH2.children = [])).push(h);
|
||||
// }
|
||||
// });
|
||||
// return headers.filter((h:any) => h.level === 2);
|
||||
// }
|
||||
// function mapHeaders(headers:any) {
|
||||
// return headers.map((header:any) => {
|
||||
// let children = [];
|
||||
// if(header.children ){
|
||||
// children = mapHeaders(header.children)
|
||||
// }
|
||||
// return {
|
||||
// text: header.title,
|
||||
// link: `#${header.slug}`,
|
||||
// children: children
|
||||
// }
|
||||
// });
|
||||
|
||||
// }
|
@ -0,0 +1,46 @@
|
||||
<script setup lang="ts">
|
||||
import { useSideBar } from './sidebar/sideBar'
|
||||
import { SideBarLink } from './SideBarLink'
|
||||
const items = useSideBar()
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="seize-a-seat" v-if="items.length > 0"></div>
|
||||
<div class="side-box" v-if="items.length > 0">
|
||||
<h2>💡 目录</h2>
|
||||
<ul class="sidebar-links">
|
||||
<SideBarLink v-for="(item,index) of items" :item="item" :key="index"/>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
<style scoped>
|
||||
.side-box{
|
||||
background-color: #f0faf9;
|
||||
padding: 20px;
|
||||
background-image: linear-gradient(180deg, #fff, #fff);
|
||||
margin-right: 10px;
|
||||
}
|
||||
.dark .side-box{
|
||||
background-image: linear-gradient(180deg, #1a1a1a, #1a1a1a);
|
||||
}
|
||||
.seize-a-seat{
|
||||
width: 0;
|
||||
height: 0;
|
||||
}
|
||||
.sidebar-links{
|
||||
list-style: revert;
|
||||
}
|
||||
.sidebar-links{
|
||||
padding: 0;
|
||||
padding-left: 20px;
|
||||
padding-top: 6px;
|
||||
}
|
||||
@media (max-width: 1200px){
|
||||
.side-box{
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -0,0 +1,55 @@
|
||||
<template>
|
||||
<SwitchButton
|
||||
class="vt-switch-appearance"
|
||||
:aria-checked="isDark"
|
||||
@click="toggle"
|
||||
>
|
||||
<SunIcon class="vt-switch-appearance-sun" />
|
||||
<MoonIcon class="vt-switch-appearance-moon" />
|
||||
</SwitchButton>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue'
|
||||
import SwitchButton from './SwitchButton.vue'
|
||||
import SunIcon from './SunIcon.vue'
|
||||
import MoonIcon from './MoonIcon.vue'
|
||||
|
||||
const storageKey = 'vitepress-theme-appearance'
|
||||
const { isDark, toggle } = typeof localStorage !== 'undefined'
|
||||
? useAppearance()
|
||||
: { isDark: false, toggle: () => {}}
|
||||
|
||||
function useAppearance() {
|
||||
let userPreference = localStorage.getItem(storageKey) || 'auto'
|
||||
const query = window.matchMedia(`(prefers-color-scheme: dark)`)
|
||||
const classList = document.documentElement.classList
|
||||
const isDark = ref(
|
||||
userPreference === 'auto' ? query.matches : userPreference === 'dark'
|
||||
)
|
||||
const setClass = (dark: boolean) => classList[dark ? 'add' : 'remove']('dark')
|
||||
|
||||
query.onchange = (e) => {
|
||||
if (userPreference === 'auto') {
|
||||
setClass((isDark.value = e.matches))
|
||||
}
|
||||
}
|
||||
|
||||
const toggle = () => {
|
||||
setClass((isDark.value = !isDark.value))
|
||||
localStorage.setItem(
|
||||
storageKey,
|
||||
(userPreference = isDark.value
|
||||
? query.matches
|
||||
? 'auto'
|
||||
: 'dark'
|
||||
: query.matches
|
||||
? 'light'
|
||||
: 'auto')
|
||||
)
|
||||
}
|
||||
|
||||
return { isDark, toggle }
|
||||
}
|
||||
</script>
|
||||
|
@ -0,0 +1,5 @@
|
||||
<template>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewBox="0 0 24 24">
|
||||
<path d="M12.1,22c-0.3,0-0.6,0-0.9,0c-5.5-0.5-9.5-5.4-9-10.9c0.4-4.8,4.2-8.6,9-9c0.4,0,0.8,0.2,1,0.5c0.2,0.3,0.2,0.8-0.1,1.1c-2,2.7-1.4,6.4,1.3,8.4c2.1,1.6,5,1.6,7.1,0c0.3-0.2,0.7-0.3,1.1-0.1c0.3,0.2,0.5,0.6,0.5,1c-0.2,2.7-1.5,5.1-3.6,6.8C16.6,21.2,14.4,22,12.1,22zM9.3,4.4c-2.9,1-5,3.6-5.2,6.8c-0.4,4.4,2.8,8.3,7.2,8.7c2.1,0.2,4.2-0.4,5.8-1.8c1.1-0.9,1.9-2.1,2.4-3.4c-2.5,0.9-5.3,0.5-7.5-1.1C9.2,11.4,8.1,7.7,9.3,4.4z" />
|
||||
</svg>
|
||||
</template>
|
@ -0,0 +1,13 @@
|
||||
<template>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewBox="0 0 24 24">
|
||||
<path d="M12,18c-3.3,0-6-2.7-6-6s2.7-6,6-6s6,2.7,6,6S15.3,18,12,18zM12,8c-2.2,0-4,1.8-4,4c0,2.2,1.8,4,4,4c2.2,0,4-1.8,4-4C16,9.8,14.2,8,12,8z" />
|
||||
<path d="M12,4c-0.6,0-1-0.4-1-1V1c0-0.6,0.4-1,1-1s1,0.4,1,1v2C13,3.6,12.6,4,12,4z" />
|
||||
<path d="M12,24c-0.6,0-1-0.4-1-1v-2c0-0.6,0.4-1,1-1s1,0.4,1,1v2C13,23.6,12.6,24,12,24z" />
|
||||
<path d="M5.6,6.6c-0.3,0-0.5-0.1-0.7-0.3L3.5,4.9c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l1.4,1.4c0.4,0.4,0.4,1,0,1.4C6.2,6.5,5.9,6.6,5.6,6.6z" />
|
||||
<path d="M19.8,20.8c-0.3,0-0.5-0.1-0.7-0.3l-1.4-1.4c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l1.4,1.4c0.4,0.4,0.4,1,0,1.4C20.3,20.7,20,20.8,19.8,20.8z" />
|
||||
<path d="M3,13H1c-0.6,0-1-0.4-1-1s0.4-1,1-1h2c0.6,0,1,0.4,1,1S3.6,13,3,13z" />
|
||||
<path d="M23,13h-2c-0.6,0-1-0.4-1-1s0.4-1,1-1h2c0.6,0,1,0.4,1,1S23.6,13,23,13z" />
|
||||
<path d="M4.2,20.8c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l1.4-1.4c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-1.4,1.4C4.7,20.7,4.5,20.8,4.2,20.8z" />
|
||||
<path d="M18.4,6.6c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l1.4-1.4c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-1.4,1.4C18.9,6.5,18.6,6.6,18.4,6.6z" />
|
||||
</svg>
|
||||
</template>
|
@ -0,0 +1,9 @@
|
||||
<template>
|
||||
<button class="vt-switch" type="button" role="switch">
|
||||
<span class="vt-switch-check">
|
||||
<span class="vt-switch-icon" v-if="$slots.default">
|
||||
<slot />
|
||||
</span>
|
||||
</span>
|
||||
</button>
|
||||
</template>
|
@ -0,0 +1,72 @@
|
||||
<script lang="ts" setup>
|
||||
import DarkSwitch from "./../darkSwitch/Index.vue";
|
||||
import { useData } from 'vitepress'
|
||||
|
||||
const { theme } = useData()
|
||||
const data = theme.value.nav
|
||||
const title = theme.value.title
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="header-box max-width">
|
||||
<div class="logo-box">
|
||||
<span><a href="/" class="logo-title">{{ title }}</a></span>
|
||||
</div>
|
||||
<div class="nav-box">
|
||||
<div class="nav-list">
|
||||
<span v-for="(item, key) in data" :key="key">
|
||||
<a v-if="item.link" :href="item.link" class="nav-item">{{ item.text }}</a>
|
||||
</span>
|
||||
<div class="nav-item">
|
||||
<DarkSwitch />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.header-box {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
width: 100%;
|
||||
margin: 0 auto;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.header-box .logo-title {
|
||||
font-size: 20px;
|
||||
font-weight: 700;
|
||||
color: var(--c-main-color);
|
||||
}
|
||||
|
||||
.header-box .nav-box {
|
||||
display: flex;
|
||||
padding: 0 10px;
|
||||
justify-content: space-evenly;
|
||||
}
|
||||
|
||||
.header-box .nav-list {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.header-box .nav-item {
|
||||
line-height: 40px;
|
||||
padding: 8px 16px;
|
||||
font-weight: 700;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.nav-item:hover {
|
||||
color: var(--c-main-color);
|
||||
}
|
||||
.active {
|
||||
color: var(--c-main-color);
|
||||
}
|
||||
</style>
|
@ -0,0 +1,101 @@
|
||||
import { onMounted, onUnmounted, onUpdated } from 'vue'
|
||||
export function useActiveSidebarLinks() {
|
||||
let rootActiveLink: HTMLAnchorElement | null = null
|
||||
let activeLink: Element | null = null
|
||||
const onScroll = throttleAndDebounce(setActiveLink, 300)
|
||||
function setActiveLink() {
|
||||
const sidebarLinks = getSidebarLinks()
|
||||
const anchors = getAnchors(sidebarLinks)
|
||||
for (let i = 0; i < anchors.length; i++) {
|
||||
const anchor = anchors[i]
|
||||
const nextAnchor = anchors[i + 1]
|
||||
const [isActive, hash] = isAnchorActive(i, anchor, nextAnchor)
|
||||
if (isActive) {
|
||||
history.replaceState(null, document.title, '')
|
||||
activateLink(hash)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
function activateLink(hash: any) {
|
||||
deactiveLink(activeLink)
|
||||
deactiveLink(rootActiveLink)
|
||||
activeLink = document.querySelector(`.sidebar a[href="${hash}"]`)
|
||||
if (!activeLink) {
|
||||
return
|
||||
}
|
||||
activeLink.classList.add('active')
|
||||
// also add active class to parent h2 anchors
|
||||
const rootLi = activeLink.closest('.sidebar-links > ul > li')
|
||||
if (rootLi && rootLi !== activeLink.parentElement) {
|
||||
rootActiveLink = rootLi.querySelector('a')
|
||||
rootActiveLink && rootActiveLink.classList.add('active')
|
||||
} else {
|
||||
rootActiveLink = null
|
||||
}
|
||||
}
|
||||
function deactiveLink(link: any) {
|
||||
link && link.classList.remove('active')
|
||||
}
|
||||
onMounted(() => {
|
||||
setActiveLink()
|
||||
window.addEventListener('scroll', onScroll)
|
||||
})
|
||||
onUpdated(() => {
|
||||
// sidebar update means a route change
|
||||
activateLink(decodeURIComponent(location.hash))
|
||||
})
|
||||
onUnmounted(() => {
|
||||
window.removeEventListener('scroll', onScroll)
|
||||
})
|
||||
}
|
||||
function getSidebarLinks() {
|
||||
return [].slice.call(
|
||||
document.querySelectorAll('.sidebar a.sidebar-link-item')
|
||||
)
|
||||
}
|
||||
function getAnchors(sidebarLinks: any) {
|
||||
return [].slice
|
||||
.call(document.querySelectorAll('.header-anchor'))
|
||||
.filter((anchor: any) =>
|
||||
sidebarLinks.some((sidebarLink: any) => sidebarLink.hash === anchor.hash)
|
||||
)
|
||||
}
|
||||
function getPageOffset() {
|
||||
return (document.querySelector('.nav-bar') as HTMLElement).offsetHeight
|
||||
}
|
||||
function getAnchorTop(anchor: any) {
|
||||
const pageOffset = getPageOffset()
|
||||
return anchor.parentElement.offsetTop - pageOffset - 15
|
||||
}
|
||||
function isAnchorActive(index: number, anchor: any, nextAnchor: any) {
|
||||
const scrollTop = window.scrollY
|
||||
if (index === 0 && scrollTop === 0) {
|
||||
return [true, null]
|
||||
}
|
||||
if (scrollTop < getAnchorTop(anchor)) {
|
||||
return [false, null]
|
||||
}
|
||||
if (!nextAnchor || scrollTop < getAnchorTop(nextAnchor)) {
|
||||
return [true, decodeURIComponent(anchor.hash)]
|
||||
}
|
||||
return [false, null]
|
||||
}
|
||||
function throttleAndDebounce(fn: any, delay: any) {
|
||||
let timeout: any
|
||||
let called = false
|
||||
return () => {
|
||||
if (timeout) {
|
||||
clearTimeout(timeout)
|
||||
}
|
||||
if (!called) {
|
||||
fn()
|
||||
called = true
|
||||
setTimeout(() => {
|
||||
called = false
|
||||
}, delay)
|
||||
} else {
|
||||
timeout = setTimeout(fn, delay)
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
import { computed } from 'vue'
|
||||
import { useRoute } from 'vitepress'
|
||||
export const defaultLang = 'zh-CN'
|
||||
|
||||
export const PREFERRED_LANG_KEY = 'vuetom_lang'
|
||||
|
||||
export const breakpoints = {
|
||||
sm: 480,
|
||||
md: 768,
|
||||
lg: 960,
|
||||
xlg: 1280,
|
||||
xxl: 1440
|
||||
}
|
||||
export const useLang = () => {
|
||||
const route = useRoute()
|
||||
|
||||
return computed(() => {
|
||||
// the first part of the first slash
|
||||
const path = route.data?.relativePath
|
||||
let lang: string | undefined = ''
|
||||
|
||||
if (path && path.includes('/')) {
|
||||
lang = path.split('/').shift()
|
||||
} else {
|
||||
lang = defaultLang
|
||||
}
|
||||
|
||||
return lang
|
||||
})
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
import { computed } from 'vue'
|
||||
import { useRoute, useData } from 'vitepress'
|
||||
import { useLang } from './lang'
|
||||
import { useActiveSidebarLinks } from './activeSidebarLink'
|
||||
import { getSideBarConfig } from './support'
|
||||
export function useSideBar() {
|
||||
const route = useRoute()
|
||||
const { site } = useData()
|
||||
const lang = useLang()
|
||||
useActiveSidebarLinks()
|
||||
return computed(() => {
|
||||
// at first, we'll check if we can find the sidebar setting in frontmatter.
|
||||
const headers = route.data.headers
|
||||
const frontSidebar = route.data.frontmatter.sidebar
|
||||
const sidebarDepth = route.data.frontmatter.sidebarDepth
|
||||
// if it's `false`, we'll just return an empty array here.
|
||||
if (frontSidebar === false) {
|
||||
return []
|
||||
}
|
||||
// if it's `atuo`, render headers of the current page
|
||||
if (frontSidebar === 'auto') {
|
||||
return resolveAutoSidebar(headers, sidebarDepth)
|
||||
}
|
||||
// now, there's no sidebar setting at frontmatter; let's see the configs
|
||||
const themeSidebar = getSideBarConfig(
|
||||
site.value.themeConfig.sidebar,
|
||||
route.data.relativePath,
|
||||
lang.value ? lang.value : ''
|
||||
)
|
||||
if (themeSidebar === false) {
|
||||
return []
|
||||
}
|
||||
if (themeSidebar === 'auto') {
|
||||
return resolveAutoSidebar(headers, sidebarDepth)
|
||||
}
|
||||
return themeSidebar
|
||||
})
|
||||
}
|
||||
function resolveAutoSidebar(
|
||||
headers: Array<{ level: number; title: string; slug: string }>,
|
||||
depth: number
|
||||
) {
|
||||
const ret: Array<{
|
||||
text: string
|
||||
link: string
|
||||
}> = []
|
||||
if (headers === undefined) {
|
||||
return []
|
||||
}
|
||||
let lastH2: any = undefined
|
||||
headers.forEach(({ level, title, slug }) => {
|
||||
if (level - 1 > depth) {
|
||||
return
|
||||
}
|
||||
const item = {
|
||||
text: title,
|
||||
link: `#${slug}`
|
||||
}
|
||||
if (level === 2) {
|
||||
lastH2 = item
|
||||
ret.push(item)
|
||||
} else if (lastH2) {
|
||||
;(lastH2.children || (lastH2.children = [])).push(item)
|
||||
}
|
||||
})
|
||||
return ret
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
import { isArray, ensureStartingSlash, removeExtention } from './utils'
|
||||
|
||||
export function isSideBarConfig(sidebar: any) {
|
||||
return sidebar === false || sidebar === 'auto' || isArray(sidebar)
|
||||
}
|
||||
export function isSideBarGroup(item: any) {
|
||||
return item.children !== undefined
|
||||
}
|
||||
export function isSideBarEmpty(sidebar: any) {
|
||||
return isArray(sidebar) ? sidebar.length === 0 : !sidebar
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the `SideBarConfig` from sidebar option. This method will ensure to get
|
||||
* correct sidebar config from `MultiSideBarConfig` with various path
|
||||
* combinations such as matching `guide/` and `/guide/`. If no matching config
|
||||
* was found, it will return `auto` as a fallback.
|
||||
*/
|
||||
export function getSideBarConfig(sidebar: any, path: string, lang: string) {
|
||||
if (isSideBarConfig(sidebar)) {
|
||||
return sidebar
|
||||
}
|
||||
path = ensureStartingSlash(path)
|
||||
for (const dir in sidebar) {
|
||||
// make sure the multi sidebar key starts with slash too
|
||||
if (path.startsWith(ensureStartingSlash(`${lang}${dir}`))) {
|
||||
return sidebar[dir][lang]
|
||||
}
|
||||
}
|
||||
|
||||
return 'auto'
|
||||
}
|
||||
|
||||
/**
|
||||
* Get flat sidebar links from the sidebar items. This method is useful for
|
||||
* creating the "next and prev link" feature. It will ignore any items that
|
||||
* don't have `link` property and removes `.md` or `.html` extension if a
|
||||
* link contains it.
|
||||
*/
|
||||
export function getFlatSideBarLinks(sidebar: any) {
|
||||
return sidebar.reduce((links: any, item: any) => {
|
||||
if (item.link) {
|
||||
links.push({ text: item.text, link: removeExtention(item.link) })
|
||||
}
|
||||
if (isSideBarGroup(item)) {
|
||||
links = [...links, ...getFlatSideBarLinks(item.children)]
|
||||
}
|
||||
|
||||
return links
|
||||
}, [])
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
export const hashRE = /#.*$/
|
||||
export const extRE = /(index)?\.(md|html)$/
|
||||
export const endingSlashRE = /\/$/
|
||||
export const outboundRE = /^[a-z]+:/i
|
||||
export function isNullish(value: string) {
|
||||
return value === null || value === undefined
|
||||
}
|
||||
export function isArray(value: string) {
|
||||
return Array.isArray(value)
|
||||
}
|
||||
export function isExternal(path: string) {
|
||||
return outboundRE.test(path)
|
||||
}
|
||||
export function isActive(
|
||||
route: { data: { relativePath: string } },
|
||||
path: string
|
||||
) {
|
||||
if (path === undefined) {
|
||||
return false
|
||||
}
|
||||
const routePath = normalize(`/${route.data.relativePath}`)
|
||||
const pagePath = normalize(path)
|
||||
|
||||
return routePath === pagePath
|
||||
}
|
||||
export function normalize(path: string) {
|
||||
return decodeURI(path).replace(hashRE, '').replace(extRE, '')
|
||||
}
|
||||
export function joinUrl(base: string, path: string) {
|
||||
const baseEndsWithSlash = base.endsWith('/')
|
||||
const pathStartsWithSlash = path.startsWith('/')
|
||||
if (baseEndsWithSlash && pathStartsWithSlash) {
|
||||
return base.slice(0, -1) + path
|
||||
}
|
||||
if (!baseEndsWithSlash && !pathStartsWithSlash) {
|
||||
return `${base}/${path}`
|
||||
}
|
||||
|
||||
return base + path
|
||||
}
|
||||
|
||||
/**
|
||||
* get the path without filename (the last segment). for example, if the given
|
||||
* path is `/guide/getting-started.html`, this method will return `/guide/`.
|
||||
* Always with a trailing slash.
|
||||
*/
|
||||
export function getPathDirName(path: string) {
|
||||
const segments = path.split('/')
|
||||
if (segments[segments.length - 1]) {
|
||||
segments.pop()
|
||||
}
|
||||
|
||||
return ensureEndingSlash(segments.join('/'))
|
||||
}
|
||||
export function ensureSlash(path: string) {
|
||||
return ensureEndingSlash(ensureStartingSlash(path))
|
||||
}
|
||||
export function ensureStartingSlash(path: string) {
|
||||
return /^\//.test(path) ? path : `/${path}`
|
||||
}
|
||||
export function ensureEndingSlash(path: string) {
|
||||
return /(\.html|\/)$/.test(path) ? path : `${path}/`
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove `.md` or `.html` extention from the given path. It also converts
|
||||
* `index` to slush.
|
||||
*/
|
||||
export function removeExtention(path: string) {
|
||||
return path.replace(/(index)?(\.(md|html))?$/, '') || '/'
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
import {
|
||||
Component,
|
||||
defineComponent,
|
||||
h,
|
||||
inject,
|
||||
InjectionKey,
|
||||
provide,
|
||||
Ref
|
||||
} from 'vue'
|
||||
import { useData } from 'vitepress'
|
||||
import { Config } from '../config'
|
||||
|
||||
const configSymbol: InjectionKey<Ref<Config>> = Symbol('config')
|
||||
export function withConfigProvider(App: Component) {
|
||||
return defineComponent({
|
||||
name: 'ConfigProvider',
|
||||
setup(_, { slots }) {
|
||||
const { theme } = useData()
|
||||
provide(configSymbol, theme.value)
|
||||
return () => h(App, null, slots)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export function useConfig() {
|
||||
return {
|
||||
config: inject(configSymbol)!
|
||||
}
|
||||
}
|
@ -0,0 +1,102 @@
|
||||
import { Article, Post } from '../config/baseConfig'
|
||||
import { useData, withBase } from "vitepress";
|
||||
export function getTags(post: Post[]) {
|
||||
let data: Array<string> = []
|
||||
for (let index = 0; index < post.length; index++) {
|
||||
const element = post[index]
|
||||
const tags = element.frontMatter.tags
|
||||
if (tags && tags.length > 0) {
|
||||
tags.forEach((item) => {
|
||||
data.push(item)
|
||||
})
|
||||
}
|
||||
}
|
||||
// data = [...new Set(data)];
|
||||
return data.sort()
|
||||
}
|
||||
export function initTags(post: Post[]) {
|
||||
const data: any = {}
|
||||
for (let index = 0; index < post.length; index++) {
|
||||
const element = post[index]
|
||||
const tags = element.frontMatter.tags
|
||||
if (tags && tags.length > 0) {
|
||||
tags.forEach((item) => {
|
||||
if (data[item]) {
|
||||
data[item].push(element)
|
||||
} else {
|
||||
data[item] = []
|
||||
data[item].push(element)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
return data
|
||||
}
|
||||
export function searchData(post: Post[], keyword: string) {
|
||||
const data: Array<Article> = []
|
||||
for (let index = 0; index < post.length; index++) {
|
||||
const element = post[index]
|
||||
let hasArticle = false
|
||||
if (element.frontMatter.title.includes(keyword)) {
|
||||
hasArticle = true
|
||||
}
|
||||
if (element.frontMatter.category.includes(keyword)) {
|
||||
hasArticle = true
|
||||
}
|
||||
if (element.frontMatter.description.includes(keyword)) {
|
||||
hasArticle = true
|
||||
}
|
||||
const tags = element.frontMatter.tags
|
||||
if (tags && tags.length > 0) {
|
||||
tags.forEach((tag) => {
|
||||
if (tag && tag.includes(keyword)) {
|
||||
hasArticle = true
|
||||
}
|
||||
})
|
||||
}
|
||||
if (hasArticle) {
|
||||
data.push(element)
|
||||
}
|
||||
}
|
||||
return data
|
||||
}
|
||||
export function initLists(post: Post[], category: string) {
|
||||
const data: Array<Article> = []
|
||||
for (let index = 0; index < post.length; index++) {
|
||||
const element = post[index]
|
||||
if (element.frontMatter.category == category) {
|
||||
data.push(element)
|
||||
}
|
||||
}
|
||||
return data
|
||||
}
|
||||
export function useYearSort(post: Post[]) {
|
||||
const data = []
|
||||
let year = '0'
|
||||
let num = -1
|
||||
for (let index = 0; index < post.length; index++) {
|
||||
const element = post[index]
|
||||
if (element.frontMatter.date) {
|
||||
const y = element.frontMatter.date.split('-')[0]
|
||||
if (y === year) {
|
||||
data[num].push(element)
|
||||
} else {
|
||||
num++
|
||||
data[num] = [] as any
|
||||
data[num].push(element)
|
||||
year = y
|
||||
}
|
||||
}
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
|
||||
export function getWithBase(url: string) {
|
||||
let baseUrl = url;
|
||||
const { theme } = useData();
|
||||
if(theme.value.docRoot){
|
||||
baseUrl = url.replace('/'+theme.value.docRoot+'/', '')
|
||||
}
|
||||
return withBase(baseUrl);
|
||||
}
|
@ -0,0 +1,96 @@
|
||||
import { FooterConfig, HomeConfig, NavItem } from './config/baseConfig'
|
||||
|
||||
export interface Config {
|
||||
title:string;
|
||||
homeConfig: HomeConfig
|
||||
hasDarkSwitch: boolean
|
||||
docRoot:string
|
||||
nav?: NavItem[]
|
||||
|
||||
footer: FooterConfig
|
||||
|
||||
/**
|
||||
* Algolia configuration for the site search.
|
||||
*/
|
||||
algolia?: AlgoliaSearchOptions
|
||||
|
||||
/**
|
||||
* CarbonAds configuration
|
||||
*/
|
||||
carbonAds?: {
|
||||
code: string
|
||||
placement: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Translation/Locales links
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* The Algolia search options. Partially copied from
|
||||
* @docsearch/react/dist/esm/DocSearch.d.ts
|
||||
*/
|
||||
export interface AlgoliaSearchOptions {
|
||||
appId?: string
|
||||
apiKey: string
|
||||
indexName: string
|
||||
placeholder?: string
|
||||
searchParameters?: any
|
||||
disableUserPersonalization?: boolean
|
||||
initialQuery?: string
|
||||
translations?: Partial<DocSearchTranslations>
|
||||
}
|
||||
|
||||
export interface DocSearchTranslations {
|
||||
button?: ButtonTranslations
|
||||
modal?: ModalTranslations
|
||||
}
|
||||
|
||||
export interface ButtonTranslations {
|
||||
buttonText?: string
|
||||
buttonAriaLabel?: string
|
||||
}
|
||||
export interface ModalTranslations extends ScreenStateTranslations {
|
||||
searchBox?: {
|
||||
resetButtonTitle?: string
|
||||
resetButtonAriaLabel?: string
|
||||
cancelButtonText?: string
|
||||
cancelButtonAriaLabel?: string
|
||||
}
|
||||
footer?: {
|
||||
selectText?: string
|
||||
selectKeyAriaLabel?: string
|
||||
navigateText?: string
|
||||
navigateUpKeyAriaLabel?: string
|
||||
navigateDownKeyAriaLabel?: string
|
||||
closeText?: string
|
||||
closeKeyAriaLabel?: string
|
||||
searchByText?: string
|
||||
}
|
||||
}
|
||||
export interface ScreenStateTranslations {
|
||||
errorScreen?: {
|
||||
titleText?: string
|
||||
helpText?: string
|
||||
}
|
||||
startScreen?: {
|
||||
recentSearchesTitle?: string
|
||||
noRecentSearchesText?: string
|
||||
saveRecentSearchButtonTitle?: string
|
||||
removeRecentSearchButtonTitle?: string
|
||||
favoriteSearchesTitle?: string
|
||||
removeFavoriteSearchButtonTitle?: string
|
||||
}
|
||||
noResultsScreen?: {
|
||||
noResultsText?: string
|
||||
suggestedQueryText?: string
|
||||
reportMissingResultsText?: string
|
||||
reportMissingResultsLinkText?: string
|
||||
}
|
||||
}
|
||||
export interface MessageWithLink {
|
||||
before?: string
|
||||
link?: string
|
||||
after?: string
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
import { UserConfig } from 'vitepress'
|
||||
import { Config } from '../config'
|
||||
declare const config: UserConfig<Config>
|
||||
export default config
|
||||
export interface Article {
|
||||
regularPath: string
|
||||
frontMatter: {
|
||||
description: string
|
||||
date: string
|
||||
title: string
|
||||
tags: Array<string>
|
||||
}
|
||||
}
|
||||
export type Post = {
|
||||
frontMatter: {
|
||||
date: string
|
||||
title: string
|
||||
category: string
|
||||
tags: string[]
|
||||
description: string
|
||||
}
|
||||
regularPath: string
|
||||
}
|
||||
export interface HomeConfig {
|
||||
headline: string //大标题
|
||||
headlineHeight: string //大标题高亮
|
||||
subheading: string //小标题
|
||||
subheadingHeight: string //小标题高亮
|
||||
description: string //描述
|
||||
}
|
||||
|
||||
export interface NavItem {
|
||||
text: string
|
||||
link: string
|
||||
icon?: string
|
||||
}
|
||||
export interface FooterConfig {
|
||||
copyright: string
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
import 'normalize.css/normalize.css'
|
||||
import './styles/variables.css'
|
||||
import './styles/switch.css'
|
||||
import './styles/custom.css'
|
||||
import './styles/theme.css'
|
||||
import Layout from './components/Layout.vue'
|
||||
import Search from './components/Search.vue'
|
||||
import Archives from './components/Archives.vue'
|
||||
import Home from './components/Home.vue'
|
||||
import DefaultPage from './components/DefaultPage.vue'
|
||||
import CategoryPage from './components/CategoryPage.vue'
|
||||
import { Theme } from 'vitepress'
|
||||
import { withConfigProvider } from './composables/config'
|
||||
|
||||
const CustomTheme: Theme = {
|
||||
Layout: withConfigProvider(Layout),
|
||||
NotFound: () => 'custom 404',
|
||||
enhanceApp({ app }) {
|
||||
app.component('Search', Search)
|
||||
app.component('Archives', Archives)
|
||||
app.component('Home', Home)
|
||||
app.component('DefaultPage', DefaultPage)
|
||||
app.component('CategoryPage', CategoryPage)
|
||||
}
|
||||
}
|
||||
|
||||
export { CustomTheme }
|
||||
export type { Config } from './config'
|
@ -0,0 +1,359 @@
|
||||
/*keep the change things*/
|
||||
html {
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
font-size: 16px;
|
||||
color: var(--c-text-color-light)
|
||||
}
|
||||
.dark body {
|
||||
color: var(--c-text-color-dark);
|
||||
}
|
||||
|
||||
/*theme reset*/
|
||||
a,a:link,a:visited,a:hover,a::after{
|
||||
color: var(--c-text-color-light)
|
||||
}
|
||||
.dark a,.dark a:link,.dark a:visited,.dark a:hover,.dark a::after {
|
||||
color: var(--c-text-color-dark);
|
||||
}
|
||||
|
||||
a:link {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 1.7rem;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 1.125rem;
|
||||
margin-bottom: inherit;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
h2+h3+h3+h4+h5 {
|
||||
margin-top: 1.5rem;
|
||||
}
|
||||
|
||||
/* 设置滚动条的样式 */
|
||||
::-webkit-scrollbar {
|
||||
width: 1px;
|
||||
}
|
||||
|
||||
/* 滚动槽 */
|
||||
::-webkit-scrollbar-track {
|
||||
-webkit-box-shadow: inset006pxrgba(0, 0, 0, 0.3);
|
||||
border-radius: 1px;
|
||||
}
|
||||
|
||||
/* 滚动条滑块 */
|
||||
::-webkit-scrollbar-thumb {
|
||||
border-radius: 1px;
|
||||
background: rgba(0, 0, 0, 0.1);
|
||||
-webkit-box-shadow: inset006pxrgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb:window-inactive {
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.return-top{
|
||||
position: fixed;
|
||||
bottom: 80px;
|
||||
right: 10px;
|
||||
}
|
||||
|
||||
.max-width {
|
||||
max-width: 1200px;
|
||||
}
|
||||
|
||||
.mg-header {
|
||||
margin-top: 40px;
|
||||
}
|
||||
|
||||
/* card */
|
||||
.card-header {
|
||||
width: 100%;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.card-header .title {
|
||||
color: var(--c-main-color);
|
||||
font-size: 36px;
|
||||
text-align: center;
|
||||
line-height: 2;
|
||||
}
|
||||
|
||||
.card-header .desc {
|
||||
color: var(--c-text-color-dark);
|
||||
font-size: 18px;
|
||||
text-align: center;
|
||||
line-height: 2;
|
||||
}
|
||||
.dark .card-header .desc {
|
||||
color: var(--c-text-color-dark);
|
||||
}
|
||||
[class*='language-'] pre {
|
||||
background-color: #000;
|
||||
}
|
||||
|
||||
|
||||
.note-box {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
margin: 0 auto;
|
||||
padding: 20px 0;
|
||||
}
|
||||
|
||||
.note-box .note-item {
|
||||
flex-basis: 33%;
|
||||
padding: 15px;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.note-box .note-item .item-box {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 120px;
|
||||
background-color: rgba(229, 234, 241, 0.6);
|
||||
border-radius: 15px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.note-box .note-item .item-box .title {
|
||||
color: rgba(65, 86, 120, 1);
|
||||
}
|
||||
.dark .note-box .note-item .item-box {
|
||||
background-color: rgb(82 85 89 / 60%);
|
||||
}
|
||||
|
||||
.dark .note-box .note-item .item-box .title {
|
||||
color: #fff;
|
||||
}
|
||||
.note-box .note-item .item-box .go {
|
||||
opacity: 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
border-radius: 15px;
|
||||
background-color: var(--c-main-color);
|
||||
|
||||
}
|
||||
|
||||
.button-box {
|
||||
color: #fff;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.card-box {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
margin: 0 auto;
|
||||
padding: 20px 0;
|
||||
}
|
||||
|
||||
.card-box .card-item {
|
||||
flex-basis: 25%;
|
||||
padding: 15px;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.card-box .card-item .item-box {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border-radius: 15px;
|
||||
padding: 15px;
|
||||
background: #f8f8fc;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
.card-box .card-item .item-box {
|
||||
border-radius: 5px;
|
||||
background: #fbfafc;
|
||||
box-shadow: 0 1px 2px 0 #fbfafc;
|
||||
padding: 40px;
|
||||
}
|
||||
.dark .card-box .card-item .item-box{
|
||||
background: rgb(0 0 0 / 10%);
|
||||
box-shadow: 0 1px 2px 0 rgb(0 0 0 / 10%);
|
||||
}
|
||||
.card-box .card-item .item-box .title {
|
||||
font-size: 16px;
|
||||
line-height: 2;
|
||||
font-weight: 500;
|
||||
color: #020312;
|
||||
}
|
||||
.dark .card-box .card-item .item-box .title{
|
||||
color: #fbfafc;
|
||||
}
|
||||
.card-box .card-item .item-box .desc {
|
||||
font-size: 16px;
|
||||
line-height: 2;
|
||||
color: #717e96;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.card-box .card-item:hover .item-box .icon,
|
||||
.card-box .card-item:hover .item-box .title,
|
||||
.card-box .card-item:hover .item-box .desc,
|
||||
.card-box .card-item .item-box.active .icon,
|
||||
.card-box .card-item .item-box.active .title,
|
||||
.card-box .card-item .item-box.active .desc {
|
||||
color: var(--c-main-color);
|
||||
}
|
||||
|
||||
.card-box .item-box .mark-box {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
transition: all 0.5s ease;
|
||||
border-radius: 15px;
|
||||
margin: auto;
|
||||
opacity: 0;
|
||||
|
||||
}
|
||||
|
||||
.mark-box .mark {
|
||||
color: #fff;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
.page-banner-box {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
margin: 0 auto;
|
||||
padding: 60px 0;
|
||||
}
|
||||
|
||||
.page-banner-box .banner {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.page-banner-box .banner-right {
|
||||
flex-basis: 50%;
|
||||
font-size: 28px;
|
||||
line-height: 2;
|
||||
padding-left: 8%;
|
||||
|
||||
}
|
||||
|
||||
.page-banner-box .banner-right .title {
|
||||
color: var(--c-main-color);
|
||||
}
|
||||
|
||||
.page-banner-box .banner-right .desc {
|
||||
font-size: 18px;
|
||||
color: #888296;
|
||||
}
|
||||
|
||||
.page-banner-box .banner-right .hight {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.page-banner-box .banner-left {
|
||||
width: 320px;
|
||||
}
|
||||
|
||||
.page-banner-box .banner-left img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
|
||||
@media (max-width: 1200px) {
|
||||
body {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.logo-box {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.card-header .title {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.card-header .desc {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.page-banner-box .banner-right {
|
||||
font-size: 14px
|
||||
}
|
||||
|
||||
.page-banner-box .banner-right .desc {
|
||||
font-size: 12px
|
||||
}
|
||||
|
||||
.note-box {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.note-box .note-item {
|
||||
flex-basis: 100%;
|
||||
}
|
||||
|
||||
.card-box {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.card-box .card-item {
|
||||
flex-basis: 100%;
|
||||
}
|
||||
|
||||
.card-box .card-item .item-box {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.card-box .item-box .mark-box {
|
||||
opacity: 1;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.card-box .card-item .item-box .title {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.card-box .card-item .item-box .desc {
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
@import 'vitepress/dist/client/theme-default/styles/fonts.css';
|
||||
@import '../../core/styles/index.css';
|
||||
@import './variables.css';
|
@ -0,0 +1,69 @@
|
||||
.vt-switch {
|
||||
position: relative;
|
||||
border-radius: 11px;
|
||||
display: block;
|
||||
width: 40px;
|
||||
height: 22px;
|
||||
flex-shrink: 0;
|
||||
border: 1px solid var(--c-bg-white);
|
||||
transition: border-color 0.25s, background-color 0.25s;
|
||||
}
|
||||
|
||||
.vt-switch:hover {
|
||||
border-color: var(--c-bg-white);
|
||||
}
|
||||
|
||||
.vt-switch-check {
|
||||
position: absolute;
|
||||
top: 1px;
|
||||
left: 1px;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
border-radius: 50%;
|
||||
box-shadow: var(--vt-shadow-1);
|
||||
transition: background-color 0.25s, transform 0.25s;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.vt-switch-icon {
|
||||
position: relative;
|
||||
display: block;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.vt-switch-icon svg {
|
||||
position: absolute;
|
||||
top: 3px;
|
||||
left: 3px;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
fill: var(--vt-c-text-2);
|
||||
}
|
||||
|
||||
.dark .vt-switch-icon svg {
|
||||
fill: var(--vt-c-text-1);
|
||||
transition: opacity 0.25s;
|
||||
}
|
||||
|
||||
|
||||
.vt-switch-appearance-sun {
|
||||
opacity: 1;
|
||||
}
|
||||
.vt-switch-appearance-moon {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.dark .vt-switch-appearance-sun {
|
||||
opacity: 0;
|
||||
}
|
||||
.dark .vt-switch-appearance-moon {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.dark .vt-switch-appearance .vt-switch-check {
|
||||
transform: translateX(18px);
|
||||
}
|
@ -0,0 +1,613 @@
|
||||
|
||||
|
||||
*,:before,:after {
|
||||
box-sizing: border-box
|
||||
}
|
||||
|
||||
html {
|
||||
line-height: 1.4;
|
||||
font-size: 16px;
|
||||
-webkit-text-size-adjust: 100%
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
min-width: 320px;
|
||||
min-height: 100vh;
|
||||
line-height: 1.4;
|
||||
font-family: var(--font-family-base);
|
||||
font-size: 16px;
|
||||
font-weight: 400;
|
||||
color: var(--c-text);
|
||||
background-color: var(--c-bg);
|
||||
direction: ltr;
|
||||
font-synthesis: none;
|
||||
text-rendering: optimizeLegibility;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale
|
||||
}
|
||||
|
||||
main {
|
||||
display: block
|
||||
}
|
||||
|
||||
h1,h2,h3,h4,h5,h6 {
|
||||
margin: 0;
|
||||
line-height: 1.25
|
||||
}
|
||||
|
||||
h1,h2,h3,h4,h5,h6,strong,b {
|
||||
font-weight: 600
|
||||
}
|
||||
|
||||
h1:hover .header-anchor,h1:focus .header-anchor,h2:hover .header-anchor,h2:focus .header-anchor,h3:hover .header-anchor,h3:focus .header-anchor,h4:hover .header-anchor,h4:focus .header-anchor,h5:hover .header-anchor,h5:focus .header-anchor,h6:hover .header-anchor,h6:focus .header-anchor {
|
||||
opacity: 1
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin-top: 1.5rem;
|
||||
font-size: 1.9rem
|
||||
}
|
||||
|
||||
@media screen and (min-width: 420px) {
|
||||
h1 {
|
||||
font-size:2.2rem
|
||||
}
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin-top: 2.25rem;
|
||||
margin-bottom: 1.25rem;
|
||||
border-bottom: 1px solid var(--c-divider);
|
||||
padding-bottom: .3rem;
|
||||
line-height: 1.25;
|
||||
font-size: 1.65rem
|
||||
}
|
||||
|
||||
h2+h3 {
|
||||
margin-top: 1.5rem
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin-top: 2rem;
|
||||
font-size: 1.35rem
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: 1.15rem
|
||||
}
|
||||
|
||||
p,ol,ul {
|
||||
margin: 1rem 0;
|
||||
line-height: 1.7
|
||||
}
|
||||
|
||||
a,area,button,[role=button],input,label,select,summary,textarea {
|
||||
touch-action: manipulation
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: var(--c-brand)
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: underline
|
||||
}
|
||||
|
||||
a.header-anchor {
|
||||
float: left;
|
||||
margin-top: .125em;
|
||||
margin-left: -.87em;
|
||||
padding-right: .23em;
|
||||
font-size: .85em;
|
||||
opacity: 0
|
||||
}
|
||||
|
||||
a.header-anchor:hover,a.header-anchor:focus {
|
||||
text-decoration: none
|
||||
}
|
||||
|
||||
figure {
|
||||
margin: 0
|
||||
}
|
||||
|
||||
img {
|
||||
max-width: 100%
|
||||
}
|
||||
|
||||
ul,ol {
|
||||
padding-left: 1.25em
|
||||
}
|
||||
|
||||
li>ul,li>ol {
|
||||
margin: 0
|
||||
}
|
||||
|
||||
table {
|
||||
display: block;
|
||||
border-collapse: collapse;
|
||||
margin: 1rem 0;
|
||||
overflow-x: auto
|
||||
}
|
||||
|
||||
tr {
|
||||
border-top: 1px solid #dfe2e5
|
||||
}
|
||||
|
||||
tr:nth-child(2n) {
|
||||
background-color: #f6f8fa
|
||||
}
|
||||
|
||||
th,td {
|
||||
border: 1px solid #dfe2e5;
|
||||
padding: .6em 1em
|
||||
}
|
||||
|
||||
blockquote {
|
||||
margin: 1rem 0;
|
||||
border-left: .2rem solid #dfe2e5;
|
||||
padding: .25rem 0 .25rem 1rem;
|
||||
font-size: 1rem;
|
||||
color: #999
|
||||
}
|
||||
|
||||
blockquote>p {
|
||||
margin: 0
|
||||
}
|
||||
|
||||
form {
|
||||
margin: 0
|
||||
}
|
||||
|
||||
.theme.sidebar-open .sidebar-mask {
|
||||
display: block
|
||||
}
|
||||
|
||||
.theme.no-navbar>h1,.theme.no-navbar>h2,.theme.no-navbar>h3,.theme.no-navbar>h4,.theme.no-navbar>h5,.theme.no-navbar>h6 {
|
||||
margin-top: 1.5rem;
|
||||
padding-top: 0
|
||||
}
|
||||
|
||||
.theme.no-navbar aside {
|
||||
top: 0
|
||||
}
|
||||
|
||||
@media screen and (min-width: 720px) {
|
||||
.theme.no-sidebar aside {
|
||||
display:none
|
||||
}
|
||||
|
||||
.theme.no-sidebar main {
|
||||
margin-left: 0
|
||||
}
|
||||
}
|
||||
|
||||
.sidebar-mask {
|
||||
position: fixed;
|
||||
z-index: 2;
|
||||
display: none;
|
||||
width: 100vw;
|
||||
height: 100vh
|
||||
}
|
||||
|
||||
code {
|
||||
margin: 0;
|
||||
border-radius: 3px;
|
||||
padding: .25rem .5rem;
|
||||
font-family: var(--code-font-family);
|
||||
font-size: .85em;
|
||||
color: var(--c-text-light);
|
||||
background-color: var(--code-inline-bg-color)
|
||||
}
|
||||
|
||||
code .token.deleted {
|
||||
color: #ec5975
|
||||
}
|
||||
|
||||
code .token.inserted {
|
||||
color: var(--c-brand)
|
||||
}
|
||||
|
||||
div[class*=language-] {
|
||||
position: relative;
|
||||
margin: 1rem -1.5rem;
|
||||
background-color: var(--code-bg-color);
|
||||
overflow-x: auto
|
||||
}
|
||||
|
||||
li>div[class*=language-] {
|
||||
border-radius: 6px 0 0 6px;
|
||||
margin: 1rem -1.5rem 1rem -1.25rem;
|
||||
line-height: initial
|
||||
}
|
||||
|
||||
@media (min-width: 420px) {
|
||||
div[class*=language-] {
|
||||
margin:1rem 0;
|
||||
border-radius: 6px
|
||||
}
|
||||
|
||||
li>div[class*=language-] {
|
||||
margin: 1rem 0 1rem 0rem;
|
||||
border-radius: 6px
|
||||
}
|
||||
}
|
||||
|
||||
[class*=language-] pre,[class*=language-] code {
|
||||
text-align: left;
|
||||
white-space: pre;
|
||||
word-spacing: normal;
|
||||
word-break: normal;
|
||||
word-wrap: normal;
|
||||
-moz-tab-size: 4;
|
||||
-o-tab-size: 4;
|
||||
tab-size: 4;
|
||||
-webkit-hyphens: none;
|
||||
-moz-hyphens: none;
|
||||
-ms-hyphens: none;
|
||||
hyphens: none;
|
||||
background: transparent
|
||||
}
|
||||
|
||||
[class*=language-] pre {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
margin: 0;
|
||||
padding: 1.25rem 1.5rem;
|
||||
overflow-x: auto
|
||||
}
|
||||
|
||||
[class*=language-] code {
|
||||
padding: 0;
|
||||
line-height: var(--code-line-height);
|
||||
font-size: var(--code-font-size);
|
||||
color: #eee
|
||||
}
|
||||
|
||||
.highlight-lines {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
padding: 1.25rem 0;
|
||||
width: 100%;
|
||||
line-height: var(--code-line-height);
|
||||
font-family: var(--code-font-family);
|
||||
font-size: var(--code-font-size);
|
||||
user-select: none;
|
||||
overflow: hidden
|
||||
}
|
||||
|
||||
.highlight-lines .highlighted {
|
||||
background-color: #000000a8
|
||||
}
|
||||
|
||||
div[class*=language-].line-numbers-mode {
|
||||
padding-left: 3.5rem
|
||||
}
|
||||
|
||||
.line-numbers-wrapper {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: 3;
|
||||
border-right: 1px solid rgba(0,0,0,.5);
|
||||
padding: 1.25rem 0;
|
||||
width: 3.5rem;
|
||||
text-align: center;
|
||||
line-height: var(--code-line-height);
|
||||
font-family: var(--code-font-family);
|
||||
font-size: var(--code-font-size);
|
||||
color: #888
|
||||
}
|
||||
|
||||
div[class*=language-]:before {
|
||||
position: absolute;
|
||||
top: .6em;
|
||||
right: 1em;
|
||||
z-index: 2;
|
||||
font-size: .8rem;
|
||||
color: #888
|
||||
}
|
||||
|
||||
div[class~=language-html]:before,div[class~=language-markup]:before {
|
||||
content: "html"
|
||||
}
|
||||
|
||||
div[class~=language-md]:before,div[class~=language-markdown]:before {
|
||||
content: "md"
|
||||
}
|
||||
|
||||
div[class~=language-css]:before {
|
||||
content: "css"
|
||||
}
|
||||
|
||||
div[class~=language-sass]:before {
|
||||
content: "sass"
|
||||
}
|
||||
|
||||
div[class~=language-scss]:before {
|
||||
content: "scss"
|
||||
}
|
||||
|
||||
div[class~=language-less]:before {
|
||||
content: "less"
|
||||
}
|
||||
|
||||
div[class~=language-stylus]:before {
|
||||
content: "styl"
|
||||
}
|
||||
|
||||
div[class~=language-js]:before,div[class~=language-javascript]:before {
|
||||
content: "js"
|
||||
}
|
||||
|
||||
div[class~=language-ts]:before,div[class~=language-typescript]:before {
|
||||
content: "ts"
|
||||
}
|
||||
|
||||
div[class~=language-json]:before {
|
||||
content: "json"
|
||||
}
|
||||
|
||||
div[class~=language-rb]:before,div[class~=language-ruby]:before {
|
||||
content: "rb"
|
||||
}
|
||||
|
||||
div[class~=language-py]:before,div[class~=language-python]:before {
|
||||
content: "py"
|
||||
}
|
||||
|
||||
div[class~=language-sh]:before,div[class~=language-bash]:before {
|
||||
content: "sh"
|
||||
}
|
||||
|
||||
div[class~=language-php]:before {
|
||||
content: "php"
|
||||
}
|
||||
|
||||
div[class~=language-go]:before {
|
||||
content: "go"
|
||||
}
|
||||
|
||||
div[class~=language-rust]:before {
|
||||
content: "rust"
|
||||
}
|
||||
|
||||
div[class~=language-java]:before {
|
||||
content: "java"
|
||||
}
|
||||
|
||||
div[class~=language-c]:before {
|
||||
content: "c"
|
||||
}
|
||||
|
||||
div[class~=language-yaml]:before {
|
||||
content: "yaml"
|
||||
}
|
||||
|
||||
div[class~=language-dockerfile]:before {
|
||||
content: "dockerfile"
|
||||
}
|
||||
|
||||
div[class~=language-vue]:before {
|
||||
content: "vue"
|
||||
}
|
||||
|
||||
.token.comment,.token.block-comment,.token.prolog,.token.doctype,.token.cdata {
|
||||
color: #999
|
||||
}
|
||||
|
||||
.token.punctuation {
|
||||
color: #ccc
|
||||
}
|
||||
|
||||
.token.tag,.token.attr-name,.token.namespace,.token.deleted {
|
||||
color: #e2777a
|
||||
}
|
||||
|
||||
.token.function-name {
|
||||
color: #6196cc
|
||||
}
|
||||
|
||||
.token.boolean,.token.number,.token.function {
|
||||
color: #f08d49
|
||||
}
|
||||
|
||||
.token.property,.token.class-name,.token.constant,.token.symbol {
|
||||
color: #f8c555
|
||||
}
|
||||
|
||||
.token.selector,.token.important,.token.atrule,.token.keyword,.token.builtin {
|
||||
color: #cc99cd
|
||||
}
|
||||
|
||||
.token.string,.token.char,.token.attr-value,.token.regex,.token.variable {
|
||||
color: #7ec699
|
||||
}
|
||||
|
||||
.token.operator,.token.entity,.token.url {
|
||||
color: #67cdcc
|
||||
}
|
||||
|
||||
.token.important,.token.bold {
|
||||
font-weight: 700
|
||||
}
|
||||
|
||||
.token.italic {
|
||||
font-style: italic
|
||||
}
|
||||
|
||||
.token.entity {
|
||||
cursor: help
|
||||
}
|
||||
|
||||
.token.inserted {
|
||||
color: green
|
||||
}
|
||||
|
||||
.custom-block.tip,.custom-block.info,.custom-block.warning,.custom-block.danger {
|
||||
margin: 1rem 0;
|
||||
border-left: .5rem solid;
|
||||
padding: .1rem 1.5rem;
|
||||
overflow-x: auto
|
||||
}
|
||||
|
||||
.custom-block.tip {
|
||||
background-color: #f3f5f7;
|
||||
border-color: var(--c-brand)
|
||||
}
|
||||
|
||||
.custom-block.info {
|
||||
background-color: #f3f5f7;
|
||||
border-color: var(--c-text-light-2)
|
||||
}
|
||||
|
||||
.custom-block.warning {
|
||||
border-color: #e7c000;
|
||||
color: #6b5900;
|
||||
background-color: #ffe5644d
|
||||
}
|
||||
|
||||
.custom-block.warning .custom-block-title {
|
||||
color: #b29400
|
||||
}
|
||||
|
||||
.custom-block.warning a {
|
||||
color: var(--c-text)
|
||||
}
|
||||
|
||||
.custom-block.danger {
|
||||
border-color: #c00;
|
||||
color: #4d0000;
|
||||
background-color: #ffe6e6
|
||||
}
|
||||
|
||||
.custom-block.danger .custom-block-title {
|
||||
color: #900
|
||||
}
|
||||
|
||||
.custom-block.danger a {
|
||||
color: var(--c-text)
|
||||
}
|
||||
|
||||
.custom-block.details {
|
||||
position: relative;
|
||||
display: block;
|
||||
border-radius: 2px;
|
||||
margin: 1.6em 0;
|
||||
padding: 1.6em;
|
||||
background-color: #eee
|
||||
}
|
||||
|
||||
.custom-block.details h4 {
|
||||
margin-top: 0
|
||||
}
|
||||
|
||||
.custom-block.details figure:last-child,.custom-block.details p:last-child {
|
||||
margin-bottom: 0;
|
||||
padding-bottom: 0
|
||||
}
|
||||
|
||||
.custom-block.details summary {
|
||||
outline: none;
|
||||
cursor: pointer
|
||||
}
|
||||
|
||||
.custom-block-title {
|
||||
margin-bottom: -.4rem;
|
||||
font-weight: 600
|
||||
}
|
||||
|
||||
.sidebar-links {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none
|
||||
}
|
||||
|
||||
.sidebar-link-item {
|
||||
display: block;
|
||||
margin: 0;
|
||||
border-left: .25rem solid transparent;
|
||||
color: var(--c-text)
|
||||
}
|
||||
|
||||
a.sidebar-link-item:hover {
|
||||
text-decoration: none;
|
||||
color: var(--c-brand)
|
||||
}
|
||||
|
||||
a.sidebar-link-item.active {
|
||||
color: var(--c-brand)
|
||||
}
|
||||
|
||||
.sidebar>.sidebar-links {
|
||||
padding: .75rem 0 5rem
|
||||
}
|
||||
|
||||
@media (min-width: 720px) {
|
||||
.sidebar>.sidebar-links {
|
||||
padding:1.5rem 0
|
||||
}
|
||||
}
|
||||
|
||||
.sidebar>.sidebar-links>.sidebar-link+.sidebar-link {
|
||||
padding-top: .5rem
|
||||
}
|
||||
|
||||
@media (min-width: 720px) {
|
||||
.sidebar>.sidebar-links>.sidebar-link+.sidebar-link {
|
||||
padding-top:1.25rem
|
||||
}
|
||||
}
|
||||
|
||||
.sidebar>.sidebar-links>.sidebar-link>.sidebar-link-item {
|
||||
padding: .35rem 1.5rem .35rem 1.25rem;
|
||||
font-size: 1.1rem;
|
||||
font-weight: 700
|
||||
}
|
||||
|
||||
.sidebar>.sidebar-links>.sidebar-link>a.sidebar-link-item.active {
|
||||
border-left-color: var(--c-brand);
|
||||
font-weight: 600
|
||||
}
|
||||
|
||||
.sidebar>.sidebar-links>.sidebar-link>.sidebar-links>.sidebar-link>.sidebar-link-item {
|
||||
display: block;
|
||||
padding: .35rem 1.5rem .35rem 2rem;
|
||||
line-height: 1.4;
|
||||
font-size: 1rem;
|
||||
font-weight: 400
|
||||
}
|
||||
|
||||
.sidebar>.sidebar-links>.sidebar-link>.sidebar-links>.sidebar-link>a.sidebar-link-item.active {
|
||||
border-left-color: var(--c-brand);
|
||||
font-weight: 600
|
||||
}
|
||||
|
||||
.sidebar>.sidebar-links>.sidebar-link>.sidebar-links>.sidebar-link>.sidebar-links>.sidebar-link>.sidebar-link-item {
|
||||
display: block;
|
||||
padding: .3rem 1.5rem .3rem 3rem;
|
||||
line-height: 1.4;
|
||||
font-size: .9rem;
|
||||
font-weight: 400
|
||||
}
|
||||
|
||||
.sidebar>.sidebar-links>.sidebar-link>.sidebar-links>.sidebar-link>.sidebar-links>.sidebar-link>.sidebar-links>.sidebar-link>.sidebar-link-item {
|
||||
display: block;
|
||||
padding: .3rem 1.5rem .3rem 4rem;
|
||||
line-height: 1.4;
|
||||
font-size: .9rem;
|
||||
font-weight: 400
|
||||
}
|
||||
|
||||
.wrap {
|
||||
background-color: var(--c-bg-white);
|
||||
}
|
||||
|
||||
.dark .wrap {
|
||||
background-color: var(--c-bg-black);
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
:root {
|
||||
--c-bg-white: #ffffff;
|
||||
--c-bg-black: #1a1a1a;
|
||||
--c-text-white: #ffffff;
|
||||
--c-text-black: #1a1a1a;
|
||||
--c-main-color:#80adff;
|
||||
--c-text-color-light:#000000;
|
||||
--c-text-color-dark:#ffffff;
|
||||
--c-divider-light: #e2e8f0;
|
||||
--c-divider-dark: rgba(84, 84, 88, 0.48);
|
||||
--c-brand: #000;
|
||||
--c-brand-light: #80adff;
|
||||
|
||||
--font-family-base: PingFangSC-regular, 'Microsoft Yahei', sans-serif;
|
||||
--font-family-mono: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace;
|
||||
|
||||
--header-height: 3.6rem;
|
||||
--code-bg-color: #fff;
|
||||
|
||||
/* pure theme color */
|
||||
--li-dot-color: #737373;
|
||||
--title-color: #334155;
|
||||
--date-color: #64748b;
|
||||
--date-font-family: Georgia, sans-serif;
|
||||
--tag-bg: #eff6ff;
|
||||
--c-white: #ffffff;
|
||||
--c-white-dark: #f8f8f8;
|
||||
--c-black: #000000;
|
||||
--c-divider-light: rgba(60, 60, 67, .12);
|
||||
--c-divider-dark: rgba(84, 84, 88, .48);
|
||||
--c-text-light-1: #2c3e50;
|
||||
--c-text-light-2: #476582;
|
||||
--c-text-light-3: #90a4b7;
|
||||
|
||||
--font-family-base: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
|
||||
--font-family-mono: source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace;
|
||||
--z-index-navbar: 10;
|
||||
--z-index-sidebar: 6;
|
||||
--shadow-1: 0 1px 2px rgba(0, 0, 0, .04), 0 1px 2px rgba(0, 0, 0, .06);
|
||||
--shadow-2: 0 3px 12px rgba(0, 0, 0, .07), 0 1px 4px rgba(0, 0, 0, .07);
|
||||
--shadow-3: 0 12px 32px rgba(0, 0, 0, .1), 0 2px 6px rgba(0, 0, 0, .08);
|
||||
--shadow-4: 0 14px 44px rgba(0, 0, 0, .12), 0 3px 9px rgba(0, 0, 0, .12);
|
||||
--shadow-5: 0 18px 56px rgba(0, 0, 0, .16), 0 4px 12px rgba(0, 0, 0, .16);
|
||||
--header-height: 3.6rem
|
||||
}
|
||||
|
||||
:root {
|
||||
--c-divider: var(--c-divider-light);
|
||||
--c-text: var(--c-text-light-1);
|
||||
--c-text-light: var(--c-text-light-2);
|
||||
--c-text-lighter: var(--c-text-light-3);
|
||||
--c-bg: var(--c-white);
|
||||
--c-bg-accent: var(--c-white-dark);
|
||||
--code-line-height: 24px;
|
||||
--code-font-family: var(--font-family-mono);
|
||||
--code-font-size: 14px;
|
||||
--code-inline-bg-color: rgba(27, 31, 35, .05);
|
||||
--code-bg-color: #282c34
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
import { CustomTheme } from 'ppst-vitepress-theme'
|
||||
import { h } from 'vue'
|
||||
|
||||
import './override.css'
|
||||
|
||||
export default {
|
||||
...CustomTheme,
|
||||
Layout() {
|
||||
return h(CustomTheme.Layout, null, {
|
||||
})
|
||||
}
|
||||
}
|
@ -0,0 +1,97 @@
|
||||
:root {
|
||||
--c-main-color:#80adff;
|
||||
}
|
||||
|
||||
|
||||
/* card */
|
||||
|
||||
.news-box {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
margin: 0 auto;
|
||||
padding: 20px 0;
|
||||
}
|
||||
.news-box .card-item {
|
||||
flex-basis: 25%;
|
||||
padding: 15px;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
.news-box .card-item .item-box {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
border-radius: 15px;
|
||||
padding: 15px;
|
||||
margin-bottom: 140px;
|
||||
background: #f8f8fc;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
.news-box .card-item .item-box .icon {
|
||||
font-size: 48px;
|
||||
color: var(--c-main-color);
|
||||
}
|
||||
.news-box .card-item .item-box .title {
|
||||
font-size: 18px;
|
||||
line-height: 2;
|
||||
font-weight: 500;
|
||||
color: #020312;
|
||||
}
|
||||
.news-box .card-item .item-box .desc {
|
||||
font-size: 16px;
|
||||
line-height: 2;
|
||||
color: #717e96;
|
||||
overflow: hidden;
|
||||
}
|
||||
.news-box .card-item .item-box .desc {
|
||||
font-size: 16px;
|
||||
line-height: 2;
|
||||
color: #717e96;
|
||||
}
|
||||
.news-box .card-item:hover .item-box {
|
||||
background: var(--c-main-color);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
.news-box .card-item .item-box.active {
|
||||
background: var(--c-main-color);
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.news-box .card-item:hover .item-box .icon,
|
||||
.news-box .card-item:hover .item-box .title,
|
||||
.news-box .card-item:hover .item-box .desc,
|
||||
.news-box .card-item .item-box.active .icon,
|
||||
.news-box .card-item .item-box.active .title,
|
||||
.news-box .card-item .item-box.active .desc {
|
||||
color: #fff;
|
||||
}
|
||||
@media (max-width: 1200px) {
|
||||
.banner .banner-left {
|
||||
font-size: 14px;
|
||||
}
|
||||
.banner .banner-left .desc {
|
||||
font-size: 12px;
|
||||
}
|
||||
.note-box {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.note-box .note-item {
|
||||
flex-basis: 100%;
|
||||
}
|
||||
.news-box {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.news-box .card-item {
|
||||
flex-basis: 100%;
|
||||
}
|
||||
.news-box .card-item .item-box {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.news-box .card-item .item-box .title {
|
||||
font-size: 14px;
|
||||
}
|
||||
.news-box .card-item .item-box .desc {
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
@ -0,0 +1,95 @@
|
||||
---
|
||||
page: true
|
||||
date: 2021-06-30
|
||||
title: 自定义标题
|
||||
sidebar: false
|
||||
---
|
||||
<script setup>
|
||||
</script>
|
||||
<Home>
|
||||
|
||||
<template #banner>
|
||||
<img src="/img/page.png" />
|
||||
</template>
|
||||
|
||||
<template #description>
|
||||
<!-- 一些其他描述 -->
|
||||
</template>
|
||||
|
||||
<div class="card-header max-width">
|
||||
<div class="title">手册</div>
|
||||
<div class="desc">基础知识手册(学习基础笔记)</div>
|
||||
</div>
|
||||
<div class="note-box max-width">
|
||||
<div class="note-item">
|
||||
<div class="item-box">
|
||||
<div class="title">💡CSS手册</div>
|
||||
<div class="go">
|
||||
<span class="button-box"
|
||||
><a href="https://css.web.ppst.top/">💡CSS手册</a></span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="note-item">
|
||||
<div class="item-box">
|
||||
<div class="title">💡JS手册</div>
|
||||
<div class="go">
|
||||
<span class="button-box"><a href="https://js.web.ppst.top/">💡JS手册</a></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="note-item">
|
||||
<div class="item-box">
|
||||
<div class="title">💡博客</div>
|
||||
<div class="go">
|
||||
<span class="button-box"><a href="https://blog.web.ppst.top/">💡博客</a></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-header max-width">
|
||||
<div class="title">随笔</div>
|
||||
<div class="desc">最常用随笔分类</div>
|
||||
</div>
|
||||
|
||||
<div class="news-box max-width">
|
||||
<div class="card-item">
|
||||
<div class="item-box">
|
||||
<div class="icon">?</div>
|
||||
<div class="title">JS笔记</div>
|
||||
<div class="desc">
|
||||
我就是记录一些笔记,以及异常处理经验记录,工作中遇到问题记录解决方案
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-item">
|
||||
<div class="item-box active">
|
||||
<div class="icon">?</div>
|
||||
<div class="title">vue笔记</div>
|
||||
<div class="desc">
|
||||
我就是记录一些笔记,以及异常处理经验记录,工作中遇到问题记录解决方案
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-item">
|
||||
<div class="item-box">
|
||||
<div class="icon">?</div>
|
||||
<div class="title">服务器笔记</div>
|
||||
<div class="desc">
|
||||
我就是记录一些笔记,以及异常处理经验记录,工作中遇到问题记录解决方案
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-item">
|
||||
<div class="item-box active">
|
||||
<div class="icon">?</div>
|
||||
<div class="title">浏览器笔记</div>
|
||||
<div class="desc">
|
||||
我就是记录一些笔记,以及异常处理经验记录,工作中遇到问题记录解决方案
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Home>
|
@ -0,0 +1,13 @@
|
||||
---
|
||||
page: true
|
||||
title: Archive
|
||||
description: Archive
|
||||
sidebar: false
|
||||
---
|
||||
<Archives>
|
||||
|
||||
<template #banner>
|
||||
<img src="/img/banner.png" />
|
||||
</template>
|
||||
|
||||
</Archives>
|
@ -0,0 +1,13 @@
|
||||
---
|
||||
page: true
|
||||
title: 分类
|
||||
description: 分类
|
||||
sidebar: false
|
||||
---
|
||||
<CategoryPage title='分类' category='demo' description="分类">
|
||||
|
||||
<template #banner>
|
||||
<img src="/img/banner.png" />
|
||||
</template>
|
||||
|
||||
</CategoryPage>
|
@ -0,0 +1,13 @@
|
||||
---
|
||||
page: true
|
||||
title: 默认
|
||||
description: 默认
|
||||
sidebar: false
|
||||
---
|
||||
<DefaultPage title='默认' category='default' description="默认">
|
||||
<template #banner>
|
||||
<img src="/img/banner.png" />
|
||||
</template>
|
||||
|
||||
</DefaultPage>
|
||||
|
@ -0,0 +1,11 @@
|
||||
---
|
||||
page: true
|
||||
title: 搜索
|
||||
description: 全文检索
|
||||
sidebar: false
|
||||
---
|
||||
<Search>
|
||||
<template #banner>
|
||||
<img src="/img/banner.png" />
|
||||
</template>
|
||||
</Search>
|
@ -0,0 +1,63 @@
|
||||
---
|
||||
title: default
|
||||
date: 2018-09-14 13:57:02
|
||||
category: default
|
||||
tags:
|
||||
- default
|
||||
---
|
||||
# 主标题
|
||||
|
||||
## 副标题
|
||||
|
||||
我是内容
|
||||
|
||||
```js
|
||||
let a = '我是js代码'
|
||||
```
|
||||
|
||||
```css
|
||||
.default{
|
||||
color:red;
|
||||
}
|
||||
```
|
||||
|
||||
```shell
|
||||
npm install default
|
||||
```
|
||||
|
||||
### 副标题1
|
||||
|
||||
我是内容
|
||||
|
||||
```js
|
||||
let a = '我是js代码'
|
||||
```
|
||||
|
||||
```css
|
||||
.default{
|
||||
color:red;
|
||||
}
|
||||
```
|
||||
|
||||
```shell
|
||||
npm install default
|
||||
```
|
||||
|
||||
|
||||
#### 副标题111
|
||||
|
||||
我是内容
|
||||
|
||||
```js
|
||||
let a = '我是js代码'
|
||||
```
|
||||
|
||||
```css
|
||||
.default{
|
||||
color:red;
|
||||
}
|
||||
```
|
||||
|
||||
```shell
|
||||
npm install default
|
||||
```
|
@ -0,0 +1,63 @@
|
||||
---
|
||||
title: demo
|
||||
date: 2018-09-14 13:57:02
|
||||
category: demo
|
||||
tags:
|
||||
- demo
|
||||
---
|
||||
# 主标题
|
||||
|
||||
## 副标题
|
||||
|
||||
我是内容
|
||||
|
||||
```js
|
||||
let a = '我是js代码'
|
||||
```
|
||||
|
||||
```css
|
||||
.demo{
|
||||
color:red;
|
||||
}
|
||||
```
|
||||
|
||||
```shell
|
||||
npm install demo
|
||||
```
|
||||
|
||||
### 副标题1
|
||||
|
||||
我是内容
|
||||
|
||||
```js
|
||||
let a = '我是js代码'
|
||||
```
|
||||
|
||||
```css
|
||||
.demo{
|
||||
color:red;
|
||||
}
|
||||
```
|
||||
|
||||
```shell
|
||||
npm install demo
|
||||
```
|
||||
|
||||
|
||||
#### 副标题111
|
||||
|
||||
我是内容
|
||||
|
||||
```js
|
||||
let a = '我是js代码'
|
||||
```
|
||||
|
||||
```css
|
||||
.demo{
|
||||
color:red;
|
||||
}
|
||||
```
|
||||
|
||||
```shell
|
||||
npm install demo
|
||||
```
|
Binary file not shown.
After Width: | Height: | Size: 4.0 KiB |
Binary file not shown.
After Width: | Height: | Size: 60 KiB |
Binary file not shown.
After Width: | Height: | Size: 83 KiB |
@ -0,0 +1,20 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"outDir": "dist",
|
||||
"allowJs": true,
|
||||
"module": "esnext",
|
||||
"moduleResolution": "node",
|
||||
"strict": true,
|
||||
"jsx": "preserve",
|
||||
"esModuleInterop": true,
|
||||
"noUnusedLocals": true,
|
||||
"lib": ["ESNext", "DOM"],
|
||||
"skipLibCheck": true,
|
||||
"paths": {
|
||||
"ppst-vitepress-theme": ["src/index.ts"]
|
||||
}
|
||||
},
|
||||
"include": ["src", "demo/.vitepress/theme", "test/.vitepress/theme"],
|
||||
"exclude": ["node_modules"]
|
||||
}
|
Loading…
Reference in New Issue