修复bug
This commit is contained in:
parent
0663b14792
commit
20bdb63636
|
|
@ -1,5 +1,4 @@
|
|||
const nav = require('./config/nav.js');
|
||||
// const sidebar = require('./config/sidebar.js');
|
||||
|
||||
module.exports = {
|
||||
title: "Evan's blog",
|
||||
|
|
@ -21,7 +20,8 @@ module.exports = {
|
|||
markdown: {
|
||||
lineNumbers: true // 代码行号
|
||||
},
|
||||
theme: require.resolve('../../vuepress-theme-vdoing'), // 使用的主题
|
||||
// theme: 'vdoing', // 使用依赖包主题
|
||||
theme: require.resolve('../../vuepress-theme-vdoing'), // 使用本地主题
|
||||
themeConfig: { // 主题配置
|
||||
nav,
|
||||
sidebarDepth: 2, // 侧边栏显示深度,默认1,最大2(显示到h3标题)
|
||||
|
|
@ -98,12 +98,6 @@ module.exports = {
|
|||
// color: '#11a8cd', // 爱心颜色,默认随机色
|
||||
// excludeClassName: 'theme-vdoing-content' // 要排除元素的class, 默认空''
|
||||
// }],
|
||||
// [require('./plugins/title-badge'), { // h1标题徽章
|
||||
// // badges: [ // 替换默认的徽章图标,可选
|
||||
// // 'base64图片1',
|
||||
// // 'base64图片2',
|
||||
// // ]
|
||||
// }],
|
||||
|
||||
['thirdparty-search', { // 可以添加第三方搜索链接的搜索框(原官方搜索框的参数仍可用)
|
||||
thirdparty: [ // 可选,默认 []
|
||||
|
|
|
|||
|
|
@ -1,74 +0,0 @@
|
|||
# vuepress 中文全文搜索插件
|
||||
|
||||
> 代码来自[https://github.com/leo-buneev/vuepress-plugin-fulltext-search](https://github.com/leo-buneev/vuepress-plugin-fulltext-search),但是只支持英文全文搜索,做了部分改动
|
||||
|
||||
## 改动说明
|
||||
+ 修改[flexsearch](https://github.com/nextapps-de/flexsearch)默认配置
|
||||
|
||||
+ 使用中文分词模块[segmentit](https://github.com/linonetwo/segmentit)
|
||||
|
||||
```js
|
||||
// ./services/flexsearchSvc.js
|
||||
// flexsearch 默认配置的修改, 以及引入中文分词模块
|
||||
let defaultOptions = {
|
||||
encode: false,
|
||||
async: true,
|
||||
tokenize: function(str){
|
||||
var result = segmentit.doSegment(str, {
|
||||
simple: true
|
||||
});
|
||||
return result;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
## 如何使用
|
||||
|
||||
+ 把整体代码拷贝到vuepress项目目录下,如
|
||||
|
||||
```
|
||||
.
|
||||
├─ docs
|
||||
├─ myPlugins
|
||||
│ └─ fullSearchBox // 当前插件所在文件夹
|
||||
└─ package.json
|
||||
```
|
||||
|
||||
|
||||
|
||||
+ 在`config.js`中引用该插件
|
||||
|
||||
```js
|
||||
plugins: [
|
||||
require.resolve('../../myPlugins/fullSearchBox/')
|
||||
]
|
||||
```
|
||||
|
||||
+ 在`package.json`中加入以下依赖
|
||||
|
||||
```json
|
||||
"devDependencies": {
|
||||
"flexsearch": "nextapps-de/flexsearch",
|
||||
"html-to-text": "^5.1.1",
|
||||
"segmentit": "^2.0.3",
|
||||
}
|
||||
```
|
||||
|
||||
+ 安装依赖
|
||||
|
||||
```
|
||||
npm i
|
||||
```
|
||||
|
||||
+ 运行
|
||||
|
||||
## 不足的地方
|
||||
|
||||
加载segment词典会有1 - 2s的卡顿
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
|
|
@ -1 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" width="12" height="13"><g stroke-width="2" stroke="#aaa" fill="none"><path d="M11.29 11.71l-4-4"/><circle cx="5" cy="5" r="4"/></g></svg>
|
||||
|
Before Width: | Height: | Size: 215 B |
|
|
@ -1,279 +0,0 @@
|
|||
<template>
|
||||
<div class="search-box">
|
||||
<input
|
||||
ref="input"
|
||||
aria-label="Search"
|
||||
:value="query"
|
||||
:class="{ focused: focused }"
|
||||
:placeholder="placeholder"
|
||||
autocomplete="off"
|
||||
spellcheck="false"
|
||||
@input="query = $event.target.value"
|
||||
@focus="focused = true"
|
||||
@blur="focused = false"
|
||||
@keyup.enter="go(focusIndex)"
|
||||
@keyup.up="onUp"
|
||||
@keyup.down="onDown"
|
||||
/>
|
||||
<ul v-if="showSuggestions" class="suggestions" :class="{ 'align-right': alignRight }" @mouseleave="unfocus">
|
||||
<li
|
||||
v-for="(s, i) in suggestions"
|
||||
:key="i"
|
||||
class="suggestion"
|
||||
:class="{ focused: i === focusIndex }"
|
||||
@mousedown="go(i)"
|
||||
@mouseenter="focus(i)"
|
||||
>
|
||||
<a :href="s.path + s.slug" @click.prevent>
|
||||
<div v-if="s.parentPageTitle" class="parent-page-title" v-html="highlight(s.parentPageTitle)" />
|
||||
<div class="suggestion-row">
|
||||
<div class="page-title">{{ s.title || s.path }}</div>
|
||||
<div class="suggestion-content">
|
||||
<div v-if="s.headingStr" class="header">{{ s.headingStr }}</div>
|
||||
<div v-if="s.contentStr">{{ s.contentStr }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import flexsearchSvc from '../services/flexsearchSvc'
|
||||
/* global SEARCH_MAX_SUGGESTIONS, SEARCH_PATHS, SEARCH_HOTKEYS */
|
||||
export default {
|
||||
name: 'SearchBox',
|
||||
data() {
|
||||
return {
|
||||
query: '',
|
||||
focused: false,
|
||||
focusIndex: 0,
|
||||
placeholder: undefined,
|
||||
suggestions: null,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
queryTerms() {
|
||||
if (!this.query) return []
|
||||
return this.query
|
||||
.trim()
|
||||
.toLowerCase()
|
||||
// .split(/[^\w]+/i)
|
||||
.split(' ')
|
||||
.filter(t => t)
|
||||
},
|
||||
showSuggestions() {
|
||||
return this.focused && this.suggestions && this.suggestions.length
|
||||
},
|
||||
|
||||
// make suggestions align right when there are not enough items
|
||||
alignRight() {
|
||||
const navCount = (this.$site.themeConfig.nav || []).length
|
||||
const repo = this.$site.repo ? 1 : 0
|
||||
return navCount + repo <= 2
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
query() {
|
||||
this.getSuggestions()
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
flexsearchSvc.buildIndex(this.$site.pages)
|
||||
this.placeholder = this.$site.themeConfig.searchPlaceholder || ''
|
||||
document.addEventListener('keydown', this.onHotkey)
|
||||
},
|
||||
beforeDestroy() {
|
||||
document.removeEventListener('keydown', this.onHotkey)
|
||||
},
|
||||
methods: {
|
||||
highlight(str) {
|
||||
if (!this.queryTerms.length) return str
|
||||
return str
|
||||
},
|
||||
async getSuggestions() {
|
||||
if (!this.query) return
|
||||
if (!this.queryTerms.length) {
|
||||
this.suggestions = []
|
||||
return
|
||||
}
|
||||
this.suggestions = await flexsearchSvc.match(
|
||||
this.query,
|
||||
this.queryTerms,
|
||||
this.$site.themeConfig.searchMaxSuggestions || SEARCH_MAX_SUGGESTIONS,
|
||||
)
|
||||
},
|
||||
getPageLocalePath(page) {
|
||||
for (const localePath in this.$site.locales || {}) {
|
||||
if (localePath !== '/' && page.path.indexOf(localePath) === 0) {
|
||||
return localePath
|
||||
}
|
||||
}
|
||||
return '/'
|
||||
},
|
||||
isSearchable(page) {
|
||||
let searchPaths = SEARCH_PATHS
|
||||
// all paths searchables
|
||||
if (searchPaths === null) {
|
||||
return true
|
||||
}
|
||||
searchPaths = Array.isArray(searchPaths) ? searchPaths : new Array(searchPaths)
|
||||
return (
|
||||
searchPaths.filter(path => {
|
||||
return page.path.match(path)
|
||||
}).length > 0
|
||||
)
|
||||
},
|
||||
onHotkey(event) {
|
||||
if (event.srcElement === document.body && SEARCH_HOTKEYS.includes(event.key)) {
|
||||
this.$refs.input.focus()
|
||||
event.preventDefault()
|
||||
}
|
||||
},
|
||||
onUp() {
|
||||
if (this.showSuggestions) {
|
||||
if (this.focusIndex > 0) {
|
||||
this.focusIndex--
|
||||
} else {
|
||||
this.focusIndex = this.suggestions.length - 1
|
||||
}
|
||||
}
|
||||
},
|
||||
onDown() {
|
||||
if (this.showSuggestions) {
|
||||
if (this.focusIndex < this.suggestions.length - 1) {
|
||||
this.focusIndex++
|
||||
} else {
|
||||
this.focusIndex = 0
|
||||
}
|
||||
}
|
||||
},
|
||||
go(i) {
|
||||
if (!this.showSuggestions) {
|
||||
return
|
||||
}
|
||||
this.$router.push(this.suggestions[i].path + this.suggestions[i].slug)
|
||||
// this.query = ''
|
||||
this.focusIndex = 0
|
||||
},
|
||||
focus(i) {
|
||||
this.focusIndex = i
|
||||
},
|
||||
unfocus() {
|
||||
this.focusIndex = -1
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="stylus">
|
||||
.search-box
|
||||
display inline-block
|
||||
position relative
|
||||
margin-right 1rem
|
||||
input
|
||||
cursor text
|
||||
width 10rem
|
||||
height: 2rem
|
||||
color lighten($textColor, 25%)
|
||||
display inline-block
|
||||
border 1px solid darken($borderColor, 10%)
|
||||
border-radius 2rem
|
||||
font-size 0.9rem
|
||||
line-height 2rem
|
||||
padding 0 0.5rem 0 2rem
|
||||
outline none
|
||||
transition all .2s ease
|
||||
background #fff url(../assets/search.svg) 0.6rem 0.5rem no-repeat
|
||||
background-size 1rem
|
||||
&:focus
|
||||
cursor auto
|
||||
border-color $accentColor
|
||||
.suggestions
|
||||
background #fff
|
||||
min-width 500px
|
||||
max-width 700px
|
||||
position absolute
|
||||
top 2 rem
|
||||
border 1px solid darken($borderColor, 10%)
|
||||
border-radius 6px
|
||||
padding 0.4rem
|
||||
list-style-type none
|
||||
&.align-right
|
||||
right 0
|
||||
.suggestion
|
||||
line-height 1.4
|
||||
// padding 0.4rem 0.6rem
|
||||
border-radius 4px
|
||||
cursor pointer
|
||||
width 100%
|
||||
a
|
||||
display block
|
||||
white-space normal
|
||||
color lighten($textColor, 15%)
|
||||
width 100%
|
||||
.parent-page-title
|
||||
color white
|
||||
font-weight 600
|
||||
background-color $accentColor
|
||||
padding 5px
|
||||
|
||||
.suggestion-row
|
||||
border-collapse collapse
|
||||
width 100%
|
||||
display table
|
||||
.page-title
|
||||
width: 35%
|
||||
border 1px solid $borderColor
|
||||
background: #f5f5f5
|
||||
border-left none
|
||||
display table-cell
|
||||
text-align right
|
||||
padding 5px
|
||||
font-weight 600
|
||||
.suggestion-content
|
||||
border 1px solid $borderColor
|
||||
font-weight 400
|
||||
border-right none
|
||||
width: 65%
|
||||
display table-cell
|
||||
padding 5px
|
||||
.header
|
||||
font-weight 600
|
||||
|
||||
&.focused
|
||||
background-color #f3f4f5
|
||||
@media (max-width: $MQNarrow)
|
||||
.search-box
|
||||
input
|
||||
cursor pointer
|
||||
width 0
|
||||
border-color transparent
|
||||
position relative
|
||||
&:focus
|
||||
cursor text
|
||||
left 0
|
||||
width 10rem
|
||||
// Match IE11
|
||||
@media all and (-ms-high-contrast: none)
|
||||
.search-box input
|
||||
height 2rem
|
||||
@media (max-width: $MQNarrow) and (min-width: $MQMobile)
|
||||
.search-box
|
||||
.suggestions
|
||||
left 0
|
||||
@media (max-width: $MQMobile)
|
||||
.search-box
|
||||
margin-right 0
|
||||
input
|
||||
left 1rem
|
||||
.suggestions
|
||||
right 0
|
||||
@media (max-width: $MQMobileNarrow)
|
||||
.search-box
|
||||
.suggestions
|
||||
width calc(100vw - 4rem)
|
||||
input:focus
|
||||
width 8rem
|
||||
</style>
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
const { path } = require('@vuepress/shared-utils')
|
||||
const htmlToText = require('html-to-text')
|
||||
|
||||
module.exports = options => ({
|
||||
extendPageData($page) {
|
||||
try {
|
||||
const { html } = $page._context.markdown.render($page._strippedContent)
|
||||
|
||||
const plaintext = htmlToText.fromString(html, {
|
||||
wordwrap: null,
|
||||
hideLinkHrefIfSameAsText: true,
|
||||
ignoreImage: true,
|
||||
uppercaseHeadings: false,
|
||||
})
|
||||
|
||||
for (const h of $page.headers || []) {
|
||||
const titlePlaintext = $page._context.markdown.renderInline(h.title)
|
||||
h.charIndex = plaintext.indexOf(titlePlaintext)
|
||||
if (h.charIndex === -1) h.charIndex = null
|
||||
}
|
||||
$page.headersStr = $page.headers ? $page.headers.map(h => h.title).join(' ') : null
|
||||
$page.content = plaintext
|
||||
$page.contentLowercase = plaintext.toLowerCase()
|
||||
} catch (e) {
|
||||
// incorrect markdown
|
||||
console.error('Error when applying fulltext-search plugin:', e)
|
||||
}
|
||||
},
|
||||
alias: {
|
||||
'@SearchBox': path.resolve(__dirname, 'components/SearchBox.vue'),
|
||||
},
|
||||
})
|
||||
|
|
@ -1,188 +0,0 @@
|
|||
import Flexsearch from 'flexsearch'
|
||||
import _ from 'lodash'
|
||||
import { Segment, useDefault } from 'segmentit';
|
||||
|
||||
let index = null
|
||||
let pagesByPath = null
|
||||
|
||||
export default {
|
||||
buildIndex(pages) {
|
||||
const segmentit = useDefault(new Segment());
|
||||
|
||||
let defaultOptions = {
|
||||
encode: false,
|
||||
async: true,
|
||||
tokenize: function(str){
|
||||
var result = segmentit.doSegment(str, {
|
||||
simple: true
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
let options = defaultOptions;
|
||||
|
||||
options = {
|
||||
...options,
|
||||
doc: {
|
||||
id: "key",
|
||||
field: ['title', 'headersStr', 'content']
|
||||
}
|
||||
}
|
||||
|
||||
index = new Flexsearch(options);
|
||||
index.add(pages)
|
||||
pagesByPath = _.keyBy(pages, 'path')
|
||||
},
|
||||
async match(queryString, queryTerms, limit = 7) {
|
||||
const searchResult = await index.search([
|
||||
{
|
||||
field: 'title',
|
||||
query: queryString,
|
||||
limit,
|
||||
boost: 10,
|
||||
},
|
||||
{
|
||||
field: 'headersStr',
|
||||
query: queryString,
|
||||
limit,
|
||||
boost: 7,
|
||||
},
|
||||
{
|
||||
field: 'content',
|
||||
query: queryString,
|
||||
limit,
|
||||
},
|
||||
])
|
||||
|
||||
const result = searchResult.map(page => ({
|
||||
...page,
|
||||
parentPageTitle: getParentPageTitle(page),
|
||||
...getAdditionalInfo(page, queryString, queryTerms),
|
||||
}))
|
||||
|
||||
const resultByParent = _.groupBy(result, 'parentPageTitle')
|
||||
return _.values(resultByParent)
|
||||
.map(arr =>
|
||||
arr.map((x, i) => {
|
||||
if (i === 0) return x
|
||||
return { ...x, parentPageTitle: null }
|
||||
}),
|
||||
)
|
||||
.flat()
|
||||
},
|
||||
}
|
||||
|
||||
function getParentPageTitle(page) {
|
||||
const pathParts = page.path.split('/')
|
||||
let parentPagePath = '/'
|
||||
if (pathParts[1]) parentPagePath = `/${pathParts[1]}/`
|
||||
|
||||
const parentPage = pagesByPath[parentPagePath] || page
|
||||
return parentPage.title
|
||||
}
|
||||
|
||||
function getAdditionalInfo(page, queryString, queryTerms) {
|
||||
const query = queryString.toLowerCase()
|
||||
const match = getMatch(page, query, queryTerms)
|
||||
if (!match)
|
||||
return {
|
||||
headingStr: getFullHeading(page),
|
||||
slug: '',
|
||||
contentStr: null,
|
||||
}
|
||||
|
||||
if (match.headerIndex != null) {
|
||||
// header match
|
||||
return {
|
||||
headingStr: getFullHeading(page, match.headerIndex),
|
||||
slug: '#' + page.headers[match.headerIndex].slug,
|
||||
contentStr: null,
|
||||
}
|
||||
}
|
||||
|
||||
// content match
|
||||
let headerIndex = _.findLastIndex(page.headers || [], h => h.charIndex != null && h.charIndex < match.charIndex)
|
||||
if (headerIndex === -1) headerIndex = null
|
||||
|
||||
return {
|
||||
headingStr: getFullHeading(page, headerIndex),
|
||||
slug: headerIndex == null ? '' : '#' + page.headers[headerIndex].slug,
|
||||
contentStr: getContentStr(page, match),
|
||||
}
|
||||
}
|
||||
|
||||
function getFullHeading(page, headerIndex) {
|
||||
if (headerIndex == null) return page.title
|
||||
const headersPath = []
|
||||
while (headerIndex != null) {
|
||||
const header = page.headers[headerIndex]
|
||||
headersPath.unshift(header)
|
||||
headerIndex = _.findLastIndex(page.headers, h => h.level === header.level - 1, headerIndex - 1)
|
||||
if (headerIndex === -1) headerIndex = null
|
||||
}
|
||||
return headersPath.map(h => h.title).join(' > ')
|
||||
}
|
||||
|
||||
function getMatch(page, query, terms) {
|
||||
const matches = terms
|
||||
.map(t => {
|
||||
return getHeaderMatch(page, t) || getContentMatch(page, t)
|
||||
})
|
||||
.filter(m => m)
|
||||
if (matches.length === 0) return null
|
||||
|
||||
if (matches.every(m => m.headerIndex != null)) {
|
||||
return getHeaderMatch(page, query) || matches[0]
|
||||
}
|
||||
|
||||
return getContentMatch(page, query) || matches.find(m => m.headerIndex == null)
|
||||
}
|
||||
|
||||
function getHeaderMatch(page, term) {
|
||||
if (!page.headers) return null
|
||||
for (let i = 0; i < page.headers.length; i++) {
|
||||
const h = page.headers[i]
|
||||
const charIndex = h.title.toLowerCase().indexOf(term)
|
||||
if (charIndex === -1) continue
|
||||
return {
|
||||
headerIndex: i,
|
||||
charIndex,
|
||||
termLength: term.length,
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
function getContentMatch(page, term) {
|
||||
if (!page.contentLowercase) return null
|
||||
const charIndex = page.contentLowercase.indexOf(term)
|
||||
if (charIndex === -1) return null
|
||||
|
||||
return { headerIndex: null, charIndex, termLength: term.length }
|
||||
}
|
||||
|
||||
function getContentStr(page, match) {
|
||||
const snippetLength = 120
|
||||
const { charIndex, termLength } = match
|
||||
|
||||
let lineStartIndex = page.content.lastIndexOf('\n', charIndex)
|
||||
let lineEndIndex = page.content.indexOf('\n', charIndex)
|
||||
|
||||
if (lineStartIndex === -1) lineStartIndex = 0
|
||||
if (lineEndIndex === -1) lineEndIndex = page.content.length
|
||||
|
||||
const line = page.content.slice(lineStartIndex, lineEndIndex)
|
||||
|
||||
if (snippetLength >= line.length) return line
|
||||
|
||||
const lineCharIndex = charIndex - lineStartIndex
|
||||
|
||||
const additionalCharactersFromStart = (snippetLength - termLength) / 2
|
||||
const snippetStart = Math.max(lineCharIndex - additionalCharactersFromStart, 0)
|
||||
const snippetEnd = Math.min(snippetStart + snippetLength, line.length)
|
||||
let result = line.slice(snippetStart, snippetEnd)
|
||||
if (snippetStart > 0) result = '...' + result
|
||||
if (snippetEnd < line.length) result = result + '...'
|
||||
return result
|
||||
}
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
const path = require('path')
|
||||
const titleBadge = (options={}) => ({
|
||||
define: {
|
||||
BADGES: options.badges || [
|
||||
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAAAAXNSR0IArs4c6QAABGpJREFUSA3tVVtoXFUU3fvOI53UlmCaKIFmwEhsE7QK0ipFEdHEKpXaZGrp15SINsXUWvBDpBgQRKi0+KKoFeJHfZA+ED9KKoIU2gYD9UejTW4rVIzm0VSTziPzuNu1z507dibTTjL4U/DAzLn3nL3X2o91ziX6f9wMFdh6Jvbm9nNSV0msViVO6tN1Rm7NMu2OpeJ9lWBUTDxrJbYTS0hInuwciu9eLHlFxCLCZEk3MegsJmZ5K/JD6t7FkFdEvGUo1g7qJoG3MHImqRIn8/nzY1K9UPKKiJmtnUqHVE3Gbuay6vJE/N2FEmuxFjW2nUuE0yQXRRxLiTUAzs36zhZvOXJPdX850EVnnLZkB8prodQoM5JGj7Xk2mvC7JB8tG04Ef5PiXtG0UtxupRQSfTnBoCy554x18yJHI6I+G5Eru4LHmPJZEQsrvPUbMiA8G/WgMK7w7I+ez7++o2ANfbrjvaOl1tFMs+htG3IrZH9/hDX1Pr8Tc0UvH8tcX29KzAgIGcEkINyW5BF9x891hw6VYqgJHEk0huccS7vh3C6gTiODL+26huuBtbct8eZnqLML8PkxGYpuPZBqtqwkSjgc4mB5gbgig5i+y0UDK35LMxXisn9xQtK+nd26gTIHsHe/oblK/b29fUmN/8Y+9jAQrnBp56m1LcDlDp9irKTExSKduXJVWSqdBMA08pEJnEIOB3FPPMybu/oeV8zFeYN3xx576Q6RH+VmplE4ncQV5v+5rzSoyOU7PuEAg8g803PwBJ0CExno/jcMbN8tONYeOmHiuUNryvm3fRUy4tMPVLdAGkUhNWuggGrJcXPv+ouCjz0MKUHz1J2/E8IC9nqTabcxgaBYM0hPhD5Y65FsbxRQKxCQrDjDctW7PUM3HuZunFyifSAqEfuzCp48Il24luWUWZoyJCaPR82jE0+kFA643wRFVni4RYSq3ohJO2pZ7B5dO4xkDWbEpossJPLSrPjYID8rS2UHTlvyNxqIGsg674XJJ7vnh5L7PNwC4hh2sjCI96mzszOTpxLF0T7l88Yz7lAuK6OnL8gXLOnTvpzSb22YG8W7us3jSebFHeeqnXRG1vt+MoUM84LQIBmMsCTAcOauTh0T0l0neQK7m2bLMt2mGxU3HYssS0J2cdv5wljlPsrIuZLAG/2DOZIXgCYT8uMGZN+e2kSirfxZOPCsC0f24nTZzspnVn9VePS1Z5vubmAGGXG8ZFno9Hel0yfA5ZPhF7Dh972BQJ2qCpgH67lmWtBYbvk6sz02wjky2vXyz0XErP/kFB619js1BtwfOV4OPRqOQBjy3Qbk18vigUPPSD5ceHnwck7W9bhAqZdd7SuG7w4/P2F/GaJh8c7e9qgow+Q7cGBo+98WsLkuktFqiZabtXuQTu/Y5ETbR0v7tNSFnvrmu6pjdoan2KjMu8q/Hmj1EfCO2ZGfEIbIXKUlw8qaX9/b2oeSJmFksSeT/Fn0V3nSypChh4Gjh74ybO9aeZ/AN2dwciu2/MhAAAAAElFTkSuQmCC',
|
||||
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAAAAXNSR0IArs4c6QAABH1JREFUSA3tVl1oHFUUPmdmd2ltklqbpJDiNnXFmgbFktho7YMPNiJSSZM0+CAYSkUELVhM6YuwIPpgoOKDqOBDC0XE2CQoNtQXBUFTTcCi+Wlh1V2TQExsUzcltd3M9Tt3ZjZzZ2fT+OJTL8yeM+eee757fmeJbq//KQL8X3DUSFOcfr7cRsRtxNQMWueeVzOkaITIGqQHNg5y8+jNW9ldM7A6nTpAjuolUikAwq7CE3WcM2RRDz+XGVgN3FptU/aUSlvq9Pa3iZ1+sgAqJyyAFqkipd9dqiwHF3P65YycLWc/6sqGrvoEoIp6DOFaX5h6+dnfjkWprwqsPk0dUGq5vySwDImC10KxFHgGL1SWoc92O3eVht09qdXNH11I2SsTsJYqMWzihqGMi+A+Garf3BAuuLI5oGlULyNfyB/HYNujwktOfRrMr5t77NmevqaUopx0grnKAyvVpmwUDB4x6FPXuGvYLTDwWsejwgtgkYKPqRJg8SV6xaiZ3ZTppGneS4yfH5/66fZSDHv+QZci/+h5c5UHtpy67JUqGppM0sh0Nc1dW6/N1W5Yoqat8/TU/VnadmdeW2PLLSyh0cvxBs3KbqTmwYPpxN4do/mzE8nEpvX/UMu2Wbp74zUAK5q6WkHns7V0eWkdPbPzd3rxkTGybadYySumVzhcaJFbs5UrEkQ/+CK8gF5dnh/6ciIZ73gwQ927L1IitoxKLXYP3SjYdOrHHfTZhRRlFyrorafPk20B3HPD1y2G3qKZME5Jcf3t/HUC13/8tSd++vqFveMUTwAUxSUFI1QekR1+bIze3D9MF2aq6cPvG72CgnldWCFqyRw3lwH8ZMerjTD9ElRO7Gv44wNpC90aASqGfVlz/Rx17srQ57/UU26hkhQqUB7dBR71WmzQhHUnblGmVOEw0jhbV1n9OlXUDCIRGaNV5Jp43N516fN7JmnTHdfp7Hgy0luO4aMhtkLL8Bi3bUWYvzh5Mn1dTxrL6QmGuRhGL/TiTTxRoEdTszSaq9GR0NGA3KdkOz3hqSV3MIDhQ5IVX/Ivx3umBti2es2h4eZby7x8br1rkf7Mo90AqC8aQ3sJeNzqFRu+vSANAQe3PL7l0HGOAdwDCeZYvNKeoZp1Qfs6Aipndh86HmFRi0LAnEO47wsqM6cdfjh3jBPUzhZy7nvlUfFsamED1VQt6aISHVymXZ/B2aCtIG8AI8xfobj2d3en1wWVhOeHELKmLQ1s211s88comkv4UCwWyF787mJdYXtNfhKAXVqnKTq8QZvGAGGOfaTo5pGZ/PwbUCr5+DPr/1J92JNHr9aOl/F3iI5+O1nfybsGxoimvZ3ViWSluDITw3P37mypheDIPY0tw7+O/5ApbkYw+zpfaUVu32Pi98+defdUhEpZkRFq0aqyNh9FuL9hpYbEm6iwi0z2REd09ZmyENEbuhjDWzKvZXTqKYaBIr3tt5kuPtQBZFvEUwHt60vfCNu41XsksH9Ij1BMMz1Y0OOunHNShFIP5868g5zeXmuLwL9T4b6Q2+KejgAAAABJRU5ErkJggg==',
|
||||
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAAAAXNSR0IArs4c6QAABGZJREFUSA3tVGtsVFUQnnP2brst7G6ry9aCpTZNKrG7aVJrUVvBQkAKNaFajPIDjDE0USo0aqKJmproD2MihjYkNibaGAkIJAZFK62URwoSUx9gDQGhAj5oTd3KdkuXdu/xm7u99G5Z9pH4w0RPcu7Mndc3M2fOIfp//Rs7EOrsfvnKF4eK/oncZDpBFInFupj8aqzzy8p0/OLZpgVMkry6Iq+S4mCou2d1vICpytIDFtJLQhIqz1K62DPa1bM5VaCZdikDK6WAKDxTwGCFVCS3BLsObjV0MyMn+RdJ9NfUwcOH56iwGiJiF4UddRUgStFep9e9VpSVha45JGFSB+7p9amIftKEZMrLTEMKAZEahuQS6CDoIASgalBKcQlHc9G5tOpA1ItIM5mkVMdQ4Xy5PLTZoOxj8jqxUHjw8WAGfJwQL05Q142/JwzB1CelM25padH6/xjyD49dISMGY0i48uaaTQoeCRgypgaPZHVhe9O1tOo9K7CRilVg5Vc0ND2kK9WIGmuQup11mk1S6bw8WlZaQguLC1CnQBNQIycTb+H8XTUL66HXreq41g8+9qwnHA7vBOASOPTWV/hcC/K9fnb8PXCZjp09T6d+GyL/rfnUXLuInI5Ma0wr/72bZleLmtJRq5D564BXrX0hdyIcPAZVPnbzrk3r3Lqu3hJTpmZ1B/rPUMeRrylnloNeX7OKZjkyYmIj8GCmJiuzqisuxCimfmwzhUUlZTvQuPIMTavcuWl9UOm0HX2ctjPOk6goz0N3FRfS3r4f6OLwCFXdXow8AYeNLo0LTdbOrq7onxnf/J8OCMkDDU33oaI3cDWe39HceFTXJ7uVEjfx+SEZM6jBs8yV7SCHptFn3/1IvoK55HE5EYWbKF/NWXTndhMkHo2ZaoCuR7pnOne3btUjEx14mebzdeFrFKXRBAweAJxMbbmfbsl10aFTZ4GJcGxvEwPxwKyy2Hus6H406pNA74nncP/qjOyNauECyovvJS+TsrT8tkLqO3c+CopkNJJ/GkYJPjHAStBc1PaztNmPIO+72W8Cm+8RU14mL1RkJenqFU5gjttJgdBY9DEBMNls6QEDbBx+jpx77vjGQEn8OR7oPfkT2v7uhB7JsGsYFz4S3Gl0JylwzBkj5QEMky8x3rQ2t8r/QURqKwaGhq/muV3RlwpTj8FLDxhN2oeE6+rXPX3zdPjE3IZtrSeOnz43XlpYMBIdLqmclQsCib0w91YDmSXa0erM0Khos8oT8WyLZ9WOHi9BqX0A/wsVxzyP8fxjgD//sPUXjGsLnspHlzdsbIrnYJWxDduyzzMvPvmtJzt3MfQdVpsb8eju9Wv5wxvfwZBswJTsy7TZGz/dteVXq1XdmuZ5Yf1qOwBXorr2/XvaGq36VPi4wOyIap5C+14D60ICR0FPsxyrBLf4XtDLaO1L+3e3bTOkaX5uCMxxVj++OWcsOPkIElgG8PnR2OoCALuyndpHH7//9kiaeP9h878Bmp511/eTzMgAAAAASUVORK5CYII=',
|
||||
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAAAAXNSR0IArs4c6QAABKFJREFUSA3tVl1oFVcQnrMbrak3QUgkya1akpJYcrUtIqW1JvFBE9LiQ5v6JmJpolbMg32rVrhgoYK0QiMY6i9Y6EMaW5D+xFJaTYItIuK2Kr3+BJNwkxBj05sQY3b3nM6cs2dv9t7NT/vQJw/sndk5M/PNzJkzewGerP+pAmy+ON8lLzUJgA8ZYxYIYZmGYRnctDaWvJJAmTtfP1pvXsBCCPP8QFcCaRkZYACgDZFO4stNIcBCajEOlmmC9XpJ9bAGCaPaPmzPl32dvLSVu3BWCTQs0XQQ6g0DYgwLIoAZbBCdW/i+781o1VVlm/410mw4h06Y7bIPHNyWDyL4FHkX03Q8SrzNhZTZriieckWt7cL6MM85YcLpsi/7O9/iXFT6MswI0DmmpkSaJ0qLxFIm3+i1THHB3zmBH3PYx9CcykcLOeQVVa7QtdxTgQgEleX2AjHYfwA+2ddV77ruGoJUbhGDI09YSNXyMpUt5ylOzxgbUmtOp7NmbNt8v3arjTBfYELmLUV+M+nSawNNAUqpT3ClJWg5I3BLT+cGW/DXNGCa6tx1aakCGEigArTn4TDIPdrXXYKCZNrHLMCOEPvHBlLQ99s9eHB7EB6NTki73CVPQ2F5MSx/uRQixfmq7rK0wYD8w8E905bnPDfwoWs/rfv93NWN/ZfvwsLIU7A09gxECyISeGJkHAau98L97tuw7NXnoPyNF8FcYGLGKsOs0mN3OEyec9esGW/ZEl945dTP34wlR2FZVQWU1q0Cw8Tr7p+hgLLNL0FPxx/Q35mA8aEUrH6nCgwEl0tn7wUiZYJnNRh6DK4UH/k0lfyrsBKdPVv/AriGIQcEDQZ65LBAGe2Rzui9Ybjz7XUppz1/uKBbyVPGkN3ZAeC6hr0x7Nr38N5+EqkoOm17xpoqR9ohQF55ERSvr4Dkr3chNfC3DMzGJlNBElW8w9nsGQvhNGIzDkXzCg8cLK951xHsFBlTJspJNi3ZFIMF2AeDV3q8DNOB+YHi6QTrChDIWDBRi5U5f+ZMfJLu3ccrqxtdxk4SKH336LFxSmkqefwU5T8fhdSdQf9IVKD6aNiwI/hnmcAZ91isYMJIaCUCx9W098+LgruikeTqzqqxKPUwqJyCPJiyemVVZBOijDGjD38Os0jOiSPL1z3SPjXNANbiNPXAdzTfukjjuknNBbyz3nwgTd3AVFqUJ5hpHlq9MveLnWwttUfoygBmvVjuikxND3znrhsELnZk7k+OjIGxeNEkomyLVta0xxn+HZhjBc4YZ/AFjHjz9u3xRZl2BN4aq9nFwWh16IrQ1aHHEd3j1+4/dB9OtH4e29A2H1DyHQRmOSfQZ1Fy7MHBTGB6J/Djq6p3OxyO2cB+4Car7v/o3GXgfAkj23+x9ID1Teoamo/SXcbvSf2PX7Vc8DdCmE1vN9di+32P9/5YR3vLnhCVGUWBjEkr3yh4H8v9CzmsbdhzOKzsJKM90iFdaTMjRPhGVsakRvOaRidljo6H6G7j+ctrJpsP+4COhDIl0La2+FS4+5mlocBaXY5QnGZysIBYoeSsl5qQzrSj/cgNrfuEzlWBfwA+EjrZyWUvpAAAAABJRU5ErkJggg=='
|
||||
]
|
||||
},
|
||||
enhanceAppFiles: [
|
||||
path.resolve(__dirname, 'title-badge.js')
|
||||
]
|
||||
})
|
||||
module.exports = titleBadge
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
export default ({ router }) => {
|
||||
if (typeof window !== "undefined") {
|
||||
|
||||
(function() {
|
||||
function insertBadge(){
|
||||
setTimeout(() =>{
|
||||
const a = document.querySelector(".theme-container .page h1 a");
|
||||
a && a.insertAdjacentHTML('afterend', `<img src="${BADGES[Math.floor(Math.random() * BADGES.length)]}" class="no-zoom">`);
|
||||
},0)
|
||||
}
|
||||
|
||||
let count = 0
|
||||
window.onload = function() {
|
||||
insertBadge();
|
||||
count++;
|
||||
}
|
||||
|
||||
router.afterEach(function (to, from) {
|
||||
if (to && from && to.path === from.path || !count) {
|
||||
return
|
||||
}
|
||||
insertBadge()
|
||||
})
|
||||
|
||||
})()
|
||||
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 54 KiB |
|
|
@ -1,14 +1,17 @@
|
|||
---
|
||||
home: true
|
||||
# heroImage: /img/logo.png
|
||||
heroText: Evan's blog
|
||||
tagline: Web前端技术博客,积跬步以至千里,致敬每个爱学习的你。
|
||||
# actionText: 立刻进入 →
|
||||
# actionLink: /img/web.png
|
||||
# bannerBgImg: /img/bg.jpeg # 可选的,如未配置此项且未配置body背景图时则默认显示网格纹背景
|
||||
|
||||
features: # 可选的
|
||||
- title: 前端
|
||||
details: JavaScript、ES6、Vue框架等前端技术
|
||||
link: /web/
|
||||
imgUrl: /img/web.png
|
||||
link: /web/ # 可选
|
||||
imgUrl: /img/web.png # 可选
|
||||
- title: 页面
|
||||
details: html(5)/css(3),前端页面相关技术
|
||||
link: /ui/
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"name": "vuepress-theme-vdoing",
|
||||
"name": "theme-vdoing-blog",
|
||||
"version": "1.0.0",
|
||||
"scripts": {
|
||||
"dev": "vuepress dev docs",
|
||||
|
|
@ -10,9 +10,7 @@
|
|||
},
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"chalk": "^4.0.0",
|
||||
"inquirer": "^7.1.0",
|
||||
"json2yaml": "^1.1.0",
|
||||
"moment": "^2.25.3",
|
||||
"vuepress": "^1.4.1",
|
||||
"vuepress-plugin-baidu-autopush": "^1.0.1",
|
||||
|
|
@ -21,12 +19,10 @@
|
|||
"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.0-beta.3",
|
||||
"yamljs": "^0.3.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@better-scroll/core": "^2.0.0-beta.6",
|
||||
"@better-scroll/slide": "^2.0.0-beta.6",
|
||||
"good-storage": "^1.1.1",
|
||||
"vuepress-plugin-comment": "^0.7.3"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,8 +18,12 @@
|
|||
v-if="homeData.features && homeData.features.length && !isMQMobile"
|
||||
>
|
||||
<div class="feature" v-for="(feature, index) in homeData.features" :key="index">
|
||||
<router-link :to="feature.link">
|
||||
<img class="feature-img" :src="$withBase(feature.imgUrl)" :alt="feature.title" />
|
||||
<router-link :to="feature.link ? feature.link : 'javascript:;'">
|
||||
<img class="feature-img"
|
||||
v-if="feature.imgUrl"
|
||||
:src="$withBase(feature.imgUrl)"
|
||||
:alt="feature.title"
|
||||
/>
|
||||
<h2>{{ feature.title }}</h2>
|
||||
<p>{{ feature.details }}</p>
|
||||
</router-link>
|
||||
|
|
@ -38,8 +42,12 @@
|
|||
<div class="slide-banner-scroll" ref="slide">
|
||||
<div class="slide-banner-wrapper">
|
||||
<div class="slide-item" v-for="(feature, index) in homeData.features" :key="index">
|
||||
<router-link :to="feature.link">
|
||||
<img class="feature-img" :src="$withBase(feature.imgUrl)" :alt="feature.title" />
|
||||
<router-link :to="feature.link ? feature.link : 'javascript:;'">
|
||||
<img class="feature-img"
|
||||
v-if="feature.imgUrl"
|
||||
:src="$withBase(feature.imgUrl)"
|
||||
:alt="feature.title"
|
||||
/>
|
||||
<h2>{{ feature.title }}</h2>
|
||||
<p>{{ feature.details }}</p>
|
||||
</router-link>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "vuepress-theme-vdoing",
|
||||
"version": "1.0.0-beta.1",
|
||||
"version": "1.0.0-beta.3",
|
||||
"description": "Vdoing theme for VuePress. 一个基于VuePress的知识管理兼博客主题。",
|
||||
"author": {
|
||||
"name": "gaoyi(Evan) Xu"
|
||||
|
|
@ -13,16 +13,14 @@
|
|||
"type": "git",
|
||||
"url": "git+https://github.com/xugaoyi/vuepress-theme-vdoing.git"
|
||||
},
|
||||
"devDependencies": {
|
||||
"chalk": "^4.0.0",
|
||||
"json2yaml": "^1.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@better-scroll/core": "^2.0.0-beta.6",
|
||||
"@better-scroll/slide": "^2.0.0-beta.6",
|
||||
"@vuepress/plugin-active-header-links": "^1.2.0",
|
||||
"@vuepress/plugin-nprogress": "^1.2.0",
|
||||
"@vuepress/plugin-search": "^1.2.0",
|
||||
"chalk": "^4.0.0",
|
||||
"json2yaml": "^1.1.0",
|
||||
"docsearch.js": "^2.5.2",
|
||||
"good-storage": "^1.1.1",
|
||||
"lodash": "^4.17.15",
|
||||
|
|
|
|||
Loading…
Reference in New Issue