lint: Run eslint --fix on bin/ and tests/

This commit is contained in:
Richard Hansen 2020-11-23 13:21:51 -05:00 committed by John McLear
parent 0625739cb8
commit b8d07a42eb
78 changed files with 4319 additions and 4599 deletions

View file

@ -20,19 +20,19 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
var marked = require('marked');
var fs = require('fs');
var path = require('path');
const marked = require('marked');
const fs = require('fs');
const path = require('path');
// parse the args.
// Don't use nopt or whatever for this. It's simple enough.
var args = process.argv.slice(2);
var format = 'json';
var template = null;
var inputFile = null;
const args = process.argv.slice(2);
let format = 'json';
let template = null;
let inputFile = null;
args.forEach(function (arg) {
args.forEach((arg) => {
if (!arg.match(/^\-\-/)) {
inputFile = arg;
} else if (arg.match(/^\-\-format=/)) {
@ -40,7 +40,7 @@ args.forEach(function (arg) {
} else if (arg.match(/^\-\-template=/)) {
template = arg.replace(/^\-\-template=/, '');
}
})
});
if (!inputFile) {
@ -49,25 +49,25 @@ if (!inputFile) {
console.error('Input file = %s', inputFile);
fs.readFile(inputFile, 'utf8', function(er, input) {
fs.readFile(inputFile, 'utf8', (er, input) => {
if (er) throw er;
// process the input for @include lines
processIncludes(inputFile, input, next);
});
var includeExpr = /^@include\s+([A-Za-z0-9-_\/]+)(?:\.)?([a-zA-Z]*)$/gmi;
var includeData = {};
const includeExpr = /^@include\s+([A-Za-z0-9-_\/]+)(?:\.)?([a-zA-Z]*)$/gmi;
const includeData = {};
function processIncludes(inputFile, input, cb) {
var includes = input.match(includeExpr);
const includes = input.match(includeExpr);
if (includes === null) return cb(null, input);
var errState = null;
let errState = null;
console.error(includes);
var incCount = includes.length;
let incCount = includes.length;
if (incCount === 0) cb(null, input);
includes.forEach(function(include) {
var fname = include.replace(/^@include\s+/, '');
includes.forEach((include) => {
let fname = include.replace(/^@include\s+/, '');
if (!fname.match(/\.md$/)) fname += '.md';
if (includeData.hasOwnProperty(fname)) {
@ -78,11 +78,11 @@ function processIncludes(inputFile, input, cb) {
}
}
var fullFname = path.resolve(path.dirname(inputFile), fname);
fs.readFile(fullFname, 'utf8', function(er, inc) {
const fullFname = path.resolve(path.dirname(inputFile), fname);
fs.readFile(fullFname, 'utf8', (er, inc) => {
if (errState) return;
if (er) return cb(errState = er);
processIncludes(fullFname, inc, function(er, inc) {
processIncludes(fullFname, inc, (er, inc) => {
if (errState) return;
if (er) return cb(errState = er);
incCount--;
@ -101,20 +101,20 @@ function next(er, input) {
if (er) throw er;
switch (format) {
case 'json':
require('./json.js')(input, inputFile, function(er, obj) {
require('./json.js')(input, inputFile, (er, obj) => {
console.log(JSON.stringify(obj, null, 2));
if (er) throw er;
});
break;
case 'html':
require('./html.js')(input, inputFile, template, function(er, html) {
require('./html.js')(input, inputFile, template, (er, html) => {
if (er) throw er;
console.log(html);
});
break;
default:
throw new Error('Invalid format: ' + format);
throw new Error(`Invalid format: ${format}`);
}
}

View file

@ -19,15 +19,15 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
var fs = require('fs');
var marked = require('marked');
var path = require('path');
const fs = require('fs');
const marked = require('marked');
const path = require('path');
module.exports = toHTML;
function toHTML(input, filename, template, cb) {
var lexed = marked.lexer(input);
fs.readFile(template, 'utf8', function(er, template) {
const lexed = marked.lexer(input);
fs.readFile(template, 'utf8', (er, template) => {
if (er) return cb(er);
render(lexed, filename, template, cb);
});
@ -35,7 +35,7 @@ function toHTML(input, filename, template, cb) {
function render(lexed, filename, template, cb) {
// get the section
var section = getSection(lexed);
const section = getSection(lexed);
filename = path.basename(filename, '.md');
@ -43,7 +43,7 @@ function render(lexed, filename, template, cb) {
// generate the table of contents.
// this mutates the lexed contents in-place.
buildToc(lexed, filename, function(er, toc) {
buildToc(lexed, filename, (er, toc) => {
if (er) return cb(er);
template = template.replace(/__FILENAME__/g, filename);
@ -63,11 +63,11 @@ function render(lexed, filename, template, cb) {
// just update the list item text in-place.
// lists that come right after a heading are what we're after.
function parseLists(input) {
var state = null;
var depth = 0;
var output = [];
let state = null;
let depth = 0;
const output = [];
output.links = input.links;
input.forEach(function(tok) {
input.forEach((tok) => {
if (state === null) {
if (tok.type === 'heading') {
state = 'AFTERHEADING';
@ -79,7 +79,7 @@ function parseLists(input) {
if (tok.type === 'list_start') {
state = 'LIST';
if (depth === 0) {
output.push({ type:'html', text: '<div class="signature">' });
output.push({type: 'html', text: '<div class="signature">'});
}
depth++;
output.push(tok);
@ -99,7 +99,7 @@ function parseLists(input) {
depth--;
if (depth === 0) {
state = null;
output.push({ type:'html', text: '</div>' });
output.push({type: 'html', text: '</div>'});
}
output.push(tok);
return;
@ -117,16 +117,16 @@ function parseLists(input) {
function parseListItem(text) {
text = text.replace(/\{([^\}]+)\}/, '<span class="type">$1</span>');
//XXX maybe put more stuff here?
// XXX maybe put more stuff here?
return text;
}
// section is just the first heading
function getSection(lexed) {
var section = '';
for (var i = 0, l = lexed.length; i < l; i++) {
var tok = lexed[i];
const section = '';
for (let i = 0, l = lexed.length; i < l; i++) {
const tok = lexed[i];
if (tok.type === 'heading') return tok.text;
}
return '';
@ -134,40 +134,39 @@ function getSection(lexed) {
function buildToc(lexed, filename, cb) {
var indent = 0;
var toc = [];
var depth = 0;
lexed.forEach(function(tok) {
const indent = 0;
let toc = [];
let depth = 0;
lexed.forEach((tok) => {
if (tok.type !== 'heading') return;
if (tok.depth - depth > 1) {
return cb(new Error('Inappropriate heading level\n' +
JSON.stringify(tok)));
return cb(new Error(`Inappropriate heading level\n${
JSON.stringify(tok)}`));
}
depth = tok.depth;
var id = getId(filename + '_' + tok.text.trim());
toc.push(new Array((depth - 1) * 2 + 1).join(' ') +
'* <a href="#' + id + '">' +
tok.text + '</a>');
tok.text += '<span><a class="mark" href="#' + id + '" ' +
'id="' + id + '">#</a></span>';
const id = getId(`${filename}_${tok.text.trim()}`);
toc.push(`${new Array((depth - 1) * 2 + 1).join(' ')
}* <a href="#${id}">${
tok.text}</a>`);
tok.text += `<span><a class="mark" href="#${id}" ` +
`id="${id}">#</a></span>`;
});
toc = marked.parse(toc.join('\n'));
cb(null, toc);
}
var idCounters = {};
const idCounters = {};
function getId(text) {
text = text.toLowerCase();
text = text.replace(/[^a-z0-9]+/g, '_');
text = text.replace(/^_+|_+$/, '');
text = text.replace(/^([^a-z])/, '_$1');
if (idCounters.hasOwnProperty(text)) {
text += '_' + (++idCounters[text]);
text += `_${++idCounters[text]}`;
} else {
idCounters[text] = 0;
}
return text;
}

View file

@ -24,24 +24,24 @@ module.exports = doJSON;
// Take the lexed input, and return a JSON-encoded object
// A module looks like this: https://gist.github.com/1777387
var marked = require('marked');
const marked = require('marked');
function doJSON(input, filename, cb) {
var root = {source: filename};
var stack = [root];
var depth = 0;
var current = root;
var state = null;
var lexed = marked.lexer(input);
lexed.forEach(function (tok) {
var type = tok.type;
var text = tok.text;
const root = {source: filename};
const stack = [root];
let depth = 0;
let current = root;
let state = null;
const lexed = marked.lexer(input);
lexed.forEach((tok) => {
const type = tok.type;
let text = tok.text;
// <!-- type = module -->
// This is for cases where the markdown semantic structure is lacking.
if (type === 'paragraph' || type === 'html') {
var metaExpr = /<!--([^=]+)=([^\-]+)-->\n*/g;
text = text.replace(metaExpr, function(_0, k, v) {
const metaExpr = /<!--([^=]+)=([^\-]+)-->\n*/g;
text = text.replace(metaExpr, (_0, k, v) => {
current[k.trim()] = v.trim();
return '';
});
@ -52,8 +52,8 @@ function doJSON(input, filename, cb) {
if (type === 'heading' &&
!text.trim().match(/^example/i)) {
if (tok.depth - depth > 1) {
return cb(new Error('Inappropriate heading level\n'+
JSON.stringify(tok)));
return cb(new Error(`Inappropriate heading level\n${
JSON.stringify(tok)}`));
}
// Sometimes we have two headings with a single
@ -61,7 +61,7 @@ function doJSON(input, filename, cb) {
if (current &&
state === 'AFTERHEADING' &&
depth === tok.depth) {
var clone = current;
const clone = current;
current = newSection(tok);
current.clone = clone;
// don't keep it around on the stack.
@ -75,7 +75,7 @@ function doJSON(input, filename, cb) {
// root is always considered the level=0 section,
// and the lowest heading is 1, so this should always
// result in having a valid parent node.
var d = tok.depth;
let d = tok.depth;
while (d <= depth) {
finishSection(stack.pop(), stack[stack.length - 1]);
d++;
@ -98,7 +98,7 @@ function doJSON(input, filename, cb) {
//
// If one of these isn't found, then anything that comes between
// here and the next heading should be parsed as the desc.
var stability
let stability;
if (state === 'AFTERHEADING') {
if (type === 'code' &&
(stability = text.match(/^Stability: ([0-5])(?:\s*-\s*)?(.*)$/))) {
@ -138,7 +138,6 @@ function doJSON(input, filename, cb) {
current.desc = current.desc || [];
current.desc.push(tok);
});
// finish any sections left open
@ -146,7 +145,7 @@ function doJSON(input, filename, cb) {
finishSection(current, stack[stack.length - 1]);
}
return cb(null, root)
return cb(null, root);
}
@ -193,14 +192,14 @@ function doJSON(input, filename, cb) {
// default: 'false' } ] } ]
function processList(section) {
var list = section.list;
var values = [];
var current;
var stack = [];
const list = section.list;
const values = [];
let current;
const stack = [];
// for now, *just* build the hierarchical list
list.forEach(function(tok) {
var type = tok.type;
list.forEach((tok) => {
const type = tok.type;
if (type === 'space') return;
if (type === 'list_item_start') {
if (!current) {
@ -217,26 +216,26 @@ function processList(section) {
return;
} else if (type === 'list_item_end') {
if (!current) {
throw new Error('invalid list - end without current item\n' +
JSON.stringify(tok) + '\n' +
JSON.stringify(list));
throw new Error(`invalid list - end without current item\n${
JSON.stringify(tok)}\n${
JSON.stringify(list)}`);
}
current = stack.pop();
} else if (type === 'text') {
if (!current) {
throw new Error('invalid list - text without current item\n' +
JSON.stringify(tok) + '\n' +
JSON.stringify(list));
throw new Error(`invalid list - text without current item\n${
JSON.stringify(tok)}\n${
JSON.stringify(list)}`);
}
current.textRaw = current.textRaw || '';
current.textRaw += tok.text + ' ';
current.textRaw += `${tok.text} `;
}
});
// shove the name in there for properties, since they are always
// just going to be the value etc.
if (section.type === 'property' && values[0]) {
values[0].textRaw = '`' + section.name + '` ' + values[0].textRaw;
values[0].textRaw = `\`${section.name}\` ${values[0].textRaw}`;
}
// now pull the actual values out of the text bits.
@ -252,9 +251,9 @@ function processList(section) {
// each item is an argument, unless the name is 'return',
// in which case it's the return value.
section.signatures = section.signatures || [];
var sig = {}
var sig = {};
section.signatures.push(sig);
sig.params = values.filter(function(v) {
sig.params = values.filter((v) => {
if (v.name === 'return') {
sig.return = v;
return false;
@ -271,7 +270,7 @@ function processList(section) {
delete value.name;
section.typeof = value.type;
delete value.type;
Object.keys(value).forEach(function(k) {
Object.keys(value).forEach((k) => {
section[k] = value[k];
});
break;
@ -289,36 +288,36 @@ function processList(section) {
// textRaw = "someobject.someMethod(a, [b=100], [c])"
function parseSignature(text, sig) {
var params = text.match(paramExpr);
let params = text.match(paramExpr);
if (!params) return;
params = params[1];
// the ] is irrelevant. [ indicates optionalness.
params = params.replace(/\]/g, '');
params = params.split(/,/)
params.forEach(function(p, i, _) {
params = params.split(/,/);
params.forEach((p, i, _) => {
p = p.trim();
if (!p) return;
var param = sig.params[i];
var optional = false;
var def;
let param = sig.params[i];
let optional = false;
let def;
// [foo] -> optional
if (p.charAt(0) === '[') {
optional = true;
p = p.substr(1);
}
var eq = p.indexOf('=');
const eq = p.indexOf('=');
if (eq !== -1) {
def = p.substr(eq + 1);
p = p.substr(0, eq);
}
if (!param) {
param = sig.params[i] = { name: p };
param = sig.params[i] = {name: p};
}
// at this point, the name should match.
if (p !== param.name) {
console.error('Warning: invalid param "%s"', p);
console.error(' > ' + JSON.stringify(param));
console.error(' > ' + text);
console.error(` > ${JSON.stringify(param)}`);
console.error(` > ${text}`);
}
if (optional) param.optional = true;
if (def !== undefined) param.default = def;
@ -332,18 +331,18 @@ function parseListItem(item) {
// the goal here is to find the name, type, default, and optional.
// anything left over is 'desc'
var text = item.textRaw.trim();
let text = item.textRaw.trim();
// text = text.replace(/^(Argument|Param)s?\s*:?\s*/i, '');
text = text.replace(/^, /, '').trim();
var retExpr = /^returns?\s*:?\s*/i;
var ret = text.match(retExpr);
const retExpr = /^returns?\s*:?\s*/i;
const ret = text.match(retExpr);
if (ret) {
item.name = 'return';
text = text.replace(retExpr, '');
} else {
var nameExpr = /^['`"]?([^'`": \{]+)['`"]?\s*:?\s*/;
var name = text.match(nameExpr);
const nameExpr = /^['`"]?([^'`": \{]+)['`"]?\s*:?\s*/;
const name = text.match(nameExpr);
if (name) {
item.name = name[1];
text = text.replace(nameExpr, '');
@ -351,24 +350,24 @@ function parseListItem(item) {
}
text = text.trim();
var defaultExpr = /\(default\s*[:=]?\s*['"`]?([^, '"`]*)['"`]?\)/i;
var def = text.match(defaultExpr);
const defaultExpr = /\(default\s*[:=]?\s*['"`]?([^, '"`]*)['"`]?\)/i;
const def = text.match(defaultExpr);
if (def) {
item.default = def[1];
text = text.replace(defaultExpr, '');
}
text = text.trim();
var typeExpr = /^\{([^\}]+)\}/;
var type = text.match(typeExpr);
const typeExpr = /^\{([^\}]+)\}/;
const type = text.match(typeExpr);
if (type) {
item.type = type[1];
text = text.replace(typeExpr, '');
}
text = text.trim();
var optExpr = /^Optional\.|(?:, )?Optional$/;
var optional = text.match(optExpr);
const optExpr = /^Optional\.|(?:, )?Optional$/;
const optional = text.match(optExpr);
if (optional) {
item.optional = true;
text = text.replace(optExpr, '');
@ -382,9 +381,9 @@ function parseListItem(item) {
function finishSection(section, parent) {
if (!section || !parent) {
throw new Error('Invalid finishSection call\n'+
JSON.stringify(section) + '\n' +
JSON.stringify(parent));
throw new Error(`Invalid finishSection call\n${
JSON.stringify(section)}\n${
JSON.stringify(parent)}`);
}
if (!section.type) {
@ -394,7 +393,7 @@ function finishSection(section, parent) {
}
section.displayName = section.name;
section.name = section.name.toLowerCase()
.trim().replace(/\s+/g, '_');
.trim().replace(/\s+/g, '_');
}
if (section.desc && Array.isArray(section.desc)) {
@ -411,10 +410,10 @@ function finishSection(section, parent) {
// Merge them into the parent.
if (section.type === 'class' && section.ctors) {
section.signatures = section.signatures || [];
var sigs = section.signatures;
section.ctors.forEach(function(ctor) {
const sigs = section.signatures;
section.ctors.forEach((ctor) => {
ctor.signatures = ctor.signatures || [{}];
ctor.signatures.forEach(function(sig) {
ctor.signatures.forEach((sig) => {
sig.desc = ctor.desc;
});
sigs.push.apply(sigs, ctor.signatures);
@ -425,7 +424,7 @@ function finishSection(section, parent) {
// properties are a bit special.
// their "type" is the type of object, not "property"
if (section.properties) {
section.properties.forEach(function (p) {
section.properties.forEach((p) => {
if (p.typeof) p.type = p.typeof;
else delete p.type;
delete p.typeof;
@ -434,27 +433,27 @@ function finishSection(section, parent) {
// handle clones
if (section.clone) {
var clone = section.clone;
const clone = section.clone;
delete section.clone;
delete clone.clone;
deepCopy(section, clone);
finishSection(clone, parent);
}
var plur;
let plur;
if (section.type.slice(-1) === 's') {
plur = section.type + 'es';
plur = `${section.type}es`;
} else if (section.type.slice(-1) === 'y') {
plur = section.type.replace(/y$/, 'ies');
} else {
plur = section.type + 's';
plur = `${section.type}s`;
}
// if the parent's type is 'misc', then it's just a random
// collection of stuff, like the "globals" section.
// Make the children top-level items.
if (section.type === 'misc') {
Object.keys(section).forEach(function(k) {
Object.keys(section).forEach((k) => {
switch (k) {
case 'textRaw':
case 'name':
@ -486,9 +485,7 @@ function finishSection(section, parent) {
// Not a general purpose deep copy.
// But sufficient for these basic things.
function deepCopy(src, dest) {
Object.keys(src).filter(function(k) {
return !dest.hasOwnProperty(k);
}).forEach(function(k) {
Object.keys(src).filter((k) => !dest.hasOwnProperty(k)).forEach((k) => {
dest[k] = deepCopy_(src[k]);
});
}
@ -497,14 +494,14 @@ function deepCopy_(src) {
if (!src) return src;
if (Array.isArray(src)) {
var c = new Array(src.length);
src.forEach(function(v, i) {
src.forEach((v, i) => {
c[i] = deepCopy_(v);
});
return c;
}
if (typeof src === 'object') {
var c = {};
Object.keys(src).forEach(function(k) {
Object.keys(src).forEach((k) => {
c[k] = deepCopy_(src[k]);
});
return c;
@ -514,21 +511,21 @@ function deepCopy_(src) {
// these parse out the contents of an H# tag
var eventExpr = /^Event(?::|\s)+['"]?([^"']+).*$/i;
var classExpr = /^Class:\s*([^ ]+).*?$/i;
var propExpr = /^(?:property:?\s*)?[^\.]+\.([^ \.\(\)]+)\s*?$/i;
var braceExpr = /^(?:property:?\s*)?[^\.\[]+(\[[^\]]+\])\s*?$/i;
var classMethExpr =
const eventExpr = /^Event(?::|\s)+['"]?([^"']+).*$/i;
const classExpr = /^Class:\s*([^ ]+).*?$/i;
const propExpr = /^(?:property:?\s*)?[^\.]+\.([^ \.\(\)]+)\s*?$/i;
const braceExpr = /^(?:property:?\s*)?[^\.\[]+(\[[^\]]+\])\s*?$/i;
const classMethExpr =
/^class\s*method\s*:?[^\.]+\.([^ \.\(\)]+)\([^\)]*\)\s*?$/i;
var methExpr =
const methExpr =
/^(?:method:?\s*)?(?:[^\.]+\.)?([^ \.\(\)]+)\([^\)]*\)\s*?$/i;
var newExpr = /^new ([A-Z][a-z]+)\([^\)]*\)\s*?$/;
const newExpr = /^new ([A-Z][a-z]+)\([^\)]*\)\s*?$/;
var paramExpr = /\((.*)\);?$/;
function newSection(tok) {
var section = {};
const section = {};
// infer the type from the text.
var text = section.textRaw = tok.text;
const text = section.textRaw = tok.text;
if (text.match(eventExpr)) {
section.type = 'event';
section.name = text.replace(eventExpr, '$1');