| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899 |
- /* ============================================================================
- * TIL search — merges the Docusaurus TIL site's results into the WordPress
- * search-results page.
- *
- * The TIL site (/til/, a separate Docusaurus build) uses docusaurus-lunr-search,
- * which ships a prebuilt lunr 2.3.9 index (/til/lunr-index.json) + a document
- * store (/til/search-doc.json). This module loads both client-side and queries
- * them exactly the way the TIL search bar does, so the results match, then
- * renders a labeled "From TIL" section on the WP search page.
- *
- * SELF-CONTAINED / REMOVABLE. Depends only on the vendored global `lunr`
- * (js/vendor/lunr.min.js) and config in window.dwTilSearch (localized in
- * functions.php). Fills #dw-til-results (placeholder in templates/search.html).
- * To remove the feature entirely, delete:
- * - this file + js/vendor/lunr.min.js
- * - the "TIL search" enqueue block in functions.php (is_search())
- * - the <!-- wp:html --> #dw-til-results block in templates/search.html
- * - the "TIL search results" CSS block in style.css
- * ==========================================================================*/
- (function () {
- 'use strict';
- var cfg = window.dwTilSearch;
- if (!cfg || !cfg.query || typeof lunr === 'undefined') return;
- var mount = document.getElementById('dw-til-results');
- if (!mount) return;
- // docusaurus-lunr-search overrides the tokenizer separator; match it so our
- // client-side tokenizing (and therefore the matches) line up with the index.
- lunr.tokenizer.separator = /[\s\-/]+/;
- Promise.all([
- fetch(cfg.index).then(function (r) { return r.json(); }),
- fetch(cfg.docs).then(function (r) { return r.json(); })
- ]).then(function (res) {
- var index = lunr.Index.load(res[0]);
- var docs = (res[1] && res[1].searchDocs) || [];
- var input = String(cfg.query);
- // Same query the plugin's LunrSearchAdapter builds: exact terms (boosted)
- // plus trailing-wildcard terms for prefix matches.
- var results = index.query(function (query) {
- var tokens = lunr.tokenizer(input);
- query.term(tokens, { boost: 10 });
- query.term(tokens, { wildcard: lunr.Query.wildcard.TRAILING });
- });
- // Map hits to docs, dedupe by URL (a page can match on title + content),
- // keep lunr's ranking order, cap to maxHits.
- var seen = {}, hits = [];
- for (var i = 0; i < results.length && hits.length < cfg.maxHits; i++) {
- var doc = docs[results[i].ref];
- if (!doc || seen[doc.url]) continue;
- seen[doc.url] = 1;
- hits.push(doc);
- }
- render(hits, input);
- }).catch(function () {
- /* TIL index unreachable (e.g. /til not deployed) — skip silently. */
- });
- function esc(s) {
- return String(s).replace(/[&<>"]/g, function (c) {
- return { '&': '&', '<': '<', '>': '>', '"': '"' }[c];
- });
- }
- // A short excerpt centered on the first query term, with the terms highlighted.
- function snippet(content, input) {
- if (!content) return '';
- var tokens = lunr.tokenizer(input).map(String);
- var lc = content.toLowerCase();
- var pos = tokens.length ? lc.indexOf(tokens[0]) : -1;
- var start = pos < 0 ? 0 : Math.max(0, pos - 60);
- var slice = content.substring(start, start + 200);
- var out = (start > 0 ? '… ' : '') + esc(slice) +
- (start + 200 < content.length ? ' …' : '');
- tokens.forEach(function (t) {
- if (!t) return;
- var re = new RegExp('(' + t.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') + ')', 'ig');
- out = out.replace(re, '<mark>$1</mark>');
- });
- return out;
- }
- function render(hits, input) {
- if (!hits.length) { mount.hidden = true; return; }
- var html = '<ul class="dw-til-list">';
- hits.forEach(function (d) {
- html += '<li class="dw-til-item">' +
- '<a class="dw-til-link" href="' + esc(d.url) + '">' + esc(d.title) + '</a>' +
- '<p class="dw-til-snippet">' + snippet(d.content, input) + '</p>' +
- '</li>';
- });
- html += '</ul>';
- mount.innerHTML = html;
- mount.hidden = false;
- }
- })();
|