docs(README): add search

This commit is contained in:
qingwei.li 2017-02-09 20:57:58 +08:00 committed by cinwell.li
parent eb5ff3e987
commit e1da2f8a84
8 changed files with 99 additions and 17 deletions

View File

@ -1,3 +1,11 @@
## 2.1.0
### Features
- Add search plugin
```html
<script src="//unpkg.com/docsify/lib/docsify.js"></script>
<script src="//unpkg.com/docsify/lib/plugins/search.js"></script>
```
## 2.0.3
### Bug fixes
- fix: rendering emojis

View File

@ -459,3 +459,39 @@ window.$docsify = {
themeColor: '#3F51B5'
}
```
## Plugins
### Full Text Search
If a document can have a search, can enhance some user experience. The introduction of search plugin is easy. such as
```html
<script src="//unpkg.com/docsify/lib/docsify.js"></script>
<script src="//unpkg.com/docsify/lib/plugins/search.js"></script>
```
By default, the hyperlink on the current page is recognized and the content is saved in `localStorage`. You can also specify the path to the files.
!> Configure the content before the plugin is installed.
```js
window.$docsify = {
search: 'auto', // default
search : [
'/', // => /README.md
'/guide', // => /guide.md
'/get-started', // => /get-started.md
'/zh-cn/', // => /zh-cn/README.md
],
// Full configuration
search: {
maxAge: 86400000, // Expiration time, the default one day
paths: [], // or 'auto'
placeholder: 'Type to search'
}
}
```

View File

@ -466,3 +466,38 @@ window.$docsify = {
themeColor: '#3F51B5'
}
```
## Plugins
### 全文检索 - search
一份文档如果能有搜索功能会提升一些用户体验,加载搜索插件也很简单,直接引入就自动安装并启用。默认情况下会自动分析当前页面上的超链接,获取内容后建立索引并存储在 localStorage 里,默认过期时间为一天,当然这是可配置的。
自动识别的方式不一定能识别完整或者如果你想指定某些文件可索引,你可以自己指定文件的路径。
```html
<script src="//unpkg.com/docsify/lib/docsify.js"></script>
<script src="//unpkg.com/docsify/lib/plugins/search.js"></script>
```
!> 配置要在 docsify 引入之前
```js
window.$docsify = {
search: 'auto', // default
search : [
'/', // => /README.md
'/guide', // => /guide.md
'/get-started', // => /get-started.md
'/zh-cn/', // => /zh-cn/README.md
],
// Full configuration
search: {
maxAge: 86400000, // Expiration time, the default one day
paths: [], // or 'auto'
placeholder: 'Type to search'
}
}
```

View File

@ -126,7 +126,7 @@ export function bindToggle (dom) {
dom.addEventListener('click', () => body.classList.toggle('close'))
if (isMobile()) {
const sidebar = document.querySelector('.sidebar div')
const sidebar = document.querySelector('.sidebar')
sidebar.addEventListener('click', () => {
body.classList.toggle('close')
setTimeout(() => activeLink(sidebar, true), 0)

View File

@ -58,6 +58,7 @@ const mainRender = function (cb) {
}
let page
if (!route) {
page = OPTIONS.homepage || 'README.md'
} else if (/\/$/.test(route)) {

View File

@ -50,14 +50,14 @@ const genFilePath = function (path) {
filePath = basePath + filePath
return filePath.replace(/\/\//g, '/')
return filePath.replace(/\/+/g, '/')
}
/**
* generate index
*/
const genIndex = function (path, content = '') {
// INDEXS[path] = {}
INDEXS[path] = { slug: '', title: '', body: '' }
let slug
content
@ -73,7 +73,7 @@ const genIndex = function (path, content = '') {
// <h1 id="xxx"></h1>
const id = attr.match(/id="(\S+)"/)[1]
slug = `#/${path}#${id}`.replace(/\/\//, '/')
slug = `#/${path}#${id}`.replace(/\/+/, '/')
INDEXS[slug] = { slug, title: text, body: '' }
} else {
// other html tag
@ -221,12 +221,10 @@ class SearchComponent {
for (let i = 0; i < data.length; i++) {
const post = data[i]
let isMatch = false
let matchingNum = 0
let resultStr = ''
const postTitle = post.title && post.title.trim()
const postContent = post.body && post.body.trim()
const postUrl = post.slug || ''
const postType = post.pagetitle
if (postTitle !== '' && postContent !== '') {
keywords.forEach((keyword, i) => {
@ -241,7 +239,6 @@ class SearchComponent {
isMatch = false
} else {
isMatch = true
matchingNum++
if (indexContent < 0) indexContent = 0
let start = 0
@ -266,9 +263,7 @@ class SearchComponent {
const matchingPost = {
title: escapeHtml(postTitle),
content: resultStr,
url: postUrl,
type: postType,
matchingNum: matchingNum
url: postUrl
}
matchingResults.push(matchingPost)
@ -280,23 +275,30 @@ class SearchComponent {
}
}
// TODO 如果不存在就重新加载
const searchPlugin = function () {
if (localStorage.getItem('docsify.search.expires') > Date.now()) {
INDEXS = JSON.parse(localStorage.getItem('docsify.search.index'))
const isAuto = CONFIG.paths === 'auto'
const isExpired = localStorage.getItem('docsify.search.expires') < Date.now()
INDEXS = JSON.parse(localStorage.getItem('docsify.search.index'))
if (isExpired) {
INDEXS = {}
} else if (!isAuto) {
return
}
const paths = CONFIG.paths === 'auto' ? getAllPaths() : CONFIG.paths
let count = 0
const paths = isAuto ? getAllPaths() : CONFIG.paths
const len = paths.length
const { load, marked, slugify } = window.Docsify.utils
let count = 0
const done = () => {
localStorage.setItem('docsify.search.expires', Date.now() + CONFIG.maxAge)
localStorage.setItem('docsify.search.index', JSON.stringify(INDEXS))
}
paths.forEach(path => {
if (INDEXS[path]) return count++
load(genFilePath(path)).then(content => {
genIndex(path, marked(content))
slugify.clear()

View File

@ -43,7 +43,7 @@ export function init () {
}
renderer.link = function (href, title, text) {
if (!/:/.test(href)) {
href = `#/${href}`.replace(/\/\//g, '/')
href = `#/${href}`.replace(/\/+/g, '/')
}
return `<a href="${href}" title="${title || ''}">${text}</a>`

View File

@ -89,7 +89,7 @@ export function getRoute () {
const loc = window.location
if (cacheHash === loc.hash && !isNil(cacheRoute)) return cacheRoute
let route = loc.hash.match(/^#\/([^#]+)/)
let route = loc.hash.replace(/%23/g, '#').match(/^#\/([^#]+)/)
if (route && route.length === 2) {
route = route[1]