eleventy-plugin-search
v0.0.2
Published
HTML-first Eleventy search plugin with Fuse.js and Cheerio
Downloads
205
Maintainers
Readme
eleventy-plugin-search
Early Development Notice: This plugin is under active development. The API may change before reaching v1.0.0. Please report issues and feedback on GitHub.
HTML-first Eleventy search plugin with Fuse.js and Cheerio. Processes final rendered HTML files after templates for accurate search indexing.
Features
- HTML-first processing: Works with final rendered HTML, not source files
- Accurate content extraction: Uses Cheerio for fast, reliable HTML parsing
- Automatic heading IDs: Generates URL-safe anchor IDs for headings without them
- Fuse.js integration: Creates search indexes optimized for client-side fuzzy search
- Configurable exclusions: Remove nav, header, footer, and other elements from indexing
- Debug support: Enable detailed logging with
DEBUG=Eleventy:search
Installation
npm install eleventy-plugin-searchUsage
Add the plugin to your Eleventy configuration:
// eleventy.config.js
import searchPlugin from 'eleventy-plugin-search';
export default function (eleventyConfig) {
eleventyConfig.addPlugin(searchPlugin, {
// Options (all optional)
indexPath: 'search-index.json',
excludeSelectors: ['nav', 'header', 'footer']
});
}The plugin runs after Eleventy builds your site and creates a search-index.json file in your output directory.
Options
| Option | Type | Default | Description |
| ------------------ | -------------------- | ----------------------------- | ----------------------------------------- |
| pattern | string | '**/*.html' | Glob pattern for HTML files to process |
| ignore | string \| string[] | ['**/search-index.json'] | Files to exclude from indexing |
| indexPath | string | 'search-index.json' | Output path for the search index |
| excludeSelectors | string[] | ['nav', 'header', 'footer'] | CSS selectors to remove before extraction |
| maxContentLength | number | 10000 | Maximum characters of content to index |
| fuseOptions | object | See below | Fuse.js configuration |
Default Fuse.js Options
{
keys: [
{ name: 'title', weight: 10 },
{ name: 'content', weight: 5 },
{ name: 'excerpt', weight: 3 }
],
threshold: 0.3,
includeScore: true,
includeMatches: true,
minMatchCharLength: 3
}Search Index Structure
The generated search-index.json contains:
{
"version": "1.0.0",
"generator": "eleventy-plugin-search",
"generated": "2025-01-22T...",
"totalEntries": 10,
"config": {
"fuseOptions": { /* Fuse.js config for client reconstruction */ }
},
"stats": {
"totalEntries": 10,
"entriesByType": { "page": 10 },
"averageContentLength": 2048,
"totalContentLength": 20480
},
"entries": [
{
"id": "page:/about",
"type": "page",
"url": "/about",
"title": "About Us",
"content": "Full page text content...",
"excerpt": "First 250 characters...",
"headings": [
{ "level": "h2", "id": "our-mission", "title": "Our Mission" },
{ "level": "h2", "id": "our-team", "title": "Our Team" }
],
"wordCount": 523
}
]
}Client-Side Search Example
import Fuse from 'fuse.js';
// Fetch the search index
const response = await fetch('/search-index.json');
const searchIndex = await response.json();
// Initialize Fuse.js with the index config
const fuse = new Fuse(searchIndex.entries, searchIndex.config.fuseOptions);
// Perform a search
const results = fuse.search('your search query');
// Results include score and matches
results.forEach((result) => {
console.log(result.item.title, result.score);
// Use headings for scroll-to functionality
result.item.headings.forEach((heading) => {
console.log(` ${heading.level}: ${heading.title} (#${heading.id})`);
});
});URL Generation
The plugin generates clean URLs from file paths:
index.html→/about/index.html→/aboutblog/first-post.html→/blog/first-post
Heading ID Generation
For headings without id attributes, the plugin generates URL-safe IDs:
- "Hello World" →
hello-world - "Chapter 1: Introduction" →
chapter-1-introduction - Duplicate headings get numeric suffixes:
section,section-1,section-2
Debugging
Enable debug output to see what the plugin is doing:
DEBUG=Eleventy:search npx @11ty/eleventyCode Quality
- ESLint: Enforces code quality rules including
prefer-const,no-var, strict equality, and complexity limits - Prettier: Ensures consistent code formatting (single quotes, no trailing commas, 100 char line width)
Run npm run prerelease before committing to ensure your code passes all checks.
Test Coverage
This plugin is tested using mocha with c8 for code coverage. Current coverage: 97%.
Requirements
- Node.js >= 20.0.0
- Eleventy >= 2.0.0
License
MIT
Development Transparency
Portions of this project were developed with the assistance of AI tools including Claude and Claude Code. These tools were used to:
- Generate or refactor code
- Assist with documentation
- Troubleshoot bugs and explore alternative approaches
All AI-assisted code has been reviewed and tested to ensure it meets project standards. See the included CLAUDE.md file for more details.
