Skip to content

Instantly share code, notes, and snippets.

@davestewart
Last active March 20, 2023 19:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save davestewart/7fbd3396d3b8743f9cfa48f5b83d9cfd to your computer and use it in GitHub Desktop.
Save davestewart/7fbd3396d3b8743f9cfa48f5b83d9cfd to your computer and use it in GitHub Desktop.
Auto indexing for Nuxt 3 Content
// modules/content-indexer.ts
import Fs from 'fs'
import Path from 'path'
import { defineNuxtModule, extendPages, extendRouteRules } from '@nuxt/kit'
import { ModuleOptions, Nuxt } from '@nuxt/schema'
import { MountOptions } from '@nuxt/content'
const name = 'content-indexer'
export default defineNuxtModule({
meta: {
name,
},
setup (options: ModuleOptions, nuxt: Nuxt) {
// config
const { srcDir, debug } = nuxt.options
const config = nuxt.options.content
const sources = config?.sources
// target dirs
const dirs = [
srcDir + '/content',
]
// additional sources
if (sources) {
// helper
const addSource = (source: MountOptions) => {
if (source.driver === 'fs') {
dirs.push(source.base)
}
}
// process
if (typeof sources === 'string') {
dirs.push(sources)
}
else if (Array.isArray(sources)) {
sources.forEach(source => {
if (typeof source === 'string') {
dirs.push(source)
}
else {
addSource(source)
}
})
}
else {
Object.keys(sources).forEach((key: string) => {
addSource(sources[key])
})
}
}
// process dirs
const logs: { route: string, redirect: string }[] = []
for (const dir of dirs) {
if (Fs.existsSync(dir)) {
const paths = walk(dir)
paths.forEach(absPath => {
const redirect = absPath.substring(dir.length)
const route = redirect.replace(/\/[^/]+$/, '')
if (route !== '') {
// debug
logs.push({ route, redirect })
// redirect on server
extendRouteRules(route, { redirect })
// redirect on client
extendPages(pages => {
pages.push({
file: '', // for Nuxt < v3.3.1
path: route,
redirect
})
})
}
})
}
}
// log
if (debug) {
const max: number = Math.max(...logs.map(log => log.route.length))
const output = logs.map(({ route, redirect }) => {
return `[${name}] ${route + ' '.repeat(max - route.length)} -> ${redirect}`
})
console.log(output.join('\n'))
}
},
})
function walk (folder: string, paths: string[] = []) {
// variables
const entries = Fs.readdirSync(folder)
let index
let first
// walk children
for (let entry of entries) {
const path = Path.join(folder, entry)
if (Fs.statSync(path).isDirectory()) {
walk(path, paths)
}
else if (/\.mdx?$/.test(entry)) {
if (!first) {
first = path
}
if (/^(\d+\.)?index\.mdx?$/.test(entry)) {
index = path
}
}
}
if (!index && first) {
paths.push(first.replace(/\d+\.|\.mdx?$/g, ''))
}
return paths
}
[content-indexer] redirect: /blog/productivity -> /blog/productivity/less-tabs
[content-indexer] redirect: /help/getting-started -> /help/getting-started/intro
[content-indexer] redirect: /help/interface -> /help/interface/history
[content-indexer] redirect: /help/open-tabs -> /help/open-tabs/display
[content-indexer] redirect: /help/closed-tabs -> /help/closed-tabs/history
[content-indexer] redirect: /help/tools -> /help/tools/data
[content-indexer] redirect: /help/customisation -> /help/customisation/personalisation
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment