From 730f9a9d32746383317e33346c2b91da85ede535 Mon Sep 17 00:00:00 2001 From: Zack Schuster Date: Thu, 29 Sep 2022 00:28:55 -0700 Subject: [PATCH] build: migrate website compilation logic to gulpfile --- Gulpfile.js | 244 +++++++++++++++++++++++++++- website/js/build.js | 378 -------------------------------------------- 2 files changed, 242 insertions(+), 380 deletions(-) delete mode 100755 website/js/build.js diff --git a/Gulpfile.js b/Gulpfile.js index 5387f61..b4b9de0 100644 --- a/Gulpfile.js +++ b/Gulpfile.js @@ -1,6 +1,10 @@ +import { existsSync } from 'node:fs'; import { writeFile, readFile, rm, mkdir } from 'node:fs/promises'; +import { URL } from 'node:url'; import gulp from 'gulp'; +import kidif from 'kidif'; +import mustache from 'mustache'; import sass from 'sass'; import { rollup } from 'rollup'; import { terser } from 'rollup-plugin-terser'; @@ -16,7 +20,7 @@ const banner = `/** @preserve */`; export const build = gulp.series(resetDistFolder, gulp.parallel(buildJs, buildCss), buildWebsite); -export const watch = () => gulp.watch(['data', 'examples', 'lib', 'templates', 'website'], build); +export const watch = () => gulp.watch(['data', 'examples', 'lib', 'templates', 'website/css', 'website/js'], build); export default build; async function resetDistFolder() { @@ -44,5 +48,241 @@ async function buildCss() { } async function buildWebsite() { - await import('./website/js/build.js'); + const docs = JSON.parse(await readFile(new URL('./data/docs.json', import.meta.url), 'utf-8')); + const { version } = JSON.parse(await readFile(new URL('./package.json', import.meta.url), 'utf-8')); + + const encoding = 'utf-8'; + const chessboardJsScript = ``; + + const [ + headTemplate, + docsTemplate, + downloadTemplate, + examplesTemplate, + homepageTemplate, + singleExampleTemplate, + licensePageTemplate, + headerTemplate, + footerTemplate, + ] = await Promise.all([ + readFile('templates/_head.mustache', encoding), + readFile('templates/docs.mustache', encoding), + readFile('templates/download.mustache', encoding), + readFile('templates/examples.mustache', encoding), + readFile('templates/homepage.mustache', encoding), + readFile('templates/single-example.mustache', encoding), + readFile('templates/license.mustache', encoding), + readFile('templates/_header.mustache', encoding), + readFile('templates/_footer.mustache', encoding), + ]); + + // grab the examples + const examples = kidif('examples/*.example'); + const examplesGroups = [ + { + name: 'Basic Usage', + examples: [1000, 1001, 1002, 1003, 1004] + }, + { + name: 'Config', + examples: [2000, 2044, 2063, 2001, 2002, 2003, 2082, 2004, 2030, 2005, 2006] + }, + { + name: 'Methods', + examples: [3000, 3001, 3002, 3003, 3004, 3005, 3006, 3007] + }, + { + name: 'Events', + examples: [4000, 4001, 4002, 4003, 4004, 4005, 4006, 4011, 4012] + }, + { + name: 'Integration', + examples: [5000, 5001, 5002, 5003, 5004, 5005] + } + ]; + + if (!existsSync('website/examples')) { + await mkdir('website/examples'); + } + + await Promise.all([ + writeFile('website/index.html', mustache.render(homepageTemplate, { + chessboardJsScript, + example2: ` + const board2 = new Chessboard('board2', { + draggable: true, + dropOffBoard: 'trash', + sparePieces: true + }) + + document.getElementById('startBtn').onclick = () => board2.start() + document.getElementById('clearBtn').onclick = () => board2.clear() + `, + footer: footerTemplate, + head: mustache.render(headTemplate, { pageTitle: 'Homepage', version }), + version + }), encoding), + + writeFile('website/examples.html', mustache.render(examplesTemplate, { + chessboardJsScript, + examplesJavaScript: buildExamplesJS(), + footer: footerTemplate, + head: mustache.render(headTemplate, { pageTitle: 'Examples', version }), + header: mustache.render(headerTemplate, { examplesActive: true, version }), + nav: buildExamplesNavHTML(), + version + }), encoding), + + writeFile('website/docs.html', mustache.render(docsTemplate, { + configTableRows: docs.config.reduce(function (html, prop) { + if (typeof prop === 'string') return html; + + html += ``; // table row + html += `${buildPropertyAndTypeHTML('config', prop.name, prop.type)}`; // property and type + html += `

${prop.default || 'n/a'}

`; // default + html += `${buildDescriptionHTML(prop.desc)}`; // description + html += `${buildExamplesCellHTML(prop.examples)}`; // examples + + return html + ''; + }, ''), + errorRows: docs.errors.reduce(function (html, error) { + if (typeof error === 'string') return html; + + html += ``; // table row + html += `

${error.id}

`; // id + html += `

${error.desc}

`; // desc + + // more information + if (error.fix) { + html += `${Array.isArray(error.fix) ? error.fix.map(p => `

${p}

`).join('') : `

${error.fix}

`}`; + } else { + html += 'n/a'; + } + + return html + ''; + }, ''), + methodTableRows: docs.methods.reduce(function (html, method) { + if (typeof method === 'string') return html; + + const nameNoParens = method.name.replace(/\(.+$/, ''); + + html += method.noId ? '' : ``; // table row + html += `

${method.name}

`; // name + html += Array.isArray(method.args) ? `${method.args.map((arg) => '

' + arg[1] + '

').join('')}` : 'none'; // args + html += `${buildDescriptionHTML(method.desc)}`; // description + html += `${buildExamplesCellHTML(method.examples)}`; // examples + + return html + ''; + }, ''), + footer: footerTemplate, + head: mustache.render(headTemplate, { pageTitle: 'Documentation', version }), + header: mustache.render(headerTemplate, { docsActive: true, version }), + version, + }), encoding), + + writeFile('website/download.html', mustache.render(downloadTemplate, { + footer: footerTemplate, + head: mustache.render(headTemplate, { pageTitle: 'Download', version }), + header: mustache.render(headerTemplate, { downloadActive: true, version }), + version + }), encoding), + + writeFile('website/license.html', mustache.render(licensePageTemplate, { version }), encoding), + + Promise.all(examples.map(example => { + if ((example.id + '').startsWith('5')) { + example.includeChessJS = true; + } + example.chessboardJsScript = chessboardJsScript; + return writeFile(`website/examples/${example.id}.html`, mustache.render(singleExampleTemplate, { version, ...example }), encoding); + })), + ]); + + // ----------------------------------------------------------------------------- + // HTML + // ----------------------------------------------------------------------------- + + function buildExamplesNavHTML() { + let html = ''; + examplesGroups.forEach(function (group, idx) { + const groupNum = idx + 1; + html += '

' + group.name + '

' + + ''; + }); + return html; + } + + function buildExamplesJS() { + let txt = 'window.CHESSBOARD_EXAMPLES = {}\n\n'; + + examples.forEach(function (ex) { + txt += 'CHESSBOARD_EXAMPLES["' + ex.id + '"] = {\n' + + ' description: ' + JSON.stringify(ex.description) + ',\n' + + ' html: ' + JSON.stringify(ex.html) + ',\n' + + ' name: ' + JSON.stringify(ex.name) + ',\n' + + ' jsStr: ' + JSON.stringify(ex.js) + ',\n' + + ' jsFn: function () {\n' + ex.js + '\n }\n' + + '};\n\n'; + }); + + return txt; + } + + function buildPropertyAndTypeHTML(section, name, type) { + let html = '

' + + '' + name + '

' + + '

' + buildTypeHTML(type) + '

'; + return html; + } + + function buildTypeHTML(type) { + if (!Array.isArray(type)) { + type = [type]; + } + + let html = ''; + for (var i = 0; i < type.length; i++) { + if (i !== 0) { + html += ' or
'; + } + html += type[i]; + } + + return html; + } + + function buildDescriptionHTML(desc) { + if (!Array.isArray(desc)) { + desc = [desc]; + } + + let html = ''; + desc.forEach(function (d) { + html += '

' + d + '

'; + }); + + return html; + } + + function buildExamplesCellHTML(examplesIds) { + if (!Array.isArray(examplesIds)) { + examplesIds = [examplesIds]; + } + + let html = ''; + examplesIds.forEach(function (exampleId) { + const example = examples.find(x => x.id === exampleId); + if (!example) return; + html += '

' + example.name + '

'; + }); + + return html; + } } diff --git a/website/js/build.js b/website/js/build.js deleted file mode 100755 index f7cf38c..0000000 --- a/website/js/build.js +++ /dev/null @@ -1,378 +0,0 @@ -#! /usr/bin/env node - -/* eslint-env node */ - -// ----------------------------------------------------------------------------- -// This file builds the contents of the website/ folder. -// ----------------------------------------------------------------------------- - -// libraries -import fs from 'node:fs'; -import { readFile } from 'node:fs/promises'; - -import kidif from 'kidif'; -import mustache from 'mustache'; - - -const docs = JSON.parse(await readFile(new URL('../../data/docs.json', import.meta.url), 'utf-8')); -const { version } = JSON.parse(await readFile(new URL('../../package.json', import.meta.url), 'utf-8')); - -const encoding = 'utf-8'; -const chessboardJsScript = ``; - -// grab some mustache templates -const docsTemplate = fs.readFileSync('templates/docs.mustache', encoding); -const downloadTemplate = fs.readFileSync('templates/download.mustache', encoding); -const examplesTemplate = fs.readFileSync('templates/examples.mustache', encoding); -const homepageTemplate = fs.readFileSync('templates/homepage.mustache', encoding); -const singleExampleTemplate = fs.readFileSync('templates/single-example.mustache', encoding); -const licensePageTemplate = fs.readFileSync('templates/license.mustache', encoding); -const headTemplate = fs.readFileSync('templates/_head.mustache', encoding); -const headerTemplate = fs.readFileSync('templates/_header.mustache', encoding); -const footerTemplate = fs.readFileSync('templates/_footer.mustache', encoding); - -// grab the examples -const examplesArr = kidif('examples/*.example'); -console.assert(examplesArr, 'Could not load the Example files'); -console.assert(examplesArr.length > 1, 'Zero examples loaded'); - -const examplesObj = examplesArr.reduce(function (examplesObj, example) { - examplesObj[example.id] = example; - return examplesObj; -}, {}); - -const examplesGroups = [ - { - name: 'Basic Usage', - examples: [1000, 1001, 1002, 1003, 1004] - }, - { - name: 'Config', - examples: [2000, 2044, 2063, 2001, 2002, 2003, 2082, 2004, 2030, 2005, 2006] - }, - { - name: 'Methods', - examples: [3000, 3001, 3002, 3003, 3004, 3005, 3006, 3007] - }, - { - name: 'Events', - examples: [4000, 4001, 4002, 4003, 4004, 4005, 4006, 4011, 4012] - }, - { - name: 'Integration', - examples: [5000, 5001, 5002, 5003, 5004, 5005] - } -]; - -function writeHomepage() { - const headHTML = mustache.render(headTemplate, { pageTitle: 'Homepage', version }); - - const html = mustache.render(homepageTemplate, { - chessboardJsScript, - example2: ` - const board2 = new Chessboard('board2', { - draggable: true, - dropOffBoard: 'trash', - sparePieces: true - }) - - document.getElementById('startBtn').onclick = () => board2.start() - document.getElementById('clearBtn').onclick = () => board2.clear() - `.trim(), - footer: footerTemplate, - head: headHTML, - version - }); - fs.writeFileSync('website/index.html', html, encoding); -} - -function writeExamplesPage() { - const headHTML = mustache.render(headTemplate, { pageTitle: 'Examples', version }); - const headerHTML = mustache.render(headerTemplate, { examplesActive: true, version }); - - const html = mustache.render(examplesTemplate, { - chessboardJsScript, - examplesJavaScript: buildExamplesJS(), - footer: footerTemplate, - head: headHTML, - header: headerHTML, - nav: buildExamplesNavHTML(), - version - }); - fs.writeFileSync('website/examples.html', html, encoding); -} - -const configTableRowsHTML = docs.config.reduce(function (html, itm) { - if (typeof itm === 'string') return html; - return html + buildConfigDocsTableRowHTML('config', itm); -}, ''); - -const methodTableRowsHTML = docs.methods.reduce(function (html, itm) { - if (typeof itm === 'string') return html; - return html + buildMethodRowHTML(itm); -}, ''); - -const errorRowsHTML = docs.errors.reduce(function (html, itm) { - if (typeof itm === 'string') return html; - return html + buildErrorRowHTML(itm); -}, ''); - -function isIntegrationExample(example) { - return (example.id + '').startsWith('5'); -} - -function writeSingleExamplePage(example) { - if (isIntegrationExample(example)) { - example.includeChessJS = true; - } - example.chessboardJsScript = chessboardJsScript; - const html = mustache.render(singleExampleTemplate, { version, ...example }); - if (!fs.existsSync('website/examples')) { - fs.mkdirSync('website/examples'); - } - fs.writeFileSync('website/examples/' + example.id + '.html', html, encoding); -} - -function writeSingleExamplesPages() { - examplesArr.forEach(writeSingleExamplePage); -} - -function writeDocsPage() { - const headHTML = mustache.render(headTemplate, { pageTitle: 'Documentation', version }); - const headerHTML = mustache.render(headerTemplate, { docsActive: true, version }); - - const html = mustache.render(docsTemplate, { - configTableRows: configTableRowsHTML, - errorRows: errorRowsHTML, - footer: footerTemplate, - head: headHTML, - header: headerHTML, - methodTableRows: methodTableRowsHTML, - version, - }); - fs.writeFileSync('website/docs.html', html, encoding); -} - -function writeDownloadPage() { - const headHTML = mustache.render(headTemplate, { pageTitle: 'Download', version }); - const headerHTML = mustache.render(headerTemplate, { downloadActive: true, version }); - - const html = mustache.render(downloadTemplate, { - footer: footerTemplate, - head: headHTML, - header: headerHTML, - version - }); - fs.writeFileSync('website/download.html', html, encoding); -} - -function writeLicensePage() { - const html = mustache.render(licensePageTemplate, { version }); - fs.writeFileSync('website/license.html', html, encoding); -} - -function writeWebsite() { - writeHomepage(); - writeExamplesPage(); - writeSingleExamplesPages(); - writeDocsPage(); - writeDownloadPage(); - writeLicensePage(); -} - -writeWebsite(); - -// ----------------------------------------------------------------------------- -// HTML -// ----------------------------------------------------------------------------- - -function buildExampleGroupHTML(idx, groupName, examplesInGroup) { - const groupNum = idx + 1; - let html = '

' + groupName + '

' + - ''; - - return html; -} - -function buildExamplesNavHTML() { - let html = ''; - examplesGroups.forEach(function (group, idx) { - html += buildExampleGroupHTML(idx, group.name, group.examples); - }); - return html; -} - -function buildExamplesJS() { - let txt = 'window.CHESSBOARD_EXAMPLES = {}\n\n'; - - examplesArr.forEach(function (ex) { - txt += 'CHESSBOARD_EXAMPLES["' + ex.id + '"] = {\n' + - ' description: ' + JSON.stringify(ex.description) + ',\n' + - ' html: ' + JSON.stringify(ex.html) + ',\n' + - ' name: ' + JSON.stringify(ex.name) + ',\n' + - ' jsStr: ' + JSON.stringify(ex.js) + ',\n' + - ' jsFn: function () {\n' + ex.js + '\n }\n' + - '};\n\n'; - }); - - return txt; -} - -function buildConfigDocsTableRowHTML(propType, prop) { - let html = ''; - - // table row - html += ''; - - // property and type - html += '' + buildPropertyAndTypeHTML(propType, prop.name, prop.type) + ''; - - // default - html += '

' + buildDefaultHTML(prop.default) + '

'; - - // description - html += '' + buildDescriptionHTML(prop.desc) + ''; - - // examples - html += '' + buildExamplesCellHTML(prop.examples) + ''; - - html += ''; - - return html; -} - -function buildMethodRowHTML(method) { - const nameNoParens = method.name.replace(/\(.+$/, ''); - - let html = ''; - - // table row - if (method.noId) { - html += ''; - } else { - html += ''; - } - - // name - html += '

' + - '' + method.name + '

'; - - // args - if (method.args) { - html += ''; - method.args.forEach(function (arg) { - html += '

' + arg[1] + '

'; - }); - html += ''; - } else { - html += 'none'; - } - - // description - html += '' + buildDescriptionHTML(method.desc) + ''; - - // examples - html += '' + buildExamplesCellHTML(method.examples) + ''; - - html += ''; - - return html; -} - -function buildPropertyAndTypeHTML(section, name, type) { - let html = '

' + - '' + name + '

' + - '

' + buildTypeHTML(type) + '

'; - return html; -} - -function buildTypeHTML(type) { - if (!Array.isArray(type)) { - type = [type]; - } - - let html = ''; - for (var i = 0; i < type.length; i++) { - if (i !== 0) { - html += ' or
'; - } - html += type[i]; - } - - return html; -} - -function buildDescriptionHTML(desc) { - if (!Array.isArray(desc)) { - desc = [desc]; - } - - let html = ''; - desc.forEach(function (d) { - html += '

' + d + '

'; - }); - - return html; -} - -function buildDefaultHTML(defaultValue) { - if (!defaultValue) { - return 'n/a'; - } - return defaultValue; -} - -function buildExamplesCellHTML(examplesIds) { - if (!Array.isArray(examplesIds)) { - examplesIds = [examplesIds]; - } - - let html = ''; - examplesIds.forEach(function (exampleId) { - var example = examplesObj[exampleId]; - if (!example) return; - html += '

' + example.name + '

'; - }); - - return html; -} - -function buildErrorRowHTML(error) { - let html = ''; - - // table row - html += ''; - - // id - html += '' + - '

' + error.id + '

'; - - // desc - html += '

' + error.desc + '

'; - - // more information - if (error.fix) { - if (!Array.isArray(error.fix)) { - error.fix = [error.fix]; - } - - html += ''; - error.fix.forEach(function (p) { - html += '

' + p + '

'; - }); - html += ''; - } else { - html += 'n/a'; - } - - html += ''; - - return html; -}