Skip to content

Commit 360b4d7

Browse files
feat(search): update search to DocSearch v3 (#383)
* feat(search): update search to DocSearch v3 * fix(search): update DocSearch imports Closes #410.
1 parent 35b4a9b commit 360b4d7

File tree

5 files changed

+124
-134
lines changed

5 files changed

+124
-134
lines changed

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
"build": "vuepress build src"
1010
},
1111
"dependencies": {
12+
"@docsearch/js": "^1.0.0-alpha.27",
13+
"@docsearch/css": "^1.0.0-alpha.27",
1214
"axios": "^0.19.1",
1315
"intersection-observer": "^0.11.0",
1416
"showdown": "^1.9.1"

src/.vuepress/config.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,11 @@ module.exports = {
296296
'/api/': sidebar.api,
297297
'/examples/': sidebar.examples
298298
},
299-
smoothScroll: false
299+
smoothScroll: false,
300+
algolia: {
301+
indexName: 'vuejs-v3',
302+
apiKey: 'bc6e8acb44ed4179c30d0a45d6140d3f'
303+
}
300304
},
301305
plugins: [
302306
[
Lines changed: 109 additions & 130 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,23 @@
11
<template>
2-
<form
3-
id="search-form"
4-
class="algolia-search-wrapper search-box"
5-
role="search"
6-
>
7-
<input
8-
id="algolia-search-input"
9-
class="search-query"
10-
:placeholder="placeholder"
11-
>
12-
</form>
2+
<div id="docsearch"></div>
133
</template>
144

155
<script>
6+
function isSpecialClick(event) {
7+
return (
8+
event.button === 1 ||
9+
event.altKey ||
10+
event.ctrlKey ||
11+
event.metaKey ||
12+
event.shiftKey
13+
)
14+
}
15+
1616
export default {
1717
name: 'AlgoliaSearchBox',
1818
1919
props: ['options'],
2020
21-
data () {
22-
return {
23-
placeholder: undefined
24-
}
25-
},
26-
2721
watch: {
2822
$lang (newValue) {
2923
this.update(this.options, newValue)
@@ -36,135 +30,120 @@ export default {
3630
3731
mounted () {
3832
this.initialize(this.options, this.$lang)
39-
this.placeholder = this.$site.themeConfig.searchPlaceholder || ''
4033
},
4134
4235
methods: {
36+
getRelativePath (absoluteUrl) {
37+
const { pathname, hash } = new URL(absoluteUrl)
38+
const url = pathname.replace(this.$site.base, '/') + hash
39+
40+
return url
41+
},
4342
initialize (userOptions, lang) {
4443
Promise.all([
45-
import(/* webpackChunkName: "docsearch" */ 'docsearch.js/dist/cdn/docsearch.min.js'),
46-
import(/* webpackChunkName: "docsearch" */ 'docsearch.js/dist/cdn/docsearch.min.css')
44+
import(/* webpackChunkName: "docsearch" */ '@docsearch/js'),
45+
import(/* webpackChunkName: "docsearch" */ '@docsearch/css')
4746
]).then(([docsearch]) => {
4847
docsearch = docsearch.default
49-
const { algoliaOptions = {}} = userOptions
50-
docsearch(Object.assign(
51-
{},
52-
userOptions,
53-
{
54-
inputSelector: '#algolia-search-input',
55-
// #697 Make docsearch work well at i18n mode.
56-
algoliaOptions: Object.assign({
57-
'facetFilters': [`lang:${lang}`].concat(algoliaOptions.facetFilters || [])
58-
}, algoliaOptions),
59-
handleSelected: (input, event, suggestion) => {
60-
const { pathname, hash } = new URL(suggestion.url)
61-
const routepath = pathname.replace(this.$site.base, '/')
62-
this.$router.push(`${routepath}${hash}`)
48+
49+
docsearch(
50+
Object.assign(
51+
{
52+
placeholder: this.$site.themeConfig.searchPlaceholder
53+
},
54+
userOptions,
55+
{
56+
container: '#docsearch',
57+
// #697 Make DocSearch work well in i18n mode.
58+
searchParameters: Object.assign(
59+
{},
60+
// lang && {
61+
// facetFilters: [`lang:${lang}`].concat(
62+
// userOptions.facetFilters || []
63+
// )
64+
// },
65+
userOptions.searchParameters
66+
),
67+
navigator: {
68+
navigate: ({ suggestionUrl }) => {
69+
const { pathname: hitPathname } = new URL(
70+
window.location.origin + suggestionUrl
71+
)
72+
73+
// Vue Router doesn't handle same-page navigation so we use
74+
// the native browser location API for anchor navigation.
75+
if (this.$router.history.current.path === hitPathname) {
76+
window.location.assign(
77+
window.location.origin + suggestionUrl
78+
)
79+
} else {
80+
this.$router.push(suggestionUrl)
81+
}
82+
}
83+
},
84+
transformItems: items => {
85+
return items.map(item => {
86+
return Object.assign({}, item, {
87+
url: this.getRelativePath(item.url)
88+
})
89+
})
90+
},
91+
hitComponent: ({ hit, children }) => {
92+
return {
93+
type: 'a',
94+
ref: undefined,
95+
constructor: undefined,
96+
key: undefined,
97+
props: {
98+
href: hit.url,
99+
onClick: event => {
100+
if (isSpecialClick(event)) {
101+
return
102+
}
103+
104+
// We rely on the native link scrolling when user is
105+
// already on the right anchor because Vue Router doesn't
106+
// support duplicated history entries.
107+
if (this.$router.history.current.fullPath === hit.url) {
108+
return
109+
}
110+
111+
const { pathname: hitPathname } = new URL(
112+
window.location.origin + hit.url
113+
)
114+
115+
// If the hits goes to another page, we prevent the native link behavior
116+
// to leverage the Vue Router loading feature.
117+
if (this.$router.history.current.path !== hitPathname) {
118+
event.preventDefault()
119+
}
120+
121+
this.$router.push(hit.url)
122+
},
123+
children
124+
}
125+
}
126+
}
63127
}
64-
}
65-
))
128+
)
129+
)
66130
})
67131
},
68132
69-
update (options, lang) {
70-
this.$el.innerHTML = '<input id="algolia-search-input" class="search-query">'
133+
update(options, lang) {
134+
this.$el.innerHTML = '<div id="docsearch"></div>'
71135
this.initialize(options, lang)
72136
}
73137
}
74138
}
75139
</script>
76140

77-
<style lang="stylus">
78-
.algolia-search-wrapper
79-
& > span
80-
vertical-align middle
81-
.algolia-autocomplete
82-
line-height normal
83-
.ds-dropdown-menu
84-
background-color #fff
85-
border 1px solid #999
86-
border-radius 4px
87-
font-size 16px
88-
margin 6px 0 0
89-
padding 4px
90-
text-align left
91-
&:before
92-
border-color #999
93-
[class*=ds-dataset-]
94-
border none
95-
padding 0
96-
.ds-suggestions
97-
margin-top 0
98-
.ds-suggestion
99-
border-bottom 1px solid $borderColor
100-
.algolia-docsearch-suggestion--highlight
101-
color #2c815b
102-
.algolia-docsearch-suggestion
103-
border-color $borderColor
104-
padding 0
105-
.algolia-docsearch-suggestion--category-header
106-
padding 5px 10px
107-
margin-top 0
108-
background $accentColor
109-
color #fff
110-
font-weight 600
111-
.algolia-docsearch-suggestion--highlight
112-
background rgba(255, 255, 255, 0.6)
113-
.algolia-docsearch-suggestion--wrapper
114-
padding 0
115-
.algolia-docsearch-suggestion--title
116-
font-weight 600
117-
margin-bottom 0
118-
color $textColor
119-
.algolia-docsearch-suggestion--subcategory-column
120-
vertical-align top
121-
padding 5px 7px 5px 5px
122-
border-color $borderColor
123-
background #f1f3f5
124-
&:after
125-
display none
126-
.algolia-docsearch-suggestion--subcategory-column-text
127-
color #555
128-
.algolia-docsearch-footer
129-
border-color $borderColor
130-
.ds-cursor .algolia-docsearch-suggestion--content
131-
background-color #e7edf3 !important
132-
color $textColor
133-
134-
@media (min-width: $MQMobile)
135-
.algolia-search-wrapper
136-
.algolia-autocomplete
137-
.algolia-docsearch-suggestion
138-
.algolia-docsearch-suggestion--subcategory-column
139-
float none
140-
width 150px
141-
min-width 150px
142-
display table-cell
143-
.algolia-docsearch-suggestion--content
144-
float none
145-
display table-cell
146-
width 100%
147-
vertical-align top
148-
.ds-dropdown-menu
149-
min-width 515px !important
150-
151-
@media (max-width: $MQMobile)
152-
.algolia-search-wrapper
153-
.ds-dropdown-menu
154-
min-width calc(100vw - 4rem) !important
155-
max-width calc(100vw - 4rem) !important
156-
.algolia-docsearch-suggestion--wrapper
157-
padding 5px 7px 5px 5px !important
158-
.algolia-docsearch-suggestion--subcategory-column
159-
padding 0 !important
160-
background white !important
161-
.algolia-docsearch-suggestion--subcategory-column-text:after
162-
content " > "
163-
font-size 10px
164-
line-height 14.4px
165-
display inline-block
166-
width 5px
167-
margin -3px 3px 0
168-
vertical-align middle
141+
<style lang="scss">
142+
@import '@theme/styles/_settings.scss';
169143
144+
.DocSearch {
145+
--docsearch-primary-color: #{$green};
146+
--docsearch-highlight-color: var(--docsearch-primary-color);
147+
--docsearch-searchbox-shadow: inset 0 0 0 2px var(--docsearch-primary-color);
148+
}
170149
</style>

src/.vuepress/theme/components/Navbar.vue

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,17 @@
2323
'max-width': linksWrapMaxWidth + 'px'
2424
} : {}"
2525
>
26-
<AlgoliaSearchBox v-if="isAlgoliaSearch" :options="algolia" />
2726
<SearchBox
28-
v-else-if="$site.themeConfig.search !== false && $page.frontmatter.search !== false"
27+
v-if="
28+
isAlgoliaSearch === false &&
29+
!(
30+
$site.themeConfig.search !== false &&
31+
$page.frontmatter.search !== false
32+
)
33+
"
2934
/>
3035
<NavLinks class="can-hide" />
36+
<AlgoliaSearchBox v-if="isAlgoliaSearch" :options="algolia" />
3137
</div>
3238
</header>
3339
</template>

src/.vuepress/theme/package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
"@vuepress/plugin-active-header-links": "^1.3.1",
2525
"@vuepress/plugin-nprogress": "^1.3.1",
2626
"@vuepress/plugin-search": "^1.3.1",
27-
"docsearch.js": "^2.5.2",
2827
"lodash": "^4.17.15",
2928
"stylus": "^0.54.5",
3029
"stylus-loader": "^3.0.2",

0 commit comments

Comments
 (0)