2011-08-22 22:34:20 -05:00
|
|
|
#!/usr/bin/env node
|
2019-03-13 08:50:53 -05:00
|
|
|
'use strict';
|
|
|
|
// 'use strict' is here so we can use let and const in node 4
|
2011-08-22 22:34:20 -05:00
|
|
|
|
2013-02-07 03:51:43 -06:00
|
|
|
/**
|
|
|
|
* marked tests
|
|
|
|
* Copyright (c) 2011-2013, Christopher Jeffrey. (MIT Licensed)
|
2018-03-03 14:20:24 -05:00
|
|
|
* https://github.com/markedjs/marked
|
2013-02-07 03:51:43 -06:00
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Modules
|
|
|
|
*/
|
|
|
|
|
2019-03-13 08:50:53 -05:00
|
|
|
const fs = require('fs');
|
|
|
|
const path = require('path');
|
|
|
|
const fm = require('front-matter');
|
|
|
|
const g2r = require('glob-to-regexp');
|
|
|
|
let marked = require('../');
|
|
|
|
const htmlDiffer = require('./helpers/html-differ.js');
|
2013-01-03 08:29:40 -06:00
|
|
|
|
2013-02-07 03:51:43 -06:00
|
|
|
/**
|
|
|
|
* Load Tests
|
|
|
|
*/
|
|
|
|
|
2018-01-07 11:25:24 -06:00
|
|
|
function load(options) {
|
2018-02-13 20:01:53 +01:00
|
|
|
options = options || {};
|
2019-03-13 08:50:53 -05:00
|
|
|
const dir = path.join(__dirname, 'compiled_tests');
|
|
|
|
const glob = g2r(options.glob || '*', { extended: true });
|
|
|
|
|
|
|
|
const list = fs
|
2011-08-22 23:16:25 -05:00
|
|
|
.readdirSync(dir)
|
2019-03-13 08:50:53 -05:00
|
|
|
.filter(file => {
|
2016-11-29 14:59:29 +00:00
|
|
|
return path.extname(file) === '.md';
|
2011-08-22 23:16:25 -05:00
|
|
|
})
|
2018-01-06 21:09:49 -06:00
|
|
|
.sort();
|
2011-08-22 22:34:20 -05:00
|
|
|
|
2019-03-13 08:50:53 -05:00
|
|
|
const files = list.reduce((obj, item) => {
|
|
|
|
const name = path.basename(item, '.md');
|
2018-01-07 11:54:28 -06:00
|
|
|
if (glob.test(name)) {
|
2019-03-13 08:50:53 -05:00
|
|
|
const file = path.join(dir, item);
|
|
|
|
const content = fm(fs.readFileSync(file, 'utf8'));
|
2018-01-07 11:25:24 -06:00
|
|
|
|
2019-03-13 08:50:53 -05:00
|
|
|
obj[name] = {
|
2018-01-07 11:25:24 -06:00
|
|
|
options: content.attributes,
|
|
|
|
text: content.body,
|
|
|
|
html: fs.readFileSync(file.replace(/[^.]+$/, 'html'), 'utf8')
|
|
|
|
};
|
|
|
|
}
|
2019-03-13 08:50:53 -05:00
|
|
|
return obj;
|
|
|
|
}, {});
|
2018-01-07 11:25:24 -06:00
|
|
|
|
|
|
|
if (options.bench || options.time) {
|
2018-01-07 11:54:28 -06:00
|
|
|
if (!options.glob) {
|
2018-01-07 11:25:24 -06:00
|
|
|
// Change certain tests to allow
|
|
|
|
// comparison to older benchmark times.
|
2019-03-13 08:50:53 -05:00
|
|
|
fs.readdirSync(path.join(__dirname, 'new')).forEach(name => {
|
2018-01-07 11:25:24 -06:00
|
|
|
if (path.extname(name) === '.html') return;
|
|
|
|
if (name === 'main.md') return;
|
|
|
|
delete files[name];
|
|
|
|
});
|
|
|
|
}
|
2018-01-06 01:11:16 -06:00
|
|
|
|
2018-01-07 11:25:24 -06:00
|
|
|
if (files['backslash_escapes.md']) {
|
|
|
|
files['backslash_escapes.md'] = {
|
|
|
|
text: 'hello world \\[how](are you) today'
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
if (files['main.md']) {
|
|
|
|
files['main.md'].text = files['main.md'].text.replace('* * *\n\n', '');
|
|
|
|
}
|
2011-08-22 23:16:25 -05:00
|
|
|
}
|
2012-03-10 17:27:44 -06:00
|
|
|
|
|
|
|
return files;
|
2013-01-03 08:29:40 -06:00
|
|
|
}
|
2011-08-22 23:16:25 -05:00
|
|
|
|
2013-02-07 03:51:43 -06:00
|
|
|
/**
|
|
|
|
* Test Runner
|
|
|
|
*/
|
|
|
|
|
|
|
|
function runTests(engine, options) {
|
|
|
|
if (typeof engine !== 'function') {
|
|
|
|
options = engine;
|
|
|
|
engine = null;
|
|
|
|
}
|
|
|
|
|
2018-02-01 23:10:48 -06:00
|
|
|
engine = engine || marked;
|
|
|
|
options = options || {};
|
2019-03-13 08:50:53 -05:00
|
|
|
|
|
|
|
let succeeded = 0;
|
|
|
|
let failed = 0;
|
|
|
|
const files = options.files || load(options);
|
|
|
|
const filenames = Object.keys(files);
|
2011-08-22 22:34:20 -05:00
|
|
|
|
2013-02-07 03:51:43 -06:00
|
|
|
if (options.marked) {
|
|
|
|
marked.setOptions(options.marked);
|
|
|
|
}
|
|
|
|
|
2019-03-13 08:50:53 -05:00
|
|
|
for (let i = 0; i < filenames.length; i++) {
|
|
|
|
const filename = filenames[i];
|
|
|
|
const file = files[filename];
|
2011-08-22 23:16:25 -05:00
|
|
|
|
2019-03-13 08:50:53 -05:00
|
|
|
const success = testFile(engine, file, filename, i + 1);
|
2013-02-07 03:51:43 -06:00
|
|
|
|
2018-04-16 22:59:40 -05:00
|
|
|
if (success) {
|
2018-02-01 23:10:48 -06:00
|
|
|
succeeded++;
|
|
|
|
} else {
|
|
|
|
failed++;
|
|
|
|
if (options.stop) {
|
|
|
|
break;
|
|
|
|
}
|
2013-08-07 06:10:50 -05:00
|
|
|
}
|
2018-02-01 23:10:48 -06:00
|
|
|
}
|
2013-08-07 06:40:08 -05:00
|
|
|
|
2019-03-13 08:50:53 -05:00
|
|
|
console.log('\n%d/%d tests completed successfully.', succeeded, filenames.length);
|
|
|
|
if (failed) console.log('%d/%d tests failed.', failed, filenames.length);
|
2013-08-07 06:40:08 -05:00
|
|
|
|
2018-02-01 23:10:48 -06:00
|
|
|
return !failed;
|
|
|
|
}
|
2011-08-22 22:34:20 -05:00
|
|
|
|
2018-02-01 23:10:48 -06:00
|
|
|
/**
|
|
|
|
* Test a file
|
|
|
|
*/
|
2011-08-22 23:16:25 -05:00
|
|
|
|
2018-02-01 23:10:48 -06:00
|
|
|
function testFile(engine, file, filename, index) {
|
2019-03-13 08:50:53 -05:00
|
|
|
const opts = Object.keys(file.options);
|
2018-02-01 23:10:48 -06:00
|
|
|
|
|
|
|
if (marked._original) {
|
|
|
|
marked.defaults = marked._original;
|
|
|
|
delete marked._original;
|
|
|
|
}
|
2011-08-22 22:34:20 -05:00
|
|
|
|
2018-02-26 17:58:43 -06:00
|
|
|
console.log('#%d. Test %s', index, filename);
|
2011-08-22 23:16:25 -05:00
|
|
|
|
2018-02-01 23:10:48 -06:00
|
|
|
if (opts.length) {
|
|
|
|
marked._original = marked.defaults;
|
|
|
|
marked.defaults = {};
|
2019-03-13 08:50:53 -05:00
|
|
|
Object.keys(marked._original).forEach(key => {
|
2018-02-01 23:10:48 -06:00
|
|
|
marked.defaults[key] = marked._original[key];
|
|
|
|
});
|
2019-03-13 08:50:53 -05:00
|
|
|
opts.forEach(key => {
|
2018-02-01 23:10:48 -06:00
|
|
|
if (marked.defaults.hasOwnProperty(key)) {
|
|
|
|
marked.defaults[key] = file.options[key];
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
2013-02-12 01:17:28 -06:00
|
|
|
|
2019-03-13 08:50:53 -05:00
|
|
|
const before = process.hrtime();
|
|
|
|
|
|
|
|
let text, html, elapsed;
|
2018-02-01 23:10:48 -06:00
|
|
|
try {
|
2019-03-13 08:50:53 -05:00
|
|
|
text = engine(file.text);
|
|
|
|
html = file.html;
|
2018-02-01 23:10:48 -06:00
|
|
|
} catch (e) {
|
2018-02-26 17:58:43 -06:00
|
|
|
elapsed = process.hrtime(before);
|
2019-03-13 08:50:53 -05:00
|
|
|
console.log('\n failed in %dms\n', prettyElapsedTime(elapsed));
|
2018-02-01 23:10:48 -06:00
|
|
|
throw e;
|
|
|
|
}
|
2012-03-11 00:45:28 -06:00
|
|
|
|
2018-02-26 17:58:43 -06:00
|
|
|
elapsed = process.hrtime(before);
|
2012-03-11 00:45:28 -06:00
|
|
|
|
2019-03-13 08:50:53 -05:00
|
|
|
if (htmlDiffer.isEqual(text, html)) {
|
|
|
|
if (elapsed[0] > 0) {
|
|
|
|
console.log('\n failed because it took too long.\n\n passed in %dms\n', prettyElapsedTime(elapsed));
|
2018-02-01 23:10:48 -06:00
|
|
|
return false;
|
|
|
|
}
|
2019-03-13 08:50:53 -05:00
|
|
|
console.log(' passed in %dms', prettyElapsedTime(elapsed));
|
|
|
|
return true;
|
2011-08-22 22:34:20 -05:00
|
|
|
}
|
|
|
|
|
2019-03-13 08:50:53 -05:00
|
|
|
const diff = htmlDiffer.firstDiff(text, html);
|
2013-08-03 21:46:48 -07:00
|
|
|
|
2019-03-13 08:50:53 -05:00
|
|
|
console.log('\n failed in %dms', prettyElapsedTime(elapsed));
|
|
|
|
console.log(' Expected: %s', diff.expected);
|
|
|
|
console.log(' Actual: %s\n', diff.actual);
|
|
|
|
return false;
|
2013-01-03 08:29:40 -06:00
|
|
|
}
|
2011-08-22 22:34:20 -05:00
|
|
|
|
2013-02-07 03:51:43 -06:00
|
|
|
/**
|
|
|
|
* Benchmark a function
|
|
|
|
*/
|
|
|
|
|
2019-03-13 08:50:53 -05:00
|
|
|
function bench(name, files, engine) {
|
|
|
|
const start = Date.now();
|
|
|
|
|
|
|
|
for (let i = 0; i < 1000; i++) {
|
|
|
|
for (const filename in files) {
|
|
|
|
engine(files[filename].text);
|
2011-08-22 23:16:25 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-13 08:50:53 -05:00
|
|
|
const end = Date.now();
|
|
|
|
|
|
|
|
console.log('%s completed in %dms.', name, end - start);
|
2013-01-03 08:29:40 -06:00
|
|
|
}
|
2011-08-22 23:16:25 -05:00
|
|
|
|
2013-02-07 03:51:43 -06:00
|
|
|
/**
|
|
|
|
* Benchmark all engines
|
|
|
|
*/
|
|
|
|
|
|
|
|
function runBench(options) {
|
2018-02-01 23:10:48 -06:00
|
|
|
options = options || {};
|
2019-03-13 08:50:53 -05:00
|
|
|
const files = load(options);
|
2013-02-07 03:51:43 -06:00
|
|
|
|
|
|
|
// Non-GFM, Non-pedantic
|
2013-01-09 13:43:36 -06:00
|
|
|
marked.setOptions({
|
|
|
|
gfm: false,
|
|
|
|
tables: false,
|
|
|
|
breaks: false,
|
|
|
|
pedantic: false,
|
2013-02-07 03:51:43 -06:00
|
|
|
sanitize: false,
|
|
|
|
smartLists: false
|
2013-01-09 13:43:36 -06:00
|
|
|
});
|
2013-02-07 03:51:43 -06:00
|
|
|
if (options.marked) {
|
|
|
|
marked.setOptions(options.marked);
|
|
|
|
}
|
2018-01-07 11:25:24 -06:00
|
|
|
bench('marked', files, marked);
|
2011-08-22 23:16:25 -05:00
|
|
|
|
2013-02-07 03:51:43 -06:00
|
|
|
// GFM
|
2013-01-09 13:43:36 -06:00
|
|
|
marked.setOptions({
|
|
|
|
gfm: true,
|
|
|
|
tables: false,
|
|
|
|
breaks: false,
|
|
|
|
pedantic: false,
|
2013-02-07 03:51:43 -06:00
|
|
|
sanitize: false,
|
|
|
|
smartLists: false
|
2013-01-09 13:43:36 -06:00
|
|
|
});
|
2013-02-07 03:51:43 -06:00
|
|
|
if (options.marked) {
|
|
|
|
marked.setOptions(options.marked);
|
|
|
|
}
|
2018-01-07 11:25:24 -06:00
|
|
|
bench('marked (gfm)', files, marked);
|
2012-02-19 21:51:52 -06:00
|
|
|
|
2013-02-07 03:51:43 -06:00
|
|
|
// Pedantic
|
2013-01-09 13:43:36 -06:00
|
|
|
marked.setOptions({
|
|
|
|
gfm: false,
|
|
|
|
tables: false,
|
|
|
|
breaks: false,
|
|
|
|
pedantic: true,
|
2013-02-07 03:51:43 -06:00
|
|
|
sanitize: false,
|
|
|
|
smartLists: false
|
2013-01-09 13:43:36 -06:00
|
|
|
});
|
2013-02-07 03:51:43 -06:00
|
|
|
if (options.marked) {
|
|
|
|
marked.setOptions(options.marked);
|
|
|
|
}
|
2018-01-07 11:25:24 -06:00
|
|
|
bench('marked (pedantic)', files, marked);
|
2012-02-19 20:29:35 -06:00
|
|
|
|
2013-05-28 20:32:11 -05:00
|
|
|
try {
|
2019-03-13 08:50:53 -05:00
|
|
|
bench('commonmark', files, (() => {
|
|
|
|
const commonmark = require('commonmark');
|
|
|
|
const parser = new commonmark.Parser();
|
|
|
|
const writer = new commonmark.HtmlRenderer();
|
|
|
|
return function (text) {
|
2018-01-19 18:19:17 +01:00
|
|
|
return writer.render(parser.parse(text));
|
2013-05-28 20:32:11 -05:00
|
|
|
};
|
|
|
|
})());
|
|
|
|
} catch (e) {
|
2018-01-19 18:19:17 +01:00
|
|
|
console.log('Could not bench commonmark. (Error: %s)', e.message);
|
2013-05-28 20:32:11 -05:00
|
|
|
}
|
2011-08-22 23:16:25 -05:00
|
|
|
|
2018-01-06 01:44:10 -06:00
|
|
|
try {
|
2019-03-13 08:50:53 -05:00
|
|
|
bench('markdown-it', files, (() => {
|
|
|
|
const MarkdownIt = require('markdown-it');
|
|
|
|
const md = new MarkdownIt();
|
|
|
|
return md.render.bind(md);
|
2018-01-06 01:44:10 -06:00
|
|
|
})());
|
|
|
|
} catch (e) {
|
2018-01-06 14:59:21 -06:00
|
|
|
console.log('Could not bench markdown-it. (Error: %s)', e.message);
|
2018-01-06 01:44:10 -06:00
|
|
|
}
|
|
|
|
|
2013-05-28 20:32:11 -05:00
|
|
|
try {
|
2019-03-13 08:50:53 -05:00
|
|
|
bench('markdown.js', files, (() => {
|
|
|
|
const markdown = require('markdown').markdown;
|
|
|
|
return markdown.toHTML.bind(markdown);
|
2018-01-06 01:44:10 -06:00
|
|
|
})());
|
2013-05-28 20:32:11 -05:00
|
|
|
} catch (e) {
|
2018-01-06 14:59:21 -06:00
|
|
|
console.log('Could not bench markdown.js. (Error: %s)', e.message);
|
2013-05-28 20:32:11 -05:00
|
|
|
}
|
2018-01-06 01:44:10 -06:00
|
|
|
|
|
|
|
return true;
|
2013-01-03 08:29:40 -06:00
|
|
|
}
|
2011-08-22 22:34:20 -05:00
|
|
|
|
2013-02-07 03:51:43 -06:00
|
|
|
/**
|
|
|
|
* A simple one-time benchmark
|
|
|
|
*/
|
|
|
|
|
|
|
|
function time(options) {
|
2018-02-01 23:10:48 -06:00
|
|
|
options = options || {};
|
2019-03-13 08:50:53 -05:00
|
|
|
const files = load(options);
|
2013-02-07 03:51:43 -06:00
|
|
|
if (options.marked) {
|
|
|
|
marked.setOptions(options.marked);
|
|
|
|
}
|
2018-01-07 11:25:24 -06:00
|
|
|
bench('marked', files, marked);
|
|
|
|
|
|
|
|
return true;
|
2013-01-03 08:29:40 -06:00
|
|
|
}
|
2011-10-22 08:36:34 -05:00
|
|
|
|
2013-02-12 01:17:28 -06:00
|
|
|
/**
|
|
|
|
* Markdown Test Suite Fixer
|
|
|
|
* This function is responsible for "fixing"
|
|
|
|
* the markdown test suite. There are
|
|
|
|
* certain aspects of the suite that
|
|
|
|
* are strange or might make tests
|
|
|
|
* fail for reasons unrelated to
|
|
|
|
* conformance.
|
|
|
|
*/
|
|
|
|
|
2018-01-02 13:53:05 -06:00
|
|
|
function fix() {
|
2019-03-13 08:50:53 -05:00
|
|
|
['compiled_tests', 'original', 'new', 'redos'].forEach(dir => {
|
2013-02-12 01:17:28 -06:00
|
|
|
try {
|
2018-03-04 07:40:04 -06:00
|
|
|
fs.mkdirSync(path.resolve(__dirname, dir));
|
2013-02-12 01:17:28 -06:00
|
|
|
} catch (e) {
|
2019-03-11 13:41:33 -05:00
|
|
|
// directory already exists
|
2013-02-12 01:17:28 -06:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
// rm -rf tests
|
2019-03-13 08:50:53 -05:00
|
|
|
fs.readdirSync(path.resolve(__dirname, 'compiled_tests')).forEach(file => {
|
2018-01-02 13:57:24 -06:00
|
|
|
fs.unlinkSync(path.resolve(__dirname, 'compiled_tests', file));
|
2013-02-12 01:17:28 -06:00
|
|
|
});
|
|
|
|
|
|
|
|
// cp -r original tests
|
2019-03-13 08:50:53 -05:00
|
|
|
fs.readdirSync(path.resolve(__dirname, 'original')).forEach(file => {
|
|
|
|
let text = fs.readFileSync(path.resolve(__dirname, 'original', file), 'utf8');
|
2018-01-06 01:11:16 -06:00
|
|
|
|
2018-01-23 04:52:04 +01:00
|
|
|
if (path.extname(file) === '.md') {
|
2018-02-09 03:56:52 +01:00
|
|
|
if (fm.test(text)) {
|
|
|
|
text = fm(text);
|
2019-03-13 10:39:01 -05:00
|
|
|
text = `---\n${text.frontmatter}\ngfm: false\n---\n${text.body}`;
|
2018-02-09 03:56:52 +01:00
|
|
|
} else {
|
2019-03-13 10:39:01 -05:00
|
|
|
text = `---\ngfm: false\n---\n${text}`;
|
2018-02-09 03:56:52 +01:00
|
|
|
}
|
2013-08-07 06:10:50 -05:00
|
|
|
}
|
2018-01-06 10:46:21 -06:00
|
|
|
|
2018-01-06 01:11:16 -06:00
|
|
|
fs.writeFileSync(path.resolve(__dirname, 'compiled_tests', file), text);
|
2013-02-12 01:17:28 -06:00
|
|
|
});
|
|
|
|
|
|
|
|
// node fix.js
|
2019-03-13 08:50:53 -05:00
|
|
|
const dir = path.join(__dirname, 'compiled_tests');
|
2013-02-12 01:17:28 -06:00
|
|
|
|
2019-03-13 08:50:53 -05:00
|
|
|
fs.readdirSync(dir).filter(file => {
|
2013-02-12 01:17:28 -06:00
|
|
|
return path.extname(file) === '.html';
|
2019-03-13 08:50:53 -05:00
|
|
|
}).forEach(file => {
|
2018-02-01 23:10:48 -06:00
|
|
|
file = path.join(dir, file);
|
2019-03-13 08:50:53 -05:00
|
|
|
let html = fs.readFileSync(file, 'utf8');
|
2013-02-12 01:17:28 -06:00
|
|
|
|
2013-08-04 06:52:02 -05:00
|
|
|
// fix unencoded quotes
|
2013-02-12 01:17:28 -06:00
|
|
|
html = html
|
|
|
|
.replace(/='([^\n']*)'(?=[^<>\n]*>)/g, '=&__APOS__;$1&__APOS__;')
|
|
|
|
.replace(/="([^\n"]*)"(?=[^<>\n]*>)/g, '=&__QUOT__;$1&__QUOT__;')
|
|
|
|
.replace(/"/g, '"')
|
|
|
|
.replace(/'/g, ''')
|
|
|
|
.replace(/&__QUOT__;/g, '"')
|
|
|
|
.replace(/&__APOS__;/g, '\'');
|
|
|
|
|
|
|
|
fs.writeFileSync(file, html);
|
|
|
|
});
|
|
|
|
|
|
|
|
// turn <hr /> into <hr>
|
2019-03-13 08:50:53 -05:00
|
|
|
fs.readdirSync(dir).forEach(file => {
|
2018-02-01 23:10:48 -06:00
|
|
|
file = path.join(dir, file);
|
2019-03-13 08:50:53 -05:00
|
|
|
let text = fs.readFileSync(file, 'utf8');
|
2013-02-12 01:17:28 -06:00
|
|
|
|
|
|
|
text = text.replace(/(<|<)hr\s*\/(>|>)/g, '$1hr$2');
|
|
|
|
|
|
|
|
fs.writeFileSync(file, text);
|
|
|
|
});
|
|
|
|
|
|
|
|
// markdown does some strange things.
|
|
|
|
// it does not encode naked `>`, marked does.
|
2019-03-13 08:50:53 -05:00
|
|
|
{
|
2019-03-13 10:39:01 -05:00
|
|
|
const file = `${dir}/amps_and_angles_encoding.html`;
|
2019-03-13 08:50:53 -05:00
|
|
|
const html = fs.readFileSync(file, 'utf8')
|
2013-02-12 01:17:28 -06:00
|
|
|
.replace('6 > 5.', '6 > 5.');
|
|
|
|
|
|
|
|
fs.writeFileSync(file, html);
|
2019-03-13 08:50:53 -05:00
|
|
|
}
|
2013-02-12 01:17:28 -06:00
|
|
|
|
|
|
|
// cp new/* tests/
|
2019-03-13 08:50:53 -05:00
|
|
|
fs.readdirSync(path.resolve(__dirname, 'new')).forEach(file => {
|
2018-01-02 13:57:24 -06:00
|
|
|
fs.writeFileSync(path.resolve(__dirname, 'compiled_tests', file),
|
2013-02-12 01:17:28 -06:00
|
|
|
fs.readFileSync(path.resolve(__dirname, 'new', file)));
|
|
|
|
});
|
2019-03-11 13:41:33 -05:00
|
|
|
|
|
|
|
// cp redos/* tests/
|
2019-03-13 08:50:53 -05:00
|
|
|
fs.readdirSync(path.resolve(__dirname, 'redos')).forEach(file => {
|
2019-03-11 13:41:33 -05:00
|
|
|
fs.writeFileSync(path.resolve(__dirname, 'compiled_tests', file),
|
|
|
|
fs.readFileSync(path.resolve(__dirname, 'redos', file)));
|
|
|
|
});
|
2013-02-12 01:17:28 -06:00
|
|
|
}
|
|
|
|
|
2013-02-07 03:51:43 -06:00
|
|
|
/**
|
|
|
|
* Argument Parsing
|
|
|
|
*/
|
|
|
|
|
2019-03-09 23:32:54 -06:00
|
|
|
function parseArg(argv) {
|
2019-03-11 15:07:34 -05:00
|
|
|
argv = argv.slice(2);
|
2019-03-13 08:50:53 -05:00
|
|
|
|
|
|
|
const options = {};
|
|
|
|
const orphans = [];
|
|
|
|
|
2013-02-07 03:51:43 -06:00
|
|
|
function getarg() {
|
2019-03-13 08:50:53 -05:00
|
|
|
let arg = argv.shift();
|
2013-02-07 03:51:43 -06:00
|
|
|
|
|
|
|
if (arg.indexOf('--') === 0) {
|
|
|
|
// e.g. --opt
|
|
|
|
arg = arg.split('=');
|
|
|
|
if (arg.length > 1) {
|
|
|
|
// e.g. --opt=val
|
|
|
|
argv.unshift(arg.slice(1).join('='));
|
|
|
|
}
|
|
|
|
arg = arg[0];
|
|
|
|
} else if (arg[0] === '-') {
|
|
|
|
if (arg.length > 2) {
|
|
|
|
// e.g. -abc
|
2019-03-13 08:50:53 -05:00
|
|
|
argv = arg.substring(1).split('').map(ch => {
|
2019-03-13 10:39:01 -05:00
|
|
|
return `-${ch}`;
|
2013-02-07 03:51:43 -06:00
|
|
|
}).concat(argv);
|
|
|
|
arg = argv.shift();
|
|
|
|
} else {
|
|
|
|
// e.g. -a
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// e.g. foo
|
|
|
|
}
|
|
|
|
|
|
|
|
return arg;
|
2013-01-03 08:29:40 -06:00
|
|
|
}
|
|
|
|
|
2013-02-07 03:51:43 -06:00
|
|
|
while (argv.length) {
|
2019-03-13 08:50:53 -05:00
|
|
|
let arg = getarg();
|
2013-02-07 03:51:43 -06:00
|
|
|
switch (arg) {
|
2013-02-12 01:17:28 -06:00
|
|
|
case '-f':
|
|
|
|
case '--fix':
|
|
|
|
case 'fix':
|
2018-01-02 13:53:05 -06:00
|
|
|
if (options.fix !== false) {
|
|
|
|
options.fix = true;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case '--no-fix':
|
|
|
|
case 'no-fix':
|
|
|
|
options.fix = false;
|
2013-02-12 01:17:28 -06:00
|
|
|
break;
|
2013-02-07 03:51:43 -06:00
|
|
|
case '-b':
|
|
|
|
case '--bench':
|
|
|
|
options.bench = true;
|
|
|
|
break;
|
|
|
|
case '-s':
|
|
|
|
case '--stop':
|
|
|
|
options.stop = true;
|
|
|
|
break;
|
|
|
|
case '-t':
|
|
|
|
case '--time':
|
|
|
|
options.time = true;
|
|
|
|
break;
|
2018-02-09 01:18:57 +01:00
|
|
|
case '-m':
|
|
|
|
case '--minified':
|
|
|
|
options.minified = true;
|
|
|
|
break;
|
2018-01-07 11:54:28 -06:00
|
|
|
case '--glob':
|
|
|
|
arg = argv.shift();
|
|
|
|
options.glob = arg.replace(/^=/, '');
|
2018-01-07 11:25:24 -06:00
|
|
|
break;
|
2013-02-07 03:51:43 -06:00
|
|
|
default:
|
|
|
|
if (arg.indexOf('--') === 0) {
|
2019-03-13 08:50:53 -05:00
|
|
|
const opt = camelize(arg.replace(/^--(no-)?/, ''));
|
2013-02-07 03:51:43 -06:00
|
|
|
if (!marked.defaults.hasOwnProperty(opt)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
options.marked = options.marked || {};
|
|
|
|
if (arg.indexOf('--no-') === 0) {
|
|
|
|
options.marked[opt] = typeof marked.defaults[opt] !== 'boolean'
|
|
|
|
? null
|
|
|
|
: false;
|
|
|
|
} else {
|
|
|
|
options.marked[opt] = typeof marked.defaults[opt] !== 'boolean'
|
|
|
|
? argv.shift()
|
|
|
|
: true;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
orphans.push(arg);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2011-08-22 23:16:25 -05:00
|
|
|
}
|
2013-01-03 08:29:40 -06:00
|
|
|
|
2013-02-07 03:51:43 -06:00
|
|
|
return options;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Helpers
|
|
|
|
*/
|
|
|
|
|
|
|
|
function camelize(text) {
|
2019-03-13 08:50:53 -05:00
|
|
|
return text.replace(/(\w)-(\w)/g, (_, a, b) => a + b.toUpperCase());
|
2013-01-03 08:29:40 -06:00
|
|
|
}
|
|
|
|
|
2013-02-07 03:51:43 -06:00
|
|
|
/**
|
|
|
|
* Main
|
|
|
|
*/
|
|
|
|
|
|
|
|
function main(argv) {
|
2019-03-13 08:50:53 -05:00
|
|
|
const opt = parseArg(argv);
|
2013-02-07 03:51:43 -06:00
|
|
|
|
2018-01-02 13:53:05 -06:00
|
|
|
if (opt.fix !== false) {
|
|
|
|
fix();
|
|
|
|
}
|
|
|
|
|
2013-02-12 01:17:28 -06:00
|
|
|
if (opt.fix) {
|
2018-01-06 11:56:47 -06:00
|
|
|
// only run fix
|
2018-01-02 13:53:05 -06:00
|
|
|
return;
|
2013-02-12 01:17:28 -06:00
|
|
|
}
|
|
|
|
|
2013-02-07 03:51:43 -06:00
|
|
|
if (opt.bench) {
|
|
|
|
return runBench(opt);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (opt.time) {
|
|
|
|
return time(opt);
|
|
|
|
}
|
|
|
|
|
2018-02-09 01:18:57 +01:00
|
|
|
if (opt.minified) {
|
2019-03-13 08:50:53 -05:00
|
|
|
marked = require('../marked.min.js');
|
2018-02-09 01:18:57 +01:00
|
|
|
}
|
2013-08-04 07:12:52 -05:00
|
|
|
return runTests(opt);
|
2013-02-07 03:51:43 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Execute
|
|
|
|
*/
|
|
|
|
|
2013-01-03 08:29:40 -06:00
|
|
|
if (!module.parent) {
|
2013-02-07 03:51:43 -06:00
|
|
|
process.title = 'marked';
|
2019-03-11 15:33:58 -05:00
|
|
|
process.exit(main(process.argv.slice()) ? 0 : 1);
|
2011-08-22 23:16:25 -05:00
|
|
|
} else {
|
2013-02-07 03:51:43 -06:00
|
|
|
exports = main;
|
|
|
|
exports.main = main;
|
|
|
|
exports.runTests = runTests;
|
2018-02-13 20:01:53 +01:00
|
|
|
exports.testFile = testFile;
|
2013-02-07 03:51:43 -06:00
|
|
|
exports.runBench = runBench;
|
|
|
|
exports.load = load;
|
|
|
|
exports.bench = bench;
|
|
|
|
module.exports = exports;
|
2011-08-22 23:16:25 -05:00
|
|
|
}
|
2018-02-26 16:58:46 -05:00
|
|
|
|
|
|
|
// returns time to millisecond granularity
|
|
|
|
function prettyElapsedTime(hrtimeElapsed) {
|
2019-03-13 08:50:53 -05:00
|
|
|
const seconds = hrtimeElapsed[0];
|
|
|
|
const frac = Math.round(hrtimeElapsed[1] / 1e3) / 1e3;
|
2018-02-26 17:58:43 -06:00
|
|
|
return seconds * 1e3 + frac;
|
2018-02-26 16:58:46 -05:00
|
|
|
}
|