mirror of
https://github.com/shoelace-style/webawesome.git
synced 2026-01-12 04:09:12 +00:00
269 lines
6.8 KiB
JavaScript
269 lines
6.8 KiB
JavaScript
import Eleventy from '@11ty/eleventy';
|
|
|
|
import copy from 'recursive-copy';
|
|
|
|
import chalk from 'chalk';
|
|
import { deleteAsync } from 'del';
|
|
import { join } from 'path';
|
|
import { getCdnDir, getDocsDir, getEleventyConfigPath, getSiteDir } from './utils.js';
|
|
|
|
let eleventyBuildResolver;
|
|
let eleventyBuildPromise;
|
|
|
|
function queueBuild() {
|
|
eleventyBuildPromise = new Promise(resolve => {
|
|
eleventyBuildResolver = resolve;
|
|
});
|
|
}
|
|
|
|
// 11ty
|
|
export async function createEleventy(options = {}) {
|
|
let { isIncremental, isDeveloping, rootDir } = options;
|
|
|
|
isDeveloping ??= process.argv.includes('--develop');
|
|
isIncremental ??= isDeveloping && !process.argv.includes('--no-incremental');
|
|
|
|
const eleventy = new Eleventy(rootDir || getDocsDir(), getSiteDir(), {
|
|
quietMode: true,
|
|
configPath: getEleventyConfigPath(),
|
|
config: eleventyConfig => {
|
|
if (isDeveloping || isIncremental) {
|
|
eleventyConfig.setUseTemplateCache(false);
|
|
|
|
eleventyConfig.on('eleventy.before', function () {
|
|
queueBuild();
|
|
});
|
|
eleventyConfig.on('eleventy.beforeWatch', async function () {
|
|
queueBuild();
|
|
});
|
|
eleventyConfig.on('eleventy.after', async function () {
|
|
eleventyBuildResolver();
|
|
});
|
|
}
|
|
},
|
|
source: 'script',
|
|
runMode: isIncremental ? 'watch' : 'build',
|
|
});
|
|
eleventy.setIncrementalBuild(isIncremental);
|
|
|
|
await eleventy.init();
|
|
|
|
eleventy.logger.isChalkEnabled = false;
|
|
eleventy.logger.overrideLogger(new CustomLogger());
|
|
|
|
if (isIncremental) {
|
|
await eleventy.watch();
|
|
|
|
process.on('SIGINT', async () => {
|
|
await eleventy.stopWatch();
|
|
process.exitCode = 0;
|
|
});
|
|
}
|
|
|
|
return eleventy;
|
|
}
|
|
|
|
/**
|
|
* Generates the documentation site.
|
|
*/
|
|
export async function generateDocs(options = {}) {
|
|
let { spinner, isIncremental, isDeveloping } = options;
|
|
|
|
isDeveloping ??= process.argv.includes('--develop');
|
|
isIncremental ??= isDeveloping && !process.argv.includes('--no-incremental');
|
|
|
|
/**
|
|
* Used by the webawesome-app to skip doc generation since it will do its own.
|
|
*/
|
|
if (process.env.SKIP_ELEVENTY === 'true') {
|
|
return;
|
|
}
|
|
|
|
let eleventy = globalThis.eleventy;
|
|
|
|
spinner?.start?.('Writing the docs');
|
|
|
|
const outputs = {
|
|
warn: [],
|
|
};
|
|
|
|
function stubConsole(key) {
|
|
const originalFn = console[key];
|
|
console[key] = function (...args) {
|
|
outputs[key].push(...args);
|
|
};
|
|
return originalFn;
|
|
}
|
|
|
|
// Works around a bug in 11ty where it still prints warnings despite the logger being overriden and in quietMode.
|
|
const originalWarn = stubConsole('warn');
|
|
|
|
let output = '';
|
|
|
|
try {
|
|
if (isIncremental) {
|
|
if (!globalThis.eleventy) {
|
|
// First run
|
|
globalThis.eleventy = await createEleventy(options);
|
|
eleventy = globalThis.eleventy;
|
|
output = chalk.gray(`(${eleventy.logFinished()})`);
|
|
} else {
|
|
// eleventy incremental does its own writing, so we just kinda trust it for right now.
|
|
eleventy = globalThis.eleventy;
|
|
|
|
await eleventyBuildPromise;
|
|
let info = eleventy.logger.logger.outputs.log;
|
|
|
|
// TODO: The first write with incremental seems to be 1 behind. Not sure why. But its good enough for now.
|
|
info = info.filter(line => {
|
|
return !line.includes('Watching');
|
|
});
|
|
const lastLine = info[info.length - 1];
|
|
output = chalk.gray(`(${info.join('')})`);
|
|
eleventy.logger.logger.reset();
|
|
}
|
|
} else {
|
|
// Cleanup
|
|
await deleteAsync(getSiteDir());
|
|
|
|
globalThis.eleventy = await createEleventy(options);
|
|
eleventy = globalThis.eleventy;
|
|
|
|
// Write it
|
|
await eleventy.write();
|
|
output = chalk.gray(`(${eleventy.logFinished()})`);
|
|
}
|
|
|
|
// Copy dist (production only)
|
|
if (!isDeveloping) {
|
|
await copy(getCdnDir(), join(getSiteDir(), 'dist'));
|
|
}
|
|
|
|
if (spinner) {
|
|
spinner.succeed(`Writing the docs ${output}`);
|
|
} else {
|
|
console.log(`Writing the docs ${output}`);
|
|
}
|
|
} catch (error) {
|
|
console.warn = originalWarn;
|
|
|
|
console.error('\n\n' + chalk.red(error) + '\n');
|
|
|
|
if (spinner) {
|
|
spinner.fail(chalk.red(`Error while writing the docs.`));
|
|
} else {
|
|
console.error(chalk.red(`Error while writing the docs.`));
|
|
}
|
|
|
|
if (!isDeveloping) {
|
|
process.exit(1);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Much of this code is taken from 11ty's ConsoleLogger here:
|
|
* https://github.com/11ty/eleventy/blob/main/src/Util/ConsoleLogger.js
|
|
*
|
|
* Patches 11ty logger so it doesnt log everything, but we can still use its output for our own build.
|
|
* @typedef {'error'|'log'|'warn'|'info'} LogType
|
|
*/
|
|
class CustomLogger {
|
|
#outputStream;
|
|
|
|
constructor() {
|
|
this.reset();
|
|
}
|
|
|
|
flush() {
|
|
Object.keys(this.outputs).forEach(outputType => {
|
|
console[outputType](this.outputs[outputType].join(''));
|
|
});
|
|
this.reset();
|
|
}
|
|
|
|
reset() {
|
|
this.outputs = {
|
|
log: [],
|
|
info: [],
|
|
warn: [],
|
|
error: [],
|
|
};
|
|
}
|
|
|
|
/** @param {string} msg */
|
|
log(msg) {
|
|
this.message(msg);
|
|
}
|
|
|
|
/**
|
|
* @typedef LogOptions
|
|
* @property {string} message
|
|
* @property {string=} prefix
|
|
* @property {LogType=} type
|
|
* @property {string=} color
|
|
* @property {boolean=} force
|
|
* @param {LogOptions} options
|
|
*/
|
|
logWithOptions({ message, type, prefix, color, force }) {
|
|
this.message(message, type, color, force, prefix);
|
|
}
|
|
|
|
/** @param {string} msg */
|
|
forceLog(msg) {
|
|
this.message(msg, undefined, undefined, true);
|
|
}
|
|
|
|
/** @param {string} msg */
|
|
info(msg) {
|
|
this.message(msg, 'info', 'blue');
|
|
}
|
|
|
|
/** @param {string} msg */
|
|
warn(msg) {
|
|
this.message(msg, 'warn', 'yellow');
|
|
}
|
|
|
|
/** @param {string} msg */
|
|
error(msg) {
|
|
this.message(msg, 'error', 'red');
|
|
}
|
|
|
|
get outputStream() {
|
|
if (!this.#outputStream) {
|
|
this.#outputStream = new Readable({
|
|
read() {},
|
|
});
|
|
}
|
|
return this.#outputStream;
|
|
}
|
|
|
|
/** @param {string} msg */
|
|
toStream(msg) {
|
|
this.outputStream.push(msg);
|
|
}
|
|
|
|
closeStream() {
|
|
this.outputStream.push(null);
|
|
return this.outputStream;
|
|
}
|
|
|
|
/**
|
|
* Formats the message to log.
|
|
*
|
|
* @param {string} message - The raw message to log.
|
|
* @param {LogType} [type='log'] - The error level to log.
|
|
* @param {string|undefined} [chalkColor=undefined] - Color name or falsy to disable
|
|
* @param {boolean} [forceToConsole=false] - Enforce a log on console instead of specified target.
|
|
*/
|
|
message(message, type = 'log', chalkColor = undefined, _forceToConsole = false, prefix = '') {
|
|
// if (chalkColor && this.isChalkEnabled) {
|
|
// message = `${chalk.gray(prefix)} ${message.split("\n").join(`\n${chalk.gray(prefix)} `)}`;
|
|
// this.outputs[type].push(chalk[chalkColor](message));
|
|
// } else {
|
|
message = `${prefix}${message.split('\n').join(`\n${prefix}`)}`;
|
|
this.outputs[type].push(message);
|
|
// }
|
|
}
|
|
}
|