packer-cn/website/scripts/index_search_content.js

96 lines
4.0 KiB
JavaScript

require('dotenv').config()
const fs = require('fs')
const path = require('path')
const {
indexContent,
getDocsSearchObject,
} = require('@hashicorp/react-search/tools')
const resolveNavData = require('../components/remote-plugin-docs/utils/resolve-nav-data')
// Run indexing
indexContent({ getSearchObjects })
async function getSearchObjects() {
// Resolve /docs, /guides, and /intro nav data, which
// corresponds to all the content we will actually render
// This avoids indexing non-rendered content, and partials.
// Fetch objects for `docs` content
async function fetchDocsObjects() {
const navFile = 'data/docs-nav-data.json'
const contentDir = 'content/docs'
const opts = { remotePluginsFile: 'data/docs-remote-plugins.json' }
const navData = await resolveNavData(navFile, contentDir, opts)
return await searchObjectsFromNavData(navData, 'docs')
}
// Fetch objects for `guides` content
async function fetchGuidesObjects() {
const navFile = 'data/guides-nav-data.json'
const contentDir = 'content/guides'
const navData = await resolveNavData(navFile, contentDir)
return await searchObjectsFromNavData(navData, 'guides')
}
// Fetch objects for `intro` content
async function fetchIntroObjects() {
const navFile = 'data/intro-nav-data.json'
const contentDir = 'content/intro'
const navData = await resolveNavData(navFile, contentDir)
return await searchObjectsFromNavData(navData, 'intro')
}
// Collect, flatten and return the collected search objects
const searchObjects = (
await Promise.all([
fetchDocsObjects(),
fetchGuidesObjects(),
fetchIntroObjects(),
])
).reduce((acc, array) => acc.concat(array), [])
return searchObjects
}
/**
* Given navData, return a flat array of search objects
* for each content file referenced in the navData nodes
* @param {Object[]} navData - an array of nav-data nodes, as detailed in [mktg-032](https://docs.google.com/document/d/1kYvbyd6njHFSscoE1dtDNHQ3U8IzaMdcjOS0jg87rHg)
* @param {string} baseRoute - the base route where the navData will be rendered. For example, "docs".
* @returns {Object[]} - an array of searchObjects to pass to Algolia. Must include an objectID property. See https://www.algolia.com/doc/api-reference/api-methods/add-objects/?client=javascript#examples.
*/
async function searchObjectsFromNavData(navData, baseRoute = '') {
const searchObjectsFromNodes = await Promise.all(
navData.map((n) => searchObjectsFromNavNode(n, baseRoute))
)
const flattenedSearchObjects = searchObjectsFromNodes.reduce(
(acc, searchObjects) => acc.concat(searchObjects),
[]
)
return flattenedSearchObjects
}
/**
* Given a single navData node, return a flat array of search objects.
* For "leaf" nodes, this will yield an array with a single object.
* For "branch" nodes, this may yield an array with zero or more search objects.
* For all other nodes, this will yield an empty array.
* @param {object} node - a nav-data nodes, as detailed in [mktg-032](https://docs.google.com/document/d/1kYvbyd6njHFSscoE1dtDNHQ3U8IzaMdcjOS0jg87rHg)
* @param {string} baseRoute - the base route where the navData will be rendered. For example, "docs".
* @returns {Object[]} - an array of searchObjects to pass to Algolia. Must include an objectID property. See https://www.algolia.com/doc/api-reference/api-methods/add-objects/?client=javascript#examples.
*/
async function searchObjectsFromNavNode(node, baseRoute) {
// If this is a node, build a search object
if (node.path) {
// Fetch the MDX file content
const fileString = node.filePath
? fs.readFileSync(path.join(process.cwd(), node.filePath), 'utf8')
: node.remoteFile.fileString
const searchObject = await getDocsSearchObject(
path.join(baseRoute, node.path),
fileString
)
return searchObject
}
// If this is a branch, recurse
if (node.routes) return await searchObjectsFromNavData(node.routes, baseRoute)
// Otherwise, return an empty array
// (for direct link nodes, divider nodes)
return []
}