Skip to content

Commit 2444a00

Browse files
authored
Merge pull request #96 from JuliaComputing/sp/pagefind
feat: make pagefind the new default search engine
2 parents 8e66ce1 + 69c633b commit 2444a00

File tree

15 files changed

+567
-201
lines changed

15 files changed

+567
-201
lines changed

.JuliaFormatter.toml

Lines changed: 0 additions & 1 deletion
This file was deleted.

.github/workflows/CI.yml

Lines changed: 9 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -39,24 +39,15 @@ jobs:
3939
${{ runner.os }}-
4040
- uses: julia-actions/julia-buildpkg@v1
4141
- uses: julia-actions/julia-runtest@v1
42-
julia-format:
43-
name: Formatter
42+
runic:
43+
name: Runic formatting
4444
runs-on: ubuntu-latest
4545
steps:
46-
- uses: julia-actions/setup-julia@latest
4746
- uses: actions/checkout@v4
48-
- name: Install JuliaFormatter and format
49-
run: |
50-
julia --color=yes -e 'using Pkg; Pkg.add(PackageSpec(name="JuliaFormatter"))'
51-
julia --color=yes -e 'using JuliaFormatter; format(".", verbose=true)'
52-
- name: Format check
53-
run: |
54-
julia --color=yes -e '
55-
out = Cmd(`git diff --name-only`) |> read |> String
56-
if out == ""
57-
exit(0)
58-
else
59-
@error "Some files have not been formatted !!!"
60-
write(stdout, out)
61-
exit(1)
62-
end'
47+
- uses: julia-actions/setup-julia@v2
48+
with:
49+
version: '1.11'
50+
- uses: julia-actions/cache@v2
51+
- uses: fredrikekre/runic-action@v1
52+
with:
53+
version: '1'

Project.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ Git = "d7ba0133-e1db-5d97-8f8c-041e4b3a1eb2"
99
Gumbo = "708ec375-b3d6-5a57-a7ce-8257bf98657a"
1010
HypertextLiteral = "ac1192a8-f4b3-4bfe-ba22-af5b92cd3ab2"
1111
JSON = "682c06a0-de6a-54ab-a142-c8b1cf79cde6"
12-
NodeJS = "2bd173c7-0d6d-553b-b6af-13a54713934c"
12+
NodeJS_22_jll = "8fca9ca2-e7a1-5ccf-8c05-43be5a78664f"
1313
Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
1414

1515
[compat]
@@ -18,7 +18,7 @@ Git = "1"
1818
Gumbo = "0.8.2"
1919
HypertextLiteral = "0.9"
2020
JSON = "0.20,0.21"
21-
NodeJS = "1, 2"
21+
NodeJS_22_jll = "22.15.0"
2222
julia = "1"
2323

2424
[extras]

assets/default/pagefind.css

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
#multi-page-nav .search {
2+
margin-left: auto;
3+
font-size: 16px;
4+
}
5+
6+
#multi-page-nav .search .search-keybinding {
7+
float: right;
8+
width: 0;
9+
transform: translateX(-1em);
10+
color: #999;
11+
}
12+
13+
#multi-page-nav .search:focus-within .search-keybinding {
14+
display: none;
15+
}
16+
17+
#multi-page-nav .search #search-input {
18+
border: 1px solid #666;
19+
border-radius: 3.2px;
20+
color: #999;
21+
background-color: unset;
22+
height: 28px;
23+
font-family: inherit;
24+
width: 20em;
25+
font-size: 14px;
26+
padding: 0 8px;
27+
}
28+
29+
#multi-page-nav .search #search-input::placeholder {
30+
color: #999;
31+
opacity: 1;
32+
}
33+
34+
#multi-page-nav .search:focus-within #search-input {
35+
background-color: #fff;
36+
outline: none;
37+
box-shadow: none;
38+
color: #000;
39+
}
40+
41+
.theme--documenter-dark #multi-page-nav .search:focus-within #search-input {
42+
background-color: #202227;
43+
color: #eee;
44+
}
45+
46+
#multi-page-nav .search:focus-within .suggestions {
47+
display: block;
48+
}
49+
50+
#multi-page-nav .hidden {
51+
display: none !important;
52+
}
53+
54+
#multi-page-nav .suggestions {
55+
margin: -5px 1.5rem 0 0;
56+
display: none;
57+
background: #fff;
58+
min-width: 20em;
59+
max-width: 50vw;
60+
position: absolute;
61+
border: 1px solid #cfd4db;
62+
border-radius: 6px;
63+
padding: .4rem;
64+
list-style-type: none;
65+
z-index: 10;
66+
right: 0;
67+
max-height: max(50vh, 250px);
68+
overflow-y: auto;
69+
}
70+
71+
.theme--documenter-dark #multi-page-nav .suggestions {
72+
background: #2e3138;
73+
border: 1px solid #5e6d6f;
74+
}
75+
76+
#multi-page-nav .suggestions mark {
77+
background-color: inherit;
78+
color: #000;
79+
}
80+
.theme--documenter-dark #multi-page-nav .suggestions mark {
81+
color: #fff;
82+
}
83+
84+
#multi-page-nav .suggestions .suggestion {
85+
line-height: 1.3;
86+
border-radius: 4px;
87+
88+
overflow: hidden;
89+
text-overflow: ellipsis;
90+
word-break: break-all;
91+
}
92+
#multi-page-nav .suggestions .sub-suggestions .suggestion {
93+
margin-left: 1rem;
94+
}
95+
96+
#multi-page-nav .suggestions .suggestion-header {
97+
padding: .4rem .6rem;
98+
}
99+
#multi-page-nav .suggestions .suggestion-header:focus-visible {
100+
outline: none;
101+
}
102+
.theme--documenter-dark #multi-page-nav .suggestions .suggestion-header:hover,
103+
.theme--documenter-dark #multi-page-nav .suggestions .suggestion-header:focus {
104+
background-color: #202227;
105+
}
106+
#multi-page-nav .suggestions .suggestion-header:hover,
107+
#multi-page-nav .suggestions .suggestion-header:focus {
108+
background-color: #eee;
109+
}
110+
111+
#multi-page-nav .suggestions .suggestion .suggestion-excerpt {
112+
font-size: small;
113+
color: #666;
114+
}
115+
.theme--documenter-dark #multi-page-nav .suggestions .suggestion .suggestion-excerpt {
116+
color: #aaa;
117+
}
118+
119+
#multi-page-nav .suggestion .suggestion-title {
120+
font-size: 1.2rem;
121+
font-weight: bold;
122+
}
123+
124+
#multi-page-nav .suggestion .sub-suggestions .suggestion-title {
125+
font-size: 1rem;
126+
}
127+
128+
#multi-page-nav .suggestion a {
129+
display: block;
130+
overflow: hidden;
131+
text-overflow: ellipsis;
132+
color: black;
133+
}
134+
135+
.theme--documenter-dark #multi-page-nav .suggestion a {
136+
color: white;
137+
}
138+
139+
#multi-page-nav .suggestions .suggestion .page-title {
140+
font-weight: bold;
141+
}
142+
143+
@media screen and (max-width: 1055px) {
144+
#multi-page-nav .search #search-input {
145+
width: 100%;
146+
}
147+
#multi-page-nav .suggestions {
148+
max-width: 100vw;
149+
width: calc(100% - 3.5rem);
150+
margin: 10px 2.5em 4.5em 0;
151+
}
152+
}
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
// custom search widget
2+
(async function() {
3+
const MAX_RESULTS = 20
4+
let FOCUSABLE_ELEMENTS = []
5+
let FOCUSED_ELEMENT_INDEX = 0
6+
7+
const pagefind = await import(window.MULTIDOCUMENTER_ROOT_PATH + "pagefind/pagefind.js")
8+
9+
function initialize() {
10+
pagefind.init()
11+
registerSearchListener()
12+
13+
document.body.addEventListener('keydown', ev => {
14+
if (document.activeElement === document.body && (ev.key === '/' || ev.key === 's')) {
15+
document.getElementById('search-input').focus()
16+
ev.preventDefault()
17+
}
18+
})
19+
}
20+
21+
function registerSearchListener() {
22+
const input = document.getElementById('search-input')
23+
const suggestions = document.getElementById('search-result-container')
24+
25+
async function runSearch() {
26+
const query = input.value
27+
28+
const search = await pagefind.debouncedSearch(query, {}, 300);
29+
30+
if (search) {
31+
buildResults(search.results)
32+
}
33+
}
34+
35+
input.addEventListener('keyup', ev => {
36+
runSearch()
37+
})
38+
39+
input.addEventListener('keydown', ev => {
40+
if (ev.key === 'ArrowDown') {
41+
FOCUSED_ELEMENT_INDEX = 0
42+
FOCUSABLE_ELEMENTS[FOCUSED_ELEMENT_INDEX].focus()
43+
ev.preventDefault()
44+
return
45+
} else if (ev.key === 'ArrowUp') {
46+
FOCUSED_ELEMENT_INDEX = FOCUSABLE_ELEMENTS.length - 1
47+
FOCUSABLE_ELEMENTS[FOCUSED_ELEMENT_INDEX].focus()
48+
ev.preventDefault()
49+
return
50+
}
51+
})
52+
53+
suggestions.addEventListener('keydown', ev => {
54+
if (ev.key === 'ArrowDown') {
55+
FOCUSED_ELEMENT_INDEX += 1
56+
if (FOCUSED_ELEMENT_INDEX < FOCUSABLE_ELEMENTS.length) {
57+
FOCUSABLE_ELEMENTS[FOCUSED_ELEMENT_INDEX].focus()
58+
} else {
59+
FOCUSED_ELEMENT_INDEX = -1
60+
input.focus()
61+
}
62+
ev.preventDefault()
63+
} else if (ev.key === 'ArrowUp') {
64+
FOCUSED_ELEMENT_INDEX -= 1
65+
if (FOCUSED_ELEMENT_INDEX >= 0) {
66+
FOCUSABLE_ELEMENTS[FOCUSED_ELEMENT_INDEX].focus()
67+
} else {
68+
FOCUSED_ELEMENT_INDEX = -1
69+
input.focus()
70+
}
71+
ev.preventDefault()
72+
}
73+
})
74+
75+
input.addEventListener('focus', ev => {
76+
runSearch()
77+
})
78+
}
79+
80+
function renderResult(result) {
81+
const entry = document.createElement('li')
82+
entry.classList.add('suggestion')
83+
84+
const linkContainer = document.createElement('a')
85+
linkContainer.classList.add('suggestion-header')
86+
linkContainer.setAttribute('href', result.url)
87+
88+
const page = document.createElement('p')
89+
page.classList.add('suggestion-title')
90+
91+
const pageTitle = document.createElement('span')
92+
pageTitle.innerText = result.title ?? result.meta.title
93+
94+
page.appendChild(pageTitle)
95+
96+
const excerpt = document.createElement('p')
97+
excerpt.classList.add('suggestion-excerpt')
98+
excerpt.innerHTML = result.excerpt
99+
100+
linkContainer.appendChild(page)
101+
linkContainer.appendChild(excerpt)
102+
103+
entry.appendChild(linkContainer)
104+
105+
return entry
106+
}
107+
108+
async function buildResults(results) {
109+
const suggestions = document.getElementById('search-result-container')
110+
111+
const children = await Promise.all(results.slice(0, MAX_RESULTS - 1).map(async (r, i) => {
112+
const data = await r.data()
113+
114+
const entry = renderResult(data)
115+
116+
if (data.sub_results.length > 0) {
117+
const subResults = document.createElement('ol')
118+
subResults.classList.add('sub-suggestions')
119+
120+
data.sub_results.forEach(subresult => {
121+
const entry = renderResult(subresult)
122+
subResults.appendChild(entry)
123+
})
124+
entry.appendChild(subResults)
125+
}
126+
127+
return entry
128+
}))
129+
130+
if (results.length > 0) {
131+
suggestions.classList.remove('hidden')
132+
} else {
133+
suggestions.classList.add('hidden')
134+
}
135+
136+
137+
suggestions.replaceChildren(
138+
...children
139+
)
140+
141+
FOCUSED_ELEMENT_INDEX = -1
142+
FOCUSABLE_ELEMENTS = [...suggestions.querySelectorAll('a')]
143+
}
144+
145+
if (document.readyState === 'loading') {
146+
document.addEventListener('DOMContentLoaded', initialize)
147+
} else {
148+
initialize()
149+
};
150+
})()

docs/make.jl

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,12 @@ open(joinpath(@__DIR__, "src", "index.md"), write = true) do io
2323
io,
2424
"""
2525
26-
## Docstrings
26+
## Docstrings
2727
28-
```@autodocs
29-
Modules = [MultiDocumenter]
30-
```
31-
""",
28+
```@autodocs
29+
Modules = [MultiDocumenter]
30+
```
31+
""",
3232
)
3333
end
3434
cp(

0 commit comments

Comments
 (0)