Searching for a text in markdown
Hi, I am not seeing this in the docs, or maybe its not apparent to me.
Is it possible to search for a text anywhere if I had markdown files?
Say I have a bunch of markdown .md files in my content dir, and I would like to present a separate page to search anywhere in these md files?
In my case:
- user would search by search term
- that searches anywhere in
.mdfiles incontentdirectory - I preset user the list of page titles and a little excerpt from the page where match was found
Questions:
- if this is presently achievable, and if yes, how?
- inf not, if its possible to put it on a feature request list?
I am looking at the queries, I guess there is body with all of its children but that is likely hard to search.
A workaround would be to provide a custom field in .md files
---
bodyPlainText: ... // copy of all the text without markdown in the md document
---
And then use query content:
const articles = await queryContent()
.where({ bodyPlainText: { $contains: ['my search text'] } })
.find()
but bodyPlainText and its value would need to be built programmatically.
(this is obviously naive approach, lots of things to consider like ordering best results etc.)
Supporting full-text search is not planned yet. To generate bodyPlainText for contents you can use transformers.
@farnabaz yeah, I figured so. Depending on the requirement it could be searched also by traversing trees like so:
// getting all the articles - I guess this approach would be very computational intensive if there is a large amount
// of content to be searched on the client side and not using something like Algolia
// In the below code example, all results are aggregated per `_path` (so per page).
// But could be easily modified to a different strategy
// The search match is wrapped inside the <strong> tag so it could be highlighted (needs to be interpolated with `v-html`)
// Handy lib for traversing trees
import { visit } from 'unist-util-visit'
const articles = await queryContent().find()
const searchResults = ref([])
const getSearchResults = (searchTerm: string) => {
searchResults.value = []
const searchTermLowerCase = searchTerm.toLocaleLowerCase()
articles.forEach((article: ParsedContent) => {
visit(article.body, 'text', (node) => {
if (node.value.toLocaleLowerCase().includes(searchTermLowerCase)) {
const existingPageResult = searchResults.value.find(
(result) => result.path === article._path
)
const searchResult = node.value.replaceAll(
new RegExp(searchTermLowerCase, 'gi'),
(match) => `<strong>${match}</strong>`
)
if (existingPageResult) {
existingPageResult.searchResult += `<br />${searchResult }`
} else {
searchResults.value.push({
title: article.title,
searchResult
})
}
}
})
})
}