Lunr integration for Astro; client-side search for statically hosted pages.
| 0 | import fs from 'node:fs'; | ||
| 1 | import path from 'node:path'; | ||
| ... | |||
| 54 | } | ||
| 55 | |||
| 56 | + | ||
| 57 | + | export function createVitePlugin({ config }) { | |
| 58 | + | return { | |
| 59 | + | name: 'astro-lunr:dev-server', | |
| 60 | + | configureServer(viteServer) { | |
| 61 | + | viteServer.middlewares.use((req, res, next) => { | |
| 62 | + | if(req.url.endsWith("/idx.json") || req.url.endsWith("/docs.json")){ | |
| 63 | + | let path = req.url.slice(1); | |
| 64 | + | if(config.base && config.base != "./"){ | |
| 65 | + | let base = config.base.startsWith("./") ? config.base.slice(2) : config.base; | |
| 66 | + | path = path.replace(base, "./"); | |
| 67 | + | } | |
| 68 | + | let preBuiltPath = new URL(path, config.outDir); | |
| 69 | + | try { | |
| 70 | + | var stat = fs.statSync(preBuiltPath); | |
| 71 | + | } catch(err){ | |
| 72 | + | err.message = "Could not find pre-built lunr-files - search is not available without first building your astro-pages at least once. " + err.toString(); | |
| 73 | + | throw err; | |
| 74 | + | } | |
| 75 | + | res.writeHead(200, { | |
| 76 | + | 'Content-Type': 'application/json', | |
| 77 | + | 'Content-Length': stat.size | |
| 78 | + | }); | |
| 79 | + | return fs.createReadStream(preBuiltPath).pipe(res); | |
| 80 | + | } | |
| 81 | + | return next(); | |
| 82 | + | }); | |
| 83 | + | }, | |
| 84 | + | }; | |
| 85 | + | } | |
| 86 | + | ||
| 87 | + | function getViteConfiguration(config) { | |
| 88 | + | return { | |
| 89 | + | plugins: [createVitePlugin(config)] | |
| 90 | + | }; | |
| 91 | + | } | |
| 92 | + | ||
| 93 | + | ||
| 94 | export default function createPlugin({pathFilter, subDir, documentFilter, initialize, mapDocument, verbose}){ | ||
| 95 | let config = {}; | ||
| ... | |||
| 104 | serverEntrypoint: 'astro-lunr/server/renderer.js', | ||
| 105 | }); | ||
| 106 | + | options.updateConfig({ vite: getViteConfiguration(options) }); | |
| 107 | } | ||
| 108 | }, | ||
| ... | |||
| 156 | } | ||
| 157 | } |
| 0 | |||
| 1 | |||
| ... | |||
| 100 | ### Searching in Dev-mode | ||
| 101 | |||
| 102 | - | Due to the nature of indexing, to properly search in dev-mode, one needs to first build the page at least once to create the index | |
| 103 | + | Due to the nature of indexing, to properly search in dev-mode, one needs to first build the pages at least once to create the index | |
| 104 | |||
| 105 | - | Furthermore, to make the dev-server accept the index-files, you might need to symbolically link the index-files from the public-folder. These should be included in `.gitignore` or equivalent. | |
| 106 | - | ||
| 107 | - | Example of how this is done automatically for `astro-git-view`: | |
| 108 | - | ||
| 109 | - | ```json | |
| 110 | - | "scripts": { | |
| 111 | - | "dev": "(ln -s ../dist/lunr ./public/lunr 2> /dev/null || true) && astro dev", | |
| 112 | - | "start": "(ln -s ../dist/lunr ./public/lunr 2> /dev/null || true) && astro dev", | |
| 113 | - | "build": "(rm ./public/lunr 2> /dev/null || true) && astro build", | |
| 114 | - | "preview": "astro preview" | |
| 115 | - | }, | |
| 116 | - | ``` | |
| 117 | - | ||
| 118 | - | A potential future solution would be to "trick" the dev-server into serving certain files from `./dist` without the end-user needing to think, or by writing the files to both dist and public. | |
| 119 | - | ||
| 120 | ### Searching in SSR-mode | ||
| 121 | |||
| 122 | To properly search files that are not usually genereated in the build-step, you would need to have a separate build-step that includes all pages that might be generated. | ||
| 123 |