chore: migrate to docsearch (#5233)
This commit is contained in:
Родитель
d4ea1247e8
Коммит
18a7cb1df1
|
@ -108,7 +108,7 @@ describe('electronjs.org', () => {
|
||||||
cy.get('.nav-search').clear()
|
cy.get('.nav-search').clear()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('the results returned from searching match the results returned from each algolia index', () => {
|
xit('the results returned from searching match the results returned from each algolia index', () => {
|
||||||
cy.get('.nav-search').type('window')
|
cy.get('.nav-search').type('window')
|
||||||
cy.wait(500)
|
cy.wait(500)
|
||||||
let types = ['#tutorial-hits', '#api-hits', '#package-hits', '#app-hits']
|
let types = ['#tutorial-hits', '#api-hits', '#package-hits', '#app-hits']
|
||||||
|
@ -124,7 +124,7 @@ describe('electronjs.org', () => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('highlights what is typed in the input', () => {
|
xit('highlights what is typed in the input', () => {
|
||||||
cy.get('.nav-search').type('window')
|
cy.get('.nav-search').type('window')
|
||||||
cy.wait(500)
|
cy.wait(500)
|
||||||
cy.get('.ais-hits--item em').contains('window')
|
cy.get('.ais-hits--item em').contains('window')
|
||||||
|
|
|
@ -1,7 +1,4 @@
|
||||||
import search from './search'
|
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
search()
|
|
||||||
require('./lazy-load-images')()
|
require('./lazy-load-images')()
|
||||||
require('./get-localized-strings')()
|
require('./get-localized-strings')()
|
||||||
require('./create-filter-list')()
|
require('./create-filter-list')()
|
||||||
|
|
|
@ -1,200 +0,0 @@
|
||||||
const templates = require('../templates')
|
|
||||||
import instantsearch from 'instantsearch.js'
|
|
||||||
import { searchBox, hits } from 'instantsearch.js/es/widgets'
|
|
||||||
const pluralize = require('pluralize')
|
|
||||||
const searchWithYourKeyboard = require('search-with-your-keyboard')
|
|
||||||
const searches = {}
|
|
||||||
const types = [
|
|
||||||
{
|
|
||||||
name: 'api',
|
|
||||||
path: '/docs/api',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'tutorial',
|
|
||||||
path: '/docs/tutorial',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'package',
|
|
||||||
path: '/community',
|
|
||||||
},
|
|
||||||
]
|
|
||||||
const typeNames = types.map((type) => type.name)
|
|
||||||
|
|
||||||
export default () => {
|
|
||||||
buildMultiSearch()
|
|
||||||
buildSearchUIHandlers()
|
|
||||||
determineOrder()
|
|
||||||
searchWithYourKeyboard('#search-input', '.ais-hits--item')
|
|
||||||
}
|
|
||||||
|
|
||||||
function buildSearch(type, isPrimarySearch = false, searches) {
|
|
||||||
const opts = {
|
|
||||||
appId: 'L9LD9GHGQJ',
|
|
||||||
apiKey: '24e7e99910a15eb5d9d93531e5682370',
|
|
||||||
indexName: pluralize(type),
|
|
||||||
advancedSyntax: true,
|
|
||||||
}
|
|
||||||
|
|
||||||
// the primary search delegates queries to secondary searches
|
|
||||||
if (isPrimarySearch) {
|
|
||||||
// sync search input with query param in address bar
|
|
||||||
opts.routing = {
|
|
||||||
stateMapping: {
|
|
||||||
stateToRoute(UIstate) {
|
|
||||||
// Use 'q' parameter in route instead of 'query'
|
|
||||||
return { q: UIstate.query }
|
|
||||||
},
|
|
||||||
routeToState(routeState) {
|
|
||||||
return { query: routeState.q }
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
opts.searchFunction = (helper) => {
|
|
||||||
let query = helper.state.query
|
|
||||||
|
|
||||||
// should search be isolated to a specific type?
|
|
||||||
// e.g. `is:app foo` or `app:foo`
|
|
||||||
const isolatedType = typeNames.find((typeName) => {
|
|
||||||
return (
|
|
||||||
query.includes(`is:${typeName}`) || query.includes(`${typeName}:`)
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
// hide hit containers if a specific type is isolated
|
|
||||||
typeNames.forEach((typeName) => {
|
|
||||||
const display =
|
|
||||||
!isolatedType || isolatedType === typeName ? 'block' : 'none'
|
|
||||||
document.getElementById(`${typeName}-hits`).style.display = display
|
|
||||||
})
|
|
||||||
|
|
||||||
// remove `is:foo` filter from query
|
|
||||||
// TODO: figure out a way to make this affect the search
|
|
||||||
// without affecting the input element or the query param
|
|
||||||
// if (isolatedType) {
|
|
||||||
// query = query.replace(`is:${isolatedType}`, '').trim()
|
|
||||||
// }
|
|
||||||
|
|
||||||
// hide the primary search results' container if no results
|
|
||||||
const primarySearch = searches[types[0].name]
|
|
||||||
if (primarySearch && primarySearch.helper)
|
|
||||||
primarySearch.helper.once('result', onResult)
|
|
||||||
|
|
||||||
// delegate query to secondary searches
|
|
||||||
types.slice(1).forEach((type) => {
|
|
||||||
const search = searches[type.name]
|
|
||||||
if (search && search.helper) {
|
|
||||||
search.helper.once('result', onResult)
|
|
||||||
search.helper.setQuery(query).search()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// trigger the primary search
|
|
||||||
helper.setQuery(query).search()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://community.algolia.com/algoliasearch-helper-js/reference.html#AlgoliaSearchHelper#event:search
|
|
||||||
function onResult(results, state) {
|
|
||||||
const id = `${state.index.replace(/s$/, '')}-hits`
|
|
||||||
document.getElementById(id).style.display =
|
|
||||||
results.hits.length === 0 ? 'none' : 'block'
|
|
||||||
}
|
|
||||||
|
|
||||||
const search = instantsearch(opts)
|
|
||||||
|
|
||||||
search.addWidget(
|
|
||||||
hits({
|
|
||||||
container: `#${type}-hits`,
|
|
||||||
templates: {
|
|
||||||
// empty: 'No results',
|
|
||||||
item: templates[type],
|
|
||||||
},
|
|
||||||
transformData: {
|
|
||||||
item: (data) => {
|
|
||||||
// useful for viewing template context:
|
|
||||||
// console.log(`${type} data`, data)
|
|
||||||
return data
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
)
|
|
||||||
|
|
||||||
if (isPrimarySearch) {
|
|
||||||
search.addWidget(
|
|
||||||
searchBox({
|
|
||||||
container: '#search-input',
|
|
||||||
placeholder: `Search Electron ${pluralize(type)}`,
|
|
||||||
autofocus: false,
|
|
||||||
})
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
search.on('render', (...args) => {
|
|
||||||
// console.log(`algolia render (${type})`, args)
|
|
||||||
})
|
|
||||||
|
|
||||||
search.on('error', (...args) => {
|
|
||||||
console.log(`algolia error (${type})`, args)
|
|
||||||
})
|
|
||||||
|
|
||||||
searches[type] = search
|
|
||||||
|
|
||||||
search.start()
|
|
||||||
}
|
|
||||||
|
|
||||||
function determineOrder() {
|
|
||||||
types.forEach((type) => {
|
|
||||||
if (location.pathname === type.path)
|
|
||||||
document.getElementById(`${type.name}-hits`).className = 'first'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function buildMultiSearch() {
|
|
||||||
types.forEach((type) => {
|
|
||||||
buildSearch(type.name, type.name === types[0].name, searches)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function buildSearchUIHandlers() {
|
|
||||||
if (location.search.includes('query=')) showHits()
|
|
||||||
|
|
||||||
let navInput = document.querySelector('.nav-search')
|
|
||||||
let hits = document.getElementById('hits')
|
|
||||||
navInput.addEventListener('input', (e) => {
|
|
||||||
navInput.value ? showHits() : hideHits()
|
|
||||||
})
|
|
||||||
navInput.addEventListener('focus', (e) => {
|
|
||||||
navInput.value ? showHits() : hideHits()
|
|
||||||
})
|
|
||||||
window.addEventListener('click', (e) => {
|
|
||||||
if (!navInput.value) return hideHits()
|
|
||||||
|
|
||||||
e.target === navInput || checkIfChild(hits, e.target)
|
|
||||||
? showHits()
|
|
||||||
: hideHits()
|
|
||||||
})
|
|
||||||
|
|
||||||
// window.addEventListener('click', e => {
|
|
||||||
// if (e.target === document.querySelector('.dialog-button')) document.querySelector('#search-hint-dialog').style.display = 'none'
|
|
||||||
// })
|
|
||||||
|
|
||||||
function showHits() {
|
|
||||||
document.getElementById('hits').style.display = 'block'
|
|
||||||
// document.getElementById('search-hint').style.display="none"
|
|
||||||
// document.querySelector('#search-hint-dialog').style.display = "none"
|
|
||||||
}
|
|
||||||
|
|
||||||
function hideHits() {
|
|
||||||
document.getElementById('hits').style.display = 'none'
|
|
||||||
// document.getElementById('search-hint').style.display = "inline"
|
|
||||||
}
|
|
||||||
|
|
||||||
function checkIfChild(parentElement, checkElement) {
|
|
||||||
parentElement.childNodes.forEach((node) => {
|
|
||||||
if (node === checkElement) return true
|
|
||||||
checkIfChild(node, checkElement)
|
|
||||||
})
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -23,5 +23,13 @@
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<script src="{{static-asset "js" "index.js"}}"></script>
|
<script src="{{static-asset "js" "index.js"}}"></script>
|
||||||
|
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/docsearch.js@2/dist/cdn/docsearch.min.js"></script>
|
||||||
|
<script type="text/javascript"> docsearch({
|
||||||
|
apiKey: 'c9e8f898b3b32afe40f0a96637e7ea85',
|
||||||
|
indexName: 'electronjs',
|
||||||
|
inputSelector: '#search-input',
|
||||||
|
debug: false // Set debug to true if you want to inspect the dropdown
|
||||||
|
});
|
||||||
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -44,6 +44,7 @@
|
||||||
<link rel="alternate" type="application/rss+xml" title="Electron Releases" href="https://electronjs.org/releases.xml" />
|
<link rel="alternate" type="application/rss+xml" title="Electron Releases" href="https://electronjs.org/releases.xml" />
|
||||||
<link rel='stylesheet' href='{{static-asset "css" "index.css"}}'>
|
<link rel='stylesheet' href='{{static-asset "css" "index.css"}}'>
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/docsearch.js@2/dist/cdn/docsearch.min.css" />
|
||||||
<script>
|
<script>
|
||||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||||||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
||||||
|
|
Загрузка…
Ссылка в новой задаче