Skip to content

Commit 5f1edbb

Browse files
authored
Infra: add pagefind search (#4247)
1 parent 67c8714 commit 5f1edbb

File tree

5 files changed

+218
-1
lines changed

5 files changed

+218
-1
lines changed

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ ALLSPHINXOPTS = --builder $(BUILDER) \
2222
.PHONY: html
2323
html: venv
2424
$(SPHINXBUILD) $(ALLSPHINXOPTS)
25+
$(VENVDIR)/bin/python3 -m pagefind --site $(BUILDDIR) --verbose
2526

2627
## htmlview to open the index page built by the html target in your browser
2728
.PHONY: htmlview

pep_sphinx_extensions/pep_theme/static/mq.css

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@
1717
nav#pep-sidebar {
1818
display: none;
1919
}
20+
/* Show mobile search container on small screens */
21+
.mobile-search-container {
22+
display: block;
23+
}
2024
pre {
2125
font-size: 0.8175rem;
2226
}
@@ -46,6 +50,10 @@
4650
float: left;
4751
margin-right: 2%;
4852
}
53+
/* Hide mobile search container on larger screens */
54+
.mobile-search-container {
55+
display: none;
56+
}
4957
/* Make less prominent when sidebar ToC is available */
5058
details > summary {
5159
font-size: 1rem;

pep_sphinx_extensions/pep_theme/static/style.css

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,182 @@ dl.footnote > dd {
427427
padding-bottom: 2rem;
428428
font-weight: bold;
429429
}
430+
/* Pagefind search styling (custom, no default CSS) */
431+
.pagefind-ui {
432+
--pagefind-ui-primary: var(--colour-links);
433+
--pagefind-ui-text: var(--colour-text);
434+
--pagefind-ui-background: var(--colour-background);
435+
--pagefind-ui-border: var(--colour-background-accent-strong);
436+
font-family: inherit;
437+
width: 100%;
438+
}
439+
440+
/* Search form */
441+
.pagefind-ui__form {
442+
position: relative;
443+
}
444+
445+
/* Search icon */
446+
.pagefind-ui__form::before {
447+
background-color: var(--pagefind-ui-text);
448+
width: 14px;
449+
height: 14px;
450+
top: 8px;
451+
left: 8px;
452+
content: "";
453+
position: absolute;
454+
display: block;
455+
opacity: 0.5;
456+
-webkit-mask-image: url("data:image/svg+xml,%3Csvg width='18' height='18' viewBox='0 0 18 18' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12.7549 11.255H11.9649L11.6849 10.985C12.6649 9.845 13.2549 8.365 13.2549 6.755C13.2549 3.165 10.3449 0.255005 6.75488 0.255005C3.16488 0.255005 0.254883 3.165 0.254883 6.755C0.254883 10.345 3.16488 13.255 6.75488 13.255C8.36488 13.255 9.84488 12.665 10.9849 11.685L11.2549 11.965V12.755L16.2549 17.745L17.7449 16.255L12.7549 11.255ZM6.75488 11.255C4.26488 11.255 2.25488 9.245 2.25488 6.755C2.25488 4.26501 4.26488 2.255 6.75488 2.255C9.24488 2.255 11.2549 4.26501 11.2549 6.755C11.2549 9.245 9.24488 11.255 6.75488 11.255Z' fill='%23000000'/%3E%3C/svg%3E%0A");
457+
mask-image: url("data:image/svg+xml,%3Csvg width='18' height='18' viewBox='0 0 18 18' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12.7549 11.255H11.9649L11.6849 10.985C12.6649 9.845 13.2549 8.365 13.2549 6.755C13.2549 3.165 10.3449 0.255005 6.75488 0.255005C3.16488 0.255005 0.254883 3.165 0.254883 6.755C0.254883 10.345 3.16488 13.255 6.75488 13.255C8.36488 13.255 9.84488 12.665 10.9849 11.685L11.2549 11.965V12.755L16.2549 17.745L17.7449 16.255L12.7549 11.255ZM6.75488 11.255C4.26488 11.255 2.25488 9.245 2.25488 6.755C2.25488 4.26501 4.26488 2.255 6.75488 2.255C9.24488 2.255 11.2549 4.26501 11.2549 6.755C11.2549 9.245 9.24488 11.255 6.75488 11.255Z' fill='%23000000'/%3E%3C/svg%3E%0A");
458+
-webkit-mask-size: 100%;
459+
mask-size: 100%;
460+
z-index: 9;
461+
pointer-events: none;
462+
}
463+
464+
/* Search input */
465+
.pagefind-ui__search-input {
466+
height: 30px;
467+
padding: 4px 28px 4px 28px;
468+
background-color: var(--pagefind-ui-background);
469+
border: 1px solid var(--pagefind-ui-border);
470+
border-radius: 3px;
471+
font-size: 0.875rem;
472+
font-family: inherit;
473+
appearance: none;
474+
-webkit-appearance: none;
475+
width: 100%;
476+
box-sizing: border-box;
477+
color: var(--pagefind-ui-text);
478+
}
479+
.pagefind-ui__search-input:focus {
480+
outline: none;
481+
border-color: var(--pagefind-ui-primary);
482+
}
483+
.pagefind-ui__search-input::placeholder {
484+
color: var(--pagefind-ui-text);
485+
opacity: 0.5;
486+
}
487+
488+
/* Clear button - fixed position relative to input (30px height, center button) */
489+
.pagefind-ui__search-clear {
490+
position: absolute;
491+
top: 5px;
492+
right: 4px;
493+
padding: 2px 6px;
494+
color: var(--pagefind-ui-text);
495+
font-size: 0.75rem;
496+
cursor: pointer;
497+
background-color: var(--pagefind-ui-background);
498+
border: none;
499+
opacity: 0.6;
500+
}
501+
.pagefind-ui__search-clear:hover {
502+
opacity: 1;
503+
}
504+
505+
/* Results container */
506+
.pagefind-ui__results-area {
507+
margin-top: 0.5rem;
508+
}
509+
510+
/* Results list */
511+
#pep-sidebar .pagefind-ui__results {
512+
list-style: none;
513+
padding: 0;
514+
margin: 0;
515+
}
516+
517+
/* Individual result */
518+
.pagefind-ui__result {
519+
padding: 0.5rem 0 0.5rem 0.5rem;
520+
border-bottom: 1px solid var(--colour-rule-light);
521+
}
522+
.pagefind-ui__result:last-child {
523+
border-bottom: none;
524+
}
525+
526+
/* Result link */
527+
.pagefind-ui__result-link {
528+
font-weight: bold;
529+
font-size: 0.9rem;
530+
text-decoration: none;
531+
color: var(--colour-links);
532+
}
533+
.pagefind-ui__result-link:hover {
534+
text-decoration: underline;
535+
}
536+
537+
/* Result title */
538+
.pagefind-ui__result-title {
539+
margin: 0;
540+
}
541+
542+
/* Result excerpt/snippet */
543+
.pagefind-ui__result-excerpt {
544+
font-size: 0.8rem;
545+
color: var(--colour-text);
546+
margin: 0.25rem 0 0;
547+
line-height: 1.4;
548+
}
549+
550+
/* Highlight matches in results */
551+
.pagefind-ui__result-excerpt mark,
552+
mark.pagefind-ui__highlight {
553+
background-color: var(--colour-caution);
554+
color: inherit;
555+
padding: 0 2px;
556+
}
557+
558+
/* Message when no results */
559+
.pagefind-ui__message {
560+
font-size: 0.85rem;
561+
color: var(--colour-text);
562+
padding: 0.5rem 0;
563+
}
564+
565+
/* Loading state */
566+
.pagefind-ui__loading {
567+
font-size: 0.85rem;
568+
color: var(--colour-text);
569+
opacity: 0.7;
570+
}
571+
572+
/* Sub-results (nested) */
573+
.pagefind-ui__result-nested {
574+
margin-left: 1rem;
575+
padding: 0.25rem 0;
576+
}
577+
.pagefind-ui__result-nested .pagefind-ui__result-link {
578+
font-weight: normal;
579+
font-size: 0.85rem;
580+
}
581+
582+
/* Button styling */
583+
.pagefind-ui__button {
584+
background: var(--colour-background-accent-light);
585+
border: 1px solid var(--colour-background-accent-strong);
586+
padding: 0.4rem 0.8rem;
587+
border-radius: 4px;
588+
cursor: pointer;
589+
font-size: 0.85rem;
590+
color: var(--colour-text);
591+
margin-top: 0.5rem;
592+
}
593+
.pagefind-ui__button:hover {
594+
background: var(--colour-background-accent-medium);
595+
}
596+
597+
/* Drawer (expandable results container) */
598+
.pagefind-ui__drawer {
599+
overflow: hidden;
600+
}
601+
602+
/* Suppress unused pagefind elements */
603+
.pagefind-ui__suppressed {
604+
display: none;
605+
}
430606

431607
.reference.external > strong {
432608
font-weight: normal; /* Fix strong links for :pep: and :rfc: roles */

pep_sphinx_extensions/pep_theme/templates/page.html

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
</script>
3434
<section id="pep-page-section">
3535
<header>
36-
<h1>Python Enhancement Proposals</h1>
36+
<h1 data-pagefind-ignore>Python Enhancement Proposals</h1>
3737
<ul class="breadcrumbs">
3838
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li>
3939
<li><a href="{{ pathto("pep-0000") }}">PEP Index</a> &raquo; </li>
@@ -46,11 +46,21 @@ <h1>Python Enhancement Proposals</h1>
4646
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
4747
</button>
4848
</header>
49+
{# Mobile search box - visible only on small screens #}
50+
<div id="mobile-search" class="mobile-search-container"></div>
51+
{# Exclude noisy non-PEP pages from Pagefind indexing #}
52+
{%- if pagename.startswith(("404", "numerical", "pep-0000", "topic")) %}
4953
<article>
54+
{%- else %}
55+
<article data-pagefind-body>
56+
{%- endif %}
57+
{# Add pagefind meta for the title to improve search result display #}
58+
<span data-pagefind-meta="title:{{ title }}" data-pagefind-weight="10" class="visually-hidden">{{ title }}</span>
5059
{{ body }}
5160
</article>
5261
{%- if not pagename.startswith(("404", "numerical")) %}
5362
<nav id="pep-sidebar">
63+
<div id="search"></div>
5464
<h2>Contents</h2>
5565
{{ toc }}
5666
<br>
@@ -65,5 +75,25 @@ <h2>Contents</h2>
6575
<script src="{{ pathto('_static/sticky_banner.js', resource=True) }}"></script>
6676
<script src="https://analytics.python.org/js/script.outbound-links.js"
6777
data-domain="peps.python.org" defer></script>
78+
<script src="/pagefind/pagefind-ui.js"></script>
79+
<script>
80+
window.addEventListener('DOMContentLoaded', (event) => {
81+
// Ranking configuration to boost exact title matches
82+
const searchOptions = {
83+
ranking: {
84+
termSimilarity: 9.0, // Higher values favor exact matches
85+
termFrequency: 0.5, // Lower values reduce penalty for low term frequency
86+
pageLength: 0.2, // Lower values reduce the impact of page length
87+
}
88+
};
89+
90+
// Initialize pagefind for either mobile or desktop, not both
91+
if (window.innerWidth <= 640) {
92+
new PagefindUI({ element: "#mobile-search", ...searchOptions, showSubResults: false });
93+
} else {
94+
new PagefindUI({ element: "#search", ...searchOptions, showSubResults: true });
95+
}
96+
});
97+
</script>
6898
</body>
6999
</html>

requirements.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ Pygments >= 2.19
66
Sphinx >= 5.1.1, != 6.1.0, != 6.1.1, < 8.1.0
77
docutils >= 0.19.0
88
sphinx-notfound-page >= 1.0.2
9+
# For search
10+
pagefind[bin] >= 1.4.0
911

1012
# For tests
1113
pytest>=9

0 commit comments

Comments
 (0)