@docfy/ember-vite
Version:
Vite plugin for Docfy Ember integration with @embroider/vite
148 lines (147 loc) • 5.38 kB
JavaScript
import path from 'path';
import { pathToFileURL } from 'url';
import debugFactory from 'debug';
const debug = debugFactory('@docfy/ember-vite:config');
const DEFAULT_CONFIG = {
sources: [
{
pattern: '**/*.md',
urlPrefix: 'docs',
},
],
};
export async function loadDocfyConfig(root, options = {}) {
let docfyConfig = {};
// Load package.json for repository info
const pkg = await loadPackageJson(root);
// If config is provided directly, use it
if (options.config) {
docfyConfig = options.config;
debug('Using inline config');
}
else {
// Determine config file path
let configPath;
if (options.configFile) {
configPath = path.resolve(root, options.configFile);
}
else {
// Try default config files in order
const defaultConfigFiles = ['docfy.config.js', 'docfy.config.mjs'];
configPath = '';
for (const filename of defaultConfigFiles) {
const testPath = path.join(root, filename);
try {
const fs = await import('fs');
if (fs.existsSync(testPath)) {
configPath = testPath;
break;
}
}
catch {
// Continue to next file
}
}
// Fallback to first default if none found
if (!configPath) {
configPath = path.join(root, defaultConfigFiles[0]);
}
}
try {
// Use dynamic import for both CJS and ESM
const imported = await import(pathToFileURL(configPath).href);
docfyConfig = imported?.default ?? imported;
debug('Loaded config', { configPath });
}
catch (e) {
const notFound = e.code === 'ERR_MODULE_NOT_FOUND' || e.message?.includes('Cannot find module');
if (!notFound) {
throw e;
}
debug('No config file found, using defaults', { configPath });
docfyConfig = {};
}
}
// Merge with options and set defaults
const mergedConfig = await mergeConfig(docfyConfig, options, pkg, !!options.config);
debug('Final config', { sources: mergedConfig.sources?.length });
return mergedConfig;
}
async function loadPackageJson(root) {
try {
const pkgPath = path.join(root, 'package.json');
const fs = await import('fs');
const content = fs.readFileSync(pkgPath, 'utf-8');
return JSON.parse(content);
}
catch (e) {
debug('Could not load package.json', { root, error: e });
return {};
}
}
async function mergeConfig(docfyConfig, options, pkg, isInlineConfig = false) {
if (typeof docfyConfig !== 'object' || docfyConfig == null) {
docfyConfig = {};
}
// Merge sources
if (!Array.isArray(docfyConfig.sources)) {
docfyConfig.sources = DEFAULT_CONFIG.sources;
}
// Merge plugins
if (!Array.isArray(docfyConfig.plugins)) {
docfyConfig.plugins = [];
}
// Add Docfy core plugins for demo and preview template processing
const { demoComponents, previewTemplates, docfyLinkConversion } = await import('./docfy-plugins/index.js');
// Debug: plugins loaded
docfyConfig.plugins.unshift(previewTemplates, // Process preview templates first
demoComponents, // Then process demo components
docfyLinkConversion // Finally replace internal links with DocfyLink
);
// Setup remark plugins
if (!Array.isArray(docfyConfig.remarkPlugins)) {
docfyConfig.remarkPlugins = [];
}
// Add remark-hbs plugin
const remarkHbs = (await import('remark-hbs')).default;
docfyConfig.remarkPlugins.push([remarkHbs, docfyConfig.remarkHbsOptions || {}]);
// Setup repository info
const repoUrl = pkg.repository?.url || pkg.repository;
if (!docfyConfig.repository && typeof repoUrl === 'string' && repoUrl !== '') {
docfyConfig.repository = {
url: repoUrl,
};
}
// Set root for sources
docfyConfig.sources.forEach(source => {
if (typeof source.root === 'undefined') {
source.root = path.join(options.root || process.cwd(), 'docs');
}
});
// Merge with runtime options, excluding plugin-specific options
const {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
root,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
hmr,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
config,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
configFile, ...docfyOptions } = options;
// If inline config was provided, only merge docfyOptions that aren't already set in the inline config
if (isInlineConfig) {
const result = { ...docfyConfig };
// Only merge docfyOptions that don't already exist in the inline config
Object.keys(docfyOptions).forEach(key => {
if (!(key in docfyConfig)) {
result[key] = docfyOptions[key];
}
});
return result;
}
// For file-based config, merge normally
return {
...docfyConfig,
...docfyOptions,
};
}