This commit is contained in:
xugaoyi 2020-05-28 22:06:41 +08:00
parent 15b2668dcb
commit e6686038e4
12 changed files with 441 additions and 35 deletions

View File

@ -50,9 +50,13 @@ npm run dev # or yarn dev
```
## 赞赏
**愿这款知识管理主题能够助你变得强大。**
你任何形式的支持都是对我的肯定,我会坚持初心把这个项目做得更好。当然,能获得赞赏将会使我更有动力去做好这个项目😀~~
如果你觉得这个项目对你有帮助,可以给作者打赏一杯咖啡☕ ,前往 [赞赏](https://xugaoyi.github.io/vuepress-theme-vdoing-doc/pages/1b12ed/) 。
## 致谢
感谢为这个项目贡献过代码的朋友们 → [PR](https://github.com/xugaoyi/vuepress-theme-vdoing/pulls?q=is%3Apr+is%3Aclosed)
## 许可证
[MIT](https://github.com/xugaoyi/vuepress-theme-vdoing/blob/master/LICENSE)

View File

@ -6,36 +6,108 @@ article: false
sidebar: false
---
# 小伙伴们 o(^∇^*)
以下是卡片容器测试
| 小伙伴 | 介绍 |
| ------------------------------------------------------------ | -------------------- |
| <img src="https://cdn.jsdelivr.net/gh/xugaoyi/image_store/blog/20200122153807.jpg" class="headImg">[麋鹿鲁哟](https://www.cnblogs.com/miluluyo/) | 大道至简,知易行难。`#Web` `#二次元` `#美少女` |
| <img src="https://cdn.jsdelivr.net/gh/xaoxuu/assets@master/avatar/avatar.png" class="headImg">[xaoxuu](https://xaoxuu.com) | `#iOS` [`#Volantis主题作者`](https://volantis.js.org/) |
| <img src="https://zpj80231.gitee.io/znote/vuepress/head-fish.jpg" class="headImg">[znote](https://zpj80231.gitee.io/znote/) | 荷尽已无擎雨盖,菊残犹有傲霜枝。|
| <img src="https://reinness.com/avatar.png" class="headImg">[平凡的你我](https://reinness.com) | 理想成为大牛的小陈同学 |
## 普通卡片列表
<!--
普通卡片列表容器,可用于友情链接、项目推荐、古诗词展示等。
cardList 后面可跟随一个数字表示每行最多显示多少个选值范围1~4默认3。在小屏时会根据屏幕宽度减少每行显示数量。
-->
::: cardList 2
```yaml
- name: 麋鹿鲁哟
desc: 大道至简,知易行难
avatar: https://cdn.jsdelivr.net/gh/xugaoyi/image_store/blog/20200122153807.jpg # 可选
link: https://www.cnblogs.com/miluluyo/ # 可选
bgColor: '#C1E5FA' # 可选默认var(--bodyBg)。颜色值有#号时请添加单引号
textColor: '#6854A1' # 可选默认var(--textColor)
- name: XAOXUU
desc: '#IOS #Volantis主题作者'
avatar: https://cdn.jsdelivr.net/gh/xaoxuu/assets@master/avatar/avatar.png
link: https://xaoxuu.com
bgColor: '#718971'
textColor: '#fff'
- name: znote
desc: 荷尽已无擎雨盖,菊残犹有傲霜枝
avatar: https://zpj80231.gitee.io/znote/vuepress/head-fish.jpg
link: https://zpj80231.gitee.io/znote/
bgColor: '#FCE0B4'
textColor: '#7B2532'
- name: 平凡的你我
desc: 理想成为大牛的小陈同学
avatar: https://reinness.com/avatar.png
link: https://reinness.com
bgColor: '#FCD183'
textColor: '#A05F2C'
```
:::
<br><br>
#### 友链申请
## 图文卡片列表
<!--
卡片图片列表,可用于项目展示、产品展示等。
cardImgList 后面可跟随一个数字表示每行最多显示多少个选值范围1~4默认3。在小屏时会根据屏幕宽度减少每行显示数量。
-->
::: cardImgList
```yaml
- img: https://assets.awwwards.com/awards/media/cache/thumb_834_598/external/2020/05/5ebd082bb77bf137658772.jpg
link: https://www.spotify.com/int/why-not-available/
name: 图文标题
# desc: 图文描述内容图文描述内容图文描述内容图文描述内容图文描述内容 # 描述,可选
# author: Evan Xu # 作者,可选
# avatar: https://cdn.jsdelivr.net/gh/xugaoyi/image_store/blog/20200103123203.jpg # 头像,可选
- img: https://assets.awwwards.com/awards/images/2020/05/Somt_may-2020-powerhouse_thumbc.jpg
link: https://www.spotify.com/int/why-not-available/
name: 图文标题
desc: 图文描述内容图文描述内容图文描述内容图文描述内容图文描述内容图文描述内容图文描述内容图文描述内容图文描述内容图文描述内容 # 描述,可选
author: Evan Xu # 作者,可选
avatar: https://cdn.jsdelivr.net/gh/xugaoyi/image_store/blog/20200103123203.jpg # 头像,可选
- img: https://cdn.jsdelivr.net/gh/xugaoyi/image_store/blog/20200103123203.jpg
link: https://www.spotify.com/int/why-not-available/
name: 图文标题
desc: 图文描述内容图文描述内容图文描述内容图文描述内容图文描述内容 # 描述,可选
author: Evan Xu # 作者,可选
avatar: https://cdn.jsdelivr.net/gh/xugaoyi/image_store/blog/20200103123203.jpg # 头像,可选
- img: https://cdn.jsdelivr.net/gh/xugaoyi/image_store/blog/20200103123203.jpg
link: https://www.spotify.com/int/why-not-available/
name: 图文标题
desc: 图文描述内容图文描述内容图文描述内容图文描述内容图文描述内容 # 描述,可选
author: Evan Xu # 作者,可选
avatar: https://cdn.jsdelivr.net/gh/xugaoyi/image_store/blog/20200103123203.jpg # 头像,可选
- img: https://assets.awwwards.com/awards/media/cache/thumb_834_598/external/2020/05/5ebd082bb77bf137658772.jpg
link: https://www.spotify.com/int/why-not-available/
name: 图文标题
desc: 图文描述内容图文描述内容图文描述内容图文描述内容图文描述内容 # 描述,可选
author: Evan Xu # 作者,可选
avatar: https://cdn.jsdelivr.net/gh/xugaoyi/image_store/blog/20200103123203.jpg # 头像,可选
- img: https://assets.awwwards.com/awards/images/2020/05/Somt_may-2020-powerhouse_thumbc.jpg
link: https://www.spotify.com/int/why-not-available/
name: 图文标题
desc: 图文描述内容图文描述内容图文描述内容图文描述内容图文描述内容图文描述内容图文描述内容图文描述内容图文描述内容图文描述内容 # 描述,可选
author: Evan Xu # 作者,可选
avatar: https://cdn.jsdelivr.net/gh/xugaoyi/image_store/blog/20200103123203.jpg # 头像,可选
```
:::
### 友链申请
与我[ 联系 ](/about/#联系)或者 在本页面评论区留言您的友链信息,格式:
::: tip
昵称Evan's blog
链接:<https://xugaoyi.com/>
介绍:积跬步以至千里,喜欢学习喜欢你。
头像:<https://cdn.jsdelivr.net/gh/xugaoyi/image_store/blog/20200103123203.jpg>
:::
```yaml
- name: Evan's blog # 昵称
desc: 积跬步以至千里,喜欢学习喜欢你。 # 介绍
avatar: https://cdn.jsdelivr.net/gh/xugaoyi/image_store/blog/20200103123203.jpg # 头像
link: https://xugaoyi.com/ # 链接
```
申请前记得先添加本站哦 ↑(^∀^●)ノ↑~
<style scoped>
.custom-block-title{display:none;}
.headImg{width:60px;height:60px;border-radius: 50%;float: left;margin-right: 12px;}
.headImg + a{line-height:60px;}
</style>

View File

@ -20,7 +20,7 @@
"vuepress-plugin-one-click-copy": "^1.0.2",
"vuepress-plugin-thirdparty-search": "^1.0.2",
"vuepress-plugin-zooming": "^1.1.7",
"vuepress-theme-vdoing": "^1.0.1",
"vuepress-theme-vdoing": "^1.1.0",
"yamljs": "^0.3.0"
},
"dependencies": {

View File

@ -47,7 +47,7 @@ export default {
}
},
components: { MainLayout, PostList, Pagination, CategoriesBar },
beforeMount() {
mounted() {
const queryCategory = this.$route.query.category
if (queryCategory) {
this.category = queryCategory
@ -58,8 +58,7 @@ export default {
if (this.$route.query.p) {
this.currentPage = Number(this.$route.query.p)
}
},
mounted() {
//
const cateEl = document.querySelector('.categories')
if (cateEl) {

View File

@ -181,8 +181,6 @@ export default {
},
beforeMount(){
this.isMQMobile = window.innerWidth < MOBILE_DESKTOP_BREAKPOINT ? true : false; // vupressbeforeCreate(),created()访apiwindow
},
mounted() {
if (this.$route.query.p) {

View File

@ -47,7 +47,7 @@ export default {
}
},
components: { MainLayout, PostList, Pagination, TagsBar },
beforeMount() {
mounted() {
const queryTag = this.$route.query.tag
if (queryTag) {

View File

@ -3,8 +3,12 @@ const setFrontmatter = require('./node_utils/setFrontmatter')
const getSidebarData = require('./node_utils/getSidebarData')
const {createPage, deletePage} = require('./node_utils/handlePage')
const chalk = require('chalk') // 命令行打印美化
const yaml = require('js-yaml') // yaml转js
const log = console.log
// md容器名
const CARD_LIST = 'cardList'
const CARD_IMG_LIST = 'cardImgList'
// Theme API.
module.exports = (options, ctx) => {
@ -71,6 +75,8 @@ module.exports = (options, ctx) => {
['@vuepress/active-header-links', options.activeHeaderLinks],
'@vuepress/search',
'@vuepress/plugin-nprogress',
['smooth-scroll', enableSmoothScroll],
['container', {
type: 'tip',
defaultTitle: {
@ -92,7 +98,144 @@ module.exports = (options, ctx) => {
'/zh/': '警告'
}
}],
['smooth-scroll', enableSmoothScroll]
// 卡片列表
[
'container',
{
type: CARD_LIST,
render: (tokens, idx) => {
// tokens 是整个md文件的虚拟dom结构数组
// idx 是tokens中':::' 所在的索引而且是当前指定type的':::'分别有开始和结束两次的idx
// if (tokens[idx].nesting === 1) { // 开头的 ':::' 标记
// } else { // 结束的 ':::' 标记
// }
// 注意修改这里面的代码后需要在md文件保存一下才会重新执行渲染
return renderCardList(tokens, idx, CARD_LIST)
}
},
],
// 图文卡片列表
[
'container',
{
type: CARD_IMG_LIST,
render: (tokens, idx) => {
return renderCardList(tokens, idx, CARD_IMG_LIST)
}
},
],
]
}
}
// 渲染md容器的卡片列表
function renderCardList(tokens, idx, type) {
const END_TYPE = `container_${type}_close`,
_tokens$idx = tokens[idx],
nesting = _tokens$idx.nesting,
info = _tokens$idx.info;
if (nesting === 1) { // 渲染开头的 ':::' 标记
let yamlStr = '';
for (let i = idx; i < tokens.length; i++) {
let _tokens$i = tokens[i],
type = _tokens$i.type,
content = _tokens$i.content,
_info = _tokens$i.info;
if (type === END_TYPE) break; // 遇到结束的 ':::' 时
if (!content) continue;
if (type === 'fence' && _info === 'yaml') { // 是代码块类型并且是yaml代码
yamlStr = content
}
}
if (yamlStr) { // 正确解析出yaml字符串后
const dataObj = yaml.safeLoad(yamlStr) // 将yaml字符串解析成js对象
let dataList = []
if (dataObj) { // 正确解析出数据对象
dataList = Array.isArray(dataObj) ? dataObj : dataObj.list
}
if (dataList && dataList.length) { // 有列表数据
// 每行显示几个
let row = Number(info.split(' ').pop())
if (!row || row > 4 || row < 1) {
row = 3 // 默认 3
}
let listDOM = ''
if (type === CARD_LIST) { // 普通卡片列表
listDOM = getCardListDOM(dataList, row)
} else if (type === CARD_IMG_LIST) { // 卡片图片列表
listDOM = getCardImgListDOM(dataList, row)
}
return `<div class="${type}Container"><div class="card-list">${ listDOM }</div>`
}
}
} else { // 渲染':::' 结尾
return '</div>'
}
}
// 将数据解析成DOM结构 - 普通卡片列表
function getCardListDOM(dataList, row) {
let listDOM = ''
dataList.forEach(item => {
listDOM += `
<${item.link ? 'a href="' + item.link +'" target="_blank"' : 'span' } class="card-item ${ row ? 'row-' + row : '' }"
style="${ item.bgColor ? 'background-color:' + item.bgColor + ';': '' }${ item.textColor ? 'color:' + item.textColor + ';': '' }"
>
${ item.avatar ? '<img src="'+ item.avatar +'" class="no-zoom">' : '' }
<div>
<p class="name">${item.name}</p>
<p class="desc">${item.desc}</p>
</div>
</${item.link ? 'a' : 'span'}>
`
})
return listDOM
}
// 将数据解析成DOM结构 - 图文卡片列表
function getCardImgListDOM(dataList, row) {
let listDOM = ''
dataList.forEach(item => {
listDOM += `
<div class="card-item ${ row ? 'row-' + row : '' }" >
<div class="box-img">
<a href="${item.link}" target="_blank">
<img src="${item.img}" class="no-zoom">
</a>
</div>
<div class="box-info">
<a href="${item.link}" target="_blank">
<p class="name">${item.name}</p>
${item.desc ? `<p class="desc">${item.desc}</p>` : ''}
</a>
</div>
${item.avatar || item.author
? `<div class="box-footer">
<a href="${item.link}" target="_blank">
${item.avatar ? `<img src="${item.avatar}" class="no-zoom">` : ''}
${item.author ? `<span>${item.author}</span>` : ''}
</a>
</div>`
: ''
}
</div>
`
})
return listDOM
}

View File

@ -109,7 +109,7 @@ function getCategories(file, categoryText) {
let categories = []
if (file.filePath.indexOf('_posts') === -1) { // 不在_posts文件夹
const filePathArr = file.filePath.split(path.sep)
const filePathArr = file.filePath.split(path.sep) // path.sep用于兼容不同系统下的路径斜杠
const c = filePathArr[filePathArr.length - 3].split('.').pop() // 获取分类1
if (c !== 'docs') {
categories.push(c)

View File

@ -1,6 +1,6 @@
{
"name": "vuepress-theme-vdoing",
"version": "1.0.1",
"version": "1.1.0",
"description": "Vdoing theme for VuePress. 一个基于VuePress的知识管理兼博客主题。",
"author": {
"name": "gaoyi(Evan) Xu"
@ -21,6 +21,7 @@
"@vuepress/plugin-search": "^1.2.0",
"chalk": "^4.0.0",
"json2yaml": "^1.1.0",
"js-yaml": "^3.13.1",
"docsearch.js": "^2.5.2",
"good-storage": "^1.1.1",
"lodash": "^4.17.15",

View File

@ -7,6 +7,8 @@
@require './arrow'
@require './wrapper'
@require './toc'
@require './markdown-container'
html, body
padding 0
@ -57,6 +59,13 @@ a,input,button
.theme-vdoing-wrapper
margin 0 auto
//
body .search-box
input
background-color transparent
color var(--textColor)
border 1px solid var(--borderColor, #ccc)
.page

View File

@ -0,0 +1,180 @@
// markdown
//
.cardListContainer
margin .7rem 0
&>:not(.card-list)
display none
.card-list
margin -0.35rem
display: flex;
flex-wrap: wrap;
align-items: flex-start;
.card-item
width calc(100%/3 - .7rem)
margin .35rem
background var(--bodyBg)
border-radius 3px
color var(--textColor)
display flex
box-shadow 1px 1px 2px 0 rgba(0,0,0,.06)
&:hover
text-decoration none
img
transform rotate(8deg) scale(1.1, 1.1)
box-shadow 3px 2px 7px rgba(0, 0, 0, 0.15)
div p
text-shadow 3px 2px 5px rgba(0, 0, 0, 0.15)
img
width 60px
height 60px
border-radius 50%
border 2px solid #fff
margin 1rem
margin-right 0
box-shadow 3px 2px 5px rgba(0, 0, 0, 0.08)
transition all .4s
div
flex 1
display inline-block
float right
padding 1rem 0
p
margin 0
padding 0 1rem
transition text-shadow .4s
text-align center
.name
margin .2rem 0 .3rem 0
.desc
font-size .8rem
line-height 1.1rem
opacity .8
margin-bottom .2rem
.card-item.row-1
width calc(100% - .7rem)
img
margin-left 2rem
.card-item.row-2
width calc(100%/2 - .7rem)
img
margin-left 1.5rem
.card-item.row-3
width calc(100%/3 - .7rem)
.card-item.row-4
width calc(100%/4 - .7rem)
//
.cardImgListContainer
margin 1rem 0
&>:not(.card-list)
display none
.card-list
margin -0.5rem
display: flex;
flex-wrap: wrap;
align-items: flex-start;
.card-item
width calc(100%/3 - 1rem)
margin .5rem
background var(--mainBg)
border 1px solid rgba(0,0,0,0.08)
box-sizing: border-box
border-radius 3px
overflow hidden
color var(--textColor)
box-shadow 2px 2px 10px rgba(0,0,0,.04)
display flex
flex-direction: column;
justify-content: flex-start;
align-items: stretch;
align-content: stretch;
transition: box-shadow .3s
&:hover
box-shadow 1px 1px 20px rgba(0,0,0,.07)
.box-img
overflow hidden
position relative
background #000
img
display block
width 100%
height auto
transition: all .3s
&:hover
img
transform: scale(1.1, 1.1)
opacity .75
a
color var(--textColor)
transition: color .3s
&:hover
color $accentColor
text-decoration none
.box-info
padding: .8rem 1rem
p
margin 0
.desc
margin-top: .3rem
opacity .8
font-size: .9rem
line-height: 1.1rem
.box-footer
overflow hidden
padding: .8rem 1rem
border-top: 1px solid rgba(0,0,0,0.05)
img
width 1.8rem
height 1.8rem
border-radius 50%
float left
span
line-height 1.8rem
float left
margin-left: .6rem
font-size: .8rem
.card-item.row-1
width calc(100% - 1rem)
.card-item.row-2
width calc(100%/2 - 1rem)
.card-item.row-3
width calc(100%/3 - 1rem)
.card-item.row-4
width calc(100%/4 - 1rem)
//
@media (max-width: 900px)
.cardListContainer
.card-list
.card-item.row-4
width calc(100%/3 - .7rem)
.cardImgListContainer
.card-list
.card-item.row-4
width calc(100%/3 - 1rem)
@media (max-width: 720px)
.cardListContainer
.card-list
.card-item.row-3, .card-item.row-4
width calc(100%/2 - .7rem)
img
margin-left 1.5rem
.cardImgListContainer
.card-list
.card-item.row-3, .card-item.row-4
width calc(100%/2 - 1rem)
@media (max-width: 500px)
.cardListContainer
.card-list
.card-item.row-1, .card-item.row-2, .card-item.row-3, .card-item.row-4
width calc(100% - .7rem)
img
margin-left 1.5rem
.cardImgListContainer
.card-list
.card-item.row-1, .card-item.row-2, .card-item.row-3, .card-item.row-4
width calc(100% - 1rem)

View File

@ -64,7 +64,7 @@ $mobileSidebarWidth = $sidebarWidth * 0.9
padding-right $rightMenuWidth
&.no-sidebar
.page
padding-left 0
padding-left 0!important
@media (max-width: $MQNarrow)
.theme-container
&.sidebar-open:not(.on-sidebar)