Skip to content

The One True Search™ #1204

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 37 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
17b12bb
add search icon
SIGSTACKFAULT May 15, 2024
8ec4515
on second thought, hard-code the svg.
SIGSTACKFAULT May 27, 2024
46cc43c
add search button to top bar
SIGSTACKFAULT May 15, 2024
c3177d1
rename icon() to search_icon()
SIGSTACKFAULT May 15, 2024
caa4430
styling i'm vaguely happy with
SIGSTACKFAULT May 15, 2024
a19fa34
more stuff but still no script
SIGSTACKFAULT May 15, 2024
4fc633d
some comments about when things are hidden
SIGSTACKFAULT May 15, 2024
a3922fe
add history and tip randomization
SIGSTACKFAULT May 15, 2024
2f230d7
set default language (required for build_search_index)
SIGSTACKFAULT May 15, 2024
5c5dfc9
sorta kinda working
SIGSTACKFAULT May 16, 2024
ed06fe3
add ability to click out of the search dialog
SIGSTACKFAULT May 20, 2024
cbd6ef3
rewrite time already
SIGSTACKFAULT May 20, 2024
e39198a
aosdifpoaisdfm this will all be squashed anyway
SIGSTACKFAULT May 20, 2024
40241e8
use js modules
SIGSTACKFAULT May 20, 2024
e6db573
don't need the underscores anymore
SIGSTACKFAULT May 20, 2024
5abc19b
working Fuse search except only with a Zola patch i wrote
SIGSTACKFAULT May 20, 2024
4671eb7
faffing about
SIGSTACKFAULT May 21, 2024
31ed0a4
switch back to elastic so this can actually ship without waiting for …
SIGSTACKFAULT May 27, 2024
cc62b50
move examples to the end
SIGSTACKFAULT May 27, 2024
eb0318c
deprioritize examples in a way that doesn't mess up the tab order
SIGSTACKFAULT May 27, 2024
72a3fa0
strip the host part of the url
SIGSTACKFAULT May 27, 2024
ee67737
prioritize results with similar paths
SIGSTACKFAULT May 27, 2024
9017b29
remove commented out line
SIGSTACKFAULT May 27, 2024
7aa371c
bind ctrl+k to search
SIGSTACKFAULT May 27, 2024
c17ac07
seperate buttons for mobile and desktop
SIGSTACKFAULT May 27, 2024
c147484
make it good on mobile
SIGSTACKFAULT May 27, 2024
73b3d18
rework mobile menu to use a vertical flexbox
SIGSTACKFAULT May 27, 2024
f78b7b1
add close button
SIGSTACKFAULT May 29, 2024
002e02f
update config for 0.19.1
SIGSTACKFAULT Jul 7, 2024
9e022b6
unremove padding from .search-button
SIGSTACKFAULT Jul 7, 2024
c0f3706
remove elasticlunr imports
SIGSTACKFAULT Jul 7, 2024
1ef188d
directly set `window.SEARCH` instead of exporting
SIGSTACKFAULT Jul 7, 2024
c4e6603
technically working again
SIGSTACKFAULT Jul 8, 2024
6c58fec
change the placeholder when changing the dropdown
SIGSTACKFAULT Jul 9, 2024
da46706
add a semi
SIGSTACKFAULT Jul 9, 2024
e732d39
update_placeholder => change_placeholder
SIGSTACKFAULT Jul 9, 2024
d93bdd0
focus the search input if the dialog is already open
SIGSTACKFAULT Jul 9, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ title = "Bevy Engine"
compile_sass = true

# Whether to build a search index to be used later on by a JavaScript library
default_language = "en"
build_search_index = true

generate_feed = true
rss_limit = 1000
highlight_theme = "charcoal"
generate_feeds = true
feed_limit = 1000

taxonomies = [
{name = "news", feed = true},
Expand All @@ -26,3 +26,7 @@ highlight_theme = "css"

[extra]
# Put all your custom variables here

[search]
index_format="fuse_json"
include_path = true
2 changes: 1 addition & 1 deletion generate-wasm-examples/generate_wasm_examples.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/bin/bash
#!/usr/bin/env bash

echo Generating WASM example list...

Expand Down
35 changes: 26 additions & 9 deletions sass/components/_main-menu.scss
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@

&:hover {
color: $color-blue;
svg {
fill: $color-blue; // (2024-05-15) only actually used by search button
}
}

&--active {
Expand All @@ -51,6 +54,10 @@
outline: $focus-outline;
}
}

&__search {
display: none; // re-enabled below
}
}

// MODE: Off-Canvas Mobile Menu
Expand All @@ -59,9 +66,10 @@
$padding: 8px;
$bottom-buffer: 60px; // Add extra length to compensate for address-bar

--main-menu-switch-height: 0px;

position: fixed;
display: flex;
flex-direction: column;
gap: 0.5em;
top: 0px;
left: -$mobile-menu-width;
width: $mobile-menu-width;
Expand All @@ -75,8 +83,6 @@
box-shadow: 0px 0px 16px rgba(#000, 0.3);

&--with-page-menu {
--main-menu-switch-height: 56px;

.main-menu__page-menu-switch {
display: block;
}
Expand All @@ -97,15 +103,22 @@
}
}

&__search__mobile {
display: flex;
padding: 0 $padding;
.search-button {
flex-grow: 1;
}
}

&__page-menu-switch {
display: none;
padding: $padding $padding 0 $padding;
height: var(--main-menu-switch-height);
padding: 0 $padding;
}

&__content {
position: relative;
height: calc(100% - var(--header-height) - var(--main-menu-switch-height));
flex-grow: 1;
overflow-x: hidden;
}

Expand All @@ -124,13 +137,13 @@
&__menu {
display: flex;
flex-direction: column;
padding: $padding;
padding: 0 $padding;
transform: translateX(0px);
}

&__page-menu {
margin: 0;
padding: $padding;
padding: 0 $padding;
transform: translateX(#{$mobile-menu-width});
}

Expand Down Expand Up @@ -180,5 +193,9 @@
font-weight: 500;
text-decoration: none;
}

&__search__desktop {
display: block;
}
}
}
130 changes: 130 additions & 0 deletions sass/components/_search.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
.search-button {
display: flex;
gap: 1em;
// reset <button> defaults
border: none;
background: none;

&__svg {
height: 1em;
fill: $default-color;
aspect-ratio: 1/1;
}
}

#search-dialog {
$highlight: $color-pink;
width: min(80ch, 90%);
max-height: 80vh;
border: none;
padding: 0;
background-color: transparent;
overflow: visible;

&::backdrop {
background-color: rgba($color-grey-800, 0.7);
}

.search-dialog__close {
position: absolute;
right: -24px;
background: none;
border: none;
}

.search-dialog__inner {
flex-grow: 1;
padding: 1em;
border: 2px solid $highlight;
border-radius: $border-radius;
background-color: $color-grey-900;
aspect-ratio: 3/2;
}

[role=form] {
$input-height: 2em;
display: flex;
gap: 1em;
align-items: center;
margin-bottom: 1em;

input {
width: 100%;
outline: none;
border: none;
font-size: $input-height;
background-color: transparent;
border-radius: 0;
}

label svg {
height: $input-height;
fill: $highlight;
}
}

#search-dialog__results {
display: grid;
grid-template-columns: 1fr 1fr;
margin: 0;
padding: 1em;
gap: 1em;

a {
&::before {
color: $subtitle-color;
text-decoration: none;
display: inline-block;
padding-right: 8px;
}

// &[href*="/examples/"], &[href*="/examples-webgpu"] {
// order: 10;
// }

// vaguely in top bar order

&[href^="/learn/book/"]::before {
content: "book:";
}

&[href^="/learn/quick-start/"]::before {
content: "quick start:";
}

&[href^="/news/"]::before {
content: "news:";
}

&[href^="/foundation/"]::before {
content: "foundation:";
}

&[href^="/examples/"]::before {
content: "examples (webgl):";
}

&[href^="/examples-webgpu/"]::before {
content: "examples (webgpu):";
}

&[href^="/donate/"]::before {
content: "donate:";
}
}
}

.search-dialog__tip ul {
display: inline;
margin: 0;
padding: 0;

li {
display: none;
}

li[data-chosen=true] {
display: inline;
}
}
}
1 change: 1 addition & 0 deletions sass/site.scss
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
@import "components/on-this-page";
@import "components/page-with-menu";
@import "components/pr-list";
@import "components/search";
@import "components/sponsors";
@import "components/syntax-theme";
@import "components/tree-menu";
Expand Down
111 changes: 111 additions & 0 deletions static/search.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
import Fuse from 'https://cdn.jsdelivr.net/npm/[email protected]/dist/fuse.mjs'

document.getElementById("search-dialog").addEventListener('click', function (event) {
// allow clicking out of the search dialog
// based on https://stackoverflow.com/a/69421512
var rect = this.getBoundingClientRect();
if (event.target == this && !(rect.top <= event.clientY && event.clientY <= rect.top + rect.height
&& rect.left <= event.clientX && event.clientX <= rect.left + rect.width)) {
this.close();
}
});

document.addEventListener("keydown", event => {
if (event.ctrlKey && event.key == "k") {
event.preventDefault();
SEARCH.open();
}
})

class Search {
RESULTS_LIMIT = 10;
FUSE_OPTIONS = {
keys: ["title", "body"],
includeMatches: true,
minMatchCharLength: 3,
};
index = null;
previous_search = null;
$dialog = document.getElementById("search-dialog")
$input = document.getElementById("search-dialog__input")
$results = document.getElementById("search-dialog__results")
$select = document.getElementById("search-dialog__select")
$search_tip_list = document.querySelector("#search-dialog aside ul");

async setup() {
this.index ??= await (await fetch("/search_index.en.json")).json();
this.fuse ??= new Fuse(this.index, this.FUSE_OPTIONS);
console.debug("fetched search index", this.index);
}

async open() {
if(this.$dialog.getAttribute("open") !== null) {
// already open
this.$input.focus();
} else {
this.$dialog.showModal();
this.change_tip();
this.change_placeholder();
await this.setup();
await this.search();
}
}

close() {
this.$dialog.close();
}

change_tip() {
let length = this.$search_tip_list.children.length;
let choice = Math.floor(Math.random() * length);
console.debug("chose tip", choice);
Array.from(this.$search_tip_list.children).forEach(
(tip, i) => tip.setAttribute("data-chosen", i == choice
));
}

change_placeholder() {
let second_part = "";
switch (this.$select.value) {
case "docs":
second_part = "'s Documentation";
break;
case "assets":
second_part = "'s Assets";
break;
case "examples":
second_part = "'s Examples";
break;
}
this.$input.setAttribute("placeholder", `Search Bevy${second_part}...`);
}

async search() {
let current_path = window.location.pathname.split("/");
/** @type {string} */
const query = this.$input.value;
console.debug(`search: "${query}"`);
if (query == this.previous_search) {
// cursor movements trigger this function
return;
}
this.previous_search = query;
if (query.length == 0) {
return;
}
/** @type {{item: any}[]} */
let results = this.fuse.search(query);
console.debug(results);
let results_limit = results.slice(0, this.RESULTS_LIMIT);
this.$results.innerHTML = "";
results_limit.forEach((result) => {
let a = document.createElement("a");
a.innerText = result.item.title;
a.href = result.item.path;
this.$results.appendChild(a);
});
}

}

window.SEARCH = new Search()
Loading