Add search functionality (#370)

This should solve #23.

This is a fully static search implementation powered by [Pagefind](https://pagefind.app/).

In terms of UI, I found and implemented a section in the sidebar for searching the documentation. It was hidden presumably waiting for implementation. It mentioned using the slash (/) key for searching, so I implemented the hotkey as well.

I made the indexing command required by Pagefind run after Eleventy finishes building using the `.after` hook.

Reviewed-on: https://codeberg.org/Codeberg/Documentation/pulls/370
Co-authored-by: oatbiscuits <oatbiscuits@noreply.codeberg.org>
Co-committed-by: oatbiscuits <oatbiscuits@noreply.codeberg.org>
This commit is contained in:
oatbiscuits 2023-11-30 21:33:22 +00:00 committed by Gusted
parent 57b888bd6c
commit 55a504e33a
8 changed files with 140 additions and 10 deletions

View file

@ -6,6 +6,7 @@ const markdownItAnchor = require('markdown-it-anchor')
const library = require('@fortawesome/fontawesome-svg-core').library; const library = require('@fortawesome/fontawesome-svg-core').library;
const icon = require('@fortawesome/fontawesome-svg-core').icon; const icon = require('@fortawesome/fontawesome-svg-core').icon;
const fas = require('@fortawesome/free-solid-svg-icons').fas; const fas = require('@fortawesome/free-solid-svg-icons').fas;
const { execSync } = require('child_process');
module.exports = function(eleventyConfig) { module.exports = function(eleventyConfig) {
eleventyConfig.addPlugin(navigationPlugin) eleventyConfig.addPlugin(navigationPlugin)
@ -58,6 +59,10 @@ module.exports = function(eleventyConfig) {
<div class="admonition-content">${content}</div> <div class="admonition-content">${content}</div>
</div>` </div>`
}); });
eleventyConfig.on('eleventy.after', () => {
execSync(`npx pagefind`, { encoding: 'utf-8' })
})
return { return {
dir: { dir: {

View file

@ -87,8 +87,9 @@ This website uses [Eleventy](https://www.11ty.dev/), a static site generator.
It's supplied as a dev-dependency in `package.json` and its dependencies are locked It's supplied as a dev-dependency in `package.json` and its dependencies are locked
with `package-lock.json` to try to ensure reproducible builds. with `package-lock.json` to try to ensure reproducible builds.
It also uses [PageFind](https://pagefind.app/), a static search library.
## License and Contributors ## License and Contributors
This website (excluding bundled fonts) is licensed under CC BY-SA 4.0. See the [LICENSE](LICENSE.md) file for details. This website (excluding bundled fonts) is licensed under CC BY-SA 4.0. See the [LICENSE](LICENSE.md) file for details.
Please refer to the [commit log](https://codeberg.org/Codeberg/Documentation/commits/branch/main) for an exhaustive list of contributors to Codeberg Documentation. Please refer to the [commit log](https://codeberg.org/Codeberg/Documentation/commits/branch/main) for an exhaustive list of contributors to Codeberg Documentation.

View file

@ -161,4 +161,23 @@ code:not(pre > code) {
.admonition-content > *:last-child { .admonition-content > *:last-child {
margin-bottom: 0; margin-bottom: 0;
} }
#search-results {
overflow: hidden;
word-wrap: anywhere;
white-space: break-spaces;
--pagefind-ui-background: var(--dm-sidebar-bg-color);
--pagefind-ui-primary: var(--dm-sidebar-link-text-color);
--pagefind-ui-border: var(--dm-sidebar-divider-bg-color);
}
#search-results li {
margin-bottom: 0;
gap: 0;
padding: 10px 0px;
}
.pagefind-modular-list-thumb {
display: none;
}

View file

@ -1,4 +1,4 @@
<div class="card"> <div class="card" data-pagefind-ignore="all">
<p>Hey there! 👋 Thank you for reading this article!</p> <p>Hey there! 👋 Thank you for reading this article!</p>
<p> <p>
Is there something missing, or do you have an idea on how to improve the documentation? Is there something missing, or do you have an idea on how to improve the documentation?

View file

@ -32,6 +32,25 @@
<!-- Details and License: https://fonts.codeberg.org/fonts/fontawesome5 --> <!-- Details and License: https://fonts.codeberg.org/fonts/fontawesome5 -->
<link rel="stylesheet" type="text/css" href="https://fonts.codeberg.org/dist/fontawesome6/css/svg-with-js.css"> <link rel="stylesheet" type="text/css" href="https://fonts.codeberg.org/dist/fontawesome6/css/svg-with-js.css">
<link href="/pagefind/pagefind-modular-ui.css" rel="stylesheet">
<script src="/pagefind/pagefind-modular-ui.js"></script>
<script>
window.addEventListener('DOMContentLoaded', (event) => {
const instance = new PagefindModularUI.Instance();
instance.add(new PagefindModularUI.Input({
containerElement: "#search-input"
}));
instance.add(new PagefindModularUI.ResultList({
containerElement: "#search-results"
}));
document.addEventListener('keydown', (event) => {
if (event.code == "Slash") {
event.preventDefault();
document.getElementById("search-input").focus();
}
}, false);
});
</script>
{% if page.url != '/' %} {% if page.url != '/' %}
<script> <script>
@ -101,13 +120,14 @@
<div class="sidebar"> <div class="sidebar">
<div class="sidebar-menu"> <div class="sidebar-menu">
{# <!-- Sidebar content with the search box --> <!-- Sidebar content with the search box -->
<div class="sidebar-content"> <div class="sidebar-content">
<input type="text" class="form-control" placeholder="Filter Docs" id="search-input"> <input type="text" class="form-control" placeholder="Filter Docs" id="search-input">
<div class="mt-10 font-size-12"> <div class="mt-10 font-size-12">
Press <kbd>/</kbd> to focus Press <kbd>/</kbd> to focus
</div> </div>
</div> #} <div id="search-results"></div>
</div>
{% for entry in collections.all | eleventyNavigation %} {% for entry in collections.all | eleventyNavigation %}
{% set active = entry.url == page.url or entry.key == eleventyNavigation.parent %} {% set active = entry.url == page.url or entry.key == eleventyNavigation.parent %}
@ -135,19 +155,19 @@
<div class="content-wrapper"> <div class="content-wrapper">
<div class="container-lg"> <div class="container-lg">
<div class="content"> <div class="content" data-pagefind-body>
{% if eleventyNavigation.title %} {% if eleventyNavigation.title %}
<h1 class="content-title font-size-24">{{ eleventyNavigation.title }}</h1> <h1 class="content-title font-size-24">{{ eleventyNavigation.title }}</h1>
{% endif %} {% endif %}
{% if eleventyNavigation.draft %} {% if eleventyNavigation.draft %}
<strong>Please note that this article is still a draft and might not have any contents yet.</strong> <strong data-pagefind-ignore="all">Please note that this article is still a draft and might not have any contents yet.</strong>
{% endif %} {% endif %}
{{ content | safe }} {{ content | safe }}
<hr class="mb-20"> <hr class="mb-20">
{% if page.url != '/' %} {% if page.url != '/' %}
{% include 'contribution_invitation.njk' %} {% include 'contribution_invitation.njk' %}
{% endif %} {% endif %}
<div class="font-size-16 text-right"> <div class="font-size-16 text-right" data-pagefind-ignore="all">
<p>&copy; Codeberg Docs Contributors. See <a href="#modal-1" role="button">LICENSE</a></p> <p>&copy; Codeberg Docs Contributors. See <a href="#modal-1" role="button">LICENSE</a></p>
</div> </div>
</div> </div>

84
package-lock.json generated
View file

@ -12,7 +12,8 @@
"@fortawesome/fontawesome-svg-core": "^6.4.0", "@fortawesome/fontawesome-svg-core": "^6.4.0",
"@fortawesome/free-solid-svg-icons": "^6.4.0", "@fortawesome/free-solid-svg-icons": "^6.4.0",
"@toycode/markdown-it-class": "^1.2.4", "@toycode/markdown-it-class": "^1.2.4",
"markdown-it-anchor": "^8.6.7" "markdown-it-anchor": "^8.6.7",
"pagefind": "^1.0.4"
} }
}, },
"node_modules/@11ty/dependency-tree": { "node_modules/@11ty/dependency-tree": {
@ -282,6 +283,71 @@
"node": ">= 8" "node": ">= 8"
} }
}, },
"node_modules/@pagefind/darwin-arm64": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/@pagefind/darwin-arm64/-/darwin-arm64-1.0.4.tgz",
"integrity": "sha512-2OcthvceX2xhm5XbgOmW+lT45oLuHqCmvFeFtxh1gsuP5cO8vcD8ZH8Laj4pXQFCcK6eAdSShx+Ztx/LsQWZFQ==",
"cpu": [
"arm64"
],
"dev": true,
"optional": true,
"os": [
"darwin"
]
},
"node_modules/@pagefind/darwin-x64": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/@pagefind/darwin-x64/-/darwin-x64-1.0.4.tgz",
"integrity": "sha512-xkdvp0D9Ld/ZKsjo/y1bgfhTEU72ITimd2PMMQtts7jf6JPIOJbsiErCvm37m/qMFuPGEq/8d+fZ4pydOj08HQ==",
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"darwin"
]
},
"node_modules/@pagefind/linux-arm64": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/@pagefind/linux-arm64/-/linux-arm64-1.0.4.tgz",
"integrity": "sha512-jGBrcCzIrMnNxLKVtogaQyajVfTAXM59KlBEwg6vTn8NW4fQ6nuFbbhlG4dTIsaamjEM5e8ZBEAKZfTB/qd9xw==",
"cpu": [
"arm64"
],
"dev": true,
"optional": true,
"os": [
"linux"
]
},
"node_modules/@pagefind/linux-x64": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/@pagefind/linux-x64/-/linux-x64-1.0.4.tgz",
"integrity": "sha512-LIn/QcvcEtLEBqKe5vpSbSC2O3fvqbRCWOTIklslqSORisCsvzsWbP6j+LYxE9q0oWIfkdMoWV1vrE/oCKRxHg==",
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"linux"
]
},
"node_modules/@pagefind/windows-x64": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/@pagefind/windows-x64/-/windows-x64-1.0.4.tgz",
"integrity": "sha512-QlBCVeZfj9fc9sbUgdOz76ZDbeK4xZihOBAFqGuRJeChfM8pnVeH9iqSnXgO3+m9oITugTf7PicyRUFAG76xeQ==",
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"win32"
]
},
"node_modules/@sindresorhus/slugify": { "node_modules/@sindresorhus/slugify": {
"version": "1.1.2", "version": "1.1.2",
"resolved": "https://registry.npmjs.org/@sindresorhus/slugify/-/slugify-1.1.2.tgz", "resolved": "https://registry.npmjs.org/@sindresorhus/slugify/-/slugify-1.1.2.tgz",
@ -1788,6 +1854,22 @@
"wrappy": "1" "wrappy": "1"
} }
}, },
"node_modules/pagefind": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/pagefind/-/pagefind-1.0.4.tgz",
"integrity": "sha512-oRIizYe+zSI2Jw4zcMU0ebDZm27751hRFiSOBLwc1OIYMrsZKk+3m8p9EVaOmc6zZdtqwwdilNUNxXvBeHcP9w==",
"dev": true,
"bin": {
"pagefind": "lib/runner/bin.cjs"
},
"optionalDependencies": {
"@pagefind/darwin-arm64": "1.0.4",
"@pagefind/darwin-x64": "1.0.4",
"@pagefind/linux-arm64": "1.0.4",
"@pagefind/linux-x64": "1.0.4",
"@pagefind/windows-x64": "1.0.4"
}
},
"node_modules/parse-srcset": { "node_modules/parse-srcset": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/parse-srcset/-/parse-srcset-1.0.2.tgz", "resolved": "https://registry.npmjs.org/parse-srcset/-/parse-srcset-1.0.2.tgz",

View file

@ -15,6 +15,7 @@
"@fortawesome/fontawesome-svg-core": "^6.4.0", "@fortawesome/fontawesome-svg-core": "^6.4.0",
"@fortawesome/free-solid-svg-icons": "^6.4.0", "@fortawesome/free-solid-svg-icons": "^6.4.0",
"@toycode/markdown-it-class": "^1.2.4", "@toycode/markdown-it-class": "^1.2.4",
"markdown-it-anchor": "^8.6.7" "markdown-it-anchor": "^8.6.7",
"pagefind": "^1.0.4"
} }
} }

2
pagefind.yml Normal file
View file

@ -0,0 +1,2 @@
site: _site
output_subdir: pagefind