У меня есть сайт документации, созданный с использованием Docusaurus.io, и я использую Docsearch в качестве поиска на панели навигации - это работает нормально. Однако я бы хотел реализовать мгновенный поиск Algolia и на целевой странице сайта. Код работает нормально со старым индексом, настроенным с помощью мгновенного поиска, но когда я подключаю ключ API и идентификатор нового индекса Docsearch к функции конфигурации мгновенного поиска, я получаю поток объектов JSON, которые я не могу понять .
Это шаблон, который я пытаюсь использовать (который работал с моим старым индексом на сайте Jekyll):
const hitTemplate = function(hit) {
console.info(hit);
let url = hit.url;
const title = hit.lvl1;
const content = hit._highlightResult.matchedWords;
return `
<div class = "post-item">
<a class = "post-link" href = "${url}">
<h4>${title}</h4>
</a>
<div class = "search-article-description">${content}</div>
<a href = "${url}" class = "read-more">Read More »</a>
</div>
`;
В результате получается пустой <div>
.
Когда шаблон не применяется, мои результаты возвращаются как вложенные объекты JSON.
Я пытаюсь реализовать дополнительный мгновенный поиск, который появляется только на домашней странице сайта документации. Насколько я понимаю, у меня не может быть двух селекторов ввода в Docsearch, поэтому я пытался использовать мгновенный поиск. Мне нужен шаблон, который работает с тем, как Docsearch API возвращает данные.
После недели проб и ошибок и очень ценной помощи со стороны разработчиков Docsearch через github я придумал решение, которое работает для моего сайта документации, и делюсь им здесь в надежде, что другие разочарованные пользователи Docusaurus, Docsearch и Instantsearch найти свой путь к этому решению:
В instantsearch.js
(находится на сайте / static / js):
// instantSearch on homepage
document.addEventListener('DOMContentLoaded', () => {
// Set initial parameters for instantsearch on the homepage
const mainSearch = instantsearch({
appId: '...',
apiKey: '...',
indexName: 'your-docsearch-index-name',
searchParameters: {
hitsPerPage: 10
},
routing: true
});
mainSearch.addWidget(
instantsearch.widgets.configure({
filters: 'version:1.5.5' // set latest version here
})
);
// initialize SearchBox
mainSearch.addWidget(
instantsearch.widgets.searchBox({
container: '#search_input_main',
placeholder: 'Search the Docs',
autofocus: false,
poweredBy: true
})
);
// add hits cont
mainSearch.addWidget(
instantsearch.widgets.hits({
container: '#search-hits',
templates: {
empty: 'No results for the search term <em>"{{query}}"</em>.',
item: $('#results-template').html() // this is the template at index.js
},
hitsPerPage: 10
})
);
// add pagination
mainSearch.addWidget(
instantsearch.widgets.pagination({
container: '#pagination-container',
maxPages: 20,
// default is to scroll to 'body', here we disable this behavior
scrollTo: '#search-container'
})
);
mainSearch.start();
// Toggle search results
const search_input_main = document.querySelector('#search_input_main');
const searchContainer = document.querySelector('#search-container');
// Bind keyup event on the input
search_input_main.addEventListener('keyup', function() {
if (search_input_main.value.length > 0) {
searchContainer.classList.remove('hidden');
} else {
searchContainer.classList.add('hidden');
}
});
// hide results on reset
document.querySelector('.ais-search-box--reset').addEventListener('click', function() {
searchContainer.classList.add('hidden');
});
});
А это мои страницы / en / index.js:
const React = require('react');
...
// for homepage instantsearch
let resultsTemplate = `
<script type = "text/template" id = "results-template">
<div class = "ais-result">
{{#hierarchy.lvl0}}
<div class = "ais-lvl0">
<a title = "{{_highlightResult.hierarchy.lvl1.value}}" href = "{{{url}}}"><h4>{{{_highlightResult.hierarchy.lvl0.value}}}</h4></a>
</div>
{{/hierarchy.lvl0}}
<div class = "ais-lvl1 breadcrumbs">
{{#hierarchy.lvl1}} {{{_highlightResult.hierarchy.lvl1.value}}} {{/hierarchy.lvl1}} {{#hierarchy.lvl2}} > {{{_highlightResult.hierarchy.lvl2.value}}} {{/hierarchy.lvl2}} {{#hierarchy.lvl3}} > {{{_highlightResult.hierarchy.lvl3.value}}} {{/hierarchy.lvl3}}
{{#hierarchy.lvl4}} > {{{_highlightResult.hierarchy.lvl4.value}}} {{/hierarchy.lvl4}}
</div>
<div class = "ais-content">
{{{#content}}} {{{_highlightResult.content.value}}} {{{/content}}}
</div>
</div>
</script>
`
...
const SearchInput = () => (
<div>
<div className='productShowcaseSection small-paddingBottom paddingTop' style = {{textAlign: 'center'}}>
<h3>Get the most out of Stackery's serverless toolkit</h3>
<Container>
<div className='search_input_div'>
<input id = "search_input_main" type = "text" className = "form-control" placeholder = "Search the docs" aria-label = "Search" aria-describedby = "search"></input>
</div>
</Container>
</div>
</div>
);
const SearchHits = () => {
return (
<Container className='hidden' id='search-container'>
<h3>Search results:</h3>
<div id='search-hits'></div>
<div id='pagination-container'></div>
<div
dangerouslySetInnerHTML = {{ __html: resultsTemplate }}
/>
</Container>
)
}
class HomeSplash extends React.Component {
render () {
const language = this.props.language || '';
return (
<SplashContainer>
<div className='inner'>
<ProjectTitle />
<PromoSection>
...
</PromoSection>
<SearchInput />
</div>
</SplashContainer>
);
}
}
...
class Index extends React.Component {
render () {
const language = this.props.language || '';
return (
<div>
<HomeSplash language = {language} />
<SearchHits />
<BrowseDocs />
<TryIt />
</div>
);
}
}
module.exports = Index;
На заметку:
filters: 'version:your-version'
, иначе мгновенный поиск вернет результаты для каждой версии, которая у вас есть, что приведет к множеству повторений.instantsearch.js
предназначен для отображения и скрытия <div>
, где отображаются результаты поиска в зависимости от события нажатия клавиши в поле поиска.const mainSearch = instantsearch({...
вместо const search
, заключается в том, что в панели навигации по умолчанию Docsearch уже используется переменная search
. Если у вас есть более одного поиска на странице, вам необходимо это сделать.