From 2da5e431ef5eb5c580519ff59562ce0cc8fa9e00 Mon Sep 17 00:00:00 2001 From: Karolin Varner <karo@cupdev.net> Date: Fri, 9 Aug 2019 17:26:53 +0200 Subject: [PATCH] chore: Manual eslint/style fixes --- .eslintrc.js | 10 +- cli.js | 55 +++++++---- lib/header.js | 26 +++-- lib/main.js | 2 + lib/markdownWriter.js | 74 +++++++------- lib/prettyMarkdown.js | 4 +- lib/readSchemaFile.js | 42 ++++---- lib/readmeWriter.js | 19 ++-- lib/schema.js | 161 ++++++++++++++++++------------- lib/schemaWriter.js | 8 +- lib/writeFiles.js | 9 +- spec/lib/header.spec.js | 3 +- spec/lib/integrationTest.spec.js | 25 ++--- 13 files changed, 249 insertions(+), 189 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index fd6e0c6..c263959 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -39,7 +39,15 @@ module.exports = { 'no-else-return': 'off', // allow dangling underscores for 'fields' - 'no-underscore-dangle': ['error', {'allowAfterThis': true}], + 'no-underscore-dangle': 'off', + + // Allow marking variables unused using a underscore at the start + 'no-unused-vars': ["error", { + "varsIgnorePattern": "^_.*$", + "argsIgnorePattern": "^_.*$", + "caughtErrorsIgnorePattern": "^_.*$" + }], + // enforce license header (todo: improve plugin to support patterns for multi-lines) 'header/header': [2, 'block', ['', diff --git a/cli.js b/cli.js index 6e0e776..f3c5711 100755 --- a/cli.js +++ b/cli.js @@ -11,6 +11,7 @@ * governing permissions and limitations under the License. */ +const Optimist = require('optimist'); const Promise = require('bluebird'); const path = require('path'); const _ = require('lodash'); @@ -18,12 +19,13 @@ const fs = Promise.promisifyAll(require('fs')); const readdirp = require('readdirp'); const Ajv = require('ajv'); const logger = require('winston'); +const i18n = require('i18n'); const Schema = require('./lib/schema'); const readSchemaFile = require('./lib/readSchemaFile'); // parse/process command line arguments -const { argv } = require('optimist') +const { argv } = Optimist .usage('Generate Markdown documentation from JSON Schema.\n\nUsage: $0') .demand('d') .alias('d', 'input') @@ -48,21 +50,23 @@ const { argv } = require('optimist') .describe('link-*', 'Add this file as a link the explain the * attribute, e.g. --link-abstract=abstract.md') .check((args) => { if (!fs.existsSync(args.input)) { - throw `Input file "${args.input}" does not exist!`; + throw new Error(`Input file "${args.input}" does not exist!`); } if (args.s && !fs.existsSync(args.s)) { - throw `Meta schema file "${args.s}" does not exist!`; + throw new Error(`Meta schema file "${args.s}" does not exist!`); } }) .alias('i', 'i18n') .describe('i', 'path to a locales folder with an en.json file in it. This file will be used for all text parts in all templates') .alias('h', 'header') .describe('h', 'if the value is false the header will be skipped') - .default('h', true) - .argv; + .default('h', true); -const docs = _.fromPairs(_.toPairs(argv).filter(([key, value]) => key.startsWith('link-')).map(([key, value]) => [key.substr(5), value])); -const i18n = require('i18n'); +const docs = _.fromPairs( + _.toPairs(argv) + .filter(([key, _value]) => key.startsWith('link-')) + .map(([key, value]) => [key.substr(5), value]), +); logger.configure({ level: 'info', @@ -78,37 +82,41 @@ logger.configure({ const ajv = new Ajv({ allErrors: true, messages: true, schemaId: 'auto', logger, }); -console.log(argv.v); +logger.info(argv.v); if (argv.v === '06' || argv.v === 6) { - console.log('enabling draft-06 support'); + logger.info('enabling draft-06 support'); + // eslint-disable-next-line global-require ajv.addMetaSchema(require('ajv/lib/refs/json-schema-draft-06.json')); } else if (argv.v === '04' || argv.v === 4) { + // eslint-disable-next-line global-require ajv.addMetaSchema(require('ajv/lib/refs/json-schema-draft-04.json')); } const schemaPathMap = {}; const metaElements = {}; const schemaPath = path.resolve(argv.d); const outDir = path.resolve(argv.o); -const schemaDir = argv.x === '-' ? '' : argv.x ? path.resolve(argv.x) : outDir; +// eslint-disable-next-line no-nested-ternary +const schemaDir = argv.x === '-' ? '' : (argv.x ? path.resolve(argv.x) : outDir); const target = fs.statSync(schemaPath); const readme = argv.n !== true; const schemaExtension = argv.e || 'schema.json'; if (argv.s) { + // eslint-disable-next-line import/no-dynamic-require, global-require ajv.addMetaSchema(require(path.resolve(argv.s))); } if (argv.m) { if (_.isArray(argv.m)) { _.each(argv.m, (item) => { - const meta = item.split('='); - if (meta.length === 2) { - metaElements[meta[0]] = meta[1]; + const [key, val] = item.split('='); + if (val !== undefined) { + metaElements[key] = val; } }); } else { - const meta = (argv.m).split('='); - if (meta.length === 2) { - metaElements[meta[0]] = meta[1]; + const [key, val] = (argv.m).split('='); + if (val !== undefined) { + metaElements[key] = val; } } } @@ -134,6 +142,7 @@ if (target.isDirectory()) { .on('data', (entry) => { files.push(entry.fullPath); try { + // eslint-disable-next-line import/no-dynamic-require, global-require ajv.addSchema(require(entry.fullPath), entry.fullPath); } catch (e) { logger.error('Ajv processing error for schema at path %s', entry.fullPath); @@ -146,8 +155,14 @@ if (target.isDirectory()) { Schema.setSchemaPathMap(schemaPathMap); return Promise.reduce(files, readSchemaFile, schemaPathMap) .then((schemaMap) => { - logger.info('finished reading all *.%s files in %s, beginning processing….', schemaExtension, schemaPath); - return Schema.process(schemaMap, schemaPath, outDir, schemaDir, metaElements, readme, docs, argv); + logger.info( + 'finished reading all *.%s files in %s, beginning processing….', + schemaExtension, schemaPath, + ); + return Schema.process( + schemaMap, schemaPath, outDir, schemaDir, metaElements, + readme, docs, argv, + ); }) .then(() => { logger.info('Processing complete.'); @@ -164,11 +179,13 @@ if (target.isDirectory()) { } else { readSchemaFile(schemaPathMap, schemaPath) .then((schemaMap) => { + // eslint-disable-next-line import/no-dynamic-require, global-require ajv.addSchema(require(schemaPath), schemaPath); Schema.setAjv(ajv); Schema.setSchemaPathMap(schemaPathMap); logger.info('finished reading %s, beginning processing....', schemaPath); - return Schema.process(schemaMap, schemaPath, outDir, schemaDir, metaElements, false, docs, argv); + return Schema.process(schemaMap, schemaPath, outDir, schemaDir, + metaElements, false, docs, argv); }) .then(() => { logger.info('Processing complete.'); diff --git a/lib/header.js b/lib/header.js index 693faf7..dc5e255 100644 --- a/lib/header.js +++ b/lib/header.js @@ -16,7 +16,7 @@ const path = require('path'); function custom(schema) { if (schema.allOf) { - for (let i = 0; i < schema.allOf.length; i++) { + for (let i = 0; i < schema.allOf.length; i += 1) { if (schema.allOf[i].$ref && schema.allOf[i].$ref === 'https://ns.adobe.com/xdm/common/extensible.schema.json#/definitions/@context') { return true; } @@ -49,10 +49,10 @@ class Header { this.renderValue = this.render(this.value, this.links, this.base); } - render(text, link, base) { - return function () { - if (link) { - return `[${text}](${base}${link})`; + render(text, ref, base) { + return () => { + if (ref) { + return `[${text}](${base}${ref})`; } else { return text; } @@ -67,14 +67,12 @@ function header(name, docs, value, links) { this.links = links; - this.render = function (text, link) { - return function () { - if (link) { - return `[${text}](${link})`; - } else { - return text; - } - }; + this.render = (text, ref) => () => { + if (ref) { + return `[${text}](${ref})`; + } else { + return text; + } }; this.renderHeader = this.render(this.name, this.docs); this.renderValue = this.render(this.value, this.links); @@ -114,7 +112,7 @@ function headers(schema, indir, filename, docs) { this.myheaders.push(new Header(i18n.__('header.tabel.additionalProperties'), link(indir, filename, this.doclinks.additional), props.additionalProperties)); this.myheaders.push(new Header(i18n.__('header.tabel.definedIn'), undefined, props.original, path.basename(props.original))); - this.render = function () { + this.render = () => { let buf = ''; // header diff --git a/lib/main.js b/lib/main.js index e0559f2..0e87230 100644 --- a/lib/main.js +++ b/lib/main.js @@ -10,6 +10,8 @@ * governing permissions and limitations under the License. */ +/* eslint-disable global-require */ + module.exports = { writer: require('./writeFiles'), reader: require('./readSchemaFile'), diff --git a/lib/markdownWriter.js b/lib/markdownWriter.js index 71f5c5b..87e0bba 100644 --- a/lib/markdownWriter.js +++ b/lib/markdownWriter.js @@ -9,6 +9,9 @@ * OF ANY KIND, either express or implied. See the License for the specific language * governing permissions and limitations under the License. */ + +/* eslint-disable no-param-reassign */ + const i18n = require('i18n'); const Promise = require('bluebird'); const path = require('path'); @@ -16,7 +19,6 @@ const _ = require('lodash'); const ejs = require('ejs'); const pejs = Promise.promisifyAll(ejs); -const validUrl = require('valid-url'); const GithubSlugger = require('github-slugger'); const { headers } = require('./header'); const prettyMarkdown = require('./prettyMarkdown'); @@ -25,7 +27,7 @@ const writeFile = require('./writeFiles'); function createGithubSlugs(names) { const slugger = new GithubSlugger(); slugger.reset(); - names = names.sort(); + names = Array.from(names).sort(); return names.reduce((result, item) => { result[item] = slugger.slug(item); return result; @@ -41,7 +43,7 @@ function build(total, fragment) { } function assoc(obj, key, value) { - if (obj == null) { + if (obj === null) { return assoc({}, key, value); } obj[key] = value; @@ -65,7 +67,6 @@ function stringifyExamples(examples) { if (typeof examples === 'string') { examples = [examples]; } - // console.log(examples); return examples.map(example => JSON.stringify(example, null, 2)); } else { return false; @@ -82,6 +83,7 @@ function simpletype(prop) { if (prop.$linkVal !== undefined) { prop.simpletype = prop.$linkVal; } else { + // eslint-disable-next-line no-console console.log(`unresolved reference: ${prop.$ref}`); prop.simpletype = 'reference'; } @@ -90,7 +92,7 @@ function simpletype(prop) { if (prop['meta:enum'] === undefined) { prop['meta:enum'] = {}; } - for (let i = 0; i < prop.enum.length; i++) { + for (let i = 0; i < prop.enum.length; i += 1) { if (prop['meta:enum'][prop.enum[i]] === undefined) { // setting an empty description for each unknown enum prop['meta:enum'][prop.enum[i]] = ''; @@ -116,22 +118,19 @@ function simpletype(prop) { if (innertype.simpletype === 'complex') { prop.simpletype = '`array`'; } else { - // console.log(prop.title); prop.simpletype = innertype.simpletype.replace(/(`)$/, '[]$1'); } } else { prop.simpletype = '`array`'; } } else if (Array.isArray(type)) { - function nullfilter(str) { - return str !== 'null'; - } + const nullfilter = str => str !== 'null'; const filtered = type.filter(nullfilter); if (type.length - 1 === filtered.length) { prop.nullable = true; } if (filtered.length === 1) { - prop.type = filtered[0]; + ([prop.type] = filtered); prop.simpletype = `\`${filtered[0]}\``; } else { prop.type = filtered; @@ -151,9 +150,9 @@ function simpletype(prop) { */ function requiredProperties(properties, required) { if (required) { - for (let i = 0; i < required.length; i++) { - if (properties[required[i]]) { - properties[required[i]].isrequired = true; + for (const prop of required) { + if (properties[prop]) { + properties[prop].isrequired = true; } } } @@ -166,32 +165,35 @@ function ejsRender(template, ctx) { // return JSON.stringify(obj, null, 2); } -const generateMarkdown = (filename, schema, schemaPath, outDir, dependencyMap, docs, consoleArgs) => { +const generateMarkdown = (filename, schema, schemaPath, outDir, + dependencyMap, docs, consoleArgs) => { outDir = outDir || path.resolve(path.join('.', 'out')); // this structure allows us to have separate templates for each element. Instead of having // one huge template, each block can be built individually - outDir = outDir ? outDir : path.resolve(path.join('.', 'out')); + outDir = outDir || path.resolve(path.join('.', 'out')); let multi = []; - multi.push([ 'frontmatter.ejs', { meta: schema.metaElements } ]); - if (!consoleArgs||consoleArgs.header){ - multi.push([ 'header.ejs', { - i18n: i18n, - schema: schema, + multi.push(['frontmatter.ejs', { meta: schema.metaElements }]); + if (!consoleArgs || consoleArgs.header) { + multi.push(['header.ejs', { + i18n, + schema, dependencies: flatten(dependencyMap), - table: headers(schema, schemaPath, filename, docs).render() } ]); + table: headers(schema, schemaPath, filename, docs).render(), + }]); } - multi.push([ 'examples.ejs', { examples: stringifyExamples(schema.examples), title: schema.title, i18n: i18n } ]); - const required = []; //to store required of whole schema, even those in definitions + multi.push(['examples.ejs', { examples: stringifyExamples(schema.examples), title: schema.title, i18n }]); + const required = []; // to store required of whole schema, even those in definitions - // Processing schema.definitions before schema.properties to get any required properties present in definitions + // Processing schema.definitions before schema.properties to get any + // required properties present in definitions if (_.keys(schema.definitions).length > 0) { const abstract = {}; - for (let i = 0; i < _.keys(schema.definitions).length; i++) { + for (let i = 0; i < _.keys(schema.definitions).length; i += 1) { if (schema.definitions[_.keys(schema.definitions)[i]].properties !== undefined) { const definition = schema.definitions[_.keys(schema.definitions)[i]].properties; const tempRequired = schema.definitions[_.keys(schema.definitions)[i]].required; const hasRequiredProperties = (tempRequired !== undefined); - for (let j = 0; j < _.keys(definition).length; j++) { + for (let j = 0; j < _.keys(definition).length; j += 1) { const name = _.keys(definition)[j]; const property = definition[_.keys(definition)[j]]; if (hasRequiredProperties && tempRequired.includes(name)) { @@ -215,7 +217,7 @@ const generateMarkdown = (filename, schema, schemaPath, outDir, dependencyMap, d propertiesSlugs, i18n, }]); - for (let i = 0; i < _.keys(abstract).length; i++) { + for (let i = 0; i < _.keys(abstract).length; i += 1) { const name = _.keys(abstract).sort()[i]; multi.push(['property.ejs', { name, @@ -231,7 +233,9 @@ const generateMarkdown = (filename, schema, schemaPath, outDir, dependencyMap, d } const propertiesSlugs = createGithubSlugs(_.keys(schema.properties)); if (_.keys(schema.properties).length > 0) { - if (schema.required === undefined) { schema.required = []; } + if (schema.required === undefined) { + schema.required = []; + } schema.required = _.union(schema.required, required); // table of contents multi.push(['properties.ejs', { @@ -243,7 +247,7 @@ const generateMarkdown = (filename, schema, schemaPath, outDir, dependencyMap, d i18n, }]); // regular properties - for (let i = 0; i < _.keys(schema.properties).length; i++) { + for (let i = 0; i < _.keys(schema.properties).length; i += 1) { const name = _.keys(schema.properties).sort()[i]; multi.push(['property.ejs', { name, @@ -259,7 +263,7 @@ const generateMarkdown = (filename, schema, schemaPath, outDir, dependencyMap, d if (_.keys(schema.patternProperties).length > 0) { // patterns properties - for (let i = 0; i < _.keys(schema.patternProperties).length; i++) { + for (let i = 0; i < _.keys(schema.patternProperties).length; i += 1) { const name = _.keys(schema.patternProperties)[i]; multi.push(['pattern-property.ejs', { name, @@ -293,10 +297,12 @@ const generateMarkdown = (filename, schema, schemaPath, outDir, dependencyMap, d return Promise.reduce(Promise.map(multi, render), build, '').then((str) => { const mdfile = `${path.basename(filename).slice(0, -5)}.md`; - return writeFile(path.join(path.join(outDir), path.dirname(filename.substr(schemaPath.length))), mdfile, prettyMarkdown(str)); - }).then(out => - // console.log('markdown written (promise)', out); - out); + return writeFile( + path.join(outDir, path.dirname(filename.substr(schemaPath.length))), + mdfile, + prettyMarkdown(str), + ); + }); }; module.exports = generateMarkdown; diff --git a/lib/prettyMarkdown.js b/lib/prettyMarkdown.js index f47b710..89a4df5 100644 --- a/lib/prettyMarkdown.js +++ b/lib/prettyMarkdown.js @@ -12,8 +12,6 @@ const prettier = require('prettier'); -const prettyMarkdown = function (str) { - return prettier.format(str, { parser: 'markdown', proseWrap: 'always', printWidth: 119 }); -}; +const prettyMarkdown = str => prettier.format(str, { parser: 'markdown', proseWrap: 'always', printWidth: 119 }); module.exports = prettyMarkdown; diff --git a/lib/readSchemaFile.js b/lib/readSchemaFile.js index 3a8002e..294ffc7 100644 --- a/lib/readSchemaFile.js +++ b/lib/readSchemaFile.js @@ -10,6 +10,8 @@ * governing permissions and limitations under the License. */ +/* eslint-disable no-param-reassign */ + const Promise = require('bluebird'); const fs = Promise.promisifyAll(require('fs')); @@ -22,26 +24,24 @@ const fs = Promise.promisifyAll(require('fs')); * @param {map} schemaPathMap - the map of schema paths and JSON schemas * @param {*} fullPath - the full path to the schema */ -module.exports = function readSchemaFile(schemaPathMap, fullPath) { - if (!schemaPathMap) { - schemaPathMap = {}; - } - return fs.readFileAsync(fullPath) - .then((data) => { - const schema = JSON.parse(data); - const obj = {}; - obj.filePath = fullPath; - obj.jsonSchema = schema; - if (schema.$id && schema.$id.length > 0) { - if (!schemaPathMap[schema.$id]) { - schemaPathMap[schema.$id] = obj; - } - // TODO err - // TODO check Missing Specific properties to throw warning // function for warning - } else { - console.warn(`schema ${fullPath} has no $id`); - schemaPathMap[fullPath] = obj; +const readSchemaFile = (schemaPathMap, fullPath) => { + schemaPathMap = schemaPathMap || {}; + return fs.readFileAsync(fullPath).then((data) => { + const schema = JSON.parse(data); + const obj = {}; + obj.filePath = fullPath; + obj.jsonSchema = schema; + if (schema.$id && schema.$id.length > 0) { + if (!schemaPathMap[schema.$id]) { + schemaPathMap[schema.$id] = obj; } - return schemaPathMap; - }); + } else { + // eslint-disable-next-line no-console + console.warn(`schema ${fullPath} has no $id`); + schemaPathMap[fullPath] = obj; + } + return schemaPathMap; + }); }; + +module.exports = readSchemaFile; diff --git a/lib/readmeWriter.js b/lib/readmeWriter.js index 9806203..eb3be7f 100644 --- a/lib/readmeWriter.js +++ b/lib/readmeWriter.js @@ -10,6 +10,8 @@ * governing permissions and limitations under the License. */ +/* eslint-disable no-param-reassign */ + const Promise = require('bluebird'); const _ = require('lodash'); const ejs = require('ejs'); @@ -21,7 +23,7 @@ const i18n = require('i18n'); const prettyMarkdown = require('./prettyMarkdown'); const writeFile = require('./writeFiles'); -function relativePath(full, base) { +const relativePath = (full, base) => { full = full.replace(/\\/g, '/'); base = base.replace(/\\/g, '/'); if (full.indexOf(base) === 0) { @@ -29,11 +31,9 @@ function relativePath(full, base) { } else { return full; } -} +}; -function directory(full, base) { - return relativePath(full, base).replace(/[^\/]+$/, ''); -} +const directory = (full, base) => relativePath(full, base).replace(/[^/]+$/, ''); /** * Generates a README.md file from the `schemas` passed in at directory `out` @@ -42,7 +42,7 @@ function directory(full, base) { * @param {string} out - output directory * @param {string} base - schema base directory */ -const generateReadme = function (paths, schemas, out, base) { +const generateReadme = (paths, schemas, out, base) => { const coreinfo = _.values(schemas).map(schema => ({ id: schema.jsonSchema.$id, title: schema.jsonSchema.title, @@ -61,12 +61,7 @@ const generateReadme = function (paths, schemas, out, base) { core: coreinfo, groups: _.groupBy(coreinfo, key => key.dir), }; - return pejs.renderFileAsync(path.join(__dirname, '../templates/md/readme.ejs'), ctx, { debug: false }, i18n).then((str) => { - console.log('Writing README'); - return writeFile(out, 'README.md', prettyMarkdown(str)); - }).then(out => - // console.log('markdown written (promise)', out); - out); + return pejs.renderFileAsync(path.join(__dirname, '../templates/md/readme.ejs'), ctx, { debug: false }, i18n).then(str => writeFile(out, 'README.md', prettyMarkdown(str))); }; module.exports = generateReadme; diff --git a/lib/schema.js b/lib/schema.js index e8c7ec4..88113ef 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -10,40 +10,42 @@ * governing permissions and limitations under the License. */ +/* eslint-disable no-param-reassign, no-console, no-use-before-define */ + const path = require('path'); const _ = require('lodash'); const logger = require('winston'); const readdirp = require('readdirp'); const Promise = require('bluebird'); const fs = Promise.promisifyAll(require('fs')); +const pointer = require('json-pointer'); const markdownWriter = require('./markdownWriter'); const schemaWriter = require('./schemaWriter'); const readmeWriter = require('./readmeWriter'); const deff = '#/definitions/'; const absUrlRegex = new RegExp('^(?:[a-z]+:)?//', 'i'); -const pointer = require('json-pointer'); let smap; // TODO remove global let sPath; const wmap = {}; function get$refType(refValue) { - let startpart = ''; let endpart = ''; var - refType = ''; + let startpart = ''; + let endpart = ''; + let refType = ''; const arr = refValue.split('#'); - if (arr.length > 1) { endpart = arr[1]; } + if (arr.length > 1) { + // eslint-disable-next-line prefer-destructuring + endpart = arr[1]; + } + // eslint-disable-next-line prefer-destructuring startpart = arr[0]; - // TODO yRelNoDef - // relative-- yRelWithDef, yRelNoDef, - // absolute-- yAbsWithDef, yAbsFSchema, yAbsWithFragment - var refType = ''; - const deff = '/definitions/'; // if( absUrlRegex.test(refVal) ){ if (startpart.length > 1) { if (startpart in smap) { - if (endpart.startsWith(deff)) { + if (endpart.startsWith('/definitions/')) { refType = 'yAbsWithDef'; } else if (endpart.length === 0) { refType = 'yAbsFSchema'; @@ -51,7 +53,7 @@ function get$refType(refValue) { refType = 'yAbsWithFragment'; } } - } else if (endpart.startsWith(deff)) { + } else if (endpart.startsWith('/definitions/')) { refType = 'yRelWithDef'; } // } @@ -60,20 +62,24 @@ function get$refType(refValue) { function normaliseLinks(obj, refArr) { const basepath = refArr.startpart; - let $linkVal = ''; let - $linkPath = ''; + let $linkVal = ''; + let $linkPath = ''; if (basepath in smap) { const newpath = path.relative(path.dirname(sPath), smap[basepath].filePath).replace(/\\/g, '/'); // to cater windows paths const temp = newpath.slice(0, -5).split('/'); $linkVal = obj.title ? obj.title : path.basename(newpath).slice(0, -5); $linkPath = `${temp.join('/')}.md`; return { $linkVal, $linkPath }; + } else { + return undefined; } } const resolve$ref = Promise.method((val, base$id) => { - let obj; let - link; - if (!(base$id in wmap)) { wmap[base$id] = {}; } + let obj; + let link; + if (!(base$id in wmap)) { + wmap[base$id] = {}; + } const refArr = get$refType(val.$ref); if (refArr.refType === 'yRelWithDef') { refArr.startpart = base$id; @@ -103,8 +109,9 @@ const resolve$ref = Promise.method((val, base$id) => { return processISchema(ischema, refArr.startpart); } } + return undefined; }); -var processFurther = Promise.method((val, key, $id) => { +const processFurther = Promise.method((val, key, $id) => { const base$id = $id; if (val.$ref) { return resolve$ref(val, base$id); @@ -135,6 +142,7 @@ var processFurther = Promise.method((val, key, $id) => { // go recursively down to check for a $ref return processFurther(propertyValue, propertyKey, base$id); } + return undefined; }); return val; @@ -143,9 +151,10 @@ var processFurther = Promise.method((val, key, $id) => { return val; } }); -function processISchema() {} // define w/ function so it gets hoisted and we avoid eslint errors about what is defined first: processISchema or resolve$ref. Both rely on each other! -processISchema = Promise.method((schema, base$id) => { - if (!(base$id in wmap)) { wmap[base$id] = {}; } +const processISchema = Promise.method((schema, base$id) => { + if (!(base$id in wmap)) { + wmap[base$id] = {}; + } if (schema.anyOf || schema.oneOf) { // var $definitions=[] schema.type = schema.anyOf ? 'anyOf' : 'oneOf'; @@ -169,16 +178,13 @@ processISchema = Promise.method((schema, base$id) => { if (schema.items) { const val = schema.items; - if (!schema.type) { schema.type = 'array'; } - if (_.isArray(val)) { - // TODO - - } else if (val.$ref) { + if (!schema.type) { + schema.type = 'array'; + } + if (val.$ref && !_.isArray(val)) { resolve$ref(val, base$id).then((piSchema) => { // check // not sending correct id schema.items = piSchema; }); - } else { - // TODO if such a scenario } } // schema.$definitions = $definitions @@ -186,15 +192,19 @@ processISchema = Promise.method((schema, base$id) => { }); function processSchema(schema) { return new Promise((resolve, reject) => { - if (!schema.properties) { schema.properties = {}; } + if (!schema.properties) { + schema.properties = {}; + } const $id = schema.$id || schema.id; const base$id = $id; - if (!(base$id in wmap)) { wmap[base$id] = {}; } + if (!(base$id in wmap)) { + wmap[base$id] = {}; + } if (schema.allOf) { _.each(schema.allOf, (value) => { if (value.$ref) { - let obj; let - link; + let obj; + let link; const refArr = get$refType(value.$ref); if (refArr.refType === 'yRelWithDef') { refArr.startpart = base$id; @@ -242,10 +252,12 @@ function processSchema(schema) { schema.properties[key].$oSchema.$linkPath = link.$linkPath; } if (ischema.required) { - if (key in ischema.required) { schema.required.push(key); } + if (key in ischema.required) { + schema.required.push(key); + } } } else { - reject('No further schema found'); + reject(new Error('No further schema found')); } }); }); @@ -287,12 +299,12 @@ function processSchema(schema) { } -const Schema = function (ajv, schemaMap) { +const Schema = (ajv, schemaMap) => { this._ajv = ajv; this._schemaPathMap = schemaMap; }; -Schema.resolveRef = function (key, obj, currpath) { +Schema.resolveRef = (key, obj, currpath) => { if (key === '$ref') { const refVal = obj[key]; let temp; @@ -320,27 +332,14 @@ Schema.resolveRef = function (key, obj, currpath) { obj.$linkPath = `${temp.join('/')}.md`; } } - if (key === 'anyOf' || key === 'oneOf' || key === 'allOf') { obj.$type = key; } -}; - -/* The following function does not seem to be used anymore! -var traverseSchema = function(object,schemaFilePath){ - return new Promise((resolve,reject) => { - var recurse=function(curr,key,prev){ - if (key){ - if (key === 'anyOf' || key === 'oneOf' || key === 'allOf') {prev.$type=key;} - } - var result; - if (Array.isArray(curr)) {curr.map((item,index) => recurse(item,index,curr));} else { - (typeof curr === 'object') ? Object.keys(curr).map(key => recurse(curr[key],key,curr)):Schema.resolveRef(key,prev,schemaFilePath); - } - return object; - }; - resolve(recurse(object)); - }); + if (key === 'anyOf' || key === 'oneOf' || key === 'allOf') { + obj.$type = key; + } }; -*/ +// TODO: For some exceedingly strange reason this generates test failures +// when an arrow function is used… +// eslint-disable-next-line func-names Schema.getExamples = function (filePath, schema) { const exampleFileNames = []; let examples = []; @@ -352,13 +351,17 @@ Schema.getExamples = function (filePath, schema) { .on('data', entry => exampleFileNames.push(entry.fullPath)) .on('end', () => resolve(exampleFileNames)) .on('error', err => reject(err)); - }).then((exampleFileNames) => { + }).then(() => { if (exampleFileNames.length > 0) { const validate = this._ajv.compile(schema); return Promise.map(exampleFileNames, entry => fs.readFileAsync(entry).then((example) => { const data = JSON.parse(example.toString()); const valid = validate(data); - if (valid) { examples.push({ filename: entry, data }); } else { logger.error(`${entry} is an invalid Example`); } + if (valid) { + examples.push({ filename: entry, data }); + } else { + logger.error(`${entry} is an invalid Example`); + } })).then(() => { // Sort according to filenames in order not to have random prints examples.sort((a, b) => (a.filename > b.filename ? 1 : -1)); @@ -367,11 +370,13 @@ Schema.getExamples = function (filePath, schema) { schema.examples = examples; return schema; }); - } else { return schema; } + } else { + return schema; + } }); }; -Schema.getDescription = function (filePath, schema) { +Schema.getDescription = (filePath, schema) => { let temp = path.basename(filePath, path.extname(filePath)); // TODO should err be thrown here? temp = `${temp.split('.')[0]}.description.md`; @@ -383,10 +388,16 @@ Schema.getDescription = function (filePath, schema) { .catch(() => schema); }; +// TODO: For some exceedingly strange reason this generates test failures +// when an arrow function is used… +// eslint-disable-next-line func-names Schema.setAjv = function (ajv) { this._ajv = ajv; }; +// TODO: For some exceedingly strange reason this generates test failures +// when an arrow function is used… +// eslint-disable-next-line func-names Schema.setSchemaPathMap = function (schemaMap) { this._schemaPathMap = schemaMap; }; @@ -395,17 +406,20 @@ Schema.setSchemaPathMap = function (schemaMap) { * @param {*} schemaMap * @param {*} schemaPath * @param {string} docDir - where documentation will be generated - * @param {string} schemaDir - where schemas will be generated, if not set, no schema's will be output - * @param {map} metaElements - a map of additional YAML frontmatter to be added to the generated Markdown + * @param {string} schemaDir - where schemas will be generated, if not set, no schema's + * will be output + * @param {map} metaElements - a map of additional YAML frontmatter to be added to + * the generated Markdown * @param {boolean} readme - generate a README.md directory listing * @param {map} docs - a map of documentation links for headers */ -Schema.process = function (schemaMap, schemaPath, docDir, schemaDir, metaElements, readme, docs, consoleArgs) { +Schema.process = (schemaMap, schemaPath, docDir, schemaDir, + metaElements, readme, docs, consoleArgs) => { smap = schemaMap; const keys = Object.keys(schemaMap); return Promise.mapSeries(keys, (schemaKey) => { const props = Object.keys(wmap); - for (let i = 0; i < props.length; i++) { + for (let i = 0; i < props.length; i += 1) { delete wmap[props[i]]; } @@ -425,9 +439,26 @@ Schema.process = function (schemaMap, schemaPath, docDir, schemaDir, metaElement return { mSchema, wSchema: allSchema, dep: wmap }; }); }).then((object) => { - const outputTasks = [markdownWriter(schemaMap[schemaKey].filePath, object.mSchema, schemaPath, docDir, object.dep, docs, consoleArgs)]; + const outputTasks = [ + markdownWriter( + schemaMap[schemaKey].filePath, + object.mSchema, + schemaPath, + docDir, + object.dep, + docs, + consoleArgs, + ), + ]; if (schemaDir !== '') { - outputTasks.push(schemaWriter(schemaMap[schemaKey].filePath, object.wSchema, schemaPath, schemaDir)); + outputTasks.push( + schemaWriter( + schemaMap[schemaKey].filePath, + object.wSchema, + schemaPath, + schemaDir, + ), + ); } return Promise.all(outputTasks); }) @@ -442,7 +473,7 @@ Schema.process = function (schemaMap, schemaPath, docDir, schemaDir, metaElement const markdowns = result.map(r => r[0]); return readmeWriter(markdowns, schemaMap, docDir, schemaPath); } else { - console.log('Output processed.'); + return undefined; } }); }; diff --git a/lib/schemaWriter.js b/lib/schemaWriter.js index c06d240..5b8e7d6 100644 --- a/lib/schemaWriter.js +++ b/lib/schemaWriter.js @@ -13,8 +13,10 @@ const path = require('path'); const writeFile = require('./writeFiles'); -const generateNewSchemaFiles = function (filename, schema, schemaPath, outDir) { - return writeFile(path.join(path.join(outDir), path.dirname(filename.substr(schemaPath.length))), path.basename(filename), JSON.stringify(schema, null, 4)); -}; +const generateNewSchemaFiles = (filename, schema, schemaPath, outDir) => writeFile( + path.join(outDir, path.dirname(filename.substr(schemaPath.length))), + path.basename(filename), + JSON.stringify(schema, null, 4), +); module.exports = generateNewSchemaFiles; diff --git a/lib/writeFiles.js b/lib/writeFiles.js index b4cf524..848080d 100644 --- a/lib/writeFiles.js +++ b/lib/writeFiles.js @@ -15,12 +15,13 @@ const fs = Promise.promisifyAll(require('fs')); const path = require('path'); const mkdirp = Promise.promisify(require('mkdirp')); -const writeFile = function (outputDir, fileName, data) { +const writeFile = (outputDir, fileName, data) => Promise.resolve().then(() => { if (!fs.existsSync(outputDir)) { - return mkdirp(outputDir).then(() => fs.writeFileAsync(path.join(outputDir, fileName), data).then(() => path.join(outputDir, fileName))); + return mkdirp(outputDir); } else { - return fs.writeFileAsync(path.join(outputDir, fileName), data).then(() => path.join(outputDir, fileName)); + return Promise.resolve(); } -}; +}).then(() => fs.writeFileAsync(path.join(outputDir, fileName), data)) + .then(() => path.join(outputDir, fileName)); module.exports = writeFile; diff --git a/spec/lib/header.spec.js b/spec/lib/header.spec.js index a7f38ce..6663fbf 100644 --- a/spec/lib/header.spec.js +++ b/spec/lib/header.spec.js @@ -14,10 +14,11 @@ const i18n = require('i18n'); const path = require('path'); +const diff = require('jasmine-diff'); const { Header, headers } = require('../../lib/header'); beforeEach(() => { - jasmine.addMatchers(require('jasmine-diff')(jasmine, { + jasmine.addMatchers(diff(jasmine, { colors: true, inline: true, })); diff --git a/spec/lib/integrationTest.spec.js b/spec/lib/integrationTest.spec.js index 9b07850..9be1e27 100644 --- a/spec/lib/integrationTest.spec.js +++ b/spec/lib/integrationTest.spec.js @@ -15,11 +15,12 @@ const { spawn } = require('child_process'); const path = require('path'); const { readFileSync, readdirSync, statSync } = require('fs'); +const diff = require('jasmine-diff'); beforeEach(() => { jasmine.DEFAULT_TIMEOUT_INTERVAL = 20000; jasmine.addMatchers( - require('jasmine-diff')(jasmine, { + diff(jasmine, { colors: true, inline: true, }), @@ -68,22 +69,22 @@ describe('Compare results', () => { ]); ls.on('close', (code) => { expect(code).toEqual(0); - const files = readdirSync('./spec/examples').filter(item => !(/(^|\/)\.[^\/\.]/g).test(item)); + const files = readdirSync('./spec/examples').filter(item => !(/(^|\/)\.[^/.]/g).test(item)); expect(files.length).toEqual(23); files.forEach((file) => { if (statSync(`./spec/examples/${file}`).isFile()) { const expectedstr = readFileSync(path.resolve('./spec/examples/', file)).toString(); let actualstr = readFileSync(path.resolve('./examples/docs/', file)).toString(); - actualstr=actualstr.replace(/\r\n/g, '\n'); - expect(actualstr).toEqual(expectedstr, file + ' does not match'); + actualstr = actualstr.replace(/\r\n/g, '\n'); + expect(actualstr).toEqual(expectedstr, `${file} does not match`); } }); done(); }); }); - it('Run jsonschema2md for a file and do not generate a header', done => { + it('Run jsonschema2md for a file and do not generate a header', (done) => { const ls = spawn('node', [ 'cli.js', '-d', @@ -94,17 +95,17 @@ describe('Compare results', () => { 'examples/generated-schemas', '--no-header', '-v', - '06' + '06', ]); - ls.on('close', code => { + ls.on('close', (code) => { expect(code).toEqual(0); - const files = readdirSync('./spec/examples/withoutHeader').filter(item => !(/(^|\/)\.[^\/\.]/g).test(item)); - files.forEach(file => { - if (statSync('./spec/examples/withoutHeader/' + file).isFile()) { + const files = readdirSync('./spec/examples/withoutHeader').filter(item => !(/(^|\/)\.[^/.]/g).test(item)); + files.forEach((file) => { + if (statSync(`./spec/examples/withoutHeader/${file}`).isFile()) { const expectedstr = readFileSync(path.resolve('./spec/examples/withoutHeader/', file)).toString(); - let actualstr = readFileSync(path.resolve('./examples/docsWithoutHeader/', file)).toString(); - expect(actualstr).toEqual(expectedstr, file + ' does not match'); + const actualstr = readFileSync(path.resolve('./examples/docsWithoutHeader/', file)).toString(); + expect(actualstr).toEqual(expectedstr, `${file} does not match`); } }); done(); -- GitLab