UNPKG

join2

Version:

combine stream chunks pairwise

170 lines (148 loc) 5.12 kB
#!/usr/bin/env node /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 'use strict' const { execFileSync } = require('child_process') const fsx = require('fs-extra') const getopts = require('getopts') const path = require('path') const pump = require('pump') const pumpify = require('pumpify') const { Transform } = require('readable-stream') const snippin = require('snippin') const split2 = require('split2') const tmp = require('tmp') const join2 = require('../index.js') const ERR_USAGE = 1 const usage = `Usage: render-readme.js [-h] [FORMAT] Render the README file to the given FORMAT: - markdown write the output to README.md - html write the output to public/index.html The default format is "markdown". Options: -h, --help do nothing and show this usage message instead` const fatalUsage = () => { console.warn(usage) process.exit(ERR_USAGE) } const opts = getopts(process.argv.slice(2), { alias: { 'h': 'help' }, boolean: ['h'], unknown: opt => { console.warn(`Unknown option ${JSON.stringify(opt)}`) fatalUsage() } }) if (opts._.length > 1) { fatalUsage() } if (opts.h) { console.log(usage) process.exit(0) } let doccoLayout const fmt = opts._.length === 1 ? opts._[0] : 'markdown' switch (fmt) { case 'html': doccoLayout = 'linear' break case 'markdown': doccoLayout = 'plain-markdown' break default: fatalUsage() } const repoRoot = path.normalize(path.join(__dirname, '..')) const tmpDir = tmp.dirSync() const doccoOutDir = `${tmpDir.name}/out` // Docco doesn't expose an API, and only works on whole files, so we have to // do some gymnastics to work around its limitations. Here's what we'll do: // // 1. Convert the source README.in document into "javascript" by adding // "// " in front of every line, i.e. converting the whole file to one big // javascript comment. // 2. Expand snippets // 3. Rewrite relative requires to something copy-pastable // 4. Call docco on this "javascript" file to get the final document we want. const commentOut = new Transform({ transform (line, encoding, callback) { line = line.toString() const space = line.length ? ' ' : '' callback(null, '//' + space + line) } }) // There's some require expressions in the examples that reference files via // relative paths; those can't be copy-pasted as-is by users of this library. // We'll replace those by what they would look like to the rest of the world // installing this package from npmjs.com. const rewriteRelativeRequires = new Transform({ transform (line, encoding, callback) { line = line.toString() const m = /require\('[./]+index\.js'\)/.exec(line) if (m !== null) { line = line.replace(m[0], "require('join2')") } callback(null, line) } }) pump( fsx.createReadStream(`${repoRoot}/README.in`), split2(/(\r\n|[\n\v\f\r\x85\u2028\u2029])/), join2(), commentOut, snippin(repoRoot), rewriteRelativeRequires, fsx.createWriteStream(`${tmpDir.name}/join2`), err => { if (err) throw err const doccoExec = `${repoRoot}/node_modules/.bin/docco` const doccoArgs = ['-e', '.js', '-o', doccoOutDir, '-l', doccoLayout, 'join2'] execFileSync(doccoExec, doccoArgs, { cwd: tmpDir.name }) if (fmt === 'html') { fsx.renameSync(`${doccoOutDir}/join2.html`, `${doccoOutDir}/index.html`) fsx.copySync(doccoOutDir, `${repoRoot}/public`) } else { // Docco puts code blocks between "```" fences. But gitub/gitlab/npm will // only do syntax hightlighting if they start with "```javascript". Syntax // hightlighting is nice, so we'll pipe the docco output through a // transform that adds it before writing to the final destination, i.e. // README.md. // // Docco also adds a lot of empty lines, so we'll collapse multiple // consecutive empty lines into one while we're at it. const addSyntaxHighlighting = pumpify( split2(/(\r\n|[\n\v\f\r\x85\u2028\u2029])/), join2(), new Transform({ transform (line, encoding, callback) { line = line.toString() // Add syntax highlighting if (/^```\s*$/.test(line)) { if (!this.even) line = line.replace('```', '```javascript') this.even = !this.even } // Collapse blank lines if (/^\s*$/.test(line)) { if (this.contentStarted && !this.blankLine) this.blankLine = line line = '' } else { this.contentStarted = true if (this.blankLine) line = this.blankLine + line this.blankLine = '' } callback(null, line) } }) ) pump( fsx.createReadStream(`${doccoOutDir}/join2.html`), addSyntaxHighlighting, fsx.createWriteStream(`${repoRoot}/README.md`), err => { if (err) throw err } ) } } )