fluent-skeleton
Version:
327 lines (278 loc) • 8.83 kB
JavaScript
const {resolve} = require('path')
const ChainedMap = require('flipchain/ChainedMapExtendable')
const CLI = require('fluent-cli')
const Script = require('script-chain')
const toarr = require('to-arr')
const execa = require('execa')
const globby = require('globby')
const File = require('file-chain')
const fwf = require('funwithflags')
const log = require('fliplog')
const {exists} = require('flipfile')
const pkg = require('./pkg')
const argvs = fwf(process.argv.slice(2))
/**
* https://github.com/yeoman/generator/blob/master/jsdoc.json
*
* @desc takes in argv, calls method on CLI
* @param {AppCli} cli
* @return {void}
*/
function handle(cli) {
log.registerCatch()
delete argvs._
const argv = Object.values(argvs)
const argk = Object.keys(argvs)
log.emoji('flag').cyan('argv/flags:').data(argvs).echo()
argk.forEach((method, i) => {
const val = argv[i]
log.emoji('phone').blue('cli: ' + method).data(val).echo(true)
if (cli[method]) {
cli[method](val, argvs)
}
else {
log.emoji('find').blue('no method for: ' + method).data(val).echo(true)
}
})
}
class AppCLI extends ChainedMap {
/**
* @since 0.0.1
* @param {ChainedMap | *} parent
*/
constructor(parent) {
super(parent)
this.scriptChain = () => new Script()
}
setup() {
const pkgPath = resolve(this.dir, './package.json')
log.green('pkg: ').data({pkgPath, dir: this.dir}).echo(false)
this.pkgjson = require(pkgPath) // eslint-disable-line
return this
}
/**
* @since 0.0.1
* @param {string} dir
* @return {AppCLI} @chainable
*/
static init(dir) {
return new AppCLI(dir)
}
/**
* @since 0.0.1
* @tutorial https://github.com/nolanlawson/optimize-js
* @param {string} input
* @return {string} optimized output
*/
optimize(input) {
const optimizeJs = require('optimize-js')
return optimizeJs(input, {
sourceMap: true,
}) // now the output has source maps
}
/**
* @since 0.0.1
* @tutorial https://github.com/babel
* @param {string} string code source
* @param {Object} [config=null] babel options
* @return {string} transformed babel output
*/
babel(string, config = null) {
const babel = require('babel-core')
// result = babel.transform(str, {allowReturnOutsideFunction: true});
const parsedAst = babel.parse(string, {allowReturnOutsideFunction: true})
const {code, map, ast} = babel.transformFromAst(parsedAst, string, config)
return code
}
/**
* @since 0.0.1
* @tutorial https://github.com/prettier/prettier
* @param {string} code
* @param {Object} [config=null] prettier options
* @return {string} prettified output
*/
prettier(code, config = null) {
const prettier = require('prettier')
return prettier.format(code, {
// Indent lines with tabs
useTabs: false,
// Fit code within this line limit
printWidth: 80,
// Number of spaces it should use per tab
tabWidth: 2,
// If true, will use single instead of double quotes
singleQuote: true,
// Controls the printing of trailing commas wherever possible. Valid options:
// "none" - No trailing commas
// "es5" - Trailing commas where valid in ES5 (objects, arrays, etc)
// "all" - Trailing commas wherever possible (function arguments)
trailingComma: 'es5',
// Controls the printing of spaces inside object literals
bracketSpacing: true,
// If true, puts the `>` of a multi-line jsx element at the end of
// the last line instead of being alone on the next line
jsxBracketSameLine: false,
// Which parser to use. Valid options are "flow" and "babylon"
parser: 'babylon',
// Whether to add a semicolon at the end of every line (semi: true),
// or only at the beginning of lines that may introduce ASI failures (semi: false)
semi: false,
})
}
// --- docs ---
/**
* @since 0.0.1
* @see https://github.com/nhnent/tui.jsdoc-template
* @param {Array<string>} files
* @return {AppCli} @chainable
*/
jsdocs(files) {
files = this.docFiles(files)
const jsdoc = require('jsdoc-api')
let jsdocOpts = this.pkgjson.jsdoc || this.pkgjson.jsdocs
if (!jsdocOpts && exists(resolve(this.dir, './jsdoc.js'))) {
jsdocOpts = require(resolve(this.dir, './jsdoc.js')) // eslint-disable-line
}
if (!jsdocOpts && exists(resolve(this.dir, './jsdoc.json'))) {
jsdocOpts = require(resolve(this.dir, './jsdoc.json')) // eslint-disable-line
}
jsdocOpts.files = files
log.data({jsdocOpts}).text('jsdoc opts').echo()
jsdoc.explainSync(jsdocOpts)
return this
}
/**
* @since 0.0.1
* @TODO `typedoc --exclude 'loader/LoaderAPI.ts' --target es6 --excludeExternals --includeDeclarations --out tsdox src`
* @see https://www.npmjs.com/package/tsd-jsdoc
* @see http://ts2jsdoc.js.org/
* @param {Array<string>} files
* @return {AppCli} @chainable
*/
tsdocs(files) {
return this
}
/**
* @since 0.0.1
* https://github.com/Kegsay/flow-jsdoc
* @desc jsdocs with flow support
* @param {Array<string>} files
* @return {AppCli} @chainable
*/
flowdocs(files) {
files = this.docFiles(files)
const babel = require('babel-core')
files.forEach(file => {
const {code} = babel.transform('code', {
plugins: ['jsdoc'],
})
const content = code
log.cyan('writing docs').echo()
log.white('content: ' + content).data(file).echo()
})
return this
}
/**
* https://github.com/nhnent/tui.jsdoc-template
* @param {Array<string>} files
* @return {AppCli} @chainable
*/
doxdox(files) {
// jsdoc2md --config=jsdoc.json
// jsdoc2md --source src --config=jsdoc.json
// https://github.com/jsdoc3/jsdoc/blob/master/lib/jsdoc/env.js
// https://github.com/jsdoc3/jsdoc/blob/master/cli.js
// jsdoc src --recurse --template='node_modules/tui-jsdoc-template' --destination='docgen' --readme='README.md' ENV.conf.plugins="['node_modules/jsdoc-babel', 'plugins/markdown']"
// jsdoc --include 'src' --recurse --template='node_modules/tui-jsdoc-template' --destination='docgen' --readme='README.md'
//
// --template 'node_modules/tui-jsdoc-template'
// jsdoc src --recurse --destination 'docgen'
//
// require('fliplog').trackConsole();
//
// * @module jsdoc/opts/args
// * @requires jsdoc/opts/argparser
//
//
// ./jsdoc/jsdoc src --recurse --destination 'docgen' --plugins "node_modules/jsdoc-babel,plugins/markdown"
// node ./node_modules/jsdoc/jsdoc src --recurse --destination 'docgen' --plugins "node_modules/jsdoc-babel,node_modules/jsdoc/plugins/markdown.js"
// const doxdox = require('doxdox')
const doxdox = require('../../../nofundocs/doxdox')
files = this.docFiles(files)
log
.data({
files,
config: {
// parser: 'dox',
// layout: 'Markdown',
pkg: this.pkgjson,
},
})
.echo()
log.white('files: ').data(files).echo()
// stupid paths
doxdox
.parseInputs(files, {
// parser: 'dox',
// layout: 'markdown',
parser: require.resolve('doxdox-parser-dox').replace(process.cwd(), ''),
layout: require
.resolve('doxdox-plugin-markdown')
.replace(process.cwd(), ''),
pkg: this.pkgjson,
})
.then(content => {
log.cyan('writing docs').echo()
log.white('content: ' + content).echo()
File.src('./docs/docs.md', this.dir).setContent(content).write()
})
return this
}
/**
* @since 0.0.1
* @param {Array<string>} pattern array of glob patterns
* @return {Array<string>} file
*/
docFiles(pattern = ['disted/**/*.js']) {
if (Array.isArray(pattern) === false) {
// pattern = ['disted/**/*.js']
pattern = [pattern]
}
log.blue('docs pattern').json({pattern, dir: this.dir}).echo(true)
const files = globby.sync(pattern, {
cwd: this.dir,
absolute: true,
})
return files
}
/**
* @since 0.0.1
* @param {Array<string>} pattern array of glob patterns
* @return {AppCli} @chainable
*/
docs(pattern = ['disted/**/*.js']) {
this.doxdox([pattern])
// this.docFiles(pattern)
return this
}
/**
* @since 0.0.1
* @param {any} names npm scripts to run
* @return {CLI} @chainable
*/
npm(names = null) {
const scripts = this.scriptChain().debug(false)
toarr(names).forEach(name => scripts.add().npm(name))
scripts.run()
return this
}
/**
* @since 0.0.1
* @return {AppCli} @chainable
*/
handle() {
handle(this)
return this
}
}
module.exports = {handle, pkg, AppCLI}