71 lines
1.9 KiB
TypeScript
71 lines
1.9 KiB
TypeScript
import { access, readFile } from 'node:fs/promises'
|
|
import path from 'node:path'
|
|
import { pathToFileURL } from 'node:url'
|
|
|
|
export interface EasySlidesConfig {
|
|
title: string
|
|
description: string
|
|
slidesDir: string
|
|
outDir: string
|
|
exportDir: string
|
|
theme?: string
|
|
}
|
|
|
|
const defaults: EasySlidesConfig = {
|
|
title: 'easy-slides',
|
|
description: 'Markdown presentations powered by easy-slides',
|
|
slidesDir: 'slides',
|
|
outDir: 'dist',
|
|
exportDir: 'exports',
|
|
}
|
|
|
|
export async function loadProjectConfig(cwd = process.cwd()): Promise<EasySlidesConfig> {
|
|
const candidates = [
|
|
'easy-slides.config.mjs',
|
|
'easy-slides.config.js',
|
|
'easy-slides.config.json',
|
|
]
|
|
|
|
for (const candidate of candidates) {
|
|
const filename = path.join(cwd, candidate)
|
|
if (!(await exists(filename)))
|
|
continue
|
|
|
|
const loaded = candidate.endsWith('.json')
|
|
? JSON.parse(await readFile(filename, 'utf8'))
|
|
: (await import(`${pathToFileURL(filename).href}?t=${Date.now()}`)).default
|
|
|
|
return normalizeConfig(loaded)
|
|
}
|
|
|
|
return { ...defaults }
|
|
}
|
|
|
|
export function normalizeConfig(value: Partial<EasySlidesConfig> | undefined): EasySlidesConfig {
|
|
return {
|
|
...defaults,
|
|
...value,
|
|
slidesDir: normalizeRelativePath(value?.slidesDir ?? defaults.slidesDir, 'slidesDir'),
|
|
outDir: normalizeRelativePath(value?.outDir ?? defaults.outDir, 'outDir'),
|
|
exportDir: normalizeRelativePath(value?.exportDir ?? defaults.exportDir, 'exportDir'),
|
|
}
|
|
}
|
|
|
|
function normalizeRelativePath(value: string, field: string) {
|
|
const normalized = value.trim().replace(/[\\/]+$/, '')
|
|
const portable = normalized.replaceAll('\\', '/')
|
|
if (!normalized || path.isAbsolute(normalized) || portable === '..' || portable.startsWith('../'))
|
|
throw new Error(`${field} 必须是项目内的相对路径`)
|
|
return normalized
|
|
}
|
|
|
|
async function exists(filename: string) {
|
|
try {
|
|
await access(filename)
|
|
return true
|
|
}
|
|
catch {
|
|
return false
|
|
}
|
|
}
|