Skip to content

Commit

Permalink
config.js: Use internal VitePress path parsing
Browse files Browse the repository at this point in the history
Two Dovecot-specific documentation features need access to the list of
pages, and their mapping rewrite paths (files to URL path).

We previously created our system to handle this, but this is already done
internally by VitePress, so take advantage of that.

This does require one change to delay dovecot link parsing, for
bootstrapping reasons (the page/mapping list only becomes available after
the defineConfig() call is completed in .vitepress/config.js).
  • Loading branch information
slusarz authored and cmouse committed Oct 24, 2024
1 parent b719f8e commit 9af60ce
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 107 deletions.
19 changes: 6 additions & 13 deletions .vitepress/config.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,12 @@
import gitCommitInfo from 'git-commit-info'
import path from 'path'
import { defineConfig } from 'vitepress'
import { pagefindPlugin } from 'vitepress-plugin-pagefind'
import { generateSidebar } from 'vitepress-sidebar'
import { dovecotMdExtend, initDovecotMd } from '../lib/markdown.js'
import { frontmatterIter } from '../lib/utility.js'
import { getExcludes } from '../lib/utility.js'

const base = '/2.4'

// No need to include the "dummy" index files, used to build titles
// for the sidebar, into the final documentation bundles
const excludes = []
await frontmatterIter(function (f, data) {
if (data.exclude) {
excludes.push(path.relative('docs/', f))
}
})

// Need to bootstrap configuration for Dovecot markdown driver (specifically,
// loading all data files to allow existence checking), or else the markdown
// processing will begin before Dovecot link markup is enabled
Expand All @@ -27,8 +17,11 @@ export default defineConfig({
description: "Dovecot CE Documentation",
lang: "en-us",

srcDir: "docs",
srcExclude: excludes,
srcDir: ".",
srcExclude: [ '*.md' ].concat(getExcludes()),
rewrites: {
'docs/:path(.*)': ':path',
},

base: base,
sitemap: {
Expand Down
16 changes: 0 additions & 16 deletions .vitepress/local.js.dist
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,6 @@ export const data_paths = {
// doveadm: '../data/doveadm.js',
}

// A listing of source files (.md) for the documentation.
// Paths are relative to project base.
//
// Supports fast-glob: https://github.com/mrmlnc/fast-glob#pattern-syntax
//
// Default: [ 'docs/**/*.md' ]
export const source_paths = []

// A listing of files to watch to refresh data loaders in dev mode.
// See: https://vitepress.dev/guide/data-loading#data-from-local-files
// Paths are relative to project base.
Expand All @@ -30,14 +22,6 @@ export const source_paths = []
// Default: [ 'docs/**/*.md', 'docs/**/*.inc', 'data/**/*' ]
export const watch_paths = []

// A listing of source path translations.
//
// This is the same format as VitePress' 'rewrite' setting:
// https://vitepress.dev/reference/site-config#rewrites
//
// Default: { 'docs/:path(.*)': ':path' }
export const source_path_translations = {}

// A listing of paths containing man files.
// Paths are relative to project base.
//
Expand Down
42 changes: 40 additions & 2 deletions lib/markdown.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import fg from 'fast-glob'
import deflistPlugin from 'markdown-it-deflist'
import path from 'path'
import { createMarkdownRenderer } from 'vitepress'
import { loadData, loadDovecotLinks, manFiles, markdownExtension, pluginFiles, resolveURL } from './utility.js'
import { frontmatterIter, loadData, manFiles, markdownExtension, pluginFiles, resolveURL } from './utility.js'

let md_conf = null
export async function initDovecotMd(base) {
Expand All @@ -15,8 +15,8 @@ export async function initDovecotMd(base) {
...{
base: base,
doveadm: (await loadData('doveadm')).doveadm,
dovecotlinks: await loadDovecotLinks(base),
events: (await loadData('events')).events,
linkoverrides: (await loadData('links_overrides')).links_overrides,
man: (await manFiles()).flatMap((x) => {
return fg.sync(x).map((y) => {
const str = path.basename(y)
Expand Down Expand Up @@ -202,6 +202,8 @@ function dovecot_markdown(md, opts) {
let url = '#'
env.inner = false

initDovecotLinks()

if (!opts.dovecotlinks[parts[1]]) {
handle_error('Dovecot link missing: ' + parts[1])
return '<a>'
Expand Down Expand Up @@ -388,6 +390,42 @@ function dovecot_markdown(md, opts) {
console.error(msg)
}

function initDovecotLinks() {
if (opts.dovecotlinks) {
return
}

const links = {}
const rewrites = globalThis.VITEPRESS_CONFIG.rewrites.map

frontmatterIter(Object.keys(rewrites), function (f, data) {
if (!data.dovecotlinks) {
return
}

for (const [k, v] of Object.entries(data.dovecotlinks)) {
if (links[k]) {
throw new Error("Duplicate Dovecot Link key: " + k)
}

links[k] = {
url: resolveURL(rewrites[f].substring(0, rewrites[f].lastIndexOf('.')) + '.html', opts.base)
}

if ((typeof v) == 'object') {
links[k].text = v.text
if (v.hash) {
links[k].url += '#' + v.hash
}
} else {
links[k].text = v
}
}
})

opts.dovecotlinks = { ...links, ...opts.linkoverrides }
}

md.inline.ruler.after('emphasis', 'dovecot_brackets', process_brackets)
md.renderer.rules.dovecot_open = dovecot_open
md.renderer.rules.dovecot_body = dovecot_body
Expand Down
87 changes: 22 additions & 65 deletions lib/utility.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@
import fg from 'fast-glob'
import fs from 'fs'
import matter from 'gray-matter'
import { dirname } from 'path';
import { compile, match } from 'path-to-regexp'
import { fileURLToPath } from 'url';
import { dirname } from 'path'
import { fileURLToPath } from 'url'

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
Expand Down Expand Up @@ -67,13 +66,6 @@ export async function loadData(id) {
}
}

export async function sourceFiles() {
/* Check for config override file. */
const lconf = await loadLocalConf()

return lconf?.source_paths ?? [ 'docs/**/*.md' ]
}

export async function watchFiles() {
/* Check for config override file. */
const lconf = await loadLocalConf()
Expand Down Expand Up @@ -104,68 +96,33 @@ export async function pluginFiles() {
[ 'docs/core/plugins/*.md' ]
}

export async function frontmatterIter(callback) {
const sf = await sourceFiles()
const files = sf.flatMap((x) => fg.sync(x))

/* Check for config override file. */
const lconf = await loadLocalConf()
const spt_conf = lconf?.source_path_translations ??
{ 'docs/:path': ':path' }

const spt = Object.entries(spt_conf).map(([from, to]) => ({
toPath: compile(`/${to}`, { validate: false }),
matchUrl: match(from)
}))
export function getExcludes(srcDirs = [ 'docs' ]) {
const excludes = []

for (let f of files) {
const str = fs.readFileSync(f, 'utf8')
const data = matter(str).data

for (const { matchUrl, toPath } of spt) {
const res = matchUrl(f)
if (res) {
f = toPath(res.params).slice(1)
break
frontmatterIter(
srcDirs.flatMap((x) => fg.sync(x + '/**/*.md')),
function (f, data) {
/* Exclude all pages with "exclude" frontmatter present. */
if (data.exclude) {
excludes.push(f)
}
}
)

callback(f, data)
}
return excludes
}

export async function loadDovecotLinks(base) {
const links = {}

await frontmatterIter(function (f, data) {
if (!data.dovecotlinks) {
return
}

for (const [k,v] of Object.entries(data.dovecotlinks)) {
if (links[k]) {
throw new Error("Duplicate Dovecot Link key: " + k)
}

links[k] = {
url: resolveURL(f.substring(0, f.lastIndexOf('.')) + '.html', base)
}

if ((typeof v) == 'object') {
links[k].text = v.text
if (v.hash) {
links[k].url += '#' + v.hash
}
} else {
links[k].text = v
}
export function frontmatterIter(files, callback) {
for (let f of files) {
try {
const str = fs.readFileSync(f, 'utf8')
callback(f, matter(str).data)
} catch (err) {
/* Ignore file not exist errors, since they can occur for
* dynamically generated paths (e.g. Release Notes). */
if (err.code !== 'ENOENT') throw err
}
})

const data = await loadData('links_overrides')

/* Merge the two lists together. */
return { ...links, ...data.links_overrides }
}
}

export function resolveURL(url, base) {
Expand Down
10 changes: 0 additions & 10 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
"markdown-it-deflist": "^3.0.0",
"markdown-it-mathjax3": "^4.3.2",
"pagefind": "^1.1.1",
"path-to-regexp": "^8.1.0",
"pdc": "^0.2.3",
"remark-definition-list": "^2.0.0",
"remark-man": "^9.0.0",
Expand Down

0 comments on commit 9af60ce

Please sign in to comment.