mirror of
https://github.com/PR0M3TH3AN/Archivox.git
synced 2025-09-08 06:58:43 +00:00
Merge pull request #3 from PR0M3TH3AN/codex/add-configuration-loader-and-validation
Add config loader
This commit is contained in:
@@ -10,7 +10,8 @@
|
||||
"@11ty/eleventy": "^2.0.1",
|
||||
"gray-matter": "^4.0.3",
|
||||
"marked": "^11.1.1",
|
||||
"lunr": "^2.3.9"
|
||||
"lunr": "^2.3.9",
|
||||
"js-yaml": "^4.1.0"
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
||||
|
69
src/config/loadConfig.js
Normal file
69
src/config/loadConfig.js
Normal file
@@ -0,0 +1,69 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const yaml = require('js-yaml');
|
||||
|
||||
function deepMerge(target, source) {
|
||||
for (const key of Object.keys(source)) {
|
||||
if (
|
||||
source[key] &&
|
||||
typeof source[key] === 'object' &&
|
||||
!Array.isArray(source[key])
|
||||
) {
|
||||
target[key] = deepMerge(target[key] || {}, source[key]);
|
||||
} else if (source[key] !== undefined) {
|
||||
target[key] = source[key];
|
||||
}
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
function loadConfig(configPath = path.join(process.cwd(), 'config.yaml')) {
|
||||
let raw = {};
|
||||
if (fs.existsSync(configPath)) {
|
||||
try {
|
||||
raw = yaml.load(fs.readFileSync(configPath, 'utf8')) || {};
|
||||
} catch (e) {
|
||||
console.error(`Failed to parse ${configPath}: ${e.message}`);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
const defaults = {
|
||||
site: {
|
||||
title: 'DocForge',
|
||||
description: '',
|
||||
logo: '',
|
||||
favicon: ''
|
||||
},
|
||||
navigation: {
|
||||
search: true
|
||||
},
|
||||
footer: {},
|
||||
theme: {
|
||||
name: 'minimal',
|
||||
darkMode: false
|
||||
},
|
||||
features: {},
|
||||
plugins: []
|
||||
};
|
||||
|
||||
const config = deepMerge(defaults, raw);
|
||||
|
||||
const errors = [];
|
||||
if (
|
||||
!config.site ||
|
||||
typeof config.site.title !== 'string' ||
|
||||
!config.site.title.trim()
|
||||
) {
|
||||
errors.push('site.title is required in config.yaml');
|
||||
}
|
||||
|
||||
if (errors.length) {
|
||||
errors.forEach(err => console.error(`Config error: ${err}`));
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
module.exports = loadConfig;
|
@@ -3,6 +3,7 @@ const fs = require('fs');
|
||||
const path = require('path');
|
||||
const matter = require('gray-matter');
|
||||
const Eleventy = require('@11ty/eleventy');
|
||||
const loadConfig = require('../config/loadConfig');
|
||||
|
||||
async function readDirRecursive(dir) {
|
||||
const entries = await fs.promises.readdir(dir, { withFileTypes: true });
|
||||
@@ -50,7 +51,8 @@ function buildNav(pages) {
|
||||
return tree.children || [];
|
||||
}
|
||||
|
||||
async function generate({ contentDir = 'content', outputDir = '_site' } = {}) {
|
||||
async function generate({ contentDir = 'content', outputDir = '_site', configPath } = {}) {
|
||||
const config = loadConfig(configPath);
|
||||
if (!fs.existsSync(contentDir)) {
|
||||
console.error(`Content directory not found: ${contentDir}`);
|
||||
return;
|
||||
@@ -82,6 +84,7 @@ async function generate({ contentDir = 'content', outputDir = '_site' } = {}) {
|
||||
const nav = buildNav(pages);
|
||||
await fs.promises.mkdir(outputDir, { recursive: true });
|
||||
await fs.promises.writeFile(path.join(outputDir, 'navigation.json'), JSON.stringify(nav, null, 2));
|
||||
await fs.promises.writeFile(path.join(outputDir, 'config.json'), JSON.stringify(config, null, 2));
|
||||
|
||||
const elev = new Eleventy(contentDir, outputDir);
|
||||
elev.setConfig({
|
||||
@@ -93,6 +96,7 @@ async function generate({ contentDir = 'content', outputDir = '_site' } = {}) {
|
||||
});
|
||||
elev.configFunction = function(eleventyConfig) {
|
||||
eleventyConfig.addGlobalData('navigation', nav);
|
||||
eleventyConfig.addGlobalData('config', config);
|
||||
};
|
||||
await elev.write();
|
||||
|
||||
|
Reference in New Issue
Block a user