Skip to content

Commit

Permalink
feat: add Algolia DocSearch
Browse files Browse the repository at this point in the history
  • Loading branch information
posva committed Nov 26, 2020
1 parent b127aee commit 51dfe70
Show file tree
Hide file tree
Showing 5 changed files with 336 additions and 3 deletions.
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,11 @@
"url": "https://github.com/vuejs/vitepress/issues"
},
"dependencies": {
"@docsearch/css": "^1.0.0-alpha.28",
"@docsearch/js": "^1.0.0-alpha.28",
"@vue/compiler-sfc": "^3.0.3",
"@vue/server-renderer": "^3.0.3",
"algoliasearch": "^4.8.1",
"chalk": "^4.1.0",
"debug": "^4.1.1",
"diacritics": "^1.3.0",
Expand Down
12 changes: 11 additions & 1 deletion src/client/theme-default/Layout.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
<header class="navbar" v-if="showNavbar">
<NavBar>
<template #search>
<slot name="navbar-search" />
<slot name="navbar-search">
<AlgoliaSearchBox :options="$site.themeConfig.algolia" />
</slot>
</template>
</NavBar>
<ToggleSideBarButton @toggle="toggleSidebar" />
Expand Down Expand Up @@ -53,6 +55,7 @@ import ToggleSideBarButton from './components/ToggleSideBarButton.vue'
import SideBar from './components/SideBar.vue'
import Page from './components/Page.vue'
import { useRoute, useSiteData, useSiteDataByRoute } from 'vitepress'
import AlgoliaSearchBox from './components/AlgoliaSearchBox.vue'
const route = useRoute()
const siteData = useSiteData()
Expand Down Expand Up @@ -107,3 +110,10 @@ watch(route, hideSidebar)
// TODO: route only changes when the pathname changes
// listening to hashchange does nothing because it's prevented in router
</script>

<style>
/* remove margin added by user agent */
.DocSearch-SearchBar form {
margin-block-end: 0;
}
</style>
158 changes: 158 additions & 0 deletions src/client/theme-default/components/AlgoliaSearchBox.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
<template>
<div id="docsearch"></div>
</template>

<script lang="ts">
import { AlgoliaSearchOptions } from 'algoliasearch'
// import docsearch from '@docsearch/js'
// import '@docsearch/css'
import { useRoute, useRouter } from 'vitepress'
import { getCurrentInstance, onMounted, PropType, watch } from 'vue'
function isSpecialClick(event: MouseEvent) {
return (
event.button === 1 ||
event.altKey ||
event.ctrlKey ||
event.metaKey ||
event.shiftKey
)
}
function getRelativePath(absoluteUrl: string) {
const { pathname, hash } = new URL(absoluteUrl)
// const url = pathname.replace(this.$site.base, '/') + hash
const url = pathname + hash
return url
}
export default {
name: 'AlgoliaSearchBox',
props: {
options: {
type: Object as PropType<AlgoliaSearchOptions>,
required: true,
},
},
setup(props) {
const route = useRoute()
const router = useRouter()
const vm = getCurrentInstance()
watch(
() => props.options,
newValue => {
update(newValue)
}
)
function update(options: any) {
if (vm && vm.vnode.el) {
vm.vnode.el.innerHTML = '<div id="docsearch"></div>'
initialize(options)
}
}
function initialize(userOptions: any) {
Promise.all([
import('@docsearch/js'),
import('@docsearch/css'),
// import(/* webpackChunkName: "docsearch" */ '@docsearch/js'),
// Promise.resolve(docsearch),
// import(/* webpackChunkName: "docsearch" */ '@docsearch/css'),
]).then(([docsearch]) => {
docsearch = docsearch.default
docsearch(
Object.assign({}, userOptions, {
container: '#docsearch',
// #697 Make DocSearch work well in i18n mode.
searchParameters: Object.assign(
{},
// lang && {
// facetFilters: [`lang:${lang}`].concat(
// userOptions.facetFilters || []
// )
// },
userOptions.searchParameters
),
navigator: {
navigate: ({ suggestionUrl }: { suggestionUrl: string }) => {
const { pathname: hitPathname } = new URL(
window.location.origin + suggestionUrl
)
// Vue Router doesn't handle same-page navigation so we use
// the native browser location API for anchor navigation.
if (route.path === hitPathname) {
window.location.assign(window.location.origin + suggestionUrl)
} else {
router.go(suggestionUrl)
}
},
},
transformItems: items => {
return items.map(item => {
return Object.assign({}, item, {
url: getRelativePath(item.url),
})
})
},
hitComponent: ({ hit, children }) => {
const relativeHit = hit.url.startsWith('http')
? getRelativePath(hit.url as string)
: hit.url
return {
type: 'a',
ref: undefined,
constructor: undefined,
key: undefined,
props: {
href: hit.url,
onClick: (event: MouseEvent) => {
if (isSpecialClick(event)) {
return
}
// We rely on the native link scrolling when user is
// already on the right anchor because Vue Router doesn't
// support duplicated history entries.
if (route.path === relativeHit) {
return
}
// If the hits goes to another page, we prevent the native link behavior
// to leverage the Vue Router loading feature.
if (route.path !== relativeHit) {
event.preventDefault()
}
router.go(relativeHit)
},
children,
},
}
},
})
)
})
}
onMounted(() => {
initialize(props.options)
})
},
}
</script>

<style>
.DocSearch {
--docsearch-primary-color: #42b983;
--docsearch-highlight-color: var(--docsearch-primary-color);
--docsearch-searchbox-shadow: inset 0 0 0 2px var(--docsearch-primary-color);
}
</style>
4 changes: 2 additions & 2 deletions src/client/theme-default/styles/vars.css
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@
* Z Indexes
* --------------------------------------------------------------------- */

--z-index-navbar: 1100;
--z-index-sidebar: 1000;
--z-index-navbar: 10;
--z-index-sidebar: 6;

/**
* Sizes
Expand Down
Loading

0 comments on commit 51dfe70

Please sign in to comment.