Используйте индекс Docsearch Algolia для раздела Instantsearch.js на странице Docusaurus - PullRequest
0 голосов
/ 28 сентября 2018

У меня есть сайт документации, созданный с использованием Docusaurus.io, и я использую Docsearch в качестве поиска в панели навигации - это работает нормально.Тем не менее, я хотел бы также внедрить InstantSearch Algolia на целевой странице сайта.Код работает нормально со старым индексом, настроенным с помощью InstantSearch, но когда я подключаю ключ API и идентификатор нового индекса Docsearch в функцию конфигурации InstantSearch, я получаю поток объектов JSON, которые я не могу понять.

Это шаблон, который я пытаюсь использовать (который работал на моем старом индексе на сайте Jekyll):

const hitTemplate = function(hit) {
    console.log(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 &raquo;</a>
    </div>
  `;

, что приводит к пустому значению <div>.

Когда шаблон не применяется, мои результаты возвращаются как вложенные объекты JSON.

Я пытаюсь реализовать дополнительный поисковый запрос, который появляется только на домашней странице сайта документации.Из того, что я понимаю, у меня не может быть двух входных селекторов в Docsearch, поэтому я пытаюсь использовать InstantSearch.Мне нужен шаблон, который работает с тем, как API Docsearch возвращает данные.

1 Ответ

0 голосов
/ 28 сентября 2018

После недели проб и ошибок и некоторой очень ценной помощи от разработчиков 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 будет возвращать результаты для каждой имеющейся версии, что приведет к тоннам повторений.
  • JQuery в нижней части instantsearch.js предназначен для отображения и скрытия <div>, где отображаются результаты поиска, в зависимости от события keyup в поисковом запросе
  • Причина, по которой я использовал const mainSearch = instantsearch({... вместоconst search означает, что стандартная панель навигации Docsearch уже использует переменную search.Если у вас есть несколько поисковых запросов на странице, вам нужно сделать это.
  • Хотя это руководство относится к Docusaurus, этот полезный JSfiddle показывает, как реализовать Instantsearch с индексом Docsearch на обычном статическом сайте.: https://jsfiddle.net/s_pace/965a4w3o/1/
  • Пожалуйста, прокомментируйте, если вам нужна помощь в реализации этого на вашем собственном сайте Docusaurus, я рад помочь
...