Replace Sphinx search with Pagefind (#3186)

Co-authored-by: clydeps <U5yx99dok9>
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
This commit is contained in:
Clyde Stubbs 2024-05-19 09:21:53 +10:00 committed by GitHub
parent a1910a39be
commit dd263f2966
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 215 additions and 6 deletions

View File

@ -18,6 +18,11 @@ jobs:
build:
runs-on: ubuntu-latest
steps:
-
name: Install pagefind
uses: jaxxstorm/action-install-gh-release@v1.10.0
with:
repo: cloudcannon/pagefind
-
name: Checkout source code
uses: actions/checkout@v4.1.6

View File

@ -19,6 +19,10 @@ jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Install pagefind
uses: jaxxstorm/action-install-gh-release@v1.10.0
with:
repo: cloudcannon/pagefind
- uses: actions/checkout@v4.1.6
- name: Set up Python 3.8
uses: actions/setup-python@v5

View File

@ -1,15 +1,24 @@
ESPHOME_PATH = ../esphome
ESPHOME_REF = 2024.5.0
PAGEFIND_VERSION=1.1.0
PAGEFIND=pagefind
NET_PAGEFIND=../pagefindbin/pagefind
.PHONY: html html-strict cleanhtml deploy help live-html Makefile netlify netlify-api api netlify-dependencies svg2png copy-svg2png minify
.PHONY: html html-strict cleanhtml deploy help live-html live-pagefind Makefile netlify netlify-api api netlify-dependencies svg2png copy-svg2png minify
html:
sphinx-build -M html . _build -j auto -n $(O)
live-html:
${PAGEFIND}
live-html: html
sphinx-autobuild . _build -j auto -n $(O) --host 0.0.0.0
live-pagefind: html
${PAGEFIND} --serve
html-strict:
sphinx-build -M html . _build -W -j auto -n $(O)
${PAGEFIND}
minify:
minify _static/webserver-v1.js > _static/webserver-v1.min.js
@ -32,6 +41,10 @@ api:
fi
ESPHOME_PATH=$(ESPHOME_PATH) doxygen Doxygen
net-html:
sphinx-build -M html . _build -j auto -n $(O)
${NET_PAGEFIND}
netlify-api: netlify-dependencies
mkdir -p _build/html/api
@if [ ! -d "$(ESPHOME_PATH)" ]; then \
@ -40,15 +53,23 @@ netlify-api: netlify-dependencies
fi
ESPHOME_PATH=$(ESPHOME_PATH) ../doxybin/doxygen Doxygen
netlify-dependencies:
netlify-dependencies: pagefind-binary
mkdir -p ../doxybin
curl -L https://github.com/esphome/esphome-docs/releases/download/v1.10.1/doxygen-1.8.13.xz | xz -d >../doxybin/doxygen
chmod +x ../doxybin/doxygen
pagefind-binary:
mkdir -p ../pagefindbin
curl -o pagefind-v$(PAGEFIND_VERSION)-x86_64-unknown-linux-musl.tar.gz https://github.com/CloudCannon/pagefind/releases/download/v$(PAGEFIND_VERSION)/pagefind-v$(PAGEFIND_VERSION)-x86_64-unknown-linux-musl.tar.gz -L
tar xzf pagefind-v$(PAGEFIND_VERSION)-x86_64-unknown-linux-musl.tar.gz
rm pagefind-v$(PAGEFIND_VERSION)-x86_64-unknown-linux-musl.tar.gz
mv pagefind ${NET_PAGEFIND}
copy-svg2png:
cp svg2png/*.png _build/html/_images/
netlify: netlify-dependencies netlify-api html copy-svg2png
netlify: netlify-dependencies netlify-api net-html copy-svg2png
lint: html-strict
python3 lint.py

View File

@ -248,6 +248,34 @@ a:has(> img:only-child) {
div.body p, div.body dd, div.body li, div.body blockquote {
hyphens: none;
}
.pagefind-ui__form {
width: 100%;
max-width: 300px;
left: auto;
right: auto;
position: relative;
}
.pagefind-modular-list-excerpt, .pagefind-modular-list-title {
color: #111111 !important;
}
.search-results {
background-color: #f8f8f8;
box-shadow: 0 6px 10px rgb(0 0 0 / 0.2);
position: absolute;
z-index: 1500;
margin-top: 4px;
padding-right: 6px;
padding-left: 6px;
border-radius: 12px;
overflow: auto;
width: 0;
height: fit-content;
max-width: 650px;
transition: height, width 0.1s ease-in-out;
display: none;
}
/* dark theme */
@media (prefers-color-scheme: dark) {
@ -344,4 +372,24 @@ div.body p, div.body dd, div.body li, div.body blockquote {
background-color: #8e8129;
}
.search-results {
background-color: #313131;
box-shadow: 0 6px 10px rgb(0 0 0 / 0.8);
}
.pagefind-modular-list-excerpt, .pagefind-modular-list-title {
color: #eeeeee !important;
}
.pagefind-ui__form, .pagefind-modular-input, .search-results {
color: #ececec !important;
}
:root {
--pagefind-ui-primary: #eeeeee;
--pagefind-ui-text: #eeeeee;
--pagefind-ui-background: #152028;
--pagefind-ui-border: #152028;
--pagefind-ui-tag: #152028;
}
}

View File

@ -5,6 +5,7 @@
{% endblock %}
{%- block extrahead %}
<link href="/pagefind/pagefind-modular-ui.css" rel="stylesheet">
<link rel="stylesheet" href="{{ pathto('_static/custom.css', 1) }}?hash={{ custom_css_hash }}" type="text/css" />
<link rel="apple-touch-icon" sizes="180x180" href="/_static/apple-touch-icon.png">
<link rel="shortcut icon" href="/_static/favicon.ico">
@ -29,14 +30,16 @@
{% endblock %}
{% block relbar_top %}
{% if parents|length > 0 %}
<ul class="breadcrumbs">
{% if parents|length > 0 %}
{%- for doc in parents %}
<li><a href="{{ doc.link|e }}">{{ doc.title }}</a></li>
{%- endfor %}
<li>{{title}}</li>
</ul>
{% endif %}
</ul>
<div class="search-results" id="search-results"></div>
{% endblock %}
{% block footer %}

36
_templates/search.html Normal file
View File

@ -0,0 +1,36 @@
<!-- docs/_templates/search.html -->
{% extends "page.html" %}
{%- block htmltitle -%}
<title>{{ _("Search") }} - {{ docstitle }}</title>
{%- endblock htmltitle -%}
{% block content %}
<h1>{{ _("Search") }}</h1>
<div id="search"></div>
{% endblock %}
{% block scripts -%}
{{ super() }}
{%- endblock scripts %}
{% block extra_styles -%}
{{ super() }}
<style type="text/css">
#search form input[type="text"] {
box-sizing: border-box;
width: 100%;
line-height: 2em;
padding-inline: 0.6em;
font-size: 1.2rem;
border-radius: 0.05rem;
border: 2px solid var(--color-foreground-border);
border-bottom-color: 2px solid var(--color-foreground-secondary);
transition: border-color 20ms ease;
}
#search form input[type="text"]:focus {
border-color: var(--color-foreground-primary);
}
</style>
{%- endblock extra_styles %}

82
_templates/searchbox.html Normal file
View File

@ -0,0 +1,82 @@
<script src="/pagefind/pagefind-modular-ui.js"></script>
<div class="pagefind-ui__form" id="search"></div>
<div class="search-results" id="mobile-search-results"></div>
<script>
let callbackAdded = null;
window.addEventListener('DOMContentLoaded', (event) => {
const std_target = document.getElementById("search-results");
const mobile_target = document.getElementById("mobile-search-results");
const inpel = document.getElementById("search");
function showTarget() {
var target = std_target;
if (window.innerWidth <= 875) {
target = mobile_target;
std_target.style.display = "none";
} else {
mobile_target.style.display = "none";
}
target.style.display = "block";
const rect = target.getBoundingClientRect();
const height = window.innerHeight;
target.style.width = "100%";
target.style.height = "fit-content";
target.style.maxHeight = (height - rect.top - 10) + "px";
if (!callbackAdded) {
callbackAdded = true;
document.addEventListener('click', clickCallback);
}
}
function hideTargets() {
std_target.style.display = "none";
mobile_target.style.display = "none";
std_target.style.height = "0";
mobile_target.style.height = "0";
if (callbackAdded) {
document.removeEventListener('click', clickCallback);
callbackAdded = false;
}
}
const instance = new PagefindModularUI.Instance({
showSubResults: true,
showImages: false,
ranking: {
pageLength: 0.0,
termSaturation: 1.6,
termFrequency: 0.4,
termSimilarity: 6.0
}
});
instance.add(new PagefindModularUI.Input({
containerElement: "#search"
}));
instance.add(new PagefindModularUI.ResultList({
containerElement: "#search-results"
}));
instance.add(new PagefindModularUI.ResultList({
containerElement: "#mobile-search-results"
}));
const clickCallback = (event) => {
const path = event.composedPath();
if (path.includes(std_target) || path.includes(mobile_target) || path.includes(inpel))
return;
hideTargets();
};
if (std_target && mobile_target) {
instance.on("results", (results) => {
if (results.results.length) {
showTarget();
} else {
hideTargets();
}
});
}
});
</script>

View File

@ -167,6 +167,7 @@ html_sidebars = {
}
# -- Options for HTMLHelp output ------------------------------------------
# Output file base name for HTML help builder.

9
pagefind.yml Normal file
View File

@ -0,0 +1,9 @@
site: _build/html
exclude_selectors:
- "a.headerlink"
- ".toctree-wrapper"
- ".sphinxsidebar"
- ".breadcrumbs"
glob: "{components,cookbook,guides,projects,web-api}/**/*.html"
root_selector: div[role=main]