@@ -11,10 +11,10 @@ This is the Jekyll-based source for the official Ruby programming language websi
1111### Jekyll Site Operations
1212
1313``` bash
14- # Build the site (takes several minutes)
14+ # Build the site and its search index (takes several minutes)
1515bundle exec rake build
1616
17- # Serve locally at http://localhost:4000/
17+ # Build, watch and serve at http://localhost:4000/, search index included
1818bundle exec rake serve
1919
2020# Alternative: Jekyll direct serve with incremental builds
@@ -40,6 +40,7 @@ bundle exec rake test
4040# Run individual test suites
4141bundle exec rake test-news-plugin # News archive plugin tests
4242bundle exec rake test-linter # Linter library tests
43+ bundle exec rake test-search-index # Search index library tests
4344
4445# Linting
4546bundle exec rake lint # Markdown linter
@@ -109,6 +110,31 @@ The news system is powered by a custom Jekyll plugin (`_plugins/news.rb`):
109110- ** Archive pages** : Index, yearly archives, monthly archives
110111- ** RSS feeds** : Generated per language via ` news_feed.rss ` layout
111112
113+ ### Search (Pagefind)
114+
115+ Search is client-side and needs no backend. ` _plugins/search_index.rb ` hooks
116+ Jekyll's ` post_write ` and calls ` lib/search_index.rb ` , so every build and every
117+ regeneration under ` rake serve ` ends with a matching index. It has to run after
118+ the write because Pagefind reads the generated HTML, and it has to run every
119+ time because Jekyll deletes destination files with no source counterpart, the
120+ previous bundle included. Without Node installed the hook warns and skips.
121+
122+ - ** Indexed region** : ` _includes/search_body.html ` emits ` data-pagefind-body ` on
123+ the ` <article> ` of ` page.html ` and ` news_post.html ` . Everything outside it, and
124+ anything marked ` data-pagefind-ignore ` inside it, stays out of results.
125+ - ** Per-language indexes** : Pagefind splits the index by the ` lang ` attribute on
126+ ` <html> ` and the browser loads the one matching the page, so a translation only
127+ ever finds its own pages. The same attribute picks the interface language, so
128+ no UI strings live in ` _data/locales ` .
129+ - ** Unsupported languages** : ` search.unsupported ` in ` _config.yml ` lists the
130+ languages Pagefind cannot index well (currently ` bg ` ). Their pages get no
131+ ` data-pagefind-body ` , and ` lib/search_index.rb ` rewrites ` pagefind-entry.json `
132+ so they resolve to ` search.fallback ` . Without that rewrite Pagefind would fall
133+ back to whichever index has the most pages, which is not a language we choose.
134+ - ** UI** : ` _includes/search.html ` (button, modal, config) and
135+ ` _includes/search_assets.html ` (bundle, loaded before ` compiled.css ` so the
136+ site's ` --pf-* ` overrides win).
137+
112138### Linter (` lib/linter.rb ` )
113139
114140Enforces strict content quality rules:
@@ -178,6 +204,7 @@ lang: en
178204** Node (package.json):**
179205- ` tailwindcss ` - CSS framework
180206- ` @tailwindcss/typography ` - Prose styling plugin
207+ - ` pagefind ` - Static search index and UI
181208
182209## Important Conventions
183210
0 commit comments