/* This is the web builder script that generates the web files. Run using `npm run webber`. */ // Load modules const fs = require('fs-extra'), path = require('path'), chalk = require('chalk'), md = require('markdown-it')(), minify = require('html-minifier').minify; const util = require('./util'); var Prism = require('prismjs'); const minifyHTML = str => minify(str, { collapseBooleanAttributes: true, collapseWhitespace: true, decodeEntities: false, minifyCSS: true, minifyJS: true, keepClosingSlash: true, processConditionalComments: true, removeAttributeQuotes: false, removeComments: true, removeEmptyAttributes: false, removeOptionalTags: false, removeScriptTypeAttributes: false, removeStyleLinkTypeAttributes: false, trimCustomFragments: true }); const unescapeHTML = str => str.replace( /&|<|>|'|"/g, tag => ({ '&': '&', '<': '<', '>': '>', ''': "'", '"': '"' }[tag] || tag) ); const generateSnippetCard = ( snippetList, snippetKey, addCornerTag = false ) => `
${ addCornerTag ? `
` : '' } ${md .render(`\n${addCornerTag ? snippetList[snippetKey[0] + '.md'] : snippetList[snippetKey[0]]}`) .replace(/

/g, '

') .replace( /
/m,
      '
'
    )
    .replace(
      /
([^\0]*?)<\/code><\/pre>/gm,
      (match, p1) =>
        `
${Prism.highlight(
          unescapeHTML(p1),
          Prism.languages.javascript
        )}
` ) .replace(/<\/div>\s*
\s+
examples
/g, '

'); for (let taggedSnippet of Object.entries(tagDbData).filter(v => v[1][0] === tag)) localOutput += generateSnippetCard(snippets, taggedSnippet, true); // Add the ending static part localOutput += `\n${endPart + '\n'}`; // Optimize punctuation nodes localOutput = util.optimizeNodes( localOutput, /([^\0<]*?)<\/span>([\n\r\s]*)([^\0]*?)<\/span>/gm, (match, p1, p2, p3) => `${p1}${p2}${p3}` ); // Optimize operator nodes localOutput = util.optimizeNodes( localOutput, /([^\0<]*?)<\/span>([\n\r\s]*)([^\0]*?)<\/span>/gm, (match, p1, p2, p3) => `${p1}${p2}${p3}` ); // Optimize keyword nodes localOutput = util.optimizeNodes( localOutput, /([^\0<]*?)<\/span>([\n\r\s]*)([^\0]*?)<\/span>/gm, (match, p1, p2, p3) => `${p1}${p2}${p3}` ); pagesOutput.push({ tag: tag, content: localOutput }); } // Minify output pagesOutput.forEach(page => { page.content = minifyHTML(page.content); fs.writeFileSync( path.join(docsPath, (page.tag === 'array' ? 'index' : page.tag) + '.html'), page.content ); console.log( `${chalk.green('SUCCESS!')} ${page.tag === 'array' ? 'index' : page.tag}.html file generated!` ); }); } catch (err) { // Handle errors (hopefully not!) console.log(`${chalk.red('ERROR!')} During category page generation: ${err}`); process.exit(1); } // Create the output for the archive.html file try { // Add the static part archivedOutput += `${archivedStartPart}\n`; // Filter README.md from folder const filteredArchivedSnippets = filterSnippets(archivedSnippets, ['README.md']); // Generate archived snippets from md files for (let snippet of Object.entries(filteredArchivedSnippets)) archivedOutput += generateSnippetCard(filteredArchivedSnippets, snippet, false); // Optimize punctuation nodes archivedOutput = util.optimizeNodes( archivedOutput, /([^\0<]*?)<\/span>([\n\r\s]*)([^\0]*?)<\/span>/gm, (match, p1, p2, p3) => `${p1}${p2}${p3}` ); // Optimize operator nodes archivedOutput = util.optimizeNodes( archivedOutput, /([^\0<]*?)<\/span>([\n\r\s]*)([^\0]*?)<\/span>/gm, (match, p1, p2, p3) => `${p1}${p2}${p3}` ); // Optimize keyword nodes archivedOutput = util.optimizeNodes( archivedOutput, /([^\0<]*?)<\/span>([\n\r\s]*)([^\0]*?)<\/span>/gm, (match, p1, p2, p3) => `${p1}${p2}${p3}` ); archivedOutput += `${archivedEndPart}`; // Generate and minify 'archive.html' file const minifiedArchivedOutput = minifyHTML(archivedOutput); fs.writeFileSync(path.join(docsPath, 'archive.html'), minifiedArchivedOutput); console.log(`${chalk.green('SUCCESS!')} archive.html file generated!`); } catch (err) { console.log(`${chalk.red('ERROR!')} During archive.html generation: ${err}`); process.exit(1); } // Create the output for the glossary.html file try { // Add the static part glossaryOutput += `${glossaryStartPart}\n`; // Filter README.md from folder const filteredGlossarySnippets = filterSnippets(glossarySnippets, ['README.md']); // Generate glossary snippets from md files for (let snippet of Object.entries(filteredGlossarySnippets)) glossaryOutput += '
' + md .render(`\n${filteredGlossarySnippets[snippet[0]]}`) .replace(/

/g, '

') + '
'; glossaryOutput += `${glossaryEndPart}`; // Generate and minify 'glossary.html' file const minifiedGlossaryOutput = minifyHTML(glossaryOutput); fs.writeFileSync(path.join(docsPath, 'glossary.html'), minifiedGlossaryOutput); console.log(`${chalk.green('SUCCESS!')} glossary.html file generated!`); } catch (err) { console.log(`${chalk.red('ERROR!')} During glossary.html generation: ${err}`); process.exit(1); } // Copy static files staticFiles.forEach(f => { try { fs.copyFileSync(path.join(staticPartsPath, f), path.join(docsPath, f)); console.log(`${chalk.green('SUCCESS!')} ${f} file copied!`); } catch (err) { console.log(`${chalk.red('ERROR!')} During ${f} copying: ${err}`); process.exit(1); } }); // Log the time taken console.timeEnd('Webber');