Skip to content

Commit 9fa6a42

Browse files
committed
wip: First draft of latest/related typesense search function.
1 parent c17125a commit 9fa6a42

File tree

3 files changed

+291
-8
lines changed

3 files changed

+291
-8
lines changed

assets/js/globals.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,7 @@ export function getSidebarNodes () {
1414
export function getVersionNodes () {
1515
return window.versionNodes || []
1616
}
17+
18+
export function getSearchNodes () {
19+
return window.searchNodes || []
20+
}

assets/js/search-page.js

Lines changed: 64 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import lunr from 'lunr'
44
import { qs, escapeHtmlEntities, isBlank, getQueryParamByName, getProjectNameAndVersion } from './helpers'
55
import { setSearchInputValue } from './search-bar'
66
import searchResultsTemplate from './handlebars/templates/search-results.handlebars'
7+
import { getSearchNodes } from './globals'
78

89
const EXCERPT_RADIUS = 80
910
const SEARCH_CONTAINER_SELECTOR = '#search'
@@ -26,30 +27,85 @@ function initialize () {
2627
const pathname = window.location.pathname
2728
if (pathname.endsWith('/search.html') || pathname.endsWith('/search')) {
2829
const query = getQueryParamByName('q')
29-
search(query)
30+
const queryType = getQueryParamByName('type')
31+
search(query, queryType)
3032
}
3133
}
3234

33-
async function search (value) {
35+
async function search (value, queryType) {
3436
if (isBlank(value)) {
3537
renderResults({ value })
3638
} else {
3739
setSearchInputValue(value)
3840

39-
const index = await getIndex()
40-
4141
try {
42-
// We cannot match on atoms :foo because that would be considered
43-
// a filter. So we escape all colons not preceded by a word.
44-
const fixedValue = value.replaceAll(/(\B|\\):/g, '\\:')
45-
const results = searchResultsToDecoratedSearchItems(index.search(fixedValue))
42+
let results = []
43+
const searchNodes = getSearchNodes()
44+
45+
if (['related', 'latest'].includes(queryType) && searchNodes.length > 0) {
46+
results = await remoteSearch(value, queryType, searchNodes)
47+
} else {
48+
results = await localSearch(value)
49+
}
50+
4651
renderResults({ value, results })
4752
} catch (error) {
4853
renderResults({ value, errorMessage: error.message })
4954
}
5055
}
5156
}
5257

58+
async function localSearch (value) {
59+
const index = await getIndex()
60+
61+
// We cannot match on atoms :foo because that would be considered
62+
// a filter. So we escape all colons not preceded by a word.
63+
const fixedValue = value.replaceAll(/(\B|\\):/g, '\\:')
64+
return searchResultsToDecoratedSearchItems(index.search(fixedValue))
65+
}
66+
67+
async function remoteSearch (value, queryType, searchNodes) {
68+
let filterNodes = searchNodes
69+
70+
if (queryType === 'latest') {
71+
filterNodes = searchNodes.slice(0, 1)
72+
}
73+
74+
const filters = filterNodes.map(node => `package:=${node.name}-${node.version}`).join(' || ')
75+
76+
const params = new URLSearchParams()
77+
params.set('q', value)
78+
params.set('query_by', 'title,doc')
79+
params.set('filter_by', filters)
80+
81+
const response = await fetch(`https://search.hexdocs.pm/?${params.toString()}`)
82+
const payload = await response.json()
83+
84+
if (Array.isArray(payload.hits)) {
85+
return payload.hits.map(result => {
86+
const [packageName, packageVersion] = result.document.package.split('-')
87+
88+
const doc = result.document.doc
89+
const excerpts = [doc]
90+
const metadata = {}
91+
const ref = `https://hexdocs.pm/${packageName}/${packageVersion}/${result.document.ref}`
92+
const title = result.document.title
93+
const type = result.document.type
94+
95+
return {
96+
doc,
97+
excerpts,
98+
metadata,
99+
ref,
100+
title,
101+
type
102+
}
103+
})
104+
} else {
105+
return []
106+
}
107+
}
108+
53109
function renderResults ({ value, results, errorMessage }) {
54110
const searchContainer = qs(SEARCH_CONTAINER_SELECTOR)
55111
const resultsHtml = searchResultsTemplate({ value, results, errorMessage })

0 commit comments

Comments
 (0)