Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .vuepress/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import BlogPosts from './components/BlogPosts.vue';
import JumpToc from './components/JumpToc.vue';
import PrBy from './components/PrBy.vue';
import ReleaseToc from './components/ReleaseToc.vue';
import URLDocSearch from './components/URLDocSearch.vue';

export default defineClientConfig({
enhance({ app }) {
Expand All @@ -18,5 +19,8 @@ export default defineClientConfig({
app.component('JumpToc', JumpToc);
app.component('PrBy', PrBy);
app.component('ReleaseToc', ReleaseToc);

// Override the builtin searchbox
app.component('SearchBox', URLDocSearch);
},
});
46 changes: 46 additions & 0 deletions .vuepress/components/URLDocSearch.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<template>
<DocSearch :options="docsearchOptions" />
</template>

<script setup lang="ts">
import { DocSearch, DocSearchOptions } from '@vuepress/plugin-docsearch/client';
import { useDebounceFn, useEventListener } from '@vueuse/core';
import { onMounted, Ref, ref } from 'vue';
import { useRouter, useRoute } from 'vue-router';

const SEARCH_KEY = 'search';
const docsearchOptions: Ref<DocSearchOptions> = ref({});
const router = useRouter();
const route = useRoute();

// Handle initial search query, if one is set
onMounted(() => {
const query = new URL(window.location.href).searchParams.get(SEARCH_KEY);
if (query) {
docsearchOptions.value.initialQuery = query;
(document.querySelector('.DocSearch-Button') as HTMLButtonElement).click();
}
});

// There's some debounce builtin to docsearch, this mimics that and should
// help prevent browser history from getting filled with partial queries.
const inputHandler = useDebounceFn(handleSearchInput, 500);
useEventListener('input', (event) => inputHandler(event as InputEvent));

// Update the URL bar when the search input changes.
function handleSearchInput(event: InputEvent) {
const target = event.target as HTMLInputElement | undefined;
const searchQuery = target?.value;
if (target?.id !== 'docsearch-input' || !searchQuery) {
return;
}

// If we had already started a search, replace it instead of appending
const { path, query: routeQuery } = route;
const replace = routeQuery?.hasOwnProperty(SEARCH_KEY);
const query = { ...routeQuery }; // NOTE: must copy the query object
query[SEARCH_KEY] = searchQuery;

router.push({ path, query: { ...query }, replace });
}
</script>
9 changes: 9 additions & 0 deletions .vuepress/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,15 @@ export default defineUserConfig({
{ name: 'apple-mobile-web-app-status-bar-style', content: 'black' },
],
['link', { rel: 'icon', href: '/icon.png' }],
[
'link',
{
rel: 'search',
type: 'application/opensearchdescription+xml',
title: 'Nushell Docs', // NOTE: must match ShortName
href: '/opensearch.xml',
},
],
],
markdown: {
importCode: {
Expand Down
12 changes: 12 additions & 0 deletions .vuepress/public/opensearch.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<OpenSearchDescription
xmlns="http://a9.com/-/spec/opensearch/1.1/"
xmlns:moz="http://www.mozilla.org/2006/browser/search/"
>
<ShortName>Nushell Docs</ShortName>
<Description>Search Nushell documentation</Description>
<InputEncoding>UTF-8</InputEncoding>
<Image width="16" height="16" type="image/png">https://www.nushell.sh/icon.png</Image>
<Url type="text/html" template="https://www.nushell.sh/?search={searchTerms}" />
<Url type="application/opensearchdescription+xml" rel="self" template="https://www.nushell.sh/opensearch.xml" />
<!-- TODO: it might be possible to provide suggestions via some Algolia API? -->
</OpenSearchDescription>