123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181 |
- <template>
- <div class="algolia-search-box" id="docsearch" />
- </template>
- <script setup lang="ts">
- import '@docsearch/css'
- import { useRoute, useRouter } from 'vitepress'
- import { defineProps, getCurrentInstance, onMounted, watch } from 'vue'
- import docsearch from '@docsearch/js'
- import type { DefaultTheme } from '../config'
- import type { DocSearchHit } from '@docsearch/react/dist/esm/types'
- import { useSiteDataByRoute } from 'vitepress'
- const siteData = useSiteDataByRoute()
- const props = defineProps<{
- options: DefaultTheme.AlgoliaSearchOptions
- multilang?: boolean
- }>()
- const vm = getCurrentInstance()
- const route = useRoute()
- const router = useRouter()
- watch(
- () => props.options,
- (value) => {
- update(value)
- }
- )
- onMounted(() => {
- initialize(props.options)
- })
- 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)
- return pathname + hash
- }
- function update(options: any) {
- if (vm && vm.vnode.el) {
- vm.vnode.el.innerHTML =
- '<div class="algolia-search-box" id="docsearch"></div>'
- initialize(options)
- }
- }
- function initialize(userOptions: any) {
- // if the user has multiple locales, the search results should be filtered
- // based on the language
- const facetFilters = props.multilang
- ? ['language:' + siteData.value.lang]
- : []
- docsearch(
- Object.assign({}, userOptions, {
- container: '#docsearch',
- searchParameters: Object.assign({}, userOptions.searchParameters, {
- // pass a custom lang facetFilter to allow multiple language search
- // https://github.com/algolia/docsearch-configs/pull/3942
- facetFilters: facetFilters.concat(
- userOptions.searchParameters?.facetFilters || []
- )
- }),
- navigator: {
- navigate: ({ suggestionUrl }: { suggestionUrl: string }) => {
- const { pathname: hitPathname } = new URL(
- window.location.origin + suggestionUrl
- )
- // 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: DocSearchHit[]) => {
- return items.map((item) => {
- return Object.assign({}, item, {
- url: getRelativePath(item.url)
- })
- })
- },
- hitComponent: ({
- hit,
- children
- }: {
- hit: DocSearchHit
- children: any
- }) => {
- 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 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 Router loading feature
- if (route.path !== relativeHit) {
- event.preventDefault()
- }
- router.go(relativeHit)
- },
- children
- }
- }
- }
- })
- )
- }
- </script>
- <style>
- .algolia-search-box {
- padding-top: 1px;
- }
- @media (min-width: 720px) {
- .algolia-search-box {
- padding-left: 8px;
- }
- }
- @media (min-width: 751px) {
- .algolia-search-box {
- min-width: 176.3px; /* avoid layout shift */
- }
- .algolia-search-box .DocSearch-Button-Placeholder {
- padding-left: 8px;
- font-size: 0.9rem;
- font-weight: 500;
- }
- }
- .DocSearch {
- --docsearch-primary-color: var(--c-brand);
- --docsearch-highlight-color: var(--docsearch-primary-color);
- --docsearch-searchbox-shadow: inset 0 0 0 2px var(--docsearch-primary-color);
- --docsearch-text-color: var(--c-text-light);
- --docsearch-muted-color: var(--c-text-lighter);
- --docsearch-searchbox-background: #f2f2f2;
- }
- </style>
|