Skip to content

Commit 042f48a

Browse files
authored
docs: fix algolia search (#6865)
1 parent aaa7eb0 commit 042f48a

File tree

5 files changed

+409
-10
lines changed

5 files changed

+409
-10
lines changed
Lines changed: 325 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,325 @@
1+
<script setup lang="ts">
2+
import 'docsearch.js/dist/cdn/docsearch.min.css'
3+
import docsearch from 'docsearch.js/dist/cdn/docsearch.min.js'
4+
import { useRoute, useRouter, useData } from 'vitepress'
5+
import { getCurrentInstance, onMounted, watch } from 'vue'
6+
const props = defineProps<{
7+
options: any
8+
}>()
9+
10+
const vm = getCurrentInstance()
11+
const route = useRoute()
12+
const router = useRouter()
13+
watch(
14+
() => props.options,
15+
(value) => {
16+
update(value)
17+
}
18+
)
19+
onMounted(() => {
20+
initialize(props.options)
21+
})
22+
function isSpecialClick(event: MouseEvent) {
23+
return (
24+
event.button === 1 ||
25+
event.altKey ||
26+
event.ctrlKey ||
27+
event.metaKey ||
28+
event.shiftKey
29+
)
30+
}
31+
function getRelativePath(absoluteUrl: string) {
32+
const { pathname, hash } = new URL(absoluteUrl)
33+
return pathname + hash
34+
}
35+
function update(options: any) {
36+
if (vm && vm.vnode.el) {
37+
vm.vnode.el.innerHTML =
38+
'<input id="algolia-search-input" class="search-query">'
39+
initialize(options)
40+
}
41+
}
42+
const { lang, site } = useData()
43+
// the search results should be filtered based on the language
44+
const facetFilters: string[] = ['language:' + lang.value]
45+
if (props.options.searchParameters?.facetFilters) {
46+
facetFilters.push(...props.options.searchParameters.facetFilters)
47+
}
48+
watch(
49+
lang,
50+
(newLang, oldLang) => {
51+
const index = facetFilters.findIndex(
52+
(filter) => filter === 'language:' + oldLang
53+
)
54+
if (index > -1) {
55+
facetFilters.splice(index, 1, 'language:' + newLang)
56+
}
57+
}
58+
)
59+
function initialize(userOptions: any) {
60+
const { algoliaOptions = {}} = userOptions
61+
docsearch(Object.assign(
62+
{},
63+
userOptions,
64+
{
65+
inputSelector: '#algolia-search-input',
66+
// #697 Make docsearch work well at i18n mode.
67+
algoliaOptions: {
68+
...algoliaOptions,
69+
facetFilters: [`lang:${lang.value}`].concat(algoliaOptions.facetFilters || [])
70+
},
71+
handleSelected: (input, event, suggestion) => {
72+
const { pathname, hash } = new URL(suggestion.url)
73+
74+
// Router doesn't handle same-page navigation so we use the native
75+
// browser location API for anchor navigation
76+
if (route.path === pathname) {
77+
window.location.assign(suggestion.url)
78+
} else {
79+
const routepath = pathname.replace(site.base, '/')
80+
const _hash = decodeURIComponent(hash)
81+
router.go(`${routepath}${_hash}`)
82+
}
83+
}
84+
})
85+
)
86+
}
87+
</script>
88+
89+
<template>
90+
<form
91+
id="search-form"
92+
class="algolia-search-wrapper search-box"
93+
role="search"
94+
>
95+
<input id="algolia-search-input" class="search-query">
96+
</form>
97+
</template>
98+
99+
<style>
100+
.search-box {
101+
flex: 0 0 auto;
102+
vertical-align: top;
103+
}
104+
.algolia-search-wrapper {
105+
--border-color: #eaecef;
106+
--text-color: #2c3e50;
107+
--accent-color: #3eaf7c;
108+
}
109+
110+
.algolia-search-wrapper > span {
111+
vertical-align: middle;
112+
}
113+
.algolia-search-wrapper .algolia-autocomplete {
114+
line-height: normal;
115+
}
116+
.algolia-search-wrapper .algolia-autocomplete .ds-dropdown-menu {
117+
background-color: #fff;
118+
border: 1px solid #999;
119+
border-radius: 4px;
120+
font-size: 16px;
121+
margin: 6px 0 0;
122+
padding: 4px;
123+
text-align: left;
124+
}
125+
.algolia-search-wrapper .algolia-autocomplete .ds-dropdown-menu:before {
126+
border-color: #999;
127+
}
128+
.algolia-search-wrapper .algolia-autocomplete .ds-dropdown-menu [class*=ds-dataset-] {
129+
border: none;
130+
padding: 0;
131+
}
132+
.algolia-search-wrapper .algolia-autocomplete .ds-dropdown-menu .ds-suggestions {
133+
margin-top: 0;
134+
}
135+
.algolia-search-wrapper .algolia-autocomplete .ds-dropdown-menu .ds-suggestion {
136+
border-bottom: 1px solid var(--border-color);
137+
}
138+
.algolia-search-wrapper .algolia-autocomplete .algolia-docsearch-suggestion--highlight {
139+
color: #2c815b;
140+
}
141+
.algolia-search-wrapper .algolia-autocomplete .algolia-docsearch-suggestion {
142+
border-color: var(--border-color);
143+
padding: 0;
144+
}
145+
.algolia-search-wrapper .algolia-autocomplete .algolia-docsearch-suggestion .algolia-docsearch-suggestion--category-header {
146+
padding: 5px 10px;
147+
margin-top: 0;
148+
background: var(--accent-color);
149+
color: #fff;
150+
font-weight: 600;
151+
}
152+
.algolia-search-wrapper .algolia-autocomplete .algolia-docsearch-suggestion .algolia-docsearch-suggestion--category-header .algolia-docsearch-suggestion--highlight {
153+
background: rgba(255,255,255,0.6);
154+
}
155+
.algolia-search-wrapper .algolia-autocomplete .algolia-docsearch-suggestion .algolia-docsearch-suggestion--wrapper {
156+
padding: 0;
157+
}
158+
.algolia-search-wrapper .algolia-autocomplete .algolia-docsearch-suggestion .algolia-docsearch-suggestion--title {
159+
font-weight: 600;
160+
margin-bottom: 0;
161+
color: var(--text-color);
162+
}
163+
.algolia-search-wrapper .algolia-autocomplete .algolia-docsearch-suggestion .algolia-docsearch-suggestion--subcategory-column {
164+
vertical-align: top;
165+
padding: 5px 7px 5px 5px;
166+
border-color: var(--border-color);
167+
background: #f1f3f5;
168+
}
169+
.algolia-search-wrapper .algolia-autocomplete .algolia-docsearch-suggestion .algolia-docsearch-suggestion--subcategory-column:after {
170+
display: none;
171+
}
172+
.algolia-search-wrapper .algolia-autocomplete .algolia-docsearch-suggestion .algolia-docsearch-suggestion--subcategory-column-text {
173+
color: #555;
174+
}
175+
.algolia-search-wrapper .algolia-autocomplete .algolia-docsearch-footer {
176+
border-color: var(--border-color);
177+
}
178+
.algolia-search-wrapper .algolia-autocomplete .ds-cursor .algolia-docsearch-suggestion--content {
179+
background-color: #e7edf3 !important;
180+
color: var(--text-color);
181+
}
182+
@media (min-width: 719px) {
183+
.algolia-search-wrapper .algolia-autocomplete .algolia-docsearch-suggestion .algolia-docsearch-suggestion--subcategory-column {
184+
float: none;
185+
width: 150px;
186+
min-width: 150px;
187+
display: table-cell;
188+
}
189+
.algolia-search-wrapper .algolia-autocomplete .algolia-docsearch-suggestion .algolia-docsearch-suggestion--content {
190+
float: none;
191+
display: table-cell;
192+
width: 100%;
193+
vertical-align: top;
194+
}
195+
.algolia-search-wrapper .algolia-autocomplete .algolia-docsearch-suggestion .ds-dropdown-menu {
196+
min-width: 515px !important;
197+
}
198+
}
199+
@media (max-width: 719px) {
200+
.algolia-search-wrapper .ds-dropdown-menu {
201+
min-width: calc(100vw - 4rem) !important;
202+
max-width: calc(100vw - 4rem) !important;
203+
}
204+
.algolia-search-wrapper .algolia-docsearch-suggestion--wrapper {
205+
padding: 5px 7px 5px 5px !important;
206+
}
207+
.algolia-search-wrapper .algolia-docsearch-suggestion--subcategory-column {
208+
padding: 0 !important;
209+
background: #fff !important;
210+
}
211+
.algolia-search-wrapper .algolia-docsearch-suggestion--subcategory-column-text:after {
212+
content: " > ";
213+
font-size: 10px;
214+
line-height: 14.4px;
215+
display: inline-block;
216+
width: 5px;
217+
margin: -3px 3px 0;
218+
vertical-align: middle;
219+
}
220+
}
221+
222+
.search-box {
223+
display: inline-block;
224+
position: relative;
225+
margin-left: 1rem;
226+
}
227+
.search-box input {
228+
cursor: text;
229+
width: 10rem;
230+
height: 2rem;
231+
color: #4e6e8e;
232+
display: inline-block;
233+
border: 1px solid #cfd4db;
234+
border-radius: 2rem;
235+
font-size: 0.9rem;
236+
line-height: 2rem;
237+
padding: 0 0.5rem 0 2rem;
238+
outline: none;
239+
transition: all 0.2s ease;
240+
background: #fff url("./search.svg") 0.6rem 0.5rem no-repeat;
241+
background-size: 1rem;
242+
}
243+
.search-box input:focus {
244+
cursor: auto;
245+
border-color: #3eaf7c;
246+
}
247+
.search-box .suggestions {
248+
background: #fff;
249+
width: 20rem;
250+
position: absolute;
251+
top: 2rem;
252+
border: 1px solid #cfd4db;
253+
border-radius: 6px;
254+
padding: 0.4rem;
255+
list-style-type: none;
256+
}
257+
.search-box .suggestions.align-right {
258+
right: 0;
259+
}
260+
.search-box .suggestion {
261+
line-height: 1.4;
262+
padding: 0.4rem 0.6rem;
263+
border-radius: 4px;
264+
cursor: pointer;
265+
}
266+
.search-box .suggestion a {
267+
white-space: normal;
268+
color: #5d82a6;
269+
}
270+
.search-box .suggestion a .page-title {
271+
font-weight: 600;
272+
}
273+
.search-box .suggestion a .header {
274+
font-size: 0.9em;
275+
margin-left: 0.25em;
276+
}
277+
.search-box .suggestion.focused {
278+
background-color: #f3f4f5;
279+
}
280+
.search-box .suggestion.focused a {
281+
color: #3eaf7c;
282+
}
283+
@media (max-width: 959px) {
284+
.search-box input {
285+
cursor: pointer;
286+
width: 0;
287+
border-color: transparent;
288+
position: relative;
289+
}
290+
.search-box input:focus {
291+
cursor: text;
292+
left: 0;
293+
width: 10rem;
294+
}
295+
}
296+
@media all and (-ms-high-contrast: none) {
297+
.search-box input {
298+
height: 2rem;
299+
}
300+
}
301+
@media (max-width: 959px) and (min-width: 719px) {
302+
.search-box .suggestions {
303+
left: 0;
304+
}
305+
}
306+
@media (max-width: 719px) {
307+
.search-box {
308+
margin-right: 0;
309+
}
310+
.search-box input {
311+
left: 1rem;
312+
}
313+
.search-box .suggestions {
314+
right: 0;
315+
}
316+
}
317+
@media (max-width: 419px) {
318+
.search-box .suggestions {
319+
width: calc(100vw - 4rem);
320+
}
321+
.search-box input:focus {
322+
width: 8rem;
323+
}
324+
}
325+
</style>

docs/.vitepress/theme/index.js

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,20 @@
1+
import { h } from 'vue'
12
import DefaultTheme from 'vitepress/dist/client/theme-default'
3+
import AlgoliaSearchBox from './AlgoliaSearchBox.vue'
24
import './custom.css'
35

4-
export default DefaultTheme
6+
export default {
7+
...DefaultTheme,
8+
Layout() {
9+
return h(DefaultTheme.Layout, null, {
10+
'navbar-search': () => {
11+
return h(AlgoliaSearchBox, {
12+
options: {
13+
indexName: 'cli_vuejs',
14+
apiKey: 'f6df220f7d246aff64a56300b7f19f21',
15+
}
16+
})
17+
}
18+
})
19+
}
20+
}

docs/.vitepress/theme/search.svg

Lines changed: 2 additions & 0 deletions
Loading

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
"babel-jest": "^27.0.6",
4242
"chromedriver": "^94.0.0",
4343
"debug": "^4.1.0",
44+
"docsearch.js": "^2.6.3",
4445
"eslint": "^7.32.0",
4546
"eslint-config-prettier": "^8.3.0",
4647
"eslint-plugin-graphql": "^4.0.0",

0 commit comments

Comments
 (0)