-
Notifications
You must be signed in to change notification settings - Fork 40
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
5993529
commit 7e2f3bf
Showing
30 changed files
with
1,030 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
# Change Log | ||
|
||
All notable changes to this project will be documented in this file. | ||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. | ||
|
||
# [2.0.0-rc.18](https://github.com/vuepress/ecosystem/compare/v2.0.0-rc.17...v2.0.0-rc.18) (2024-02-29) | ||
|
||
**Note:** Version bump only for package @vuepress/plugin-search | ||
|
||
# [2.0.0-rc.15](https://github.com/vuepress/ecosystem/compare/v2.0.0-rc.14...v2.0.0-rc.15) (2024-02-19) | ||
|
||
**Note:** Version bump only for package @vuepress/plugin-search | ||
|
||
# [2.0.0-rc.14](https://github.com/vuepress/ecosystem/compare/v2.0.0-rc.13...v2.0.0-rc.14) (2024-02-08) | ||
|
||
**Note:** Version bump only for package @vuepress/plugin-search | ||
|
||
# [2.0.0-rc.12](https://github.com/vuepress/ecosystem/compare/v2.0.0-rc.11...v2.0.0-rc.12) (2024-02-06) | ||
|
||
**Note:** Version bump only for package @vuepress/plugin-search | ||
|
||
# [2.0.0-rc.11](https://github.com/vuepress/ecosystem/compare/v2.0.0-rc.10...v2.0.0-rc.11) (2024-02-05) | ||
|
||
**Note:** Version bump only for package @vuepress/plugin-search | ||
|
||
# [2.0.0-rc.10](https://github.com/vuepress/ecosystem/compare/v2.0.0-rc.9...v2.0.0-rc.10) (2024-02-05) | ||
|
||
### Bug Fixes | ||
|
||
- **plugin-search:** fix hot reload ([637db2c](https://github.com/vuepress/ecosystem/commit/637db2ccefd00bea7aee0ed74b829e079d37e2a2)) | ||
|
||
### Features | ||
|
||
- compatible with visual routes ([#57](https://github.com/vuepress/ecosystem/issues/57)) ([f1281be](https://github.com/vuepress/ecosystem/commit/f1281be141b9a5cb71d80048a2042b669cd4823e)) | ||
|
||
# [2.0.0-rc.9](https://github.com/vuepress/ecosystem/compare/v2.0.0-rc.8...v2.0.0-rc.9) (2024-02-03) | ||
|
||
**Note:** Version bump only for package @vuepress/plugin-search | ||
|
||
# [2.0.0-rc.8](https://github.com/vuepress/ecosystem/compare/v2.0.0-rc.7...v2.0.0-rc.8) (2024-02-03) | ||
|
||
**Note:** Version bump only for package @vuepress/plugin-search | ||
|
||
# [2.0.0-rc.7](https://github.com/vuepress/ecosystem/compare/v2.0.0-rc.6...v2.0.0-rc.7) (2024-02-02) | ||
|
||
**Note:** Version bump only for package @vuepress/plugin-search | ||
|
||
# [2.0.0-rc.3](https://github.com/vuepress/ecosystem/compare/v2.0.0-rc.2...v2.0.0-rc.3) (2024-01-31) | ||
|
||
**Note:** Version bump only for package @vuepress/plugin-search | ||
|
||
# 2.0.0-rc.1 (2024-01-26) | ||
|
||
### Features | ||
|
||
- bump to vp2rc1 and declare vuepress as peer ([af4f00b](https://github.com/vuepress/ecosystem/commit/af4f00b24dc64dfd3ec5f45053e78fdcf147da61)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
{ | ||
"name": "@vuepress/plugin-search", | ||
"version": "2.0.0-rc.18", | ||
"description": "VuePress plugin - built-in search", | ||
"keywords": [ | ||
"vuepress-plugin", | ||
"vuepress", | ||
"plugin", | ||
"search" | ||
], | ||
"homepage": "https://ecosystem.vuejs.press/plugins/search.html", | ||
"bugs": { | ||
"url": "https://github.com/vuepress/ecosystem/issues" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "git+https://github.com/vuepress/ecosystem.git", | ||
"directory": "plugins/plugin-search" | ||
}, | ||
"license": "MIT", | ||
"author": "meteorlxy", | ||
"type": "module", | ||
"exports": { | ||
".": "./lib/node/index.js", | ||
"./client": "./lib/client/index.js", | ||
"./package.json": "./package.json" | ||
}, | ||
"main": "./lib/node/index.js", | ||
"types": "./lib/node/index.d.ts", | ||
"files": [ | ||
"lib" | ||
], | ||
"scripts": { | ||
"build": "tsc -b tsconfig.build.json", | ||
"clean": "rimraf --glob ./lib ./*.tsbuildinfo", | ||
"copy": "cpx \"src/**/*.{d.ts,svg}\" lib", | ||
"style": "sass src:lib --no-source-map" | ||
}, | ||
"dependencies": { | ||
"chokidar": "^3.6.0", | ||
"flexsearch": "^0.6", | ||
"he": "^1.2.0", | ||
"vue": "^3.4.21" | ||
}, | ||
"peerDependencies": { | ||
"vuepress": "2.0.0-rc.8" | ||
}, | ||
"publishConfig": { | ||
"access": "public" | ||
} | ||
} |
176 changes: 176 additions & 0 deletions
176
plugins/plugin-flexsearch/src/client/components/SearchBox.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,176 @@ | ||
import { computed, defineComponent, h, ref, toRefs } from 'vue' | ||
import type { PropType } from 'vue' | ||
import { useRouteLocale, useRouter } from 'vuepress/client' | ||
import type { LocaleConfig } from 'vuepress/shared' | ||
import type { HotKeyOptions } from '../../shared/index.js' | ||
import { | ||
useHotKeys, | ||
useSearchIndex, | ||
useSearchSuggestions, | ||
useSuggestionsFocus, | ||
} from '../composables/index.js' | ||
|
||
export type SearchBoxLocales = LocaleConfig<{ | ||
placeholder: string | ||
}> | ||
|
||
export const SearchBox = defineComponent({ | ||
name: 'SearchBox', | ||
|
||
props: { | ||
locales: { | ||
type: Object as PropType<SearchBoxLocales>, | ||
required: false, | ||
default: () => ({}), | ||
}, | ||
|
||
hotKeys: { | ||
type: Array as PropType<(string | HotKeyOptions)[]>, | ||
required: false, | ||
default: () => [], | ||
}, | ||
|
||
maxSuggestions: { | ||
type: Number, | ||
required: false, | ||
default: 5, | ||
}, | ||
}, | ||
|
||
setup(props) { | ||
const { locales, hotKeys, maxSuggestions } = toRefs(props) | ||
|
||
const router = useRouter() | ||
const routeLocale = useRouteLocale() | ||
const searchIndex = useSearchIndex | ||
|
||
const input = ref<HTMLInputElement | null>(null) | ||
const isActive = ref(false) | ||
const query = ref('') | ||
const locale = computed(() => locales.value[routeLocale.value] ?? {}) | ||
|
||
const suggestions = useSearchSuggestions({ | ||
searchIndex, | ||
routeLocale, | ||
query, | ||
maxSuggestions, | ||
}) | ||
const { focusIndex, focusNext, focusPrev } = | ||
useSuggestionsFocus(suggestions) | ||
useHotKeys({ input, hotKeys }) | ||
|
||
const showSuggestions = computed( | ||
() => isActive.value && !!suggestions.value.length, | ||
) | ||
const onArrowUp = (): void => { | ||
if (!showSuggestions.value) { | ||
return | ||
} | ||
focusPrev() | ||
} | ||
const onArrowDown = (): void => { | ||
if (!showSuggestions.value) { | ||
return | ||
} | ||
focusNext() | ||
} | ||
const goTo = (index: number): void => { | ||
if (!showSuggestions.value) { | ||
return | ||
} | ||
|
||
const suggestion = suggestions.value[index] | ||
if (!suggestion) { | ||
return | ||
} | ||
|
||
router.push(suggestion.link).then(() => { | ||
query.value = '' | ||
focusIndex.value = 0 | ||
}) | ||
} | ||
|
||
return () => | ||
h( | ||
'form', | ||
{ | ||
class: 'search-box', | ||
role: 'search', | ||
}, | ||
[ | ||
h('input', { | ||
ref: input, | ||
type: 'search', | ||
placeholder: locale.value.placeholder, | ||
autocomplete: 'off', | ||
spellcheck: false, | ||
value: query.value, | ||
onFocus: () => (isActive.value = true), | ||
onBlur: () => (isActive.value = false), | ||
onInput: (event) => | ||
(query.value = (event.target as HTMLInputElement).value), | ||
onKeydown: (event) => { | ||
switch (event.key) { | ||
case 'ArrowUp': { | ||
onArrowUp() | ||
break | ||
} | ||
case 'ArrowDown': { | ||
onArrowDown() | ||
break | ||
} | ||
case 'Enter': { | ||
event.preventDefault() | ||
goTo(focusIndex.value) | ||
break | ||
} | ||
} | ||
}, | ||
}), | ||
showSuggestions.value && | ||
h( | ||
'ul', | ||
{ | ||
class: 'suggestions', | ||
onMouseleave: () => (focusIndex.value = -1), | ||
}, | ||
suggestions.value.map(({ link, title, text }, index) => | ||
h( | ||
'li', | ||
{ | ||
class: [ | ||
'suggestion', | ||
{ | ||
focus: focusIndex.value === index, | ||
}, | ||
], | ||
onMouseenter: () => (focusIndex.value = index), | ||
onMousedown: () => goTo(index), | ||
}, | ||
h( | ||
'a', | ||
{ | ||
href: link, | ||
onClick: (event) => event.preventDefault(), | ||
}, | ||
[ | ||
h( | ||
'span', | ||
{ | ||
class: 'page-title', | ||
}, | ||
title, | ||
), | ||
h('span', { | ||
class: 'suggestion-result', | ||
innerHTML: text, | ||
}), | ||
], | ||
), | ||
), | ||
), | ||
), | ||
], | ||
) | ||
}, | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from './SearchBox.js' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
export * from './useHotKeys.js' | ||
export * from './useSearchIndex.js' | ||
export * from './useSearchSuggestions.js' | ||
export * from './useSuggestionsFocus.js' |
36 changes: 36 additions & 0 deletions
36
plugins/plugin-flexsearch/src/client/composables/useHotKeys.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import { onBeforeUnmount, onMounted } from 'vue' | ||
import type { Ref } from 'vue' | ||
import type { HotKeyOptions } from '../../shared/index.js' | ||
import { isFocusingTextControl, isKeyMatched } from '../utils/index.js' | ||
|
||
export const useHotKeys = ({ | ||
input, | ||
hotKeys, | ||
}: { | ||
input: Ref<HTMLInputElement | null> | ||
hotKeys: Ref<(string | HotKeyOptions)[]> | ||
}): void => { | ||
if (hotKeys.value.length === 0) return | ||
|
||
const onKeydown = (event: KeyboardEvent): void => { | ||
if (!input.value) return | ||
if ( | ||
// key matches | ||
isKeyMatched(event, hotKeys.value) && | ||
// event does not come from the search box itself or | ||
// user isn't focusing (and thus perhaps typing in) a text control | ||
!isFocusingTextControl(event.target as EventTarget) | ||
) { | ||
event.preventDefault() | ||
input.value.focus() | ||
} | ||
} | ||
|
||
onMounted(() => { | ||
document.addEventListener('keydown', onKeydown) | ||
}) | ||
|
||
onBeforeUnmount(() => { | ||
document.removeEventListener('keydown', onKeydown) | ||
}) | ||
} |
30 changes: 30 additions & 0 deletions
30
plugins/plugin-flexsearch/src/client/composables/useSearchIndex.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import { searchIndex as searchIndexRaw } from '@internal/searchIndex' | ||
import FS from 'flexsearch' | ||
import { ref } from 'vue' | ||
|
||
export interface SearchIndexRet { | ||
path: [string, string] | ||
title: string | ||
} | ||
|
||
export type CSearchIndex = (string, number) => SearchIndexRet[] | ||
|
||
const index = FS.create({ | ||
async: false, | ||
doc: { | ||
id: 'id', | ||
field: ['title', 'content'], | ||
}, | ||
}) | ||
index.import(searchIndexRaw.idx) | ||
|
||
export const useSearchIndex = ref((q: string, c: number) => { | ||
const rr: any = index.search(q, c) | ||
return rr.map((r) => { | ||
return { | ||
path: searchIndexRaw.paths[r.id], | ||
title: r.title, | ||
content: r.content, | ||
} | ||
}) | ||
}) |
Oops, something went wrong.