From fcfe5a0404a9d5d59eeda37b0be6e1c911344caf Mon Sep 17 00:00:00 2001 From: Takuya Noguchi Date: Mon, 18 Jul 2022 07:12:57 +0000 Subject: [PATCH] Replace middleman-search with lunr with Typesense DocSearch Signed-off-by: Takuya Noguchi --- Gemfile | 1 - Gemfile.lock | 16 --- assets/javascripts/application.js | 4 +- assets/javascripts/docsearch.js | 11 ++ assets/javascripts/search.js | 146 ------------------------ assets/javascripts/search_arrows.js | 93 --------------- assets/stylesheets/_docsearch.scss | 17 +++ assets/stylesheets/_search.scss | 75 ------------ assets/stylesheets/application.css.scss | 3 +- config.rb | 12 -- source/layouts/_navbar.haml | 6 +- source/layouts/base.haml | 5 +- 12 files changed, 36 insertions(+), 353 deletions(-) create mode 100644 assets/javascripts/docsearch.js delete mode 100644 assets/javascripts/search.js delete mode 100644 assets/javascripts/search_arrows.js create mode 100644 assets/stylesheets/_docsearch.scss delete mode 100644 assets/stylesheets/_search.scss diff --git a/Gemfile b/Gemfile index 1f972b7866..656cbda277 100644 --- a/Gemfile +++ b/Gemfile @@ -6,7 +6,6 @@ gem 'middleman', '~> 4.4' gem 'middleman-syntax' gem 'middleman-blog' gem 'puma', '~> 5.6' -gem 'middleman-search', github: 'deivid-rodriguez/middleman-search', branch: 'workarea-commerce-master' gem 'rake' gem 'ronn' gem 'kramdown' diff --git a/Gemfile.lock b/Gemfile.lock index e458563122..a7e557a28d 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,13 +1,3 @@ -GIT - remote: https://github.com/deivid-rodriguez/middleman-search.git - revision: 50465e1c1580e282a45247b77036da3c2719870d - branch: workarea-commerce-master - specs: - middleman-search (0.10.0) - middleman-core (>= 3.2) - mini_racer (~> 0.5) - nokogiri (~> 1.6) - GEM remote: https://rubygems.org/ specs: @@ -52,9 +42,6 @@ GEM json (2.6.2) kramdown (2.4.0) rexml - libv8-node (16.10.0.0) - libv8-node (16.10.0.0-arm64-darwin) - libv8-node (16.10.0.0-x86_64-linux) listen (3.0.8) rb-fsevent (~> 0.9, >= 0.9.4) rb-inotify (~> 0.9, >= 0.9.7) @@ -101,8 +88,6 @@ GEM middleman-core (>= 3.2) rouge (~> 3.2) mini_portile2 (2.8.0) - mini_racer (0.5.0) - libv8-node (~> 16.10.0.0) minitest (5.14.4) mustache (1.0.5) nio4r (2.5.8) @@ -193,7 +178,6 @@ DEPENDENCIES kramdown middleman (~> 4.4) middleman-blog - middleman-search! middleman-syntax nokogiri (~> 1.13) octokit (~> 5.1) diff --git a/assets/javascripts/application.js b/assets/javascripts/application.js index 4e9a2a0524..9a2a57f117 100644 --- a/assets/javascripts/application.js +++ b/assets/javascripts/application.js @@ -1,7 +1,7 @@ -import './search' -import './search_arrows' import AnchorJS from 'anchor-js'; +import "./docsearch"; + const anchors = new AnchorJS(); anchors.options = { diff --git a/assets/javascripts/docsearch.js b/assets/javascripts/docsearch.js new file mode 100644 index 0000000000..a74d8adbca --- /dev/null +++ b/assets/javascripts/docsearch.js @@ -0,0 +1,11 @@ +docsearch({ + container: "#docsearch", + typesenseCollectionName: "bundler", + typesenseServerConfig: { + nodes: [{ + host: "k0cw8zgj4i592lsqp-1.a1.typesense.net", + protocol: "https", + }], + apiKey: "kWCn88g6vUwWdBVgEPPYUP9WSIGoqljS", + }, +}); diff --git a/assets/javascripts/search.js b/assets/javascripts/search.js deleted file mode 100644 index 071aedaddf..0000000000 --- a/assets/javascripts/search.js +++ /dev/null @@ -1,146 +0,0 @@ -import { Popover } from 'bootstrap'; -import lunr from 'lunr' - -var lunrIndex = null; -var lunrData = null; -var search = null; - -document.addEventListener('DOMContentLoaded', function() { - var oReq = new XMLHttpRequest(); - oReq.open("GET", "/search/lunr-index.json"); - oReq.addEventListener("load", function () { - lunrData = JSON.parse(oReq.response); - lunrIndex = lunr.Index.load(lunrData.index); - search = new Search(); - search.init(); - }); - oReq.send(); -}); - -(function() { - var Search = window.Search = function() { - this.SEARCH_INPUT_ID = '#input-search'; - this.POPOVER_CLASS = '.popover'; - this.POPOVER_OPTIONS = { - html: true, - container: 'body', - placement: 'bottom', - trigger: 'manual', - content: (function() { return search.getPopoverContent() }) - }; - this.LIMIT_RESULTS = 10; - this.popoverContent = ''; - this.popoverHandler = null; - - this.processText = function(text) { - if (!text || text === '') return this.hidePopover(); - - this.showPopover(text); - }; - - this.initializePopover = function() { - this.popover = new Popover(this.searchInput, this.POPOVER_OPTIONS); - }; - - this.hidePopover = function() { - const popover = Popover.getInstance(this.searchInput); - popover && popover.hide(); - this.searchArrows.destroy(); - }; - - this.showPopover = function(text) { - this.popoverContent = this.generatePopoverContent(text); - const popover = Popover.getInstance(this.searchInput); - popover.show(); - document.querySelector(".popover-body").innerHTML = this.popoverContent; - }; - - this.generatePopoverContent = function(text) { - var results = lunrIndex.search(text); - if (!results.length) return 'No results found'; - - results = results.slice(0, this.LIMIT_RESULTS); - var uniqueResults = this.uniqueResults(results); - - var generated = ''; - }; - - this.uniqueResults = function(results) { - var uniqueResults = []; - var titles = []; - [].forEach.call(results, function (el) { - if(titles.indexOf(lunrData.docs[el.ref].title) === -1) { - titles.push(lunrData.docs[el.ref].title); - uniqueResults.push(el); - } - }); - return uniqueResults; - }; - - this.initializePopoverEvents = function() { - var self = this; - - this.searchInput.addEventListener('keydown', function(e) { - if (e.which == 27) return self.hidePopover(); // esc key - }); - this.searchInput.addEventListener('input', function(e) { - var text = this.value; - self.processText(text); - }); - this.searchInput.addEventListener('focus', function(e) { - var text = this.value; - if (text === '') return; - - self.showPopover(text); - }); - this.searchInput.addEventListener('shown.bs.popover', function() { - self.popoverHandler = document.querySelector(self.POPOVER_CLASS); - self.popoverHandler.addEventListener("click", function(e) { e.stopPropagation() }); - self.searchArrows.init(); - }); - this.searchInput.addEventListener("click", function(e) { e.stopPropagation() }); - window.addEventListener("click", self.hidePopover.bind(self)); - }; - }; - - Search.prototype.init = function() { - this.searchInput = document.querySelector(this.SEARCH_INPUT_ID); - this.searchArrows = new SearchArrows(); - this.initializePopoverEvents(); - this.initializePopover(); - }; - - Search.prototype.getPopoverContent = function() { - return this.popoverContent; - }; -})(); diff --git a/assets/javascripts/search_arrows.js b/assets/javascripts/search_arrows.js deleted file mode 100644 index 0284ae6a27..0000000000 --- a/assets/javascripts/search_arrows.js +++ /dev/null @@ -1,93 +0,0 @@ -(function() { - var SearchArrows = window.SearchArrows = function() { - this.LI_SELECTOR = '.search-list-li'; - this.ACTIVE_CLASS = 'active'; - this.active = false; - this.currentSelection = null; - this.selectedLi = null; - - this.onKeydown = function(e) { - if (e.which === 40) { - e.preventDefault(); - this.onDownArrow(); - } else if (e.which === 38) { - e.preventDefault(); - this.onUpArrow(); - } else if (e.which === 13) { - this.onEnter(e); - } - }; - this.onKeydownCb = this.onKeydown.bind(this); - - this.onUpArrow = function() { - this.removeActiveClass(); - - if (this.currentSelection === 0 || this.currentSelection == null) this.markLastItem(); - else { - if (this.currentSelection === 0) this.currentSelection = this.listLength - 1; - else this.currentSelection -= 1; - - this.selectedLi = this.list[this.currentSelection]; - this.selectedLi.classList.add(this.ACTIVE_CLASS); - } - }; - - this.onDownArrow = function() { - this.removeActiveClass(); - - if (this.currentSelection === this.listLength - 1 || this.currentSelection == null) this.markFirstItem(); - else { - if (this.currentSelection === this.listLength - 1) this.currentSelection = 0; - else this.currentSelection += 1; - - this.selectedLi = this.list[this.currentSelection]; - this.selectedLi.classList.add(this.ACTIVE_CLASS); - } - }; - - this.onEnter = function() { - window.location.href = this.selectedLi.querySelector('a').getAttribute('href'); - }; - - this.removeActiveClass = function() { - if (this.selectedLi) this.selectedLi.classList.remove(this.ACTIVE_CLASS); - }; - - this.markFirstItem = function() { - this.selectedLi = this.list[0]; - this.selectedLi.classList.add(this.ACTIVE_CLASS); - this.currentSelection = 0; - }; - - this.markLastItem = function() { - this.selectedLi = this.list[this.list.length - 1]; - this.selectedLi.classList.add(this.ACTIVE_CLASS); - this.currentSelection = this.listLength - 1; - }; - }; - - SearchArrows.prototype.init = function() { - if (this.isActive()) this.destroy(); - - this.list = document.querySelectorAll(this.LI_SELECTOR); - this.listLength = this.list.length; - if (this.listLength === 0) return; - - window.addEventListener('keydown', this.onKeydownCb); - this.active = true; - }; - - SearchArrows.prototype.destroy = function() { - window.removeEventListener('keydown', this.onKeydownCb); - this.active = false; - this.currentSelection = null; - }; - - SearchArrows.prototype.isActive = function() { - return this.active; - }; - - SearchArrows.prototype.isOneOfKeys = function(keyCode) { - return ([40, 38, 13].indexOf(keyCode) !== -1); - } -})(); diff --git a/assets/stylesheets/_docsearch.scss b/assets/stylesheets/_docsearch.scss new file mode 100644 index 0000000000..09f0134f43 --- /dev/null +++ b/assets/stylesheets/_docsearch.scss @@ -0,0 +1,17 @@ +.DocSearch-Hits mark { + padding: 0; +} + +.DocSearch-Logo { + visibility: hidden; + + a:hover { + text-decoration: none; + } +} + +:root { + --docsearch-logo-color: var(--bs-gray-300); + --docsearch-primary-color: var(--bs-primary); + --docsearch-searchbox-background: #DBEAF3; // .bg-light-blue and .sidebar-nav .active +} diff --git a/assets/stylesheets/_search.scss b/assets/stylesheets/_search.scss deleted file mode 100644 index 75aa7907d3..0000000000 --- a/assets/stylesheets/_search.scss +++ /dev/null @@ -1,75 +0,0 @@ -.input-search { - width: 100%; - min-width: 18.75rem; - margin-right: -2.25rem; - padding-right: 2.5rem; - font-size: 18px; - background: transparent; - border: 0; - box-shadow: inset 0 0 0 0 transparent; - border-bottom: 2px solid #DBEAF3; - - transition-property: border-color; - transition-duration: 0.5s; - -webkit-transition-property: border-color; - -webkit-transition-duration: 0.5s; - -o-transition-property: border-color; - -o-transition-duration: 0.5s; - -moz-transition-property: border-color; - -moz-transition-duration: 0.5s; -} - -.input-search:hover, .input-search:focus, .input-search:active { - border-bottom: 2px solid rgba(100, 201, 239, 0.88); -} - -.input-search:active { - border-bottom: 2px solid #64C9EF; - box-shadow: inset 0 0 0 0px transparent; -} - -.input-search:focus { - outline: 0; -} - -.search-list-ul { - list-style-type: none; - padding-left: 0; - - hr { - margin-top: 0; - margin-bottom: 0; - } - - li:last-child hr { - height: 0; - border-top-color: #ffffff; - } - - h4 { - padding-top: 10px; - margin-bottom: 0; - } - - .active { - border: 2px solid #64C9EF !important; - - transition-property: border-color; - transition-duration: 0.3s; - -webkit-transition-property: border-color; - -webkit-transition-duration: 0.3s; - -o-transition-property: border-color; - -o-transition-duration: 0.3s; - -moz-transition-property: border-color; - -moz-transition-duration: 0.3s; - } - - .search-list-li { - border: 2px solid transparent; - padding: 2px; - } -} - -.popover{ - max-width: 100%; /* Max Width of the popover (depending on the container!) */ -} diff --git a/assets/stylesheets/application.css.scss b/assets/stylesheets/application.css.scss index 17918394d7..8988265b30 100644 --- a/assets/stylesheets/application.css.scss +++ b/assets/stylesheets/application.css.scss @@ -48,7 +48,6 @@ $icon-font-path: '~bootstrap/assets/fonts/bootstrap/'; @import "~bootstrap/scss/nav"; @import "~bootstrap/scss/navbar"; @import "~bootstrap/scss/card"; -@import "~bootstrap/scss/popover"; // Helpers @import "~bootstrap/scss/helpers"; @@ -65,7 +64,7 @@ $icon-font-path: '~bootstrap/assets/fonts/bootstrap/'; @import "team"; @import "footer"; @import "anchorjs"; -@import "search"; +@import "docsearch"; // More various utilities extended from Bootstrap 5.1 @import "opacity"; diff --git a/config.rb b/config.rb index fed8f32ac0..7df3178275 100644 --- a/config.rb +++ b/config.rb @@ -5,18 +5,6 @@ activate :syntax activate :i18n -activate :search do |search| - search.resources = ['index.html', 'guides/', "#{config[:current_version]}/", 'compatibility.html', 'conduct.html', 'contributors.html'] - - search.index_path = 'search/lunr-index.json' - - search.fields = { - title: {boost: 100, store: true, required: true}, - content: {boost: 50}, - url: {index: false, store: true}, - description: {index: false, store: true}, - } -end set :markdown_engine, :kramdown diff --git a/source/layouts/_navbar.haml b/source/layouts/_navbar.haml index b0ed72d936..4942038d03 100644 --- a/source/layouts/_navbar.haml +++ b/source/layouts/_navbar.haml @@ -3,13 +3,9 @@ = link_to 'Bundler', '/', class: "navbar-brand me-auto fw-bold" %button.navbar-toggler{type: "button", "data-bs-toggle": "collapse", "data-bs-target": "#bs-navbar-collapse", "aria-controls": "bs-navbar-collapse", "aria-expanded": "false", "aria-label": "Toggle navigation"} %span.navbar-toggler-icon + .mx-3#docsearch .collapse.navbar-collapse.flex-grow-0#bs-navbar-collapse %ul.navbar-nav - %li.nav-item - %input#input-search.input-search.my-1.ps-1.pt-1{type: :text, placeholder: t('search.placeholder')} - %svg.text-opacity-40.m-1.mb-2{xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 512 512", style: "width: 1rem; height: 1rem; fill: currentcolor;"} - / Font Awesome Free 6.1.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. - %path{d: "M500.3 443.7l-119.7-119.7c27.22-40.41 40.65-90.9 33.46-144.7C401.8 87.79 326.8 13.32 235.2 1.723C99.01-15.51-15.51 99.01 1.724 235.2c11.6 91.64 86.08 166.7 177.6 178.9c53.8 7.189 104.3-6.236 144.7-33.46l119.7 119.7c15.62 15.62 40.95 15.62 56.57 0C515.9 484.7 515.9 459.3 500.3 443.7zM79.1 208c0-70.58 57.42-128 128-128s128 57.42 128 128c0 70.58-57.42 128-128 128S79.1 278.6 79.1 208z"} %li.nav-item= link_to t('navbar.docs'), '/docs.html', class: "nav-link" %li.nav-item= link_to t('navbar.team'), '/contributors.html', class: "nav-link" %li.nav-item= link_to t('navbar.blog'), '/blog', class: "nav-link" diff --git a/source/layouts/base.haml b/source/layouts/base.haml index 8630b7723c..9d20c707f3 100644 --- a/source/layouts/base.haml +++ b/source/layouts/base.haml @@ -15,7 +15,7 @@ - if content_for?(:canonical) %link(rel="canonical" href="#{yield_content(:canonical)}") - = javascript_include_tag "application.min" + = stylesheet_link_tag "https://cdn.jsdelivr.net/npm/@docsearch/css@3.1.1/dist/style.min.css" = stylesheet_link_tag "application" = partial 'layouts/favicon' = feed_tag :atom, "#{blog.options.prefix.to_s}/feed.xml", title: "Atom Feed" @@ -30,3 +30,6 @@ .footer = partial 'layouts/footer' + = javascript_include_tag "https://cdn.jsdelivr.net/npm/typesense-docsearch.js@3.0.0-3/dist/umd/index.min.js" + = javascript_include_tag "https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.min.js" + = javascript_include_tag "application.min"