diff --git a/.eslintrc.js b/.eslintrc.js index 90b5213..2f46673 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -10,15 +10,15 @@ module.exports = { ecmaVersion: 2018 }, rules: { - "no-var": "error", - "prefer-const": "warn", - "no-console": "warn" + 'no-var': 'error', + 'prefer-const': 'warn', + 'no-console': 'warn' }, overrides: [ { files: ['**/test/*-spec.js'], env: { - mocha: true + // mocha: true } }, { diff --git a/.thought/config.js b/.thought/config.js index 2ccf1a5..1892de5 100644 --- a/.thought/config.js +++ b/.thought/config.js @@ -1,7 +1,5 @@ module.exports = { - plugins: [ - require('thought-plugin-jsdoc') - ], + plugins: [require('thought-plugin-jsdoc')], badges: { greenkeeper: true } diff --git a/.thought/snippets/plugin-loading-plugins.js b/.thought/snippets/plugin-loading-plugins.js index 83493e7..6a32565 100644 --- a/.thought/snippets/plugin-loading-plugins.js +++ b/.thought/snippets/plugin-loading-plugins.js @@ -1,10 +1,11 @@ -module.exports = function (customize) { - - return customize - // jsdoc-support - .load(require('thought-plugin-jsdoc')) - // include open-open-source disclaimer in CONTRIBUTING.md - .load(require('thought-plugin-open-open-source')) - // include standardjs-disclaimer in CONTRIBUTING.md - .load(require('thought-plugin-standardjs')) +module.exports = function(customize) { + return ( + customize + // jsdoc-support + .load(require('thought-plugin-jsdoc')) + // include open-open-source disclaimer in CONTRIBUTING.md + .load(require('thought-plugin-open-open-source')) + // include standardjs-disclaimer in CONTRIBUTING.md + .load(require('thought-plugin-standardjs')) + ) } diff --git a/customize.js b/customize.js index ae9fa52..998adf6 100644 --- a/customize.js +++ b/customize.js @@ -33,49 +33,51 @@ const defaultConfig = { * @param {String} workingDir the working directory of thought * @returns {Function} the Customize-Spec */ -module.exports = function createSpec (workingDir) { - return function thoughtSpec (customize) { +module.exports = function createSpec(workingDir) { + return function thoughtSpec(customize) { debug('creating customize config') const configFile = path.resolve('.thought', 'config.js') const config = fs.existsSync(configFile) ? require(configFile) : defaultConfig debug('config loaded', config) - return customize - .registerEngine('handlebars', require('customize-engine-handlebars')) - .merge({ handlebars: { data: { config: defaultConfig } } }) - .merge({ - handlebars: { - partials: path.join(__dirname, 'handlebars', 'partials'), - templates: path.join(__dirname, 'handlebars', 'templates'), - helpers: require.resolve('./handlebars/helpers/index.js'), - data: { - 'package': fs.readFile(path.resolve(workingDir, 'package.json'), 'utf-8').then(JSON.parse), - config: config, - workingDir: workingDir - }, - preprocessor: require('./handlebars/preprocessor.js'), - hbsOptions: { - noEscape: true + return ( + customize + .registerEngine('handlebars', require('customize-engine-handlebars')) + .merge({ handlebars: { data: { config: defaultConfig } } }) + .merge({ + handlebars: { + partials: path.join(__dirname, 'handlebars', 'partials'), + templates: path.join(__dirname, 'handlebars', 'templates'), + helpers: require.resolve('./handlebars/helpers/index.js'), + data: { + package: fs.readFile(path.resolve(workingDir, 'package.json'), 'utf-8').then(JSON.parse), + config: config, + workingDir: workingDir + }, + preprocessor: require('./handlebars/preprocessor.js'), + hbsOptions: { + noEscape: true + } } - } - }) - // Apply any customization from the config-files (such as loading modules) - .load(function (customize) { - debug('Loading modules', config) - if (config && config.plugins) { - return config.plugins.reduce((prev, plugin) => { - return prev.load(plugin) - }, customize) - } else { - return customize - } - }) - .merge({ - handlebars: { - partials: path.join(workingDir, '.thought', 'partials'), - templates: path.join(workingDir, '.thought', 'templates'), - helpers: path.resolve(workingDir, '.thought', 'helpers.js'), - preprocessor: path.resolve(workingDir, '.thought', 'preprocessor.js') - } - }) + }) + // Apply any customization from the config-files (such as loading modules) + .load(function(customize) { + debug('Loading modules', config) + if (config && config.plugins) { + return config.plugins.reduce((prev, plugin) => { + return prev.load(plugin) + }, customize) + } else { + return customize + } + }) + .merge({ + handlebars: { + partials: path.join(workingDir, '.thought', 'partials'), + templates: path.join(workingDir, '.thought', 'templates'), + helpers: path.resolve(workingDir, '.thought', 'helpers.js'), + preprocessor: path.resolve(workingDir, '.thought', 'preprocessor.js') + } + }) + ) } } diff --git a/examples/.eslintrc.js b/examples/.eslintrc.js deleted file mode 100644 index e3611dd..0000000 --- a/examples/.eslintrc.js +++ /dev/null @@ -1,10 +0,0 @@ -module.exports = { - "extends": "standard", - "plugins": [ - "standard", - "promise" - ], - "rules": { - "no-console": "off" - } -}; diff --git a/examples/example-plugin/index.js b/examples/example-plugin/index.js index 37fdaf9..9e6fc52 100644 --- a/examples/example-plugin/index.js +++ b/examples/example-plugin/index.js @@ -4,30 +4,31 @@ const path = require('path') * Return a new instance of customize with merged configuration * @param {Customize} customize */ -module.exports = function examplePlugin (customize) { - return customize - // Include thought-plugin-jsdoc whenever this plugin is used - .load(require('thought-plugin-jsdoc')) - .merge({ - handlebars: { - helpers: { - // Register a custom helper - shout: (text) => String(text).toUpperCase() - }, - // Register partials from the 'partials/'-directory of the plugin-module - partials: path.resolve(__dirname, 'partials'), - // Register templates from the 'partials/'-directory of the plugin-module - templates: path.resolve(__dirname, 'templates'), - // Register a preprocessor that modifies the package-data - preprocessor: function (data) { - return this.parent(data) - .then(resolvedData => { +module.exports = function examplePlugin(customize) { + return ( + customize + // Include thought-plugin-jsdoc whenever this plugin is used + .load(require('thought-plugin-jsdoc')) + .merge({ + handlebars: { + helpers: { + // Register a custom helper + shout: text => String(text).toUpperCase() + }, + // Register partials from the 'partials/'-directory of the plugin-module + partials: path.resolve(__dirname, 'partials'), + // Register templates from the 'partials/'-directory of the plugin-module + templates: path.resolve(__dirname, 'templates'), + // Register a preprocessor that modifies the package-data + preprocessor: function preprocessor(data) { + return this.parent(data).then(resolvedData => { resolvedData.package.description += ' (modified by example-plugin)' return resolvedData }) + } } - } - }) + }) + ) } module.exports.package = require('./package.json') diff --git a/examples/example-project-1-simple/index.js b/examples/example-project-1-simple/index.js index 1f1a1c6..fedb617 100644 --- a/examples/example-project-1-simple/index.js +++ b/examples/example-project-1-simple/index.js @@ -6,6 +6,6 @@ * @module example-project * @public */ -module.exports = function multiply (a, b) { +module.exports = function multiply(a, b) { return a * b } diff --git a/examples/example-project-2-example-license-jsdoc-badges/.thought/config.js b/examples/example-project-2-example-license-jsdoc-badges/.thought/config.js index 2ccf1a5..1892de5 100644 --- a/examples/example-project-2-example-license-jsdoc-badges/.thought/config.js +++ b/examples/example-project-2-example-license-jsdoc-badges/.thought/config.js @@ -1,7 +1,5 @@ module.exports = { - plugins: [ - require('thought-plugin-jsdoc') - ], + plugins: [require('thought-plugin-jsdoc')], badges: { greenkeeper: true } diff --git a/examples/example-project-2-example-license-jsdoc-badges/examples/example.js b/examples/example-project-2-example-license-jsdoc-badges/examples/example.js index 51104fd..efb1c35 100644 --- a/examples/example-project-2-example-license-jsdoc-badges/examples/example.js +++ b/examples/example-project-2-example-license-jsdoc-badges/examples/example.js @@ -1,7 +1,7 @@ -var multiply = require('../') +const multiply = require('../') -var x = 3 -var y = 4 -var xy = multiply(x, y) +const x = 3 +const y = 4 +const xy = multiply(x, y) console.log(xy) diff --git a/examples/example-project-2-example-license-jsdoc-badges/index.js b/examples/example-project-2-example-license-jsdoc-badges/index.js index 1f1a1c6..fedb617 100644 --- a/examples/example-project-2-example-license-jsdoc-badges/index.js +++ b/examples/example-project-2-example-license-jsdoc-badges/index.js @@ -6,6 +6,6 @@ * @module example-project * @public */ -module.exports = function multiply (a, b) { +module.exports = function multiply(a, b) { return a * b } diff --git a/examples/example-project-3-templates-partials-helpers-preprocessor/.thought/helpers.js b/examples/example-project-3-templates-partials-helpers-preprocessor/.thought/helpers.js index 802a808..1e12571 100644 --- a/examples/example-project-3-templates-partials-helpers-preprocessor/.thought/helpers.js +++ b/examples/example-project-3-templates-partials-helpers-preprocessor/.thought/helpers.js @@ -4,7 +4,7 @@ module.exports = { * @param {string} text a text to be shouted * @returns {string} the text in uppercases */ - shout: function (text) { + shout: function(text) { return text && text.toUpperCase() }, @@ -15,7 +15,7 @@ module.exports = { * @param {string} text * @returns {Promise} a promise for the text */ - delay: function (text) { + delay: function(text) { return new Promise((resolve, reject) => setTimeout(() => resolve(text), 10)) } } diff --git a/examples/example-project-3-templates-partials-helpers-preprocessor/.thought/preprocessor.js b/examples/example-project-3-templates-partials-helpers-preprocessor/.thought/preprocessor.js index 2bf9718..854b4ac 100644 --- a/examples/example-project-3-templates-partials-helpers-preprocessor/.thought/preprocessor.js +++ b/examples/example-project-3-templates-partials-helpers-preprocessor/.thought/preprocessor.js @@ -2,13 +2,13 @@ * A preprocessor can modify the incoming data. * @param data */ -module.exports = function (data) { +module.exports = function(data) { // Call the original preprocessor first (attention: It returns a promise) - return this.parent(data) - .then(function (modifiedData) { - modifiedData.preprocessorText = 'You can probably use helpers to achieve most of the things ' + - 'that a preprocessor is good for, but some day you may need one.' - console.log(modifiedData) - return modifiedData - }) + return this.parent(data).then(function(modifiedData) { + modifiedData.preprocessorText = + 'You can probably use helpers to achieve most of the things ' + + 'that a preprocessor is good for, but some day you may need one.' + console.log(modifiedData) + return modifiedData + }) } diff --git a/examples/example-project-3-templates-partials-helpers-preprocessor/index.js b/examples/example-project-3-templates-partials-helpers-preprocessor/index.js index 1f1a1c6..fedb617 100644 --- a/examples/example-project-3-templates-partials-helpers-preprocessor/index.js +++ b/examples/example-project-3-templates-partials-helpers-preprocessor/index.js @@ -6,6 +6,6 @@ * @module example-project * @public */ -module.exports = function multiply (a, b) { +module.exports = function multiply(a, b) { return a * b } diff --git a/examples/example-project-4-writing-plugins/.thought/config.js b/examples/example-project-4-writing-plugins/.thought/config.js index 3958976..3f83512 100644 --- a/examples/example-project-4-writing-plugins/.thought/config.js +++ b/examples/example-project-4-writing-plugins/.thought/config.js @@ -1,5 +1,3 @@ module.exports = { - plugins: [ - require('../../example-plugin/index') - ] + plugins: [require('../../example-plugin/index')] } diff --git a/examples/example-project-4-writing-plugins/index.js b/examples/example-project-4-writing-plugins/index.js index 1f1a1c6..fedb617 100644 --- a/examples/example-project-4-writing-plugins/index.js +++ b/examples/example-project-4-writing-plugins/index.js @@ -6,6 +6,6 @@ * @module example-project * @public */ -module.exports = function multiply (a, b) { +module.exports = function multiply(a, b) { return a * b } diff --git a/examples/javascript-usage.js b/examples/javascript-usage.js index baad038..90352e6 100644 --- a/examples/javascript-usage.js +++ b/examples/javascript-usage.js @@ -1,4 +1,4 @@ -var thought = require('../') +const thought = require('../') thought({ addToGit: true diff --git a/examples/run-thought.js b/examples/run-thought.js index 76f0976..d26bd08 100644 --- a/examples/run-thought.js +++ b/examples/run-thought.js @@ -2,19 +2,20 @@ * This script generates the documentation for all example-projects. */ -var fs = require('fs-extra') -var exeq = require('../lib/utils/exeq') -var deep = require('deep-aplus')(Promise) +const fs = require('fs-extra') +const exeq = require('../lib/utils/exeq') +const deep = require('deep-aplus')(Promise) process.chdir(__dirname) // Run thought in all example projects fs.readdir(__dirname) .then(list => list.filter(dir => dir.match(/^example-project.*$/))) - .then(list => list.map(dir => { - return exeq('thought', ['run', '-a'], { cwd: dir }) - .then((result) => { + .then(list => + list.map(dir => { + return exeq('thought', ['run', '-a'], { cwd: dir }).then(result => { console.log(`Done with '${dir}'`) }) - })) + }) + ) .then(promises => deep(promises)) .then(() => console.log('finished...')) diff --git a/handlebars/helpers/dirTree.js b/handlebars/helpers/dirTree.js index e0f9a0d..fd96de6 100644 --- a/handlebars/helpers/dirTree.js +++ b/handlebars/helpers/dirTree.js @@ -26,7 +26,7 @@ module.exports = dirTree * @access public * @memberOf helpers */ -async function dirTree (baseDir, globPattern, options) { +async function dirTree(baseDir, globPattern, options) { // Is basedir is not a string, it is probably the handlebars "options" object if (typeof globPattern !== 'string' && options == null) { options = globPattern @@ -47,7 +47,7 @@ async function dirTree (baseDir, globPattern, options) { }) debug('dirTree glob result', files) if (files.length === 0) { - throw new Error('Cannot find a single file for \'' + globPattern + '\' in \'' + baseDir + '\'') + throw new Error("Cannot find a single file for '" + globPattern + "' in '" + baseDir + "'") } files.sort() @@ -56,7 +56,7 @@ async function dirTree (baseDir, globPattern, options) { nodes: treeFromPaths(files, baseDir, ({ parent, file, explicit }) => { if (explicit && hashOptions.links) { // Compute relative path from current target-file to the listed file - var targetPath = path.relative(path.dirname(options.customize.targetFile), `${parent}/${file}`) + const targetPath = path.relative(path.dirname(options.customize.targetFile), `${parent}/${file}`) return `${file}` } return file @@ -92,9 +92,9 @@ async function dirTree (baseDir, globPattern, options) { * @returns {object} a tree structure as needed by [archy](https://www.npmjs.com/package/archy) * @access private */ -function treeFromPaths (files, parent, renderLabelFn) { - var groups = _.groupBy(files, file => file.match(/^[^/]*\/?/)) - return Object.keys(groups).map(function (groupKey) { +function treeFromPaths(files, parent, renderLabelFn) { + const groups = _.groupBy(files, file => file.match(/^[^/]*\/?/)) + return Object.keys(groups).map(function(groupKey) { const group = groups[groupKey] // Is this group explicitly part of the result, or // just implicit through its children @@ -120,7 +120,7 @@ function treeFromPaths (files, parent, renderLabelFn) { * Keep nodes with zero, two or more childs. * @access private */ -function condense (node) { +function condense(node) { if (node.nodes.length === 1 && node.nodes[0].nodes.length > 0) { return condense({ label: (node.label || '') + node.nodes[0].label, diff --git a/handlebars/helpers/index.js b/handlebars/helpers/index.js index 624d278..2bce7da 100644 --- a/handlebars/helpers/index.js +++ b/handlebars/helpers/index.js @@ -43,7 +43,7 @@ module.exports = { * @access public * @memberOf helpers */ -function json (obj) { +function json(obj) { return '```json\n' + JSON.stringify(obj, null, 2) + '\n```\n' } @@ -56,13 +56,11 @@ function json (obj) { * @access public * @memberOf helpers */ -function include (filename, language) { - return fs.readFile(filename, 'utf-8').then(function (contents) { - return '```' + - (typeof language === 'string' ? language : path.extname(filename).substr(1)) + - '\n' + - contents + - '\n```\n' +function include(filename, language) { + return fs.readFile(filename, 'utf-8').then(function(contents) { + return ( + '```' + (typeof language === 'string' ? language : path.extname(filename).substr(1)) + '\n' + contents + '\n```\n' + ) }) } @@ -73,7 +71,7 @@ function include (filename, language) { * @access public * @memberOf helpers */ -function includeRaw (filename) { +function includeRaw(filename) { return fs.readFile(filename, 'utf-8') } @@ -99,25 +97,25 @@ function includeRaw (filename) { * @access public * @memberOf helpers */ -function example (filename, options) { - return fs.readFile(filename, 'utf-8') - .then(function (contents) { - // Relative path to the current module (e.g. "../"). This path must be replaced - // by the module name in the - const modulePath = path.relative(path.dirname(filename), '.') - debug('example modulepath', modulePath) - const requireModuleRegex = new RegExp(regex`require\('${modulePath}/?(.*?)'\)`, 'g') - if (options && options.hash && options.hash.snippet) { - contents = contents.match(/------.*\n([\S\s]*?)\n.*---<\/snip>---/)[1] - } +function example(filename, options) { + return fs.readFile(filename, 'utf-8').then(function(contents) { + // Relative path to the current module (e.g. "../"). This path must be replaced + // by the module name in the + const modulePath = path.relative(path.dirname(filename), '.') + debug('example modulepath', modulePath) + const requireModuleRegex = new RegExp(regex`require\('${modulePath}/?(.*?)'\)`, 'g') + if (options && options.hash && options.hash.snippet) { + contents = contents.match(/------.*\n([\S\s]*?)\n.*---<\/snip>---/)[1] + } - return util.format('```%s\n%s\n```', - path.extname(filename).substr(1), - contents.trim().replace(requireModuleRegex, function (match, suffix) { - return `require('${require(process.cwd() + '/package').name}${suffix ? '/' + suffix : ''}')` - }) - ) - }) + return util.format( + '```%s\n%s\n```', + path.extname(filename).substr(1), + contents.trim().replace(requireModuleRegex, function(match, suffix) { + return `require('${require(process.cwd() + '/package').name}${suffix ? '/' + suffix : ''}')` + }) + ) + }) } /** @@ -128,7 +126,7 @@ function example (filename, options) { * @access public * @memberOf helpers */ -function exists (filename) { +function exists(filename) { return fs.exists(filename) } @@ -144,27 +142,26 @@ function exists (filename) { * @access public * @memberOf helpers */ -function exec (command, options) { - let start - let end +function exec(command, options) { + const cwd = options.hash && options.hash.cwd const lang = options.hash && options.hash.lang - switch (lang) { - case 'raw': - start = end = '' - break - case 'inline': - start = end = '`' - break - default: - const fenceLanguage = lang || '' - start = '```' + fenceLanguage + '\n' - end = '\n```' - } + const output = cp.execSync(command, { encoding: 'utf8', - cwd: options.hash && options.hash.cwd + cwd: cwd }) - return start + output.trim() + end + const trimmedOutput = output.trim() + + if (lang === 'raw') { + return trimmedOutput + } + if (lang === 'inline') { + return '`' + trimmedOutput + '`' + } + if (lang == null) { + return '```\n' + trimmedOutput + '\n```' + } + return '```' + lang + '\n' + trimmedOutput + '\n```' } /** @@ -197,7 +194,7 @@ function exec (command, options) { * @access public * @memberOf helpers */ -function renderTree (object, options) { +function renderTree(object, options) { const tree = require('archy')(transformTree(object, options.fn)) return '
\n' + tree + '
' } @@ -217,16 +214,15 @@ function renderTree (object, options) { * @access public * @memberOf helpers */ -function withPackageOf (filePath, options) { - return resolvePackageRoot(path.resolve(filePath)) - .then(function (resolvedPackageRoot) { - const data = Handlebars.createFrame(options.data) - data.url = _githubUrl(resolvedPackageRoot) - data.package = resolvedPackageRoot.packageJson - data.relativePath = resolvedPackageRoot.relativeFile - data.rawUrl = _rawGithubUrl(resolvedPackageRoot) - return options.fn(this, { data: data }) - }) +function withPackageOf(filePath, options) { + return resolvePackageRoot(path.resolve(filePath)).then(function(resolvedPackageRoot) { + const data = Handlebars.createFrame(options.data) + data.url = _githubUrl(resolvedPackageRoot) + data.package = resolvedPackageRoot.packageJson + data.relativePath = resolvedPackageRoot.relativeFile + data.rawUrl = _rawGithubUrl(resolvedPackageRoot) + return options.fn(this, { data: data }) + }) } /** @@ -236,7 +232,7 @@ function withPackageOf (filePath, options) { * @access public * @memberOf helpers */ -function npm (packageName) { +function npm(packageName) { return '[' + packageName + '](https://npmjs.com/package/' + packageName + ')' } @@ -262,7 +258,7 @@ function npm (packageName) { * @access public * @memberOf helpers */ -function htmlId (value) { +function htmlId(value) { // see http://stackoverflow.com/questions/19001140/amend-regular-expression-to-allow-german-umlauts-french-accents-and-other-valid // and https://github.com/mathiasbynens/unicode-data/blob/17a920119b8015c6f7fe922ee7ab9fe29bef4394/4.0.1/blocks/Katakana-regex.js // There are probably a lot of characters missing. Please make a PR, if you want to include more ranges in the valid characters. @@ -286,7 +282,7 @@ function htmlId (value) { * @access public * @memberOf helpers */ -function hasCoveralls () { +function hasCoveralls() { return _searchCiConfig('coveralls') } @@ -302,7 +298,7 @@ function hasCoveralls () { * @access public * @memberOf helpers */ -async function hasCodecov () { +async function hasCodecov() { return _searchCiConfig('codecov') } @@ -312,19 +308,21 @@ async function hasCodecov () { * @return {Promise} true, if the given string is either part of .travis.yml or appveyor.yml * @private */ -async function _searchCiConfig (searchString) { - const ciConfigs = await Promise.all(['.travis.yml', 'appveyor.yml'].map(async (filename) => { - try { - return await fs.readFile(filename, 'utf-8') - } catch (e) { - if (e.code === 'ENOENT') { - return '' +async function _searchCiConfig(searchString) { + const ciConfigs = await Promise.all( + ['.travis.yml', 'appveyor.yml'].map(async filename => { + try { + return await fs.readFile(filename, 'utf-8') + } catch (e) { + if (e.code === 'ENOENT') { + return '' + } + /* istanbul ignore next */ + throw e } - /* istanbul ignore next */ - throw e - } - })) - return ciConfigs.findIndex((contents) => contents.includes(searchString)) >= 0 + }) + ) + return ciConfigs.findIndex(contents => contents.includes(searchString)) >= 0 } /** @@ -345,7 +343,7 @@ async function _searchCiConfig (searchString) { * @throws Error if no badge is enabled but not github-repo url is found in package.json * @memberOf helpers */ -function hasGreenkeeper (options) { +function hasGreenkeeper(options) { const config = options.data.root.config const showBadge = !!(config && config.badges && config.badges.greenkeeper) // coerce to boolean if (showBadge && !githubRepo(options)) { @@ -381,12 +379,12 @@ function hasGreenkeeper (options) { * * @access private */ -function transformTree (object, fn) { +function transformTree(object, fn) { const label = fn(object).trim() if (object.children) { return { label: label, - nodes: object.children.map(function (child) { + nodes: object.children.map(function(child) { return transformTree(child, fn) }) } @@ -406,7 +404,7 @@ function transformTree (object, fn) { * @access public * @memberOf helpers */ -function github (filePath) { +function github(filePath) { // Build url to correct version and file in githubs return resolvePackageRoot(path.resolve(filePath)).then(_githubUrl) } @@ -418,7 +416,7 @@ function github (filePath) { * @access public * @memberOf helpers */ -function repoWebUrl (gitUrl) { +function repoWebUrl(gitUrl) { if (!gitUrl) { return undefined } @@ -437,7 +435,7 @@ function repoWebUrl (gitUrl) { * @access public * @memberOf helpers */ -function githubRepo (options) { +function githubRepo(options) { try { const url = options.data.root.package.repository.url const match = url.match(/.*?(:\/\/|@)github\.com[/:](.*?)(#.*?)?$/) @@ -459,7 +457,7 @@ function githubRepo (options) { * @returns {string} * @access private */ -function regex (strings, ...args) { +function regex(strings, ...args) { return String.raw(strings, ...args.map(_.escapeRegExp)) } @@ -471,7 +469,7 @@ function regex (strings, ...args) { * @access public * @memberOf helpers */ -function arr (...args) { +function arr(...args) { return args.slice(0, args.length - 1) } @@ -484,8 +482,8 @@ function arr (...args) { * @returns {string} * @private */ -function _githubUrl (resolvedPackageRoot) { - var { packageJson, relativeFile } = resolvedPackageRoot +function _githubUrl(resolvedPackageRoot) { + const { packageJson, relativeFile } = resolvedPackageRoot const url = repoWebUrl(packageJson && packageJson.repository && packageJson.repository.url) if (url && url.match(/github.com/)) { return `${url}/blob/v${packageJson.version}/${relativeFile}` @@ -496,8 +494,8 @@ function _githubUrl (resolvedPackageRoot) { * Return the raw url of a file in a githb repository * @private */ -function _rawGithubUrl (resolvedPackageRoot) { - var { packageJson, relativeFile } = resolvedPackageRoot +function _rawGithubUrl(resolvedPackageRoot) { + const { packageJson, relativeFile } = resolvedPackageRoot const orgRepo = _githubOrgRepo(packageJson && packageJson.repository && packageJson.repository.url) if (orgRepo) { return `https://raw.githubusercontent.com/${orgRepo}/v${packageJson.version}/${relativeFile}` @@ -510,7 +508,7 @@ function _rawGithubUrl (resolvedPackageRoot) { * @return {string|null} org and repository, separated by a "/" * @private */ -function _githubOrgRepo (gitUrl) { +function _githubOrgRepo(gitUrl) { if (!gitUrl) { return null } diff --git a/handlebars/preprocessor.js b/handlebars/preprocessor.js index c6b7ad9..ba5f806 100644 --- a/handlebars/preprocessor.js +++ b/handlebars/preprocessor.js @@ -1,7 +1,7 @@ -var fs = require('fs-extra') -var path = require('path') -var deep = require('deep-aplus')(Promise) -var debug = require('debug')('thought:preprocessor') +const fs = require('fs-extra') +const path = require('path') +const deep = require('deep-aplus')(Promise) +const debug = require('debug')('thought:preprocessor') /** * This function modifies the Handlebars input data prior to @@ -9,31 +9,29 @@ var debug = require('debug')('thought:preprocessor') * @param {object} data the data object of the configuration * @returns {*} */ -module.exports = function (data) { +module.exports = function(data) { // shallow clone data = Object.assign({}, data) // Detect license file and read contents debug('workingdir', data.workingDir) - data.licenseFile = fs.readdir(data.workingDir) - .then(function (files) { - debug('project files', files) - var licenseFiles = files.filter(function (filename) { - return filename.lastIndexOf('LICENSE', 0) === 0 - }) - if (licenseFiles.length > 0) { - return { - filename: licenseFiles[0], - contents: fs.readFile(path.join(data.workingDir, licenseFiles[0]), 'utf-8'), - fences: path.extname(licenseFiles[0]) !== '.md' - } - } - return null + data.licenseFile = fs.readdir(data.workingDir).then(function(files) { + debug('project files', files) + const licenseFiles = files.filter(function(filename) { + return filename.lastIndexOf('LICENSE', 0) === 0 }) + if (licenseFiles.length > 0) { + return { + filename: licenseFiles[0], + contents: fs.readFile(path.join(data.workingDir, licenseFiles[0]), 'utf-8'), + fences: path.extname(licenseFiles[0]) !== '.md' + } + } + return null + }) - return deep(data) - .then((result) => { - debug('preprocessed', result) - return result - }) + return deep(data).then(result => { + debug('preprocessed', result) + return result + }) } diff --git a/index.js b/index.js index 409d2bb..7255e7d 100644 --- a/index.js +++ b/index.js @@ -6,9 +6,9 @@ */ 'use strict' -var customize = require('customize') -var debug = require('debug')('thought:run') -var write = require('customize-write-files') +const customize = require('customize') +const debug = require('debug')('thought:run') +const write = require('customize-write-files') module.exports = thought @@ -20,20 +20,22 @@ module.exports = thought * @param {boolean} [options.addToGit] add created files to git * @api public */ -function thought (options) { +function thought(options) { options = options || {} debug('options', options) - return customize() - // Load `customize`-spec - .load(require('./customize.js')(options.cwd || '.')) - .run() - .then(write(options.cwd || '.')) - .then(async function (filenames) { - if (options.addToGit) { - var git = require('simple-git/promise')() - debug('Adding ' + filenames.join(', ') + ' to git index') - await git.add(filenames) - } - return filenames - }) + return ( + customize() + // Load `customize`-spec + .load(require('./customize.js')(options.cwd || '.')) + .run() + .then(write(options.cwd || '.')) + .then(async function(filenames) { + if (options.addToGit) { + const git = require('simple-git/promise')() + debug('Adding ' + filenames.join(', ') + ' to git index') + await git.add(filenames) + } + return filenames + }) + ) } diff --git a/lib/check-engines.js b/lib/check-engines.js index 2d90bee..e999dc4 100644 --- a/lib/check-engines.js +++ b/lib/check-engines.js @@ -4,18 +4,19 @@ * Copyright (c) 2015 Nils Knappmeier. * Released under the MIT license. */ -var exec = require('./utils/exeq') -var semver = require('semver') +const exec = require('./utils/exeq') +const semver = require('semver') -module.exports = function () { - return exec('npm', ['--version']) - .then(function (stdio) { - if (semver.lt(stdio[0], '2.13.0')) { - throw new Error('npm<2.13.0 will not execute the `version`-script in your package.json.\n' + - 'Please upgrade to at least 2.13.0.') - } else { - // eslint-disable-next-line no-console - console.log('npm@' + stdio[0].trim() + ': OK') - } - }) +module.exports = function() { + return exec('npm', ['--version']).then(function(stdio) { + if (semver.lt(stdio[0], '2.13.0')) { + throw new Error( + 'npm<2.13.0 will not execute the `version`-script in your package.json.\n' + + 'Please upgrade to at least 2.13.0.' + ) + } else { + // eslint-disable-next-line no-console + console.log('npm@' + stdio[0].trim() + ': OK') + } + }) } diff --git a/lib/cli.js b/lib/cli.js index 97a46ed..9d62e67 100644 --- a/lib/cli.js +++ b/lib/cli.js @@ -5,8 +5,8 @@ * Copyright (c) 2015 Nils Knappmeier. * Released under the MIT license. */ -var thought = require('../') -var debug = require('debug')('thought:bin') +const thought = require('../') +const debug = require('debug')('thought:bin') const { resolvePackageRoot } = require('../lib/utils/resolve-package-root') /** @@ -15,14 +15,14 @@ const { resolvePackageRoot } = require('../lib/utils/resolve-package-root') * Called by the cli-script. Exports a function for better testability * */ -module.exports = function (argv, console, done) { +module.exports = function(argv, console, done) { Error.stackTraceLimit = 0 debug('started') - var program = require('commander') + const program = require('commander') program .version(require('../package').version) - .option('-d, --debug', 'higher stack-trace-limit, long stack-traces', function (option) { + .option('-d, --debug', 'higher stack-trace-limit, long stack-traces', function(option) { Error.stackTraceLimit = 30 require('trace-and-clarify-if-possible') }) @@ -31,61 +31,52 @@ module.exports = function (argv, console, done) { .command('run') .option('-a, --add-to-git', 'git-add the modified files') .description('Generate documentation from your package.json and some templates.') - .action(function (options) { + .action(function(options) { changeDir() .then(() => resolvePackageRoot('package.json')) - .then((root) => { + .then(root => { if (!(root.packageJson.scripts && root.packageJson.scripts.thought)) { /* eslint-disable no-console */ - console.log('\nNot registered in package.json yet!\n' + - 'I can add a `scripts`-property to your package.json to ensure that ' + - 'documentation is generated automatically on version bumps.\n' + - 'If you want that, run `thought init`\n') + console.log( + '\nNot registered in package.json yet!\n' + + 'I can add a `scripts`-property to your package.json to ensure that ' + + 'documentation is generated automatically on version bumps.\n' + + 'If you want that, run `thought init`\n' + ) /* eslint-enable no-console */ } debug('running thought') }) .then(() => thought({ addToGit: options.addToGit, debug: program.debug })) - .then( - (filenames) => quit(null, 'The following files were updated: ' + filenames.join(', ')), - quit - ) + .then(filenames => quit(null, 'The following files were updated: ' + filenames.join(', ')), quit) }) program .command('init') - .description('Register scripts in the current module\'s package.json') - .action(function () { + .description("Register scripts in the current module's package.json") + .action(function() { changeDir() .then(require('../lib/check-engines.js')) .then(require('../lib/init.js')) - .then( - () => quit(null, 'OK'), - quit - ) + .then(() => quit(null, 'OK'), quit) }) program .command('check-engines') .description('Check that all engines (such as npm) have versions that ensure Thought to run correctly') - .action(function () { - require('../lib/check-engines.js')() - .then( - () => quit(null, 'OK'), - quit - ) + .action(function() { + require('../lib/check-engines.js')().then(() => quit(null, 'OK'), quit) }) program .command('up-to-date') - .description('Perform up-to-date check of the current documentation. Exit with non-zero exit-code when thought must be run again.') - .action(function () { + .description( + 'Perform up-to-date check of the current documentation. Exit with non-zero exit-code when thought must be run again.' + ) + .action(function() { changeDir() .then(require('../lib/up-to-date.js')) - .then( - () => quit(null, 'OK'), - quit - ) + .then(() => quit(null, 'OK'), quit) }) program.parse(argv) @@ -99,22 +90,25 @@ module.exports = function (argv, console, done) { // ---------------------------------------- // chdir to local module root // ---------------------------------------- - function changeDir () { - return resolvePackageRoot('package.json') - .then(root => { - /* istanbul ignore if: Situation very hard to reproduce */ - if (!root.packageJson) { - throw new Error('package.json not found!\n' + + function changeDir() { + return resolvePackageRoot('package.json').then(root => { + /* istanbul ignore if: Situation very hard to reproduce */ + if (!root.packageJson) { + throw new Error( + 'package.json not found!\n' + 'Please run me from within a node module.\n' + - 'My working directory is "' + process.cwd() + '".') - } - process.chdir(root.packageRoot) - // eslint-disable-next-line no-console - console.log('I\'m running inside module \'' + root.packageJson.name + '\' in \'' + process.cwd()) - }) + 'My working directory is "' + + process.cwd() + + '".' + ) + } + process.chdir(root.packageRoot) + // eslint-disable-next-line no-console + console.log("I'm running inside module '" + root.packageJson.name + "' in '" + process.cwd()) + }) } - function quit (err, message) { + function quit(err, message) { /* eslint-disable no-console */ if (err) { console.error(err, message) diff --git a/lib/dev-server.js b/lib/dev-server.js index 4284cdd..aff809f 100644 --- a/lib/dev-server.js +++ b/lib/dev-server.js @@ -1,8 +1,8 @@ -var customize = require('customize') +const customize = require('customize') -var thought = customize().load(require('../customize.js')('.')) +const thought = customize().load(require('../customize.js')('.')) -function handleMessage (message) { +function handleMessage(message) { switch (message.cmd) { case 'run': { // eslint-disable-next-line no-console @@ -12,11 +12,13 @@ function handleMessage (message) { } } -process.on('message', (message) => { - handleMessage(message) - .then((result) => { +process.on('message', message => { + handleMessage(message).then( + result => { process.send({ message: message, result: result }) - }, (err) => { + }, + err => { process.send({ error: err }) - }) + } + ) }) diff --git a/lib/init.js b/lib/init.js index 6531b71..8b04fbd 100644 --- a/lib/init.js +++ b/lib/init.js @@ -4,23 +4,23 @@ * Copyright (c) 2015 Nils Knappmeier. * Released under the MIT license. */ -var fs = require('fs-extra') -var debug = require('debug')('thought:init') -var exec = require('./utils/exeq') -var thoughtPackageJson = require('../package.json') +const fs = require('fs-extra') +const debug = require('debug')('thought:init') +const exec = require('./utils/exeq') +const thoughtPackageJson = require('../package.json') -module.exports = function () { - var packageJson +module.exports = function() { + let packageJson return checkPackageJsonInGit() .then(() => npmInstallThought()) .then(() => fs.readFile('package.json', 'utf-8')) - .then(function (contents) { + .then(function(contents) { packageJson = JSON.parse(contents) if (packageJson.scripts && packageJson.scripts.thought) { - throw new Error('I think scripts are already in your package.json (\'scripts.thought\' exists)') + throw new Error("I think scripts are already in your package.json ('scripts.thought' exists)") } }) - .then(function () { + .then(function() { packageJson.scripts = packageJson.scripts || {} packageJson.scripts.thought = 'thought run -a' if (packageJson.scripts.version) { @@ -31,10 +31,10 @@ module.exports = function () { packageJson.devDependencies.thought = `^${thoughtPackageJson.version}` return fs.writeFile('package.json', JSON.stringify(packageJson, null, 2)) }) - .then(function () { + .then(function() { return exec('git', ['commit', 'package.json', '-m', '[Thought] Added scripts to run thought on version-bumps']) }) - .then(function (stdio) { + .then(function(stdio) { debug('git commit package.json...', 'stdout', stdio[0], 'stderr', stdio[1]) // eslint-disable-next-line no-console console.log('\nI have committed a new package.json. Please verify the changes made to the file!') @@ -46,28 +46,29 @@ module.exports = function () { * @return {Promise} true, if everything is fine */ -function checkPackageJsonInGit () { - return exec('git', ['status', '--porcelain', 'package.json']) - .then(function ([stdout, stderr]) { - debug('git status --porcelain package.json', 'stdout', stdout, 'stderr', stderr) - if (stdout.indexOf('package.json') >= 0) { - throw new Error('package.json has changes!\n' + +function checkPackageJsonInGit() { + return exec('git', ['status', '--porcelain', 'package.json']).then(function([stdout, stderr]) { + debug('git status --porcelain package.json', 'stdout', stdout, 'stderr', stderr) + if (stdout.indexOf('package.json') >= 0) { + throw new Error( + 'package.json has changes!\n' + 'I would like to add scripts to your package.json, but ' + 'there are changes that have not been commited yet.\n' + - 'I don\'t want to damage anything, so I\'m not doing anyhting right now. ' + - 'Please commit your package.json') - } - }) + "I don't want to damage anything, so I'm not doing anyhting right now. " + + 'Please commit your package.json' + ) + } + }) } -function npmInstallThought () { +function npmInstallThought() { return new Promise((resolve, reject) => { - var cp = require('child_process') - var child = cp.spawn('npm', ['install', '--save-dev', 'thought'], { + const cp = require('child_process') + const child = cp.spawn('npm', ['install', '--save-dev', 'thought'], { stdio: 'inherit' }) child.on('error', reject) - child.on('exit', (code) => { + child.on('exit', code => { /* istanbul ignore else */ if (code === 0) { resolve() diff --git a/lib/up-to-date.js b/lib/up-to-date.js index 02fec50..f1134aa 100644 --- a/lib/up-to-date.js +++ b/lib/up-to-date.js @@ -6,9 +6,9 @@ */ 'use strict' -var customize = require('customize') -var debug = require('debug')('thought:up-to-date') -var write = require('customize-write-files') +const customize = require('customize') +const debug = require('debug')('thought:up-to-date') +const write = require('customize-write-files') module.exports = uptodateCheck @@ -18,21 +18,25 @@ module.exports = uptodateCheck * @param {string} [options.cwd] the working directory to use as project root * @api public */ -function uptodateCheck (options) { +function uptodateCheck(options) { options = options || {} debug('options', options) - return customize() - // Load `customize`-spec - .load(require('../customize')(options.cwd || '.')) - .run() - .then(write.changed(options.cwd || '.')) - .then(function (changedCheck) { - // Would a file have been changed by running thought? - debug('Changed files', changedCheck) - if (changedCheck.changed) { - var error = new Error('Source files have changed. Please re-run me.\nChanged: ' + JSON.stringify(changedCheck.files)) - error.changedFiles = changedCheck.files - throw error - } - }) + return ( + customize() + // Load `customize`-spec + .load(require('../customize')(options.cwd || '.')) + .run() + .then(write.changed(options.cwd || '.')) + .then(function(changedCheck) { + // Would a file have been changed by running thought? + debug('Changed files', changedCheck) + if (changedCheck.changed) { + const error = new Error( + 'Source files have changed. Please re-run me.\nChanged: ' + JSON.stringify(changedCheck.files) + ) + error.changedFiles = changedCheck.files + throw error + } + }) + ) } diff --git a/lib/utils/exeq.js b/lib/utils/exeq.js index 2294f3c..316a4e8 100644 --- a/lib/utils/exeq.js +++ b/lib/utils/exeq.js @@ -4,14 +4,14 @@ * Copyright (c) 2015 Nils Knappmeier. * Released under the MIT license. */ -var cp = require('child_process') +const cp = require('child_process') /** * Call child_process.execFile with `{ encoding: utf-8 }` and return a promise of `[ stdout, stderr]` */ -module.exports = function (cmd, args, options) { - return new Promise(function (resolve, reject) { - return cp.execFile(cmd, args, options, function (err, stdout, stderr) { +module.exports = function(cmd, args, options) { + return new Promise(function(resolve, reject) { + return cp.execFile(cmd, args, options, function(err, stdout, stderr) { if (err) { return reject(err) } diff --git a/lib/utils/resolve-package-root.js b/lib/utils/resolve-package-root.js index 97e8d7e..488d259 100644 --- a/lib/utils/resolve-package-root.js +++ b/lib/utils/resolve-package-root.js @@ -15,15 +15,16 @@ module.exports = { resolvePackageRoot } * @param file * @return {{packageRoot: string, packageJson: object, relativeFile: string}} the path to the package.json */ -function resolvePackageRoot (file) { +function resolvePackageRoot(file) { try { const fullPath = path.resolve(file) for (let lead = fullPath; path.dirname(lead) !== lead; lead = path.dirname(lead)) { debug('Looking for package.json in ' + lead) - let packagePath = path.join(lead, 'package.json') + const packagePath = path.join(lead, 'package.json') try { if (fs.statSync(packagePath).isFile()) { - return fs.readFile(packagePath, 'utf-8') + return fs + .readFile(packagePath, 'utf-8') .then(JSON.parse) .then(packageJson => { return { diff --git a/package-lock.json b/package-lock.json index eaf3618..53eb33e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -258,6 +258,15 @@ "integrity": "sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw==", "dev": true }, + "@samverschueren/stream-to-observable": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.0.tgz", + "integrity": "sha512-MI4Xx6LHs4Webyvi6EbspgyAb4D2Q2VtnCQ1blOJcoLS6mVa8lNN2rkIy1CVxfTUpoyIbCTkXES1rLXztFD1lg==", + "dev": true, + "requires": { + "any-observable": "^0.3.0" + } + }, "@types/color-name": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", @@ -367,6 +376,12 @@ "color-convert": "^1.9.0" } }, + "any-observable": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/any-observable/-/any-observable-0.3.0.tgz", + "integrity": "sha512-/FQM1EDkTsf63Ub2C6O7GuYFDsSXUwsaZDurV0np41ocwq0jthUAYCmhBX9f+KwlaCgIuWyr/4WlUQUBfKfZog==", + "dev": true + }, "anymatch": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", @@ -653,6 +668,59 @@ "restore-cursor": "^3.1.0" } }, + "cli-truncate": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-0.2.1.tgz", + "integrity": "sha1-nxXPuwcFAFNpIWxiasfQWrkN1XQ=", + "dev": true, + "requires": { + "slice-ansi": "0.0.4", + "string-width": "^1.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "slice-ansi": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", + "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=", + "dev": true + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + } + } + }, "cli-width": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", @@ -695,6 +763,12 @@ } } }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true + }, "collect-all": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/collect-all/-/collect-all-1.0.3.tgz", @@ -794,9 +868,9 @@ } }, "commander": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.0.tgz", - "integrity": "sha512-NIQrwvv9V39FHgGFm36+U9SMQzbiHvU79k+iADraJTpmrFFfx7Ds0IvDoAdZsDrknlkRk14OYoWXb57uTh7/sw==" + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" }, "common-sequence": { "version": "2.0.0", @@ -1134,6 +1208,12 @@ "number-is-nan": "^1.0.0" } }, + "date-fns": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.30.1.tgz", + "integrity": "sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw==", + "dev": true + }, "dateformat": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", @@ -1172,6 +1252,12 @@ } } }, + "dedent": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", + "integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=", + "dev": true + }, "deep-aplus": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/deep-aplus/-/deep-aplus-1.0.4.tgz", @@ -1285,12 +1371,27 @@ "is-obj": "^1.0.0" } }, + "elegant-spinner": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/elegant-spinner/-/elegant-spinner-1.0.1.tgz", + "integrity": "sha1-2wQ1IcldfjA/2PNFvtwzSc+wcp4=", + "dev": true + }, "emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "requires": { + "once": "^1.4.0" + } + }, "entities": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", @@ -1682,6 +1783,67 @@ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true }, + "execa": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-3.4.0.tgz", + "integrity": "sha512-r9vdGQk4bmCuK1yKQu1KTwcT2zwfWdbdaXfCtAh+5nU/4fSX+JAb7vZGvI5naJrQlvONrEB20jeruESI69530g==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.0", + "get-stream": "^5.0.0", + "human-signals": "^1.1.1", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.0", + "onetime": "^5.1.0", + "p-finally": "^2.0.0", + "signal-exit": "^3.0.2", + "strip-final-newline": "^2.0.0" + }, + "dependencies": { + "cross-spawn": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.1.tgz", + "integrity": "sha512-u7v4o84SwFpD32Z8IIcPZ6z1/ie24O6RU3RbtL5Y316l3KuHVPx9ItBgWQ6VlfAFnRnTtMUrsQ9MUUTuEZjogg==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, "external-editor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", @@ -2006,6 +2168,12 @@ "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", "dev": true }, + "get-own-enumerable-property-symbols": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz", + "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==", + "dev": true + }, "get-pkg-repo": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/get-pkg-repo/-/get-pkg-repo-1.4.0.tgz", @@ -2220,6 +2388,15 @@ "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", "dev": true }, + "get-stream": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.1.0.tgz", + "integrity": "sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, "git-raw-commits": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-2.0.0.tgz", @@ -2462,6 +2639,23 @@ "function-bind": "^1.1.1" } }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + } + } + }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -2508,6 +2702,12 @@ "integrity": "sha512-a4u9BeERWGu/S8JiWEAQcdrg9v4QArtP9keViQjGMdff20fBdd8waotXaNmODqBe6uZ3Nafi7K/ho4gCQHV3Ig==", "dev": true }, + "human-signals": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", + "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", + "dev": true + }, "husky": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/husky/-/husky-4.2.1.tgz", @@ -2789,6 +2989,15 @@ "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", "dev": true }, + "is-observable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-observable/-/is-observable-1.1.0.tgz", + "integrity": "sha512-NqCa4Sa2d+u7BWc6CukaObG3Fh+CU9bvixbpcXYhy2VvYS7vVGIdAgnIS5Ks3A/cqk4rebLJ9s8zBstT2aKnIA==", + "dev": true, + "requires": { + "symbol-observable": "^1.1.0" + } + }, "is-plain-obj": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", @@ -2810,6 +3019,12 @@ "has": "^1.0.3" } }, + "is-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", + "integrity": "sha1-/S2INUXEa6xaYz57mgnof6LLUGk=", + "dev": true + }, "is-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", @@ -3254,6 +3469,323 @@ "uc.micro": "^1.0.1" } }, + "lint-staged": { + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-10.0.3.tgz", + "integrity": "sha512-N071+M0yxKX0u67UOB8emFms29ekzrKoX1UlPcLS615O/rhx3+xRk5so8uU4tjdg4yNsD3ntdPSsuZnUPzblLA==", + "dev": true, + "requires": { + "chalk": "^3.0.0", + "commander": "^4.0.1", + "cosmiconfig": "^6.0.0", + "debug": "^4.1.1", + "dedent": "^0.7.0", + "execa": "^3.4.0", + "listr": "^0.14.3", + "log-symbols": "^3.0.0", + "micromatch": "^4.0.2", + "normalize-path": "^3.0.0", + "please-upgrade-node": "^3.2.0", + "string-argv": "0.3.1", + "stringify-object": "^3.3.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "dev": true, + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "commander": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.0.tgz", + "integrity": "sha512-NIQrwvv9V39FHgGFm36+U9SMQzbiHvU79k+iADraJTpmrFFfx7Ds0IvDoAdZsDrknlkRk14OYoWXb57uTh7/sw==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "log-symbols": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-3.0.0.tgz", + "integrity": "sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ==", + "dev": true, + "requires": { + "chalk": "^2.4.2" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "listr": { + "version": "0.14.3", + "resolved": "https://registry.npmjs.org/listr/-/listr-0.14.3.tgz", + "integrity": "sha512-RmAl7su35BFd/xoMamRjpIE4j3v+L28o8CT5YhAXQJm1fD+1l9ngXY8JAQRJ+tFK2i5njvi0iRUKV09vPwA0iA==", + "dev": true, + "requires": { + "@samverschueren/stream-to-observable": "^0.3.0", + "is-observable": "^1.1.0", + "is-promise": "^2.1.0", + "is-stream": "^1.1.0", + "listr-silent-renderer": "^1.1.1", + "listr-update-renderer": "^0.5.0", + "listr-verbose-renderer": "^0.5.0", + "p-map": "^2.0.0", + "rxjs": "^6.3.3" + }, + "dependencies": { + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true + }, + "p-map": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", + "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", + "dev": true + } + } + }, + "listr-silent-renderer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz", + "integrity": "sha1-kktaN1cVN3C/Go4/v3S4u/P5JC4=", + "dev": true + }, + "listr-update-renderer": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/listr-update-renderer/-/listr-update-renderer-0.5.0.tgz", + "integrity": "sha512-tKRsZpKz8GSGqoI/+caPmfrypiaq+OQCbd+CovEC24uk1h952lVj5sC7SqyFUm+OaJ5HN/a1YLt5cit2FMNsFA==", + "dev": true, + "requires": { + "chalk": "^1.1.3", + "cli-truncate": "^0.2.1", + "elegant-spinner": "^1.0.1", + "figures": "^1.7.0", + "indent-string": "^3.0.0", + "log-symbols": "^1.0.2", + "log-update": "^2.3.0", + "strip-ansi": "^3.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "figures": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5", + "object-assign": "^4.1.0" + } + }, + "indent-string": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", + "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=", + "dev": true + }, + "log-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz", + "integrity": "sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=", + "dev": true, + "requires": { + "chalk": "^1.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "listr-verbose-renderer": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/listr-verbose-renderer/-/listr-verbose-renderer-0.5.0.tgz", + "integrity": "sha512-04PDPqSlsqIOaaaGZ+41vq5FejI9auqTInicFRndCBgE3bXG8D6W1I+mWhk+1nqbHmyhla/6BUrd5OSiHwKRXw==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "cli-cursor": "^2.1.0", + "date-fns": "^1.27.2", + "figures": "^2.0.0" + }, + "dependencies": { + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "dev": true, + "requires": { + "restore-cursor": "^2.0.0" + } + }, + "figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "dev": true + }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "dev": true, + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "dev": true, + "requires": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + } + } + } + }, "load-json-file": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", @@ -3609,6 +4141,100 @@ "chalk": "^2.0.1" } }, + "log-update": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-2.3.0.tgz", + "integrity": "sha1-iDKP19HOeTiykoN0bwsbwSayRwg=", + "dev": true, + "requires": { + "ansi-escapes": "^3.0.0", + "cli-cursor": "^2.0.0", + "wrap-ansi": "^3.0.1" + }, + "dependencies": { + "ansi-escapes": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", + "dev": true + }, + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "dev": true, + "requires": { + "restore-cursor": "^2.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "dev": true + }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "dev": true, + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "dev": true, + "requires": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + } + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + }, + "wrap-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-3.0.1.tgz", + "integrity": "sha1-KIoE2H7aXChuBg3+jxNc6NAH+Lo=", + "dev": true, + "requires": { + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0" + } + } + } + }, "loud-rejection": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", @@ -3765,6 +4391,22 @@ } } }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "micromatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", + "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", + "dev": true, + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.0.5" + } + }, "mimic-fn": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", @@ -4038,6 +4680,23 @@ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true }, + "npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "requires": { + "path-key": "^3.0.0" + }, + "dependencies": { + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + } + } + }, "null-check": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/null-check/-/null-check-1.0.0.tgz", @@ -4360,6 +5019,12 @@ "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", "dev": true }, + "p-finally": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-2.0.1.tgz", + "integrity": "sha512-vpm09aKwq6H9phqRQzecoDpD8TmVyGw70qmWlyq5onxY7tqyTTFVvxMykxQSQKILBSFlbXpypIw2T1Ml7+DDtw==", + "dev": true + }, "p-limit": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", @@ -4572,6 +5237,16 @@ "integrity": "sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag==", "dev": true }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", @@ -5145,6 +5820,12 @@ "integrity": "sha512-DBp0lSvX5G9KGRDTkR/R+a29H+Wk2xItOF+MpZLLNDWbEV9tGPnqLPxHEYjmiz8xGtJHRIqmI+hCjmNzqoA4nQ==", "dev": true }, + "string-argv": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.1.tgz", + "integrity": "sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg==", + "dev": true + }, "string-width": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", @@ -5204,6 +5885,17 @@ } } }, + "stringify-object": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz", + "integrity": "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==", + "dev": true, + "requires": { + "get-own-enumerable-property-symbols": "^3.0.0", + "is-obj": "^1.0.1", + "is-regexp": "^1.0.0" + } + }, "strip-ansi": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", @@ -5227,6 +5919,12 @@ "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", "dev": true }, + "strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true + }, "strip-indent": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-2.0.0.tgz", @@ -5248,6 +5946,12 @@ "has-flag": "^3.0.0" } }, + "symbol-observable": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", + "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==", + "dev": true + }, "table": { "version": "5.4.6", "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", diff --git a/package.json b/package.json index 540f530..8f4346a 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,7 @@ }, "dependencies": { "archy": "^1.0.0", - "commander": "^4.1.0", + "commander": "^2.20.3", "customize": "^4.0.1", "customize-engine-handlebars": "^4.0.1", "customize-write-files": "^4.0.1", @@ -68,6 +68,7 @@ "eslint-plugin-promise": "^4.2.1", "eslint-plugin-standard": "^4.0.1", "husky": "^4.2.1", + "lint-staged": "^10.0.3", "lodash.isplainobject": "^4.0.6", "mocha": "^7.0.1", "nock": "^11.7.2", @@ -78,10 +79,16 @@ "thought-plugin-jsdoc": "^2.0.0", "thoughtful-release": "^1.0.0" }, - "standard": { - "ignore": [ - "test/fixtures/**" - ] + "keywords": [], + "husky": { + "hooks": { + "pre-commit": "lint-staged" + } }, - "keywords": [] + "lint-staged": { + "*.js": [ + "eslint --cache --fix", + "prettier --write" + ] + } } diff --git a/test/cli-spec.js b/test/cli-spec.js index 49072c6..f93f1c9 100644 --- a/test/cli-spec.js +++ b/test/cli-spec.js @@ -7,16 +7,16 @@ const cli = require('../lib/cli.js') const exec = require('../lib/utils/exeq') const cpMock = require('./lib/child-process-mock') -describe('The cli script', function () { +describe('The cli script', function() { this.timeout(30000) const scenario = new Scenario('simple-project') const stackTraceLimit = Error.stackTraceLimit - beforeEach(function () { + beforeEach(function() { // Make "npm install" faster by not really executing it cpMock.mockSpawn( - (cmd) => cmd.match(/npm/), - function (cmd, args, options) { + cmd => cmd.match(/npm/), + function(cmd, args, options) { setTimeout(() => this.emit('exit', 0), 10) } ) @@ -27,8 +27,9 @@ describe('The cli script', function () { Error.stackTraceLimit = stackTraceLimit }) - it('should report missing hooks in package.json', function () { - return scenario.prepareAndRun(() => runMockThought('run')) + it('should report missing hooks in package.json', function() { + return scenario + .prepareAndRun(() => runMockThought('run')) .then(result => { expect(result.stderr).to.equal('') expect(result.stdout).to.match(/Not registered in package.json yet/) @@ -37,8 +38,9 @@ describe('The cli script', function () { }) }) - it('should run without errors with debugging enabled', function () { - return scenario.prepareAndRun(() => runMockThought('-d', 'run')) + it('should run without errors with debugging enabled', function() { + return scenario + .prepareAndRun(() => runMockThought('-d', 'run')) .then(result => { expect(result.code).to.equal(0) expect(result.stderr).to.equal('') @@ -46,8 +48,9 @@ describe('The cli script', function () { }) }) - it('should check engines with no errors in a simple project', function () { - return scenario.prepareAndRun(() => runMockThought('check-engines')) + it('should check engines with no errors in a simple project', function() { + return scenario + .prepareAndRun(() => runMockThought('check-engines')) .then(result => { expect(result.stdout).to.equal('OK') expect(result.stderr).to.equal('') @@ -55,14 +58,15 @@ describe('The cli script', function () { }) }) - it('should fail the engine check if the npm-version does not match', function () { + it('should fail the engine check if the npm-version does not match', function() { cpMock.mockExecFile( (cmd, args) => cmd.match(/npm/) && args && args[0] === '--version', - function (cmd, args, options, callback) { + function(cmd, args, options, callback) { callback(null, '2.0.0', '') } ) - return scenario.prepareAndRun(() => runMockThought('check-engines')) + return scenario + .prepareAndRun(() => runMockThought('check-engines')) .then(result => { expect(result.code).to.equal(1) expect(result.stdout).to.equal('') @@ -70,7 +74,7 @@ describe('The cli script', function () { }) }) - it('should initialize npm scripts with the "init" command', function () { + it('should initialize npm scripts with the "init" command', function() { return scenario.prepareAndRun(() => { return exec('git', ['init']) .then(() => exec('git', ['add', '-A'])) @@ -83,8 +87,9 @@ describe('The cli script', function () { }) .then(() => runMockThought('run')) .then(result => { - expect(result.stdout, 'Do not show warning about missing npm-scripts') - .not.to.match(/Not registered in package\.json yet/) + expect(result.stdout, 'Do not show warning about missing npm-scripts').not.to.match( + /Not registered in package\.json yet/ + ) expect(result.stderr).to.equal('') expect(result.code, 'Exit code of first "thought run"').to.equal(0) }) @@ -92,14 +97,15 @@ describe('The cli script', function () { return runMockThought('init') }) .then(result => { - expect(result.stderr, 'Show errors if scripts are already there') - .to.match(/I think scripts are already in your package.json/) + expect(result.stderr, 'Show errors if scripts are already there').to.match( + /I think scripts are already in your package.json/ + ) expect(result.code, 'Exit code of first "thought init"').to.equal(1) }) }) }) - it('should perform the up-to-date check in a simple project', function () { + it('should perform the up-to-date check in a simple project', function() { return scenario.prepareAndRun(() => runMockThought('up-to-date') .then(result => { @@ -128,21 +134,21 @@ describe('The cli script', function () { * @param {...string} args the cli-arguments for thought * @returns {Promise} */ -function runMockThought (...args) { +function runMockThought(...args) { return new Promise((resolve, reject) => { const argv = ['node', require.resolve('../bin/thought')].concat(args) const fakeConsole = { stdout: [], stderr: [], - error: function (...message) { + error: function(...message) { this.stderr.push(message.join(' ')) }, - log: function (...message) { + log: function(...message) { this.stdout.push(message.join(' ')) } } delete require.cache[require.resolve('commander')] - cli(argv, fakeConsole, (code) => { + cli(argv, fakeConsole, code => { const stdout = fakeConsole.stdout.join('\n') const stderr = fakeConsole.stderr.join('\n') resolve({ code, stdout, stderr }) diff --git a/test/dev-server-spec.js b/test/dev-server-spec.js index 042a2c9..c55ac02 100644 --- a/test/dev-server-spec.js +++ b/test/dev-server-spec.js @@ -9,36 +9,38 @@ 'use strict' -var chai = require('chai') -var chaiAsPromised = require('chai-as-promised') +const chai = require('chai') +const chaiAsPromised = require('chai-as-promised') chai.use(chaiAsPromised) -var expect = chai.expect -var fs = require('fs') +const expect = chai.expect +const fs = require('fs') -xdescribe('the thought dev-server', function () { - var child = null +xdescribe('the thought dev-server', function() { + let child = null this.timeout(10000) - before(function () { + before(function() { child = require('child_process').fork(require.resolve('../lib/dev-server'), { cwd: 'test/fixtures/scenarios/simple-project/input' }) }) - it('should run thought and return the result (if a "run"-message is sent")', function (done) { + it('should run thought and return the result (if a "run"-message is sent")', function(done) { child.send({ cmd: 'run' }) - child.on('message', (message) => { + child.on('message', message => { expect(message).to.deep.equal({ - 'message': { - 'cmd': 'run' + message: { + cmd: 'run' }, - 'result': { - 'handlebars': { - 'CONTRIBUTING.md': fs.readFileSync('test/fixtures/scenarios/simple-project/expected/CONTRIBUTING.md', - { encoding: 'utf-8' }), - 'README.md': fs.readFileSync('test/fixtures/scenarios/simple-project/expected/README.md', - { encoding: 'utf-8' }) + result: { + handlebars: { + 'CONTRIBUTING.md': fs.readFileSync('test/fixtures/scenarios/simple-project/expected/CONTRIBUTING.md', { + encoding: 'utf-8' + }), + 'README.md': fs.readFileSync('test/fixtures/scenarios/simple-project/expected/README.md', { + encoding: 'utf-8' + }) } } }) diff --git a/test/git-spec.js b/test/git-spec.js index f7e8248..cee8965 100644 --- a/test/git-spec.js +++ b/test/git-spec.js @@ -9,33 +9,36 @@ 'use strict' -var Scenario = require('./lib/scenarios') -var thought = require('../') -var simpleGit = require('simple-git/promise') +const Scenario = require('./lib/scenarios') +const thought = require('../') +const simpleGit = require('simple-git/promise') -var chai = require('chai') +const chai = require('chai') chai.use(require('chai-as-promised')) chai.use(require('dirty-chai')) -var expect = chai.expect +const expect = chai.expect -describe('The "addToGit" option', function () { +describe('The "addToGit" option', function() { this.timeout(10000) - it('should add the generated files to the git-index', function () { - var scenario = new Scenario('simple-project').withTmpDir('test-output/addToGit') + it('should add the generated files to the git-index', function() { + const scenario = new Scenario('simple-project').withTmpDir('test-output/addToGit') return scenario.prepareAndRun(() => { - var git = simpleGit(scenario.actual) + const git = simpleGit(scenario.actual) - return git.init() - .then(() => thought({ addToGit: true })) - .then(() => git.status()) - // Check only which files have been added to the index - .then((status) => { - return status.files - .filter(fileEntry => fileEntry.index === 'A') - .map(fileEntry => fileEntry.path) - .sort() - }) - .then((files) => expect(files).to.deep.equal(['README.md'])) + return ( + git + .init() + .then(() => thought({ addToGit: true })) + .then(() => git.status()) + // Check only which files have been added to the index + .then(status => { + return status.files + .filter(fileEntry => fileEntry.index === 'A') + .map(fileEntry => fileEntry.path) + .sort() + }) + .then(files => expect(files).to.deep.equal(['README.md'])) + ) }) }) }) diff --git a/test/helper-spec.js b/test/helper-spec.js index 4ef21a6..f312570 100644 --- a/test/helper-spec.js +++ b/test/helper-spec.js @@ -9,27 +9,27 @@ 'use strict' -var fs = require('fs') +const fs = require('fs') const helpers = require('../handlebars/helpers/index.js') -var chai = require('chai') -var deep = require('deep-aplus')(Promise) -var chaiAsPromised = require('chai-as-promised') +const chai = require('chai') +const deep = require('deep-aplus')(Promise) +const chaiAsPromised = require('chai-as-promised') chai.use(chaiAsPromised) chai.use(require('dirty-chai')) -var expect = chai.expect -var path = require('path') +const expect = chai.expect +const path = require('path') -var engine = require('customize-engine-handlebars') +const engine = require('customize-engine-handlebars') -function executeInDir (directory) { - var oldCwd = null +function executeInDir(directory) { + let oldCwd = null - before(function () { + before(function() { oldCwd = process.cwd() process.chdir(directory) }) - after(function () { + after(function() { process.chdir(oldCwd) }) } @@ -40,7 +40,7 @@ function executeInDir (directory) { * @param {object} input the input object * @returns {*} */ -function expectHbs (template, input, filename) { +function expectHbs(template, input, filename) { filename = filename || 'README.md' return expect( Promise.resolve() @@ -63,7 +63,7 @@ function expectHbs (template, input, filename) { return engine.run(config) }) .then(deep) - .then((result) => { + .then(result => { return result[filename].trim() }) ) @@ -74,7 +74,7 @@ function expectHbs (template, input, filename) { * @param {string} filename * @returns {string} */ -function fixture (filename) { +function fixture(filename) { const absPath = path.join(__dirname, 'fixtures', filename) try { const result = fs.readFileSync(absPath, { encoding: 'utf-8' }).trim() @@ -87,172 +87,180 @@ function fixture (filename) { } } -describe('thought-helpers:', function () { - describe('The "dirTree" helper', function () { - it('should return a file-hierarchy as markdown code', function () { - return expectHbs('{{dirTree directory}}', { directory: 'test/fixtures/dir-tree' }) - .to.eventually.equal(fixture('dir-tree.output.txt')) +describe('thought-helpers:', function() { + describe('The "dirTree" helper', function() { + it('should return a file-hierarchy as markdown code', function() { + return expectHbs('{{dirTree directory}}', { directory: 'test/fixtures/dir-tree' }).to.eventually.equal( + fixture('dir-tree.output.txt') + ) }) - it('should add a label as name of the root-node, if specified', function () { - return expectHbs('{{dirTree directory label=\'rootNode\'}}', { directory: 'test/fixtures/dir-tree' }) - .to.eventually.equal(fixture('dir-tree.label.txt')) + it('should add a label as name of the root-node, if specified', function() { + return expectHbs("{{dirTree directory label='rootNode'}}", { + directory: 'test/fixtures/dir-tree' + }).to.eventually.equal(fixture('dir-tree.label.txt')) }) - it('should filter specific entries through globs', function () { - return expectHbs('{{dirTree directory glob}}', { - directory: 'test/fixtures/dir-tree', - glob: '!(subdirB)/**' - }, 'some-dir/') - .to.eventually.equal(fixture('dir-tree.output.filtered.txt')) + it('should filter specific entries through globs', function() { + return expectHbs( + '{{dirTree directory glob}}', + { + directory: 'test/fixtures/dir-tree', + glob: '!(subdirB)/**' + }, + 'some-dir/' + ).to.eventually.equal(fixture('dir-tree.output.filtered.txt')) }) - it('should condense paths with a single subdirectory into a single node', function () { - return expectHbs('{{dirTree directory glob}}', { directory: 'test/fixtures/dir-tree', glob: '**/aFile.txt' }) - .to.eventually.equal(fixture('dir-tree.output.condensed.txt')) + it('should condense paths with a single subdirectory into a single node', function() { + return expectHbs('{{dirTree directory glob}}', { + directory: 'test/fixtures/dir-tree', + glob: '**/aFile.txt' + }).to.eventually.equal(fixture('dir-tree.output.condensed.txt')) }) - it('should work with more complex globs', function () { + it('should work with more complex globs', function() { return expectHbs('{{dirTree directory glob}}', { directory: 'test/fixtures/dir-tree', glob: '**/!(aFile.txt|bFile.txt)' - }) - .to.eventually.equal(fixture('dir-tree.output.complex.filter.txt')) + }).to.eventually.equal(fixture('dir-tree.output.complex.filter.txt')) }) - it('should ignore files specified in the ignore-option', function () { + it('should ignore files specified in the ignore-option', function() { return expectHbs('{{dirTree directory glob ignore=ignore}}', { directory: 'test/fixtures/dir-tree', glob: '**', ignore: ['**/aFile.txt', '**/bFile.txt'] - }) - .to.eventually.equal(fixture('dir-tree.output.ignore.files.txt')) + }).to.eventually.equal(fixture('dir-tree.output.ignore.files.txt')) }) - it('should show dot-files if the dot-option is set', function () { + it('should show dot-files if the dot-option is set', function() { return expectHbs('{{dirTree directory glob dot=true}}', { directory: 'test/fixtures/dir-tree', glob: 'subdirA/bDir/**' - }) - .to.eventually.equal(fixture('dir-tree.output.dot.files.txt')) + }).to.eventually.equal(fixture('dir-tree.output.dot.files.txt')) }) - it('should only create links for files matching the glob-pattern', function () { - return expectHbs('{{dirTree directory glob links=\'true\'}}', { + it('should only create links for files matching the glob-pattern', function() { + return expectHbs("{{dirTree directory glob links='true'}}", { directory: 'test/fixtures/dir-tree', glob: '**/aFile.txt' - }) - .to.eventually.equal(fixture('dir-tree.output.links.matching.files.txt')) + }).to.eventually.equal(fixture('dir-tree.output.links.matching.files.txt')) }) - it('create links relative to the current target file if the "links"-option is set"', function () { + it('create links relative to the current target file if the "links"-option is set"', function() { return expectHbs( - '{{dirTree directory glob links=\'true\'}}', + "{{dirTree directory glob links='true'}}", { directory: 'test/fixtures/dir-tree/subdirA/bDir' }, 'src/test.md' - ) - .to.eventually.equal(fixture('dir-tree.output.links.relative.txt')) + ).to.eventually.equal(fixture('dir-tree.output.links.relative.txt')) }) - it('should throw an error if the glob does not resolve to any files', function () { - return expectHbs('{{dirTree directory}}', { directory: 'non-existing-dir' }) - .to.be.rejectedWith('Cannot find a single file for \'**\' in \'non-existing-dir\'') + it('should throw an error if the glob does not resolve to any files', function() { + return expectHbs('{{dirTree directory}}', { directory: 'non-existing-dir' }).to.be.rejectedWith( + "Cannot find a single file for '**' in 'non-existing-dir'" + ) }) }) - describe('The "example" helper', function () { + describe('The "example" helper', function() { executeInDir('test/fixtures/example-helper') - it('should resolve the current project properly', function () { - return expectHbs( - '{{example file}}', - { file: 'examples/full.js' } + it('should resolve the current project properly', function() { + return expectHbs('{{example file}}', { file: 'examples/full.js' }).to.eventually.equal( + fixture('example-helper/examples/output.full.md') ) - .to.eventually.equal(fixture('example-helper/examples/output.full.md')) }) - it('should return the marked part of the file if `options.hash.snippet` is true', function () { - return expectHbs( - '{{example file snippet=true}}', - { file: 'examples/snippet.js' } + it('should return the marked part of the file if `options.hash.snippet` is true', function() { + return expectHbs('{{example file snippet=true}}', { file: 'examples/snippet.js' }).to.eventually.equal( + fixture('example-helper/examples/output.snippet.md') ) - .to.eventually.equal(fixture('example-helper/examples/output.snippet.md')) }) - it('should ignore the snippet markers, if "snippet=true" is not set`', function () { - return expectHbs( - '{{example file}}', - { file: 'examples/snippet.js' } + it('should ignore the snippet markers, if "snippet=true" is not set`', function() { + return expectHbs('{{example file}}', { file: 'examples/snippet.js' }).to.eventually.equal( + fixture('example-helper/examples/output.snippet-full.md') ) - .to.eventually.equal(fixture('example-helper/examples/output.snippet-full.md')) }) }) - describe('The "json"-helper', function () { - it('should display a javascript-object as JSON', function () { - return expectHbs('{{json .}}', { a: { b: 2 }, c: [1, 2, 'a', 'b'] }) - .to.eventually.equal(fixture('json.output.simple.md')) + describe('The "json"-helper', function() { + it('should display a javascript-object as JSON', function() { + return expectHbs('{{json .}}', { a: { b: 2 }, c: [1, 2, 'a', 'b'] }).to.eventually.equal( + fixture('json.output.simple.md') + ) }) }) - describe('The "include"-helper', function () { - it('should include a file into fences', function () { - return expectHbs('{{include file}}', { file: 'test/fixtures/include/javascript.js' }) - .to.eventually.equal(fixture('include/output.javascript.md')) + describe('The "include"-helper', function() { + it('should include a file into fences', function() { + return expectHbs('{{include file}}', { file: 'test/fixtures/include/javascript.js' }).to.eventually.equal( + fixture('include/output.javascript.md') + ) }) - it('should use the file extension as language descriptor', function () { - return expectHbs('{{include file}}', { file: 'test/fixtures/include/text.txt' }) - .to.eventually.equal(fixture('include/output.text.md')) + it('should use the file extension as language descriptor', function() { + return expectHbs('{{include file}}', { file: 'test/fixtures/include/text.txt' }).to.eventually.equal( + fixture('include/output.text.md') + ) }) - it('should prefer the file language descriptor provided as second parameter', function () { - return expectHbs('{{include file "txt"}}', { file: 'test/fixtures/include/javascript.js' }) - .to.eventually.equal(fixture('include/output.javascript-as-text.md')) + it('should prefer the file language descriptor provided as second parameter', function() { + return expectHbs('{{include file "txt"}}', { file: 'test/fixtures/include/javascript.js' }).to.eventually.equal( + fixture('include/output.javascript-as-text.md') + ) }) }) - describe('The "includeRaw"-helper', function () { - it('should include a file without any fences', function () { - return expectHbs('{{includeRaw file}}', { file: 'test/fixtures/include/javascript.js' }) - .to.eventually.equal(fixture('include/javascript.js')) + describe('The "includeRaw"-helper', function() { + it('should include a file without any fences', function() { + return expectHbs('{{includeRaw file}}', { file: 'test/fixtures/include/javascript.js' }).to.eventually.equal( + fixture('include/javascript.js') + ) }) }) - describe('The "exec"-helper', function () { - it('should execute a command and return the output in a fence', function () { - return expectHbs('{{exec "node test/fixtures/shout.js"}}', {}) - .to.eventually.equal(fixture('exec.output.default.md')) + describe('The "exec"-helper', function() { + it('should execute a command and return the output in a fence', function() { + return expectHbs('{{exec "node test/fixtures/shout.js"}}', {}).to.eventually.equal( + fixture('exec.output.default.md') + ) }) - it('should add language to the fence if the "lang"-option is set', function () { - return expectHbs('{{exec "node test/fixtures/shout.js" lang="js"}}', {}) - .to.eventually.equal(fixture('exec.output.as.js.md')) + it('should add language to the fence if the "lang"-option is set', function() { + return expectHbs('{{exec "node test/fixtures/shout.js" lang="js"}}', {}).to.eventually.equal( + fixture('exec.output.as.js.md') + ) }) - it('should not output fences if lang="raw"', function () { - return expectHbs('{{exec "node test/fixtures/shout.js" lang="raw"}}', {}) - .to.eventually.equal(fixture('exec.output.raw.md')) + it('should not output fences if lang="raw"', function() { + return expectHbs('{{exec "node test/fixtures/shout.js" lang="raw"}}', {}).to.eventually.equal( + fixture('exec.output.raw.md') + ) }) - it('should surround the output with single backticks if lang="inline"', function () { - return expectHbs('{{exec "node test/fixtures/shout.js" lang="inline"}}', {}) - .to.eventually.equal(fixture('exec.output.inline.md')) + it('should surround the output with single backticks if lang="inline"', function() { + return expectHbs('{{exec "node test/fixtures/shout.js" lang="inline"}}', {}).to.eventually.equal( + fixture('exec.output.inline.md') + ) }) - it('should chdir to the directory provided as cwd="..."', function () { - return expectHbs('{{exec "node shout.js" cwd="test/fixtures"}}', {}) - .to.eventually.equal(fixture('exec.output.cwd.md')) + it('should chdir to the directory provided as cwd="..."', function() { + return expectHbs('{{exec "node shout.js" cwd="test/fixtures"}}', {}).to.eventually.equal( + fixture('exec.output.cwd.md') + ) }) }) - describe('The "renderTree"-helper', function () { - it('render a tree', function () { - return expectHbs('{{#renderTree tree}}--{{prop1}} ({{children.length}})--{{/renderTree}}', { tree: tree() }) - .to.eventually.equal(fixture('renderTree.output.md')) + describe('The "renderTree"-helper', function() { + it('render a tree', function() { + return expectHbs('{{#renderTree tree}}--{{prop1}} ({{children.length}})--{{/renderTree}}', { + tree: tree() + }).to.eventually.equal(fixture('renderTree.output.md')) }) - function tree () { + function tree() { return { prop1: 'parent', children: [ @@ -263,7 +271,6 @@ describe('thought-helpers:', function () { { prop1: 'emptyChild' } - ] } } @@ -273,271 +280,232 @@ describe('thought-helpers:', function () { * Replace some versions by versions currently in package.json * @param expectedString */ - function versions (expectedString) { - var thought = require('../package').version - var customize = require('customize/package').version - return expectedString - .replace(/THOUGHT_VERSION/g, `v${thought}`) - .replace(/CUSTOMIZE_VERSION/g, `v${customize}`) + function versions(expectedString) { + const thought = require('../package').version + const customize = require('customize/package').version + return expectedString.replace(/THOUGHT_VERSION/g, `v${thought}`).replace(/CUSTOMIZE_VERSION/g, `v${customize}`) } - describe('The "withPackageOf"-helper', function () { - it('should create a url and package.json for file on github (based on the current package version)', function () { - return expectHbs( - '{{#withPackageOf file}} {{@url}} - {{@package.name}} {{/withPackageOf}}', - { file: 'test/fixtures/shout.js' } - ) - .to.eventually.equal(versions(fixture('include/withPackageOf.default.md'))) + describe('The "withPackageOf"-helper', function() { + it('should create a url and package.json for file on github (based on the current package version)', function() { + return expectHbs('{{#withPackageOf file}} {{@url}} - {{@package.name}} {{/withPackageOf}}', { + file: 'test/fixtures/shout.js' + }).to.eventually.equal(versions(fixture('include/withPackageOf.default.md'))) }) - it('should create a rawUrl for file on github (based on the current package version)', function () { - return expectHbs( - '{{#withPackageOf file}}{{@rawUrl}}{{/withPackageOf}}', - { file: 'test/fixtures/shout.js' } + it('should create a rawUrl for file on github (based on the current package version)', function() { + return expectHbs('{{#withPackageOf file}}{{@rawUrl}}{{/withPackageOf}}', { + file: 'test/fixtures/shout.js' + }).to.eventually.equal( + versions('https://raw.githubusercontent.com/nknapp/thought/THOUGHT_VERSION/test/fixtures/shout.js') ) - .to.eventually.equal(versions('https://raw.githubusercontent.com/nknapp/thought/THOUGHT_VERSION/test/fixtures/shout.js')) }) - it('should create a url and package.json for file on github (with a git-ssh-url)', function () { - return expectHbs( - '{{#withPackageOf file}} {{@url}} - {{@package.name}} {{/withPackageOf}}', - { file: 'test/fixtures/github-ssh-repo-url/package.json' } - ) - .to.eventually.equal(versions(fixture('include/withPackageOf.ssh.md'))) + it('should create a url and package.json for file on github (with a git-ssh-url)', function() { + return expectHbs('{{#withPackageOf file}} {{@url}} - {{@package.name}} {{/withPackageOf}}', { + file: 'test/fixtures/github-ssh-repo-url/package.json' + }).to.eventually.equal(versions(fixture('include/withPackageOf.ssh.md'))) }) - it('should create a rawurl file on github (with a git-ssh-url)', function () { - return expectHbs( - '{{#withPackageOf file}}{{@rawUrl}}{{/withPackageOf}}', - { file: 'test/fixtures/github-ssh-repo-url/package.json' } + it('should create a rawurl file on github (with a git-ssh-url)', function() { + return expectHbs('{{#withPackageOf file}}{{@rawUrl}}{{/withPackageOf}}', { + file: 'test/fixtures/github-ssh-repo-url/package.json' + }).to.eventually.equal( + versions('https://raw.githubusercontent.com/nknapp/thought-plugin-jsdoc/v1.0.0/package.json') ) - .to.eventually.equal(versions('https://raw.githubusercontent.com/nknapp/thought-plugin-jsdoc/v1.0.0/package.json')) }) - it('should create a rawUrl for files in dependency projects (based on the their current package version)', function () { - return expectHbs( - '{{#withPackageOf file}}{{@rawUrl}}{{/withPackageOf}}', - { file: require.resolve('customize/helpers-io.js') } + it('should create a rawUrl for files in dependency projects (based on the their current package version)', function() { + return expectHbs('{{#withPackageOf file}}{{@rawUrl}}{{/withPackageOf}}', { + file: require.resolve('customize/helpers-io.js') + }).to.eventually.equal( + versions('https://raw.githubusercontent.com/bootprint/customize/CUSTOMIZE_VERSION/helpers-io.js') ) - .to.eventually.equal(versions('https://raw.githubusercontent.com/bootprint/customize/CUSTOMIZE_VERSION/helpers-io.js')) }) - it('should not create an url for files without repository-property in the package.json', function () { - return expectHbs( - '{{#withPackageOf file}} {{@url}} - {{@package.name}} {{/withPackageOf}}', - { file: require.resolve('./fixtures/no-git-repo/package.json') } - ) - .to.eventually.equal(versions(fixture('include/withPackageOf.no-repo.md'))) + it('should not create an url for files without repository-property in the package.json', function() { + return expectHbs('{{#withPackageOf file}} {{@url}} - {{@package.name}} {{/withPackageOf}}', { + file: require.resolve('./fixtures/no-git-repo/package.json') + }).to.eventually.equal(versions(fixture('include/withPackageOf.no-repo.md'))) }) - it('should not create a rawUrl for files without repository-property in the package.json', function () { - return expectHbs( - '{{#withPackageOf file}}{{@rawUrl}}{{/withPackageOf}}', - { file: require.resolve('./fixtures/no-git-repo/package.json') } - ) - .to.eventually.equal('') + it('should not create a rawUrl for files without repository-property in the package.json', function() { + return expectHbs('{{#withPackageOf file}}{{@rawUrl}}{{/withPackageOf}}', { + file: require.resolve('./fixtures/no-git-repo/package.json') + }).to.eventually.equal('') }) - it('should create a @relativePath for files in dependency projects', function () { - return expectHbs( - '{{#withPackageOf file}}{{@relativePath}}{{/withPackageOf}}', - { file: require.resolve('customize/helpers-io.js') } - ) - .to.eventually.equal('helpers-io.js') + it('should create a @relativePath for files in dependency projects', function() { + return expectHbs('{{#withPackageOf file}}{{@relativePath}}{{/withPackageOf}}', { + file: require.resolve('customize/helpers-io.js') + }).to.eventually.equal('helpers-io.js') }) }) - it('should create a @relativePath for projects without repository-property', function () { - return expectHbs( - '{{#withPackageOf file}}{{@relativePath}}{{/withPackageOf}}', - { file: require.resolve('./fixtures/no-git-repo/package.json') } - ) - .to.eventually.equal('package.json') + it('should create a @relativePath for projects without repository-property', function() { + return expectHbs('{{#withPackageOf file}}{{@relativePath}}{{/withPackageOf}}', { + file: require.resolve('./fixtures/no-git-repo/package.json') + }).to.eventually.equal('package.json') }) - describe('The "github"-helper', function () { - it('should create a url to file on github (based on the current package version)', function () { - return expectHbs( - '{{github file}}', - { file: 'test/fixtures/shout.js' } + describe('The "github"-helper', function() { + it('should create a url to file on github (based on the current package version)', function() { + return expectHbs('{{github file}}', { file: 'test/fixtures/shout.js' }).to.eventually.equal( + versions(fixture('include/github.default.md')) ) - .to.eventually.equal(versions(fixture('include/github.default.md'))) }) - it('should create a url files in dependency projects (based on the their current package version)', function () { - return expectHbs( - '{{github file}}', - { file: require.resolve('customize/helpers-io.js') } + it('should create a url files in dependency projects (based on the their current package version)', function() { + return expectHbs('{{github file}}', { file: require.resolve('customize/helpers-io.js') }).to.eventually.equal( + versions(fixture('include/github.dependency.md')) ) - .to.eventually.equal(versions(fixture('include/github.dependency.md'))) }) }) - describe('The "htmlId"-helper', function () { - it('should keep valid names intact', function () { + describe('The "htmlId"-helper', function() { + it('should keep valid names intact', function() { expect(helpers.htmlId('abc')).to.equal('abc') }) - it('should replace spaces by minus', function () { + it('should replace spaces by minus', function() { expect(helpers.htmlId('abc cde')).to.equal('abc-cde') }) - it('should remove invalid characters', function () { + it('should remove invalid characters', function() { expect(helpers.htmlId('a$b&c%d')).to.equal('abcd') }) - it('should keep umlaut characters', function () { + it('should keep umlaut characters', function() { expect(helpers.htmlId('mäxchen')).to.equal('mäxchen') }) - it('should convert everything to lower-case', function () { + it('should convert everything to lower-case', function() { expect(helpers.htmlId('ABCDE')).to.equal('abcde') }) - it('should not remove japanese characters', function () { + it('should not remove japanese characters', function() { expect(helpers.htmlId('ハッピークリスマス')).to.equal('ハッピークリスマス') }) }) - describe('The "npm"-helper', function () { - it('should create a link to the npm-page, given the package name', function () { - return expectHbs( - '{{npm file}}', - { file: 'bootprint-openapi' } + describe('The "npm"-helper', function() { + it('should create a link to the npm-page, given the package name', function() { + return expectHbs('{{npm file}}', { file: 'bootprint-openapi' }).to.eventually.equal( + '[bootprint-openapi](https://npmjs.com/package/bootprint-openapi)' ) - .to.eventually.equal('[bootprint-openapi](https://npmjs.com/package/bootprint-openapi)') }) }) - describe('The "hasCoveralls"-helper (positive)', function () { + describe('The "hasCoveralls"-helper (positive)', function() { executeInDir('test/fixtures/hasCoveralls-helper') - it('should return true, if coveralls is mentioned in the .travis.yml file', function () { - return expectHbs( - '{{#if (hasCoveralls)}}yeah{{else}}nope{{/if}}', - {} - ) - .to.eventually.equal('yeah') + it('should return true, if coveralls is mentioned in the .travis.yml file', function() { + return expectHbs('{{#if (hasCoveralls)}}yeah{{else}}nope{{/if}}', {}).to.eventually.equal('yeah') }) }) - describe('The "hasCoveralls"-helper (negative)', function () { + describe('The "hasCoveralls"-helper (negative)', function() { executeInDir('test/fixtures/hasCoveralls-helper-false') - it('should return true, if coveralls is not configured', function () { - return expectHbs( - '{{#if (hasCoveralls)}}yeah{{else}}nope{{/if}}', - {} - ) - .to.eventually.equal('nope') + it('should return true, if coveralls is not configured', function() { + return expectHbs('{{#if (hasCoveralls)}}yeah{{else}}nope{{/if}}', {}).to.eventually.equal('nope') }) }) - describe('The "hasCodecov"-helper (positive)', function () { + describe('The "hasCodecov"-helper (positive)', function() { executeInDir('test/fixtures/hasCodecov-helper') - it('should return true, if coveralls is mentioned in the .travis.yml file', function () { - return expectHbs( - '{{#if (hasCodecov)}}yeah{{else}}nope{{/if}}', - {} - ) - .to.eventually.equal('yeah') + it('should return true, if coveralls is mentioned in the .travis.yml file', function() { + return expectHbs('{{#if (hasCodecov)}}yeah{{else}}nope{{/if}}', {}).to.eventually.equal('yeah') }) }) - describe('The "hasCodecov"-helper (negative)', function () { + describe('The "hasCodecov"-helper (negative)', function() { executeInDir('test/fixtures/hasCodecov-helper-false') - it('should return true, if coveralls is not configured', function () { - return expectHbs( - '{{#if (hasCodecov)}}yeah{{else}}nope{{/if}}', - {} - ) - .to.eventually.equal('nope') + it('should return true, if coveralls is not configured', function() { + return expectHbs('{{#if (hasCodecov)}}yeah{{else}}nope{{/if}}', {}).to.eventually.equal('nope') }) }) - describe('The "githubRepo"-helper', function () { - it('should return the name of organization/repository in a module with a configured ' + - 'repository on github (e.g. Thought itself)', function () { - return expectHbs('{{githubRepo}}', { - 'package': { - 'name': 'no-github-repo', - 'repository': { - 'type': 'git', - 'url': 'https://github.com/nknapp/thought.git' + describe('The "githubRepo"-helper', function() { + it( + 'should return the name of organization/repository in a module with a configured ' + + 'repository on github (e.g. Thought itself)', + function() { + return expectHbs('{{githubRepo}}', { + package: { + name: 'no-github-repo', + repository: { + type: 'git', + url: 'https://github.com/nknapp/thought.git' + } } - } - }) - .to.eventually.equal('nknapp/thought') - }) + }).to.eventually.equal('nknapp/thought') + } + ) - it('should return null in a module with no configured git repo', function () { + it('should return null in a module with no configured git repo', function() { return expectHbs('{{githubRepo}}', { package: { name: 'no-git-repo' } - }) - .not.to.eventually.be.ok() + }).not.to.eventually.be.ok() }) - it('should return null in a module with a repository that is not on github', function () { + it('should return null in a module with a repository that is not on github', function() { return expectHbs('{{githubRepo}}', { - 'package': { - 'name': 'no-github-repo', - 'repository': { - 'type': 'git', - 'url': 'https://custom-git.com/somepath.git' + package: { + name: 'no-github-repo', + repository: { + type: 'git', + url: 'https://custom-git.com/somepath.git' } } - }) - .not.to.eventually.be.ok() + }).not.to.eventually.be.ok() }) }) - describe('The "hasGreenkeeper"-helper', function () { - it('should return false, if the githubRepo is not set', function () { + describe('The "hasGreenkeeper"-helper', function() { + it('should return false, if the githubRepo is not set', function() { return expectHbs('{{hasGreenkeeper}}', { package: { name: 'no-git-repo' } - }) - .to.eventually.equal('false') + }).to.eventually.equal('false') }) - it('should return false, if the project does not have a github url', function () { + it('should return false, if the project does not have a github url', function() { return expectHbs('{{hasGreenkeeper}}', { package: { name: 'no-github-repo', - 'repository': { - 'type': 'git', - 'url': 'https://custom-git.com/somepath.git' + repository: { + type: 'git', + url: 'https://custom-git.com/somepath.git' } } - }) - .to.eventually.equal('false') + }).to.eventually.equal('false') }) - it('should return false, if the project does not have greenkeeper enabled', function () { + it('should return false, if the project does not have greenkeeper enabled', function() { return expectHbs('{{hasGreenkeeper}}', { package: { name: 'greenkeeper-disabled', - 'repository': { - 'type': 'git', - 'url': 'https://github.com/group/repo.git' + repository: { + type: 'git', + url: 'https://github.com/group/repo.git' } } - }) - .to.eventually.equal('false') + }).to.eventually.equal('false') }) - it('should throw an error, if greenKeeper is enabled in the config, but not github url is found', function () { + it('should throw an error, if greenKeeper is enabled in the config, but not github url is found', function() { return expectHbs('{{hasGreenkeeper}}', { package: { name: 'no-git-repo', - 'repository': { - 'type': 'git', - 'url': 'https://gitlab.com/group/repo.git' + repository: { + type: 'git', + url: 'https://gitlab.com/group/repo.git' } }, config: { @@ -545,17 +513,16 @@ describe('thought-helpers:', function () { greenkeeper: true } } - }) - .to.be.rejectedWith(/no github-repo/) + }).to.be.rejectedWith(/no github-repo/) }) - it('should return true, if the badge is enabled in the config', function () { + it('should return true, if the badge is enabled in the config', function() { return expectHbs('{{hasGreenkeeper}}', { package: { name: 'no-git-repo', - 'repository': { - 'type': 'git', - 'url': 'https://github.com/group/repo.git' + repository: { + type: 'git', + url: 'https://github.com/group/repo.git' } }, config: { @@ -563,17 +530,16 @@ describe('thought-helpers:', function () { greenkeeper: true } } - }) - .to.eventually.equal('true') + }).to.eventually.equal('true') }) - it('should return true, if the badge is enabled in the config', function () { + it('should return true, if the badge is enabled in the config', function() { return expectHbs('{{hasGreenkeeper}}', { package: { name: 'enabledRepo', - 'repository': { - 'type': 'git', - 'url': 'https://github.com/group/repo.git' + repository: { + type: 'git', + url: 'https://github.com/group/repo.git' } }, config: { @@ -581,26 +547,25 @@ describe('thought-helpers:', function () { greenkeeper: false } } - }) - .to.eventually.equal('false') + }).to.eventually.equal('false') }) }) - describe('The "arr" helper', function () { - it('should return an array of its arguments', function () { - return expectHbs('{{#each (arr \'a\' \'b\' \'c\')}}v:{{.}} {{/each}}', {}).to.eventually.equal('v:a v:b v:c') + describe('The "arr" helper', function() { + it('should return an array of its arguments', function() { + return expectHbs("{{#each (arr 'a' 'b' 'c')}}v:{{.}} {{/each}}", {}).to.eventually.equal('v:a v:b v:c') }) }) - describe('The "repoWebUrl" helper', function () { - it('should return a github-web-url for a github-ssh-url', function () { - return expect(helpers.repoWebUrl('git+ssh://git@github.com/nknapp/thought-plugin-jsdoc.git')) - .to.equal('https://github.com/nknapp/thought-plugin-jsdoc') + describe('The "repoWebUrl" helper', function() { + it('should return a github-web-url for a github-ssh-url', function() { + return expect(helpers.repoWebUrl('git+ssh://git@github.com/nknapp/thought-plugin-jsdoc.git')).to.equal( + 'https://github.com/nknapp/thought-plugin-jsdoc' + ) }) - it('should return null for unknown urls for a github-ssh-url', function () { - return expect(helpers.repoWebUrl('git+ssh://git@example.com/nknapp/thought-plugin-jsdoc.git')) - .to.equal(null) + it('should return null for unknown urls for a github-ssh-url', function() { + return expect(helpers.repoWebUrl('git+ssh://git@example.com/nknapp/thought-plugin-jsdoc.git')).to.equal(null) }) }) }) diff --git a/test/init-spec.js b/test/init-spec.js index 190306e..6ca5c67 100644 --- a/test/init-spec.js +++ b/test/init-spec.js @@ -9,29 +9,29 @@ 'use strict' -var Scenario = require('./lib/scenarios') -var cpMock = require('./lib/child-process-mock') -var init = require('../lib/init') -var simpleGit = require('simple-git/promise') +const Scenario = require('./lib/scenarios') +const cpMock = require('./lib/child-process-mock') +const init = require('../lib/init') +const simpleGit = require('simple-git/promise') -var chai = require('chai') +const chai = require('chai') chai.use(require('chai-as-promised')) chai.use(require('dirty-chai')) -var fs = require('fs-extra') +const fs = require('fs-extra') -var expect = chai.expect +const expect = chai.expect -describe('The init option', function () { +describe('The init option', function() { let npmInstallMockCalls this.timeout(30000) - beforeEach(function () { + beforeEach(function() { npmInstallMockCalls = [] // Make "npm install" faster by not really executing it cpMock.mockSpawn( - (cmd) => cmd.match(/npm/), - function (cmd, args, options) { + cmd => cmd.match(/npm/), + function(cmd, args, options) { npmInstallMockCalls.push({ cmd, args, options }) setTimeout(() => this.emit('exit', 0), 10) } @@ -40,120 +40,142 @@ describe('The init option', function () { afterEach(() => cpMock.clearMocks()) - it('should add scripts and devDependency to package.json', function () { - var scenario = new Scenario('simple-project').withTmpDir('test-output/thought-init1') + it('should add scripts and devDependency to package.json', function() { + const scenario = new Scenario('simple-project').withTmpDir('test-output/thought-init1') return scenario.prepareAndRun(() => { - var git = simpleGit(scenario.actual) - - return git.init() - .then(() => git.add('package.json')) - .then(() => git.commit('Initial checkin')) - .then(() => fs.writeFile('.gitignore', 'node_modules')) - .then(() => init()) - .then(() => git.log()) - // Check only which files have been added to the index - .then(log => expect(log.latest.message, 'package.json must have been committed').to.match(/Added scripts to run thought on version-bumps/)) - .then(() => fs.readFile('package.json', 'utf-8')) - .then(pkgJson => expect(JSON.parse(pkgJson), 'Checking package.json').to.deep.equals({ - 'author': '', - 'description': 'A simple description', - 'devDependencies': { - 'fs-walker': '^1.0.0', - 'thought': '^' + require('../package.json').version - }, - 'license': 'ISC', - 'main': 'index.js', - 'name': 'simple-project', - 'repository': { - 'type': 'git', - 'url': 'https://github.com/unit-test/simple-project.git' - }, - 'scripts': { - 'test': 'echo "Error: no test specified" && exit 1', - 'thought': 'thought run -a', - 'version': 'npm run thought' - }, - 'version': '1.0.0' - })) - .then(() => { - expect(npmInstallMockCalls).to.deep.equal([{ - cmd: 'npm', - args: ['install', '--save-dev', 'thought'], - options: { stdio: 'inherit' } - }]) - }) + const git = simpleGit(scenario.actual) + + return ( + git + .init() + .then(() => git.add('package.json')) + .then(() => git.commit('Initial checkin')) + .then(() => fs.writeFile('.gitignore', 'node_modules')) + .then(() => init()) + .then(() => git.log()) + // Check only which files have been added to the index + .then(log => + expect(log.latest.message, 'package.json must have been committed').to.match( + /Added scripts to run thought on version-bumps/ + ) + ) + .then(() => fs.readFile('package.json', 'utf-8')) + .then(pkgJson => + expect(JSON.parse(pkgJson), 'Checking package.json').to.deep.equals({ + author: '', + description: 'A simple description', + devDependencies: { + 'fs-walker': '^1.0.0', + thought: '^' + require('../package.json').version + }, + license: 'ISC', + main: 'index.js', + name: 'simple-project', + repository: { + type: 'git', + url: 'https://github.com/unit-test/simple-project.git' + }, + scripts: { + test: 'echo "Error: no test specified" && exit 1', + thought: 'thought run -a', + version: 'npm run thought' + }, + version: '1.0.0' + }) + ) + .then(() => { + expect(npmInstallMockCalls).to.deep.equal([ + { + cmd: 'npm', + args: ['install', '--save-dev', 'thought'], + options: { stdio: 'inherit' } + } + ]) + }) + ) }) }) - it('should add scripts and devDependency to package.json (even if no scripts-property exists', function () { - var scenario = new Scenario('simple-project').withTmpDir('test-output/thought-init1') + it('should add scripts and devDependency to package.json (even if no scripts-property exists', function() { + const scenario = new Scenario('simple-project').withTmpDir('test-output/thought-init1') return scenario.prepareAndRun(() => { - var git = simpleGit(scenario.actual) - - return git.init() - .then(() => fs.readFile('package.json', 'utf-8')) - .then(JSON.parse) - .then((pkgJson) => { - delete pkgJson.scripts - return fs.writeFile('package.json', JSON.stringify(pkgJson)) - }) - .then(() => git.add('package.json')) - .then(() => git.commit('Initial checkin')) - .then(() => fs.writeFile('.gitignore', 'node_modules')) - .then(() => init()) - .then(() => git.log()) - // Check only which files have been added to the index - .then(log => expect(log.latest.message, 'package.json must have been committed').to.match(/Added scripts to run thought on version-bumps/)) - .then(() => fs.readFile('package.json', 'utf-8')) - .then(pkgJson => expect(JSON.parse(pkgJson), 'Checking package.json').to.deep.equals({ - 'author': '', - 'description': 'A simple description', - 'devDependencies': { - 'fs-walker': '^1.0.0', - 'thought': '^' + require('../package.json').version - }, - 'license': 'ISC', - 'main': 'index.js', - 'name': 'simple-project', - 'repository': { - 'type': 'git', - 'url': 'https://github.com/unit-test/simple-project.git' - }, - 'scripts': { - 'thought': 'thought run -a', - 'version': 'npm run thought' - }, - 'version': '1.0.0' - })) - .then(() => { - expect(npmInstallMockCalls).to.deep.equal([{ - cmd: 'npm', - args: ['install', '--save-dev', 'thought'], - options: { stdio: 'inherit' } - }]) - }) + const git = simpleGit(scenario.actual) + + return ( + git + .init() + .then(() => fs.readFile('package.json', 'utf-8')) + .then(JSON.parse) + .then(pkgJson => { + delete pkgJson.scripts + return fs.writeFile('package.json', JSON.stringify(pkgJson)) + }) + .then(() => git.add('package.json')) + .then(() => git.commit('Initial checkin')) + .then(() => fs.writeFile('.gitignore', 'node_modules')) + .then(() => init()) + .then(() => git.log()) + // Check only which files have been added to the index + .then(log => + expect(log.latest.message, 'package.json must have been committed').to.match( + /Added scripts to run thought on version-bumps/ + ) + ) + .then(() => fs.readFile('package.json', 'utf-8')) + .then(pkgJson => + expect(JSON.parse(pkgJson), 'Checking package.json').to.deep.equals({ + author: '', + description: 'A simple description', + devDependencies: { + 'fs-walker': '^1.0.0', + thought: '^' + require('../package.json').version + }, + license: 'ISC', + main: 'index.js', + name: 'simple-project', + repository: { + type: 'git', + url: 'https://github.com/unit-test/simple-project.git' + }, + scripts: { + thought: 'thought run -a', + version: 'npm run thought' + }, + version: '1.0.0' + }) + ) + .then(() => { + expect(npmInstallMockCalls).to.deep.equal([ + { + cmd: 'npm', + args: ['install', '--save-dev', 'thought'], + options: { stdio: 'inherit' } + } + ]) + }) + ) }) }) - it('should throw an exception, if the package.json-file has uncommitted changes', function () { - var scenario = new Scenario('simple-project').withTmpDir('test-output/thought-init2') + it('should throw an exception, if the package.json-file has uncommitted changes', function() { + const scenario = new Scenario('simple-project').withTmpDir('test-output/thought-init2') return scenario.prepareAndRun(() => { - var git = simpleGit(scenario.actual) - return git.init() - .then(() => expect(init()).to.be.rejectedWith(/package.json has changes/)) + const git = simpleGit(scenario.actual) + return git.init().then(() => expect(init()).to.be.rejectedWith(/package.json has changes/)) }) }) - it('should throw an exception, if Thought is already registered in a script', function () { - var scenario = new Scenario('simple-project').withTmpDir('test-output/thought-init2') + it('should throw an exception, if Thought is already registered in a script', function() { + const scenario = new Scenario('simple-project').withTmpDir('test-output/thought-init2') return scenario.prepareAndRun(() => { - var git = simpleGit(scenario.actual) + const git = simpleGit(scenario.actual) - return git.init() + return git + .init() .then(() => fs.readFile('package.json', 'utf-8')) .then(JSON.parse) - .then((pkgJson) => { + .then(pkgJson => { pkgJson.scripts.thought = 'thought run -a' return fs.writeFile('package.json', JSON.stringify(pkgJson)) }) @@ -163,16 +185,17 @@ describe('The init option', function () { }) }) - it('should prepend the version script, if it already exists', function () { - var scenario = new Scenario('simple-project').withTmpDir('test-output/thought-init2') + it('should prepend the version script, if it already exists', function() { + const scenario = new Scenario('simple-project').withTmpDir('test-output/thought-init2') return scenario.prepareAndRun(() => { - var git = simpleGit(scenario.actual) + const git = simpleGit(scenario.actual) - return git.init() + return git + .init() .then(() => fs.readFile('package.json', 'utf-8')) .then(JSON.parse) - .then((pkgJson) => { + .then(pkgJson => { pkgJson.scripts.version = 'run something' return fs.writeFile('package.json', JSON.stringify(pkgJson)) }) @@ -181,7 +204,7 @@ describe('The init option', function () { .then(() => init()) .then(() => fs.readFile('package.json', 'utf-8')) .then(JSON.parse) - .then((pkgJson) => expect(pkgJson.scripts.version).to.equal('npm run thought && run something')) + .then(pkgJson => expect(pkgJson.scripts.version).to.equal('npm run thought && run something')) }) }) }) diff --git a/test/lib/child-process-mock.js b/test/lib/child-process-mock.js index 1809d04..ac98c37 100644 --- a/test/lib/child-process-mock.js +++ b/test/lib/child-process-mock.js @@ -18,7 +18,7 @@ const originalExecFile = cp.execFile /** * Restore the original execFile function */ -function clearMocks () { +function clearMocks() { cp.spawn = originalSpawn cp.execFile = originalExecFile } @@ -32,8 +32,8 @@ function clearMocks () { * execution. The "this"-context for the function execution is the ChildProces-object * that is returned by the mocked spawn function. */ -function mockSpawn (predicate, mockFn) { - cp.spawn = function (command, args, options) { +function mockSpawn(predicate, mockFn) { + cp.spawn = function(command, args, options) { if (options == null && _.isPlainObject(args)) { options = args args = null @@ -57,8 +57,8 @@ function mockSpawn (predicate, mockFn) { * execution. The "this"-context for the function execution is the ChildProcess-object * that is returned by the mocked execFile function. */ -function mockExecFile (predicate, mockFn) { - cp.execFile = function (command, args, options, callback) { +function mockExecFile(predicate, mockFn) { + cp.execFile = function(command, args, options, callback) { if (callback == null && typeof options === 'function') { callback = options options = null diff --git a/test/lib/scenarios.js b/test/lib/scenarios.js index fd70761..507728e 100644 --- a/test/lib/scenarios.js +++ b/test/lib/scenarios.js @@ -1,13 +1,13 @@ -var fs = require('fs-extra') -var path = require('path') +const fs = require('fs-extra') +const path = require('path') -var basedir = path.resolve('test', 'fixtures', 'scenarios') +const basedir = path.resolve('test', 'fixtures', 'scenarios') /** * Helpe for executing thought in different repos. */ class Scenario { - constructor (name) { + constructor(name) { this.name = name this.expectFailure = name.lastIndexOf('failure-', 0) === 0 this.input = path.join(basedir, name, 'input') @@ -18,8 +18,9 @@ class Scenario { /** * Prepare setup of the scenario */ - prepare () { - return fs.remove(this.actual) + prepare() { + return fs + .remove(this.actual) .then(() => fs.copy(this.input, this.actual, { recursive: true })) .then(() => this) } @@ -29,8 +30,8 @@ class Scenario { * * @param {():Promise} fn the tester function */ - run (fn) { - var oldCwd = process.cwd() + run(fn) { + const oldCwd = process.cwd() try { process.chdir(this.actual) @@ -42,11 +43,11 @@ class Scenario { return Promise.resolve() .then(() => fn()) .then( - (result) => { + result => { process.chdir(oldCwd) return result }, - (err) => { + err => { process.chdir(oldCwd) throw err } @@ -58,7 +59,7 @@ class Scenario { * @param {():Promise} fn the callback function * @returns {Promise} */ - prepareAndRun (fn) { + prepareAndRun(fn) { return this.prepare().then(() => this.run(fn)) } @@ -66,7 +67,7 @@ class Scenario { * Create a new instance of this scenario with a different "actual" directory * @param newTmpDir */ - withTmpDir (newTmpDir) { + withTmpDir(newTmpDir) { if (!newTmpDir.match(/test-output|actual/)) { throw new Error(`${newTmpDir} must be inside test-output or the 'actual' directory of a scenario.`) // because I don't want to risk deleting important files @@ -80,7 +81,7 @@ class Scenario { * Read a file from the "actual"-folder * @param {string} relativePath the path within the folder */ - readActual (relativePath) { + readActual(relativePath) { return fs.readFileSync(path.join(this.actual, relativePath), 'utf-8') } @@ -88,13 +89,13 @@ class Scenario { * Read a file from the "expected"-folder * @param {string} relativePath the path within the folder */ - readExpected (relativePath) { + readExpected(relativePath) { return fs.readFileSync(path.join(this.expected, relativePath), 'utf-8') } } -Scenario.all = function () { - return fs.readdirSync(basedir).map((name) => { +Scenario.all = function() { + return fs.readdirSync(basedir).map(name => { return new Scenario(name) }) } diff --git a/test/resolve-package-root-spec.js b/test/resolve-package-root-spec.js index 776554c..e279625 100644 --- a/test/resolve-package-root-spec.js +++ b/test/resolve-package-root-spec.js @@ -9,44 +9,46 @@ 'use strict' -var chai = require('chai') +const chai = require('chai') chai.use(require('chai-as-promised')) chai.use(require('dirty-chai')) -var expect = chai.expect -var { resolvePackageRoot } = require('../lib/utils/resolve-package-root') +const expect = chai.expect +const { resolvePackageRoot } = require('../lib/utils/resolve-package-root') -describe('The "resolve-package-root" utility', function () { - var statSync - var fs = require('fs-extra') +describe('The "resolve-package-root" utility', function() { + let statSync + const fs = require('fs-extra') - beforeEach(function () { + beforeEach(function() { statSync = fs.statSync }) - afterEach(function () { + afterEach(function() { fs.statSync = statSync }) - it('find a package.json file and provide the relative path of the given file', function () { + it('find a package.json file and provide the relative path of the given file', function() { return expect(resolvePackageRoot('test/fixtures/mini-project/a/b/test.txt')).to.eventually.deep.equal({ packageRoot: 'test/fixtures/mini-project', relativeFile: 'a/b/test.txt', - packageJson: { 'name': 'mini-project', 'version': '1.0.0' } + packageJson: { name: 'mini-project', version: '1.0.0' } }) }) - it('find not be bothered by directory named "package.json"', function () { + it('find not be bothered by directory named "package.json"', function() { return expect(resolvePackageRoot('test/fixtures/mini-project/a/b/package.json/test.txt')).to.eventually.deep.equal({ packageRoot: 'test/fixtures/mini-project', relativeFile: 'a/b/package.json/test.txt', - packageJson: { 'name': 'mini-project', 'version': '1.0.0' } + packageJson: { name: 'mini-project', version: '1.0.0' } }) }) - it('should return a rejected promise on unexpected exceptions', function () { - fs.statSync = function () { + it('should return a rejected promise on unexpected exceptions', function() { + fs.statSync = function() { throw new Error('Test-Error') } - return expect(resolvePackageRoot('test/fixtures/mini-project/a/b/package.json/test.txt')).to.be.rejectedWith('Test-Error') + return expect(resolvePackageRoot('test/fixtures/mini-project/a/b/package.json/test.txt')).to.be.rejectedWith( + 'Test-Error' + ) }) }) diff --git a/test/scenarios-spec.js b/test/scenarios-spec.js index 905ff4c..608e0ba 100644 --- a/test/scenarios-spec.js +++ b/test/scenarios-spec.js @@ -9,16 +9,16 @@ 'use strict' -var fs = require('fs-extra') -var pify = require('pify') -var glob = pify(require('glob')) -var deep = require('deep-aplus')(Promise) -var path = require('path') -var chai = require('chai') +const fs = require('fs-extra') +const pify = require('pify') +const glob = pify(require('glob')) +const deep = require('deep-aplus')(Promise) +const path = require('path') +const chai = require('chai') chai.use(require('dirty-chai')) -var expect = chai.expect -var thought = require('../') -var Scenario = require('./lib/scenarios') +const expect = chai.expect +const thought = require('../') +const Scenario = require('./lib/scenarios') /** * Travers all files and subdirs of a base directory and @@ -27,12 +27,12 @@ var Scenario = require('./lib/scenarios') * @param relativeDir the current directory within the base directory (only for recursive calls) * @param visitor the callback / visitor */ -function walk (baseDir, relativeDir, visitor) { - var dirEntries = fs.readdirSync(path.join(baseDir, relativeDir)) - dirEntries.forEach(function (fileOrDir) { +function walk(baseDir, relativeDir, visitor) { + const dirEntries = fs.readdirSync(path.join(baseDir, relativeDir)) + dirEntries.forEach(function(fileOrDir) { const relativePath = path.join(relativeDir, fileOrDir) const fullPath = path.join(baseDir, relativePath) - var stats = fs.statSync(fullPath) + const stats = fs.statSync(fullPath) if (stats.isDirectory()) { walk(baseDir, relativePath, visitor) } else if (stats.isFile()) { @@ -41,41 +41,41 @@ function walk (baseDir, relativeDir, visitor) { }) } -describe('the integration test: ', function () { +describe('the integration test: ', function() { this.timeout(10000) beforeEach(() => { Error.stackTraceLimit = 10 }) - Scenario.all().forEach((scenario) => { - describe(`In the scenario "${scenario.name}",`, function () { + Scenario.all().forEach(scenario => { + describe(`In the scenario "${scenario.name}",`, function() { if (scenario.expectFailure) { - it('running Thought should produce an error', function () { + it('running Thought should produce an error', function() { // This scenario must be rejected return expect(scenario.run(() => thought())).to.be.rejected }) } else { // This scenario must pass - before(function () { + before(function() { return scenario.prepareAndRun(() => thought()) }) - it('the generated files in "actual" should be should match in "expected"', async function () { - var [expected, actual] = await Promise.all([ + it('the generated files in "actual" should be should match in "expected"', async function() { + const [expected, actual] = await Promise.all([ glob('**/*', { root: scenario.expected, nodir: true, dot: true }), glob('**/*', { root: scenario.actual, nodir: true, dot: true }) ]) expect(actual).to.deep.equal(expected) }) - walk(scenario.expected, '', function (file) { - it(`the file "${file.relativePath}" should match`, function () { - var expectedContents = scenario.readExpected(file.relativePath) - var actualContents = scenario.readActual(file.relativePath) - return deep({ expectedContents, actualContents }) - .then((result) => expect(result.actualContents).to.equal(result.expectedContents) - ) + walk(scenario.expected, '', function(file) { + it(`the file "${file.relativePath}" should match`, function() { + const expectedContents = scenario.readExpected(file.relativePath) + const actualContents = scenario.readActual(file.relativePath) + return deep({ expectedContents, actualContents }).then(result => + expect(result.actualContents).to.equal(result.expectedContents) + ) }) }) } diff --git a/test/utils-spec.js b/test/utils-spec.js index ea5d3f2..2eb535a 100644 --- a/test/utils-spec.js +++ b/test/utils-spec.js @@ -9,21 +9,22 @@ 'use strict' -var chai = require('chai') +const chai = require('chai') chai.use(require('chai-as-promised')) chai.use(require('dirty-chai')) -var expect = chai.expect +const expect = chai.expect -describe('The "exeq" utility', function () { - var exec = require('../lib/utils/exeq') +describe('The "exeq" utility', function() { + const exec = require('../lib/utils/exeq') this.timeout(10000) - it('should return stdout and stderr', function () { - return expect(exec(process.argv[0], ['-e', 'console.log("123");console.error("abc")'])) - .to.eventually.deep.equal(['123\n', 'abc\n']) + it('should return stdout and stderr', function() { + return expect(exec(process.argv[0], ['-e', 'console.log("123");console.error("abc")'])).to.eventually.deep.equal([ + '123\n', + 'abc\n' + ]) }) - it('should throw an error on exit-code > 0', function () { - return expect(exec(process.argv[0], ['-e', 'throw "Hommingberg"'])) - .to.rejectedWith(/Command failed:.*Hommingberg/) + it('should throw an error on exit-code > 0', function() { + return expect(exec(process.argv[0], ['-e', 'throw "Hommingberg"'])).to.rejectedWith(/Command failed:.*Hommingberg/) }) })