refactor: dox
This commit is contained in:
parent
7cc206ae6d
commit
4b2f68f048
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -122,5 +122,6 @@ dist
|
|||
# package-locals
|
||||
/packages/*/yarn.lock
|
||||
/packages/*/bun.lockb
|
||||
/website/yarn.lock
|
||||
|
||||
/.nx/cache
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
},
|
||||
"scripts": {
|
||||
"build": "lerna run build",
|
||||
"dox": "flecks dox docusaurus && cd website && DOCUSAURUS_GENERATED_FILES_DIR_NAME=node_modules/.cache/docusaurus node_modules/.bin/docusaurus",
|
||||
"lint": "lerna run lint",
|
||||
"publish": "lerna publish --conventional-commits --contents=dist --registry https://registry.npmjs.org"
|
||||
},
|
||||
|
|
|
@ -1,17 +1,10 @@
|
|||
const {
|
||||
access,
|
||||
cp,
|
||||
mkdir,
|
||||
rename,
|
||||
rmdir,
|
||||
} = require('fs/promises');
|
||||
const {dirname, join} = require('path');
|
||||
const {mkdir, writeFile} = require('fs/promises');
|
||||
const {join, relative, resolve} = require('path');
|
||||
|
||||
const {
|
||||
generate,
|
||||
resolveSiteDir,
|
||||
spawn,
|
||||
} = require('./docusaurus');
|
||||
generateDocusaurus,
|
||||
generateJson,
|
||||
} = require('./generate');
|
||||
|
||||
const {
|
||||
FLECKS_CORE_ROOT = process.cwd(),
|
||||
|
@ -19,73 +12,55 @@ const {
|
|||
|
||||
module.exports = (program, flecks) => {
|
||||
const commands = {};
|
||||
const siteDirArgument = program.createArgument('[siteDir]', 'Docusaurus directory');
|
||||
siteDirArgument.defaultValue = 'website';
|
||||
commands.docusaurus = {
|
||||
description: [
|
||||
'Create a documentation website for this project.',
|
||||
'',
|
||||
'The `build` and `start` subcommands are sugar on top of the corresponding Docusaurus commands.',
|
||||
'',
|
||||
'The `create` subcommand will create a documentation website starter template for you at `siteDir`',
|
||||
"if `siteDir` doesn't already exist (defaults to `website`). A `docusaurus.config.js`",
|
||||
"starter configuration will also be copied to your `build` directory if it doesn't already exist.",
|
||||
].join('\n'),
|
||||
action: async (subcommand, siteDir) => {
|
||||
const resolvedSiteDir = resolveSiteDir(siteDir);
|
||||
let siteDirExisted = false;
|
||||
try {
|
||||
const result = await mkdir(resolvedSiteDir);
|
||||
if (undefined === result) {
|
||||
await rmdir(resolvedSiteDir);
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
siteDirExisted = true;
|
||||
}
|
||||
commands.dox = {
|
||||
description: 'Generate documentation',
|
||||
action: async (subcommand, outputPath) => {
|
||||
let actualOutputPath = outputPath;
|
||||
if (!actualOutputPath) {
|
||||
switch (subcommand) {
|
||||
case 'build':
|
||||
if (!siteDirExisted) {
|
||||
throw new Error(`There's no website directory at ${resolvedSiteDir} to build!`);
|
||||
}
|
||||
await generate(flecks, resolvedSiteDir);
|
||||
spawn('build', resolvedSiteDir);
|
||||
case 'docusaurus':
|
||||
actualOutputPath = 'website/docs/flecks';
|
||||
break;
|
||||
case 'create': {
|
||||
if (siteDirExisted) {
|
||||
throw new Error(`A website directory at ${resolvedSiteDir} already exists!`);
|
||||
}
|
||||
const templateDirectory = dirname(require.resolve('@flecks/dox/website/sidebars.js'));
|
||||
await cp(templateDirectory, resolvedSiteDir, {recursive: true});
|
||||
// Copy the docusaurus config if it doesn't already exist.
|
||||
try {
|
||||
await access(join(FLECKS_CORE_ROOT, 'build', 'docusaurus.config.js'));
|
||||
}
|
||||
catch (error) {
|
||||
await rename(
|
||||
join(resolvedSiteDir, 'docusaurus.config.js'),
|
||||
join(FLECKS_CORE_ROOT, 'build', 'docusaurus.config.js'),
|
||||
);
|
||||
}
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(`website directory created at ${resolvedSiteDir}!`);
|
||||
break;
|
||||
}
|
||||
case 'start':
|
||||
if (!siteDirExisted) {
|
||||
throw new Error(`There's no website directory at ${resolvedSiteDir} to start!`);
|
||||
}
|
||||
await generate(flecks, resolvedSiteDir);
|
||||
spawn('start', resolvedSiteDir);
|
||||
case 'json':
|
||||
actualOutputPath = 'dist/dox';
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
actualOutputPath = resolve(FLECKS_CORE_ROOT, actualOutputPath);
|
||||
await mkdir(actualOutputPath, {recursive: true});
|
||||
let output;
|
||||
const json = await generateJson(flecks);
|
||||
switch (subcommand) {
|
||||
case 'docusaurus':
|
||||
output = Object.fromEntries(
|
||||
Object.entries(generateDocusaurus(json))
|
||||
.map(([type, page]) => [`${type}.mdx`, page]),
|
||||
);
|
||||
break;
|
||||
case 'json':
|
||||
output = Object.fromEntries(
|
||||
Object.entries(json)
|
||||
.map(([type, value]) => [`${type}.json`, JSON.stringify(value, null, 2)]),
|
||||
);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
await Promise.all(
|
||||
Object.entries(output)
|
||||
.map(([filename, output]) => (
|
||||
writeFile(join(actualOutputPath, filename), output)
|
||||
)),
|
||||
);
|
||||
// eslint-disable-next-line no-console
|
||||
console.log("Output documentation to '%s'", relative(FLECKS_CORE_ROOT, actualOutputPath));
|
||||
},
|
||||
args: [
|
||||
program.createArgument('subcommand', 'Docusaurus command to run')
|
||||
.choices(['build', 'create', 'start']),
|
||||
siteDirArgument,
|
||||
program.createArgument('subcommand', 'Generation type')
|
||||
.choices(['docusaurus', 'json']),
|
||||
program.createArgument('[output path]', 'Where the files are output'),
|
||||
],
|
||||
};
|
||||
return commands;
|
||||
|
|
|
@ -1,242 +0,0 @@
|
|||
const {mkdir, writeFile} = require('fs/promises');
|
||||
const {
|
||||
basename,
|
||||
dirname,
|
||||
extname,
|
||||
isAbsolute,
|
||||
join,
|
||||
resolve,
|
||||
} = require('path');
|
||||
|
||||
const {spawnWith} = require('@flecks/core/server');
|
||||
const {themes: prismThemes} = require('prism-react-renderer');
|
||||
const {rimraf} = require('rimraf');
|
||||
|
||||
const {
|
||||
generateBuildFilesPage,
|
||||
generateConfigPage,
|
||||
generateHookPage,
|
||||
generateTodoPage,
|
||||
} = require('./generate');
|
||||
const {parseFlecks} = require('./parser');
|
||||
|
||||
const {
|
||||
FLECKS_CORE_ROOT = process.cwd(),
|
||||
} = process.env;
|
||||
|
||||
exports.configDefaults = function configDefaults() {
|
||||
/** @type {import('@docusaurus/types').Config} */
|
||||
const config = {
|
||||
tagline: 'built with flecks',
|
||||
onBrokenLinks: 'throw',
|
||||
onBrokenMarkdownLinks: 'warn',
|
||||
i18n: {
|
||||
defaultLocale: 'en',
|
||||
locales: ['en'],
|
||||
},
|
||||
presets: [
|
||||
['classic', {
|
||||
docs: {
|
||||
sidebarPath: './sidebars.js',
|
||||
},
|
||||
pages: {
|
||||
path: 'pages',
|
||||
},
|
||||
}],
|
||||
],
|
||||
themeConfig: {
|
||||
footer: {
|
||||
style: 'dark',
|
||||
copyright: 'Built with flecks and Docusaurus.',
|
||||
},
|
||||
prism: {
|
||||
theme: prismThemes.github,
|
||||
darkTheme: prismThemes.dracula,
|
||||
},
|
||||
},
|
||||
};
|
||||
return config;
|
||||
};
|
||||
|
||||
exports.resolveSiteDir = function resolveSiteDir(siteDir) {
|
||||
return isAbsolute(siteDir)
|
||||
? siteDir
|
||||
: resolve(FLECKS_CORE_ROOT, siteDir);
|
||||
};
|
||||
|
||||
exports.generate = async function generate(flecks, siteDir) {
|
||||
// Generate "docs".
|
||||
const docsDirectory = join(siteDir, 'docs', 'flecks');
|
||||
await rimraf(docsDirectory);
|
||||
const generatedDirectory = join(docsDirectory, '@flecks', 'dox');
|
||||
await mkdir(generatedDirectory, {recursive: true});
|
||||
const parsed = await parseFlecks(flecks);
|
||||
const {
|
||||
buildFiles,
|
||||
config,
|
||||
hooks,
|
||||
todos,
|
||||
} = parsed
|
||||
.reduce(
|
||||
(
|
||||
r,
|
||||
[
|
||||
root,
|
||||
sources,
|
||||
],
|
||||
) => {
|
||||
const ensureHook = (hook) => {
|
||||
if (!r.hooks[hook]) {
|
||||
r.hooks[hook] = {
|
||||
implementations: [],
|
||||
invocations: [],
|
||||
specification: undefined,
|
||||
};
|
||||
}
|
||||
};
|
||||
sources.forEach(
|
||||
(
|
||||
[
|
||||
path,
|
||||
{
|
||||
buildFiles = [],
|
||||
config = [],
|
||||
hookImplementations = [],
|
||||
hookInvocations = [],
|
||||
hookSpecifications = [],
|
||||
todos = [],
|
||||
},
|
||||
],
|
||||
) => {
|
||||
r.buildFiles.push(...buildFiles);
|
||||
r.todos.push(...todos.map((todo) => ({
|
||||
...todo,
|
||||
filename: join(`**${root}**`, path),
|
||||
})));
|
||||
if (config.length > 0) {
|
||||
let fleck = root;
|
||||
if ('build/flecks.bootstrap.js' !== path) {
|
||||
fleck = join(fleck, path.startsWith('src') ? path.slice(4) : path);
|
||||
fleck = join(dirname(fleck), basename(fleck, extname(fleck)));
|
||||
fleck = fleck.endsWith('/index') ? fleck.slice(0, -6) : fleck;
|
||||
}
|
||||
r.config[fleck] = config;
|
||||
}
|
||||
hookImplementations.forEach(({column, hook, line}) => {
|
||||
ensureHook(hook);
|
||||
r.hooks[hook].implementations.push({
|
||||
column,
|
||||
filename: join(`**${root}**`, path),
|
||||
line,
|
||||
});
|
||||
});
|
||||
hookInvocations.forEach(({
|
||||
column,
|
||||
hook,
|
||||
line,
|
||||
type,
|
||||
}) => {
|
||||
ensureHook(hook);
|
||||
r.hooks[hook].invocations.push({
|
||||
column,
|
||||
filename: join(`**${root}**`, path),
|
||||
line,
|
||||
type,
|
||||
});
|
||||
});
|
||||
hookSpecifications.forEach(({
|
||||
hook,
|
||||
description,
|
||||
example,
|
||||
params,
|
||||
}) => {
|
||||
ensureHook(hook);
|
||||
r.hooks[hook].specification = {
|
||||
description,
|
||||
example,
|
||||
params,
|
||||
};
|
||||
});
|
||||
},
|
||||
);
|
||||
return r;
|
||||
},
|
||||
{
|
||||
buildFiles: [],
|
||||
config: {},
|
||||
hooks: {},
|
||||
todos: [],
|
||||
},
|
||||
);
|
||||
const sortedHooks = Object.fromEntries(
|
||||
Object.entries(hooks)
|
||||
.map(([hook, {implementations, invocations, specification}]) => (
|
||||
[
|
||||
hook,
|
||||
{
|
||||
implementations: implementations
|
||||
.sort(({filename: l}, {filename: r}) => (l < r ? -1 : 1)),
|
||||
invocations: invocations
|
||||
.sort(({filename: l}, {filename: r}) => (l < r ? -1 : 1)),
|
||||
specification,
|
||||
},
|
||||
]
|
||||
))
|
||||
.sort(([l], [r]) => (l < r ? -1 : 1)),
|
||||
);
|
||||
Object.entries(sortedHooks)
|
||||
.forEach(([hook, {specification}]) => {
|
||||
if (!specification) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.warn(`Warning: no specification for hook: '${hook}'`);
|
||||
}
|
||||
});
|
||||
const hookPage = generateHookPage(sortedHooks, flecks);
|
||||
const todoPage = generateTodoPage(todos, flecks);
|
||||
const buildFilesPage = generateBuildFilesPage(buildFiles);
|
||||
const configPage = generateConfigPage(config);
|
||||
await writeFile(join(generatedDirectory, 'hooks.mdx'), hookPage);
|
||||
await writeFile(join(generatedDirectory, 'TODO.mdx'), todoPage);
|
||||
await writeFile(join(generatedDirectory, 'build-configs.mdx'), buildFilesPage);
|
||||
await writeFile(join(generatedDirectory, 'config.mdx'), configPage);
|
||||
};
|
||||
|
||||
exports.spawn = function spawn(subcommand, siteDir) {
|
||||
const args = [];
|
||||
switch (subcommand) {
|
||||
case 'start':
|
||||
args.push('start', '--no-open');
|
||||
break;
|
||||
case 'build':
|
||||
args.push('build', '--out-dir', join(FLECKS_CORE_ROOT, 'dist', 'dox'));
|
||||
break;
|
||||
default: {
|
||||
const docusaurusCall = `npx docusaurus <subcommand> --config ${join(FLECKS_CORE_ROOT, 'build', 'docusaurus.config.js')}`;
|
||||
throw new Error(`@flecks/dox only supports the 'build' and 'start' subcommands. You can run docusaurus yourself with:\n\n${docusaurusCall}`);
|
||||
}
|
||||
}
|
||||
args.push('--config', join(FLECKS_CORE_ROOT, 'build', 'docusaurus.config.js'));
|
||||
const cacheDirectory = join(FLECKS_CORE_ROOT, 'node_modules', '.cache', '@flecks', 'dox');
|
||||
// Spawn `docusaurus`.
|
||||
const cmd = [
|
||||
// `npx` doesn't propagate signals!
|
||||
// 'npx', 'docusaurus',
|
||||
join(FLECKS_CORE_ROOT, 'node_modules', '.bin', 'docusaurus'),
|
||||
...args,
|
||||
siteDir,
|
||||
];
|
||||
const child = spawnWith(
|
||||
cmd,
|
||||
{
|
||||
env: {
|
||||
// Override docusaurus generation directory for cleanliness.
|
||||
DOCUSAURUS_GENERATED_FILES_DIR_NAME: join(cacheDirectory, '.docusaurus'),
|
||||
},
|
||||
},
|
||||
);
|
||||
// Clean up on exit.
|
||||
process.on('exit', () => {
|
||||
child.kill();
|
||||
});
|
||||
return child;
|
||||
};
|
|
@ -2,12 +2,4 @@ const commands = require('./commands');
|
|||
|
||||
exports.hooks = {
|
||||
'@flecks/build.commands': commands,
|
||||
'@flecks/core.config': () => ({
|
||||
/**
|
||||
* Rewrite the output filenames of source files.
|
||||
*
|
||||
* `filename.replace(new RegExp([key]), [value]);`
|
||||
*/
|
||||
filenameRewriters: {},
|
||||
}),
|
||||
};
|
||||
|
|
|
@ -1,12 +1,26 @@
|
|||
const makeFilenameRewriter = (filenameRewriters) => (filename, line, column) => (
|
||||
Object.entries(filenameRewriters)
|
||||
.reduce(
|
||||
(filename, [from, to]) => filename.replace(new RegExp(from), to),
|
||||
[filename, ...(line ? [line, column] : [])].join(':'),
|
||||
)
|
||||
);
|
||||
const {
|
||||
basename,
|
||||
dirname,
|
||||
extname,
|
||||
join,
|
||||
} = require('path');
|
||||
|
||||
exports.generateBuildFilesPage = (buildFiles) => {
|
||||
const {parseFlecks} = require('./parser');
|
||||
|
||||
exports.generateDocusaurus = function generate({
|
||||
'build-files': buildFiles,
|
||||
config,
|
||||
hooks,
|
||||
todos,
|
||||
}) {
|
||||
return {
|
||||
'build-files': exports.generateDocusaurusBuildFilesPage(buildFiles),
|
||||
config: exports.generateDocusaurusConfigPage(config),
|
||||
hooks: exports.generateDocusaurusHookPage(hooks),
|
||||
todos: exports.generateDocusaurusTodoPage(todos),
|
||||
};
|
||||
};
|
||||
exports.generateDocusaurusBuildFilesPage = (buildFiles) => {
|
||||
const source = [];
|
||||
source.push('---');
|
||||
source.push('title: Build files');
|
||||
|
@ -28,7 +42,7 @@ exports.generateBuildFilesPage = (buildFiles) => {
|
|||
return source.join('\n');
|
||||
};
|
||||
|
||||
exports.generateConfigPage = (configs) => {
|
||||
exports.generateDocusaurusConfigPage = (configs) => {
|
||||
const source = [];
|
||||
source.push('---');
|
||||
source.push('title: Fleck configuration');
|
||||
|
@ -67,9 +81,7 @@ exports.generateConfigPage = (configs) => {
|
|||
return source.join('\n');
|
||||
};
|
||||
|
||||
exports.generateHookPage = (hooks, flecks) => {
|
||||
const {filenameRewriters} = flecks.get('@flecks/dox');
|
||||
const rewriteFilename = makeFilenameRewriter(filenameRewriters);
|
||||
exports.generateDocusaurusHookPage = (hooks) => {
|
||||
const source = [];
|
||||
source.push('---');
|
||||
source.push('title: Hooks');
|
||||
|
@ -114,7 +126,7 @@ exports.generateHookPage = (hooks, flecks) => {
|
|||
source.push('<summary>Implementations</summary>');
|
||||
source.push('<ul>');
|
||||
implementations.forEach(({filename, column, line}) => {
|
||||
source.push(`<li>${rewriteFilename(filename, line, column)}</li>`);
|
||||
source.push(`<li>${[filename, line, column].join(':')}</li>`);
|
||||
});
|
||||
source.push('</ul>');
|
||||
source.push('</details>');
|
||||
|
@ -125,7 +137,7 @@ exports.generateHookPage = (hooks, flecks) => {
|
|||
source.push('<summary>Invocations</summary>');
|
||||
source.push('<ul>');
|
||||
invocations.forEach(({filename, column, line}) => {
|
||||
source.push(`<li>${rewriteFilename(filename, line, column)}</li>`);
|
||||
source.push(`<li>${[filename, line, column].join(':')}</li>`);
|
||||
});
|
||||
source.push('</ul>');
|
||||
source.push('</details>');
|
||||
|
@ -135,9 +147,7 @@ exports.generateHookPage = (hooks, flecks) => {
|
|||
return source.join('\n');
|
||||
};
|
||||
|
||||
exports.generateTodoPage = (todos, flecks) => {
|
||||
const {filenameRewriters} = flecks.get('@flecks/dox');
|
||||
const rewriteFilename = makeFilenameRewriter(filenameRewriters);
|
||||
exports.generateDocusaurusTodoPage = (todos) => {
|
||||
const source = [];
|
||||
source.push('---');
|
||||
source.push('title: TODO list');
|
||||
|
@ -154,7 +164,7 @@ exports.generateTodoPage = (todos, flecks) => {
|
|||
context,
|
||||
description,
|
||||
}) => {
|
||||
source.push(rewriteFilename(filename));
|
||||
source.push(filename);
|
||||
source.push(`> ## ${description}`);
|
||||
source.push(`> <CodeBlock>${context}</CodeBlock>`);
|
||||
source.push('');
|
||||
|
@ -163,3 +173,133 @@ exports.generateTodoPage = (todos, flecks) => {
|
|||
}
|
||||
return source.join('\n');
|
||||
};
|
||||
|
||||
exports.generateJson = async function generate(flecks) {
|
||||
const parsed = await parseFlecks(flecks);
|
||||
const {
|
||||
buildFiles,
|
||||
config,
|
||||
hooks,
|
||||
todos,
|
||||
} = parsed
|
||||
.reduce(
|
||||
(
|
||||
r,
|
||||
[
|
||||
root,
|
||||
sources,
|
||||
],
|
||||
) => {
|
||||
const ensureHook = (hook) => {
|
||||
if (!r.hooks[hook]) {
|
||||
r.hooks[hook] = {
|
||||
implementations: [],
|
||||
invocations: [],
|
||||
specification: undefined,
|
||||
};
|
||||
}
|
||||
};
|
||||
sources.forEach(
|
||||
(
|
||||
[
|
||||
path,
|
||||
{
|
||||
buildFiles = [],
|
||||
config = [],
|
||||
hookImplementations = [],
|
||||
hookInvocations = [],
|
||||
hookSpecifications = [],
|
||||
todos = [],
|
||||
},
|
||||
],
|
||||
) => {
|
||||
r.buildFiles.push(...buildFiles);
|
||||
r.todos.push(...todos.map((todo) => ({
|
||||
...todo,
|
||||
filename: join(`**${root}**`, path),
|
||||
})));
|
||||
if (config.length > 0) {
|
||||
let fleck = root;
|
||||
if ('build/flecks.bootstrap.js' !== path) {
|
||||
fleck = join(fleck, path.startsWith('src') ? path.slice(4) : path);
|
||||
fleck = join(dirname(fleck), basename(fleck, extname(fleck)));
|
||||
fleck = fleck.endsWith('/index') ? fleck.slice(0, -6) : fleck;
|
||||
}
|
||||
r.config[fleck] = config;
|
||||
}
|
||||
hookImplementations.forEach(({column, hook, line}) => {
|
||||
ensureHook(hook);
|
||||
r.hooks[hook].implementations.push({
|
||||
column,
|
||||
filename: join(`**${root}**`, path),
|
||||
line,
|
||||
});
|
||||
});
|
||||
hookInvocations.forEach(({
|
||||
column,
|
||||
hook,
|
||||
line,
|
||||
type,
|
||||
}) => {
|
||||
ensureHook(hook);
|
||||
r.hooks[hook].invocations.push({
|
||||
column,
|
||||
filename: join(`**${root}**`, path),
|
||||
line,
|
||||
type,
|
||||
});
|
||||
});
|
||||
hookSpecifications.forEach(({
|
||||
hook,
|
||||
description,
|
||||
example,
|
||||
params,
|
||||
}) => {
|
||||
ensureHook(hook);
|
||||
r.hooks[hook].specification = {
|
||||
description,
|
||||
example,
|
||||
params,
|
||||
};
|
||||
});
|
||||
},
|
||||
);
|
||||
return r;
|
||||
},
|
||||
{
|
||||
buildFiles: [],
|
||||
config: {},
|
||||
hooks: {},
|
||||
todos: [],
|
||||
},
|
||||
);
|
||||
const sortedHooks = Object.fromEntries(
|
||||
Object.entries(hooks)
|
||||
.map(([hook, {implementations, invocations, specification}]) => (
|
||||
[
|
||||
hook,
|
||||
{
|
||||
implementations: implementations
|
||||
.sort(({filename: l}, {filename: r}) => (l < r ? -1 : 1)),
|
||||
invocations: invocations
|
||||
.sort(({filename: l}, {filename: r}) => (l < r ? -1 : 1)),
|
||||
specification,
|
||||
},
|
||||
]
|
||||
))
|
||||
.sort(([l], [r]) => (l < r ? -1 : 1)),
|
||||
);
|
||||
Object.entries(sortedHooks)
|
||||
.forEach(([hook, {specification}]) => {
|
||||
if (!specification) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.warn(`Warning: no specification for hook: '${hook}'`);
|
||||
}
|
||||
});
|
||||
return {
|
||||
'build-files': buildFiles,
|
||||
config,
|
||||
hooks: sortedHooks,
|
||||
todos,
|
||||
};
|
||||
};
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
const {readFile} = require('fs/promises');
|
||||
const {join, relative} = require('path');
|
||||
const {dirname, join, relative} = require('path');
|
||||
|
||||
const {transformAsync} = require('@babel/core');
|
||||
const {default: traverse} = require('@babel/traverse');
|
||||
|
@ -125,6 +125,11 @@ exports.parseFleckRoot = async (request) => (
|
|||
exports.parseFlecks = async (flecks) => (
|
||||
Promise.all(
|
||||
flecks.roots
|
||||
.map(async ([path, request]) => [path, await exports.parseFleckRoot(request)]),
|
||||
.map(async ([path, request]) => [
|
||||
path,
|
||||
await exports.parseFleckRoot(
|
||||
dirname(await flecks.resolver.resolve(join(request, 'package.json'))),
|
||||
),
|
||||
]),
|
||||
)
|
||||
);
|
||||
|
|
|
@ -25,13 +25,7 @@
|
|||
"@babel/core": "^7.17.2",
|
||||
"@babel/traverse": "^7.17.0",
|
||||
"@babel/types": "^7.17.0",
|
||||
"@docusaurus/core": "3.0.1",
|
||||
"@docusaurus/module-type-aliases": "3.0.1",
|
||||
"@docusaurus/preset-classic": "3.0.1",
|
||||
"@docusaurus/types": "3.0.1",
|
||||
"@flecks/core": "^3.0.0",
|
||||
"@flecks/react": "^3.0.0",
|
||||
"clsx": "^2.0.0",
|
||||
"comment-parser": "^1.3.0",
|
||||
"rimraf": "^5.0.5"
|
||||
},
|
||||
|
|
23
website/README.md
Normal file
23
website/README.md
Normal file
|
@ -0,0 +1,23 @@
|
|||
# Website
|
||||
|
||||
This website is built using [Docusaurus](https://docusaurus.io/), a modern static website generator.
|
||||
|
||||
### Installation
|
||||
|
||||
```
|
||||
(cd website && yarn)
|
||||
```
|
||||
|
||||
### Local Development
|
||||
|
||||
```
|
||||
yarn dox start
|
||||
```
|
||||
|
||||
This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server.
|
||||
|
||||
### Build
|
||||
|
||||
```
|
||||
yarn dox build
|
||||
```
|
3
website/babel.config.js
Normal file
3
website/babel.config.js
Normal file
|
@ -0,0 +1,3 @@
|
|||
module.exports = {
|
||||
presets: [require.resolve('@docusaurus/core/lib/babel/preset')],
|
||||
};
|
|
@ -1,23 +1,18 @@
|
|||
---
|
||||
title: Documentation website
|
||||
title: Documentation
|
||||
description: Document your project.
|
||||
---
|
||||
|
||||
import useBaseUrl from '@docusaurus/useBaseUrl';
|
||||
import ImageRow from '@site/helpers/image-row';
|
||||
import InstallPackage from '@site/helpers/install-package';
|
||||
import ThemedImage from '@theme/ThemedImage';
|
||||
|
||||
# Documentation website
|
||||
# Documentation
|
||||
|
||||
Ah, the most ~~boring~~ awesome part of development.
|
||||
|
||||
flecks provides a fleck called `@flecks/dox` that helps you generate a documentation website for
|
||||
your project.
|
||||
flecks provides a fleck called `@flecks/dox` that helps you generate documentation for your
|
||||
project.
|
||||
|
||||
:::tip[Mmm, dog food]
|
||||
|
||||
In fact, this very website you're viewing now has been built with the same tooling!
|
||||
In fact, this very website you're viewing uses the same tooling!
|
||||
|
||||
:::
|
||||
|
||||
|
@ -29,65 +24,41 @@ To get started, add `@flecks/dox` to your project:
|
|||
npx flecks add -d @flecks/dox
|
||||
```
|
||||
|
||||
## Spin up a starter website
|
||||
## Output for Docusaurus
|
||||
|
||||
Next, run:
|
||||
|
||||
```bash
|
||||
npx flecks docusaurus create
|
||||
```
|
||||
|
||||
You should now have a starter configuration in `build/docusaurus.config.js` and a new directory
|
||||
in your project: `website`. See [the command documentation](/docs/cli#docusaurus) to discover more
|
||||
options.
|
||||
|
||||
Now, start your documentation website's development server with:
|
||||
[Docusaurus](https://docusaurus.io) is a nice way to generate a documentation website.
|
||||
`@flecks/dox` can output MDX files for Docusaurus:
|
||||
|
||||
```
|
||||
npx flecks docusaurus start
|
||||
npx flecks dox docusaurus
|
||||
```
|
||||
|
||||
You should now see a message similar to:
|
||||
By default this command will output the files to `website/docs/flecks`.
|
||||
|
||||
```bash
|
||||
[SUCCESS] Docusaurus website is running at: http://localhost:3000/
|
||||
As an example, this website defines an entry in `sidebars.js` like so:
|
||||
|
||||
```js
|
||||
{
|
||||
type: 'category',
|
||||
label: 'Generated details',
|
||||
link: {
|
||||
type: 'generated-index',
|
||||
},
|
||||
items: [
|
||||
'flecks/hooks',
|
||||
'flecks/config',
|
||||
'flecks/build-files',
|
||||
'flecks/todo',
|
||||
],
|
||||
},
|
||||
```
|
||||
|
||||
Go and have a look!
|
||||
## Raw output
|
||||
|
||||
<ImageRow>
|
||||
<ThemedImage
|
||||
alt="Screenshot of the front page of the generated documentation site"
|
||||
sources={{
|
||||
light: useBaseUrl('/flecks-dox-1-light.png'),
|
||||
dark: useBaseUrl('/flecks-dox-1.png'),
|
||||
}}
|
||||
/>
|
||||
<ThemedImage
|
||||
alt="Screenshot of the documentation introduction page of the generated documentation site"
|
||||
sources={{
|
||||
light: useBaseUrl('/flecks-dox-2-light.png'),
|
||||
dark: useBaseUrl('/flecks-dox-2.png'),
|
||||
}}
|
||||
/>
|
||||
</ImageRow>
|
||||
You may also output JSON files for your own processing:
|
||||
|
||||
Not bad, huh?
|
||||
|
||||
## Building it out
|
||||
|
||||
It's only a starter template, of course. You'll want to pop over to
|
||||
[the Docusaurus guides page](https://docusaurus.io/docs/category/guides) to build out your new
|
||||
website. Have fun!
|
||||
|
||||
:::tip[Ready to roll out!]
|
||||
|
||||
When you're ready to build for production, just run
|
||||
|
||||
```bash
|
||||
npx flecks docusaurus build
|
||||
```
|
||||
npx flecks dox json
|
||||
```
|
||||
|
||||
After successfully building, your website files will be located at `dist/dox`.
|
||||
|
||||
:::
|
||||
By default this command will output the files to `dist/dox`.
|
||||
|
|
|
@ -22,7 +22,7 @@ flecks is built with supreme attention to the developer and end-user experience.
|
|||
- The simplest application is two flecks, `core` and `server` (**7 MB** production server size): you don't pay for what you don't buy
|
||||
- Endlessly configurable through built-in [hooks](./flecks/@flecks/dox/hooks) and then your own
|
||||
- 🛠️ **Ready to build maintainable and performant production applications**
|
||||
- [Documentation website](./documentation) generation for your project with no fuss
|
||||
- [Documentation](./documentation) generation for your project with no fuss
|
||||
- [Write tests](./testing), run on server/in browser/...
|
||||
- [React](./react) / [redux](./redux)
|
||||
- [Realtime sockets](./sockets) with lots of goodies like binary packing and packet dispatching
|
||||
|
|
67
website/docusaurus.config.js
Normal file
67
website/docusaurus.config.js
Normal file
|
@ -0,0 +1,67 @@
|
|||
// @ts-check
|
||||
// `@type` JSDoc annotations allow editor autocompletion and type checking
|
||||
// (when paired with `@ts-check`).
|
||||
// There are various equivalent ways to declare your Docusaurus config.
|
||||
// See: https://docusaurus.io/docs/api/docusaurus-config
|
||||
const {themes: prismThemes} = require('prism-react-renderer');
|
||||
|
||||
// For some reason we get a webpack warning if we use import here...
|
||||
export default async function flecksDocusaurus() {
|
||||
/** @type {import('@docusaurus/types').Config} */
|
||||
const config = {
|
||||
baseUrl: '/flecks/',
|
||||
favicon: 'flecks.png',
|
||||
i18n: {
|
||||
defaultLocale: 'en',
|
||||
locales: ['en'],
|
||||
},
|
||||
markdown: {
|
||||
mermaid: true,
|
||||
},
|
||||
onBrokenLinks: 'throw',
|
||||
onBrokenMarkdownLinks: 'warn',
|
||||
organizationName: 'cha0s', // Usually your GitHub org/user name.
|
||||
presets: [
|
||||
['classic', {
|
||||
docs: {
|
||||
sidebarPath: './sidebars.js',
|
||||
},
|
||||
pages: {
|
||||
path: 'pages',
|
||||
},
|
||||
}],
|
||||
],
|
||||
projectName: 'flecks', // Usually your repo name.
|
||||
tagline: 'not static',
|
||||
themes: ['@docusaurus/theme-mermaid'],
|
||||
themeConfig:
|
||||
/** @type {import('@docusaurus/preset-classic').ThemeConfig} */
|
||||
({
|
||||
navbar: {
|
||||
title: 'flecks',
|
||||
logo: {
|
||||
alt: 'flecks logo',
|
||||
src: 'flecks-textless.png',
|
||||
},
|
||||
items: [
|
||||
{
|
||||
href: 'https://github.com/cha0s/flecks',
|
||||
label: 'GitHub',
|
||||
position: 'right',
|
||||
},
|
||||
],
|
||||
},
|
||||
prism: {
|
||||
theme: prismThemes.github,
|
||||
darkTheme: prismThemes.dracula,
|
||||
},
|
||||
footer: {
|
||||
style: 'dark',
|
||||
copyright: `Copyright © ${new Date().getFullYear()} cha0s. Built with flecks and Docusaurus.`,
|
||||
},
|
||||
}),
|
||||
title: 'flecks',
|
||||
url: 'https://cha0s.github.io',
|
||||
};
|
||||
return config;
|
||||
}
|
44
website/package.json
Normal file
44
website/package.json
Normal file
|
@ -0,0 +1,44 @@
|
|||
{
|
||||
"name": "flecks-docusaurus",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"docusaurus": "docusaurus",
|
||||
"start": "docusaurus start",
|
||||
"build": "docusaurus build",
|
||||
"swizzle": "docusaurus swizzle",
|
||||
"deploy": "docusaurus deploy",
|
||||
"clear": "docusaurus clear",
|
||||
"serve": "docusaurus serve",
|
||||
"write-translations": "docusaurus write-translations",
|
||||
"write-heading-ids": "docusaurus write-heading-ids"
|
||||
},
|
||||
"dependencies": {
|
||||
"@docusaurus/core": "3.0.1",
|
||||
"@docusaurus/preset-classic": "3.0.1",
|
||||
"@mdx-js/react": "^3.0.0",
|
||||
"clsx": "^2.0.0",
|
||||
"prism-react-renderer": "^2.3.0",
|
||||
"react": "^18.0.0",
|
||||
"react-dom": "^18.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@docusaurus/module-type-aliases": "3.0.1",
|
||||
"@docusaurus/types": "3.0.1"
|
||||
},
|
||||
"browserslist": {
|
||||
"production": [
|
||||
">0.5%",
|
||||
"not dead",
|
||||
"not op_mini all"
|
||||
],
|
||||
"development": [
|
||||
"last 3 chrome version",
|
||||
"last 3 firefox version",
|
||||
"last 5 safari version"
|
||||
]
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0"
|
||||
}
|
||||
}
|
|
@ -56,10 +56,10 @@ export default {
|
|||
type: 'generated-index',
|
||||
},
|
||||
items: [
|
||||
'flecks/@flecks/dox/hooks',
|
||||
'flecks/@flecks/dox/config',
|
||||
'flecks/@flecks/dox/build-configs',
|
||||
'flecks/@flecks/dox/TODO',
|
||||
'flecks/hooks',
|
||||
'flecks/config',
|
||||
'flecks/build-files',
|
||||
'flecks/todo',
|
||||
],
|
||||
},
|
||||
],
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 77 KiB |
Binary file not shown.
Before Width: | Height: | Size: 77 KiB |
Binary file not shown.
Before Width: | Height: | Size: 77 KiB |
Binary file not shown.
Before Width: | Height: | Size: 77 KiB |
Loading…
Reference in New Issue
Block a user