Fix several search-related issues
* CSS on mobile * Remove stale partial indices * Fix broken hit links * Leverage @hashicorp/react-search/tools
This commit is contained in:
parent
db91bfd676
commit
97e4f376fc
|
@ -13,7 +13,16 @@ export default function SearchBar() {
|
|||
</span>
|
||||
</>
|
||||
)}
|
||||
resolveHitLink={(hit) => ({
|
||||
href: {
|
||||
pathname: `/${transformIdtoUrl(hit.objectID)}`,
|
||||
},
|
||||
})}
|
||||
placeholder="Search Nomad documentation"
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function transformIdtoUrl(id) {
|
||||
return id.replace(/\/index$/, '')
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
.g-search {
|
||||
width: calc(100% - 2rem);
|
||||
max-width: 600px;
|
||||
margin-left: 0 !important;
|
||||
|
||||
& .c-hits .ais-Highlight-highlighted {
|
||||
background-color: #c1f1e0;
|
||||
|
|
|
@ -1731,14 +1731,20 @@
|
|||
}
|
||||
},
|
||||
"@hashicorp/react-search": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@hashicorp/react-search/-/react-search-1.0.0.tgz",
|
||||
"integrity": "sha512-qkeQJPVskifQuVk1Dw4Jf6VQGBV7tYqL92CdEh46CP2rsxe0yxEr5tx9pk48UytMRIr6DmdX7l0d7kfPgpACkA==",
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@hashicorp/react-search/-/react-search-2.1.0.tgz",
|
||||
"integrity": "sha512-vaTht+2G9ipsVyusK3b3TtUpuy9ccsxj3NMSWXJyGsoT39K1Oovb8aLiIlbUU5Ll72KEi5yq5OS3WAJDdSqW+g==",
|
||||
"requires": {
|
||||
"@hashicorp/react-inline-svg": "^1.0.2",
|
||||
"@hashicorp/remark-plugins": "^3.0.0",
|
||||
"algoliasearch": "^4.4.0",
|
||||
"dotenv": "^8.2.0",
|
||||
"glob": "^7.1.6",
|
||||
"gray-matter": "^4.0.2",
|
||||
"react-instantsearch-dom": "^6.7.0",
|
||||
"search-insights": "^1.6.0"
|
||||
"remark": "^12.0.1",
|
||||
"search-insights": "^1.6.0",
|
||||
"unist-util-visit": "^2.0.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"@hashicorp/react-inline-svg": {
|
||||
|
@ -13728,9 +13734,9 @@
|
|||
}
|
||||
},
|
||||
"search-insights": {
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/search-insights/-/search-insights-1.6.0.tgz",
|
||||
"integrity": "sha512-JBbu9WDL72gSgjFTaCeHntsXiOk+E0N1h6WLlWlWnjb1p/fLzza1wFx4hh1t1DrweEGfrU29+3J5ORkcHMI7Kg=="
|
||||
"version": "1.6.2",
|
||||
"resolved": "https://registry.npmjs.org/search-insights/-/search-insights-1.6.2.tgz",
|
||||
"integrity": "sha512-mpy+57HZVMZH5HsMHYMCLvkf+tUvhy+ycP2tDy1j7wmj+mQsNZ3LC61IcMYomok02NozaMR3GiGyfH6uc+ibdA=="
|
||||
},
|
||||
"section-matter": {
|
||||
"version": "1.0.0",
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
"@hashicorp/react-inline-svg": "1.0.0",
|
||||
"@hashicorp/react-mega-nav": "4.0.1-2",
|
||||
"@hashicorp/react-product-downloader": "4.0.2",
|
||||
"@hashicorp/react-search": "^1.0.0",
|
||||
"@hashicorp/react-search": "^2.1.0",
|
||||
"@hashicorp/react-section-header": "2.0.0",
|
||||
"@hashicorp/react-subnav": "3.2.3",
|
||||
"@hashicorp/react-text-and-content": "4.1.1",
|
||||
|
@ -28,11 +28,8 @@
|
|||
"@hashicorp/react-text-split-with-image": "1.3.1",
|
||||
"@hashicorp/react-use-cases": "1.0.4",
|
||||
"@hashicorp/react-vertical-text-block-list": "2.0.1",
|
||||
"algoliasearch": "^4.4.0",
|
||||
"babel-plugin-import-glob-array": "0.2.0",
|
||||
"dotenv": "^8.2.0",
|
||||
"glob": "^7.1.6",
|
||||
"gray-matter": "^4.0.2",
|
||||
"imagemin-mozjpeg": "9.0.0",
|
||||
"imagemin-optipng": "8.0.0",
|
||||
"imagemin-svgo": "8.0.0",
|
||||
|
@ -41,9 +38,7 @@
|
|||
"nuka-carousel": "4.7.0",
|
||||
"react": "16.13.1",
|
||||
"react-device-detect": "1.13.1",
|
||||
"react-dom": "16.13.1",
|
||||
"remark": "^12.0.0",
|
||||
"unist-util-visit": "^2.0.3"
|
||||
"react-dom": "16.13.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"dart-linkcheck": "2.0.15",
|
||||
|
|
|
@ -1,125 +1,3 @@
|
|||
require('dotenv').config()
|
||||
const { indexDocsContent } = require('@hashicorp/react-search/tools')
|
||||
|
||||
const algoliasearch = require('algoliasearch')
|
||||
const glob = require('glob')
|
||||
const matter = require('gray-matter')
|
||||
const path = require('path')
|
||||
const remark = require('remark')
|
||||
const visit = require('unist-util-visit')
|
||||
|
||||
// In addition to the content of the page,
|
||||
// define additional front matter attributes that will be search-indexable
|
||||
const SEARCH_DIMENSIONS = ['page_title', 'description']
|
||||
|
||||
main()
|
||||
|
||||
async function main() {
|
||||
const pagesFolder = path.join(__dirname, '../pages')
|
||||
|
||||
// Grab all search-indexable content and format for Algolia
|
||||
const searchObjects = await Promise.all(
|
||||
glob.sync(path.join(pagesFolder, '**/*.mdx')).map(async (fullPath) => {
|
||||
const { content, data } = matter.read(fullPath)
|
||||
|
||||
const searchableDimensions = SEARCH_DIMENSIONS.reduce(
|
||||
(acc, dimension) => {
|
||||
return { ...acc, [dimension]: data[dimension] }
|
||||
},
|
||||
{}
|
||||
)
|
||||
|
||||
const headings = await collectHeadings(content)
|
||||
|
||||
// Get path relative to `pages`
|
||||
const __resourcePath = fullPath.replace(`${pagesFolder}/`, '')
|
||||
|
||||
// Use clean URL for Algolia id
|
||||
const objectID = __resourcePath.replace('.mdx', '')
|
||||
|
||||
return {
|
||||
...searchableDimensions,
|
||||
headings,
|
||||
objectID,
|
||||
}
|
||||
})
|
||||
)
|
||||
|
||||
try {
|
||||
await indexSearchContent(searchObjects)
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
process.exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
async function indexSearchContent(objects) {
|
||||
const {
|
||||
NEXT_PUBLIC_ALGOLIA_APP_ID: appId,
|
||||
NEXT_PUBLIC_ALGOLIA_INDEX: index,
|
||||
ALGOLIA_API_KEY: apiKey,
|
||||
} = process.env
|
||||
|
||||
if (!apiKey || !appId || !index) {
|
||||
throw new Error(
|
||||
`[*** Algolia Search Indexing Error ***] Received: ALGOLIA_API_KEY=${apiKey} ALGOLIA_APP_ID=${appId} ALGOLIA_INDEX=${index} \n Please ensure all Algolia Search-related environment vars are set in CI settings.`
|
||||
)
|
||||
}
|
||||
|
||||
console.log(`updating ${objects.length} indices...`)
|
||||
|
||||
try {
|
||||
const searchClient = algoliasearch(appId, apiKey)
|
||||
const searchIndex = searchClient.initIndex(index)
|
||||
|
||||
const { objectIDs } = await searchIndex.partialUpdateObjects(objects, {
|
||||
createIfNotExists: true,
|
||||
})
|
||||
|
||||
let staleIds = []
|
||||
|
||||
await searchIndex.browseObjects({
|
||||
query: '',
|
||||
batch: (batch) => {
|
||||
staleIds = staleIds.concat(
|
||||
batch
|
||||
.filter(({ objectID }) => !objectIDs.includes(objectID))
|
||||
.map(({ objectID }) => objectID)
|
||||
)
|
||||
},
|
||||
})
|
||||
|
||||
if (staleIds.length > 0) {
|
||||
console.log(`deleting ${staleIds.length} stale indices:`)
|
||||
console.log(staleIds)
|
||||
|
||||
await searchIndex.deleteObjects(staleIds)
|
||||
}
|
||||
|
||||
console.log('done')
|
||||
process.exit(0)
|
||||
} catch (error) {
|
||||
throw new Error(error)
|
||||
}
|
||||
}
|
||||
|
||||
async function collectHeadings(mdxContent) {
|
||||
const headings = []
|
||||
|
||||
const headingMapper = () => (tree) => {
|
||||
visit(tree, 'heading', (node) => {
|
||||
const title = node.children.reduce((m, n) => {
|
||||
if (n.value) m += n.value
|
||||
return m
|
||||
}, '')
|
||||
// Only include level 1 or level 2 headings
|
||||
if (node.depth < 3) {
|
||||
headings.push(title)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return remark()
|
||||
.use(headingMapper)
|
||||
.process(mdxContent)
|
||||
.then(() => headings)
|
||||
}
|
||||
indexDocsContent()
|
||||
|
|
Loading…
Reference in New Issue