2011-08-22 22:34:20 -05:00
|
|
|
#!/usr/bin/env node
|
|
|
|
|
|
|
|
var fs = require('fs')
|
|
|
|
, path = require('path')
|
2011-08-22 23:40:55 -05:00
|
|
|
, marked = require('marked')
|
2011-08-22 22:34:20 -05:00
|
|
|
, dir = __dirname + '/tests';
|
|
|
|
|
2011-12-17 17:35:23 -06:00
|
|
|
var BREAK_ON_ERROR = false;
|
2011-08-22 22:34:20 -05:00
|
|
|
|
2011-08-22 23:16:25 -05:00
|
|
|
var files;
|
2011-08-22 22:34:20 -05:00
|
|
|
|
2011-08-22 23:16:25 -05:00
|
|
|
var load = function() {
|
|
|
|
files = {};
|
2011-08-22 22:34:20 -05:00
|
|
|
|
2011-08-22 23:16:25 -05:00
|
|
|
var list = fs
|
|
|
|
.readdirSync(dir)
|
|
|
|
.filter(function(file) {
|
|
|
|
return path.extname(file) !== '.html';
|
|
|
|
})
|
|
|
|
.sort(function(a, b) {
|
|
|
|
a = path.basename(a).toLowerCase().charCodeAt(0);
|
|
|
|
b = path.basename(b).toLowerCase().charCodeAt(0);
|
|
|
|
return a > b ? 1 : (a < b ? -1 : 0);
|
|
|
|
});
|
2011-08-22 22:34:20 -05:00
|
|
|
|
2011-08-22 23:16:25 -05:00
|
|
|
var i = 0
|
|
|
|
, l = list.length
|
|
|
|
, file;
|
|
|
|
|
|
|
|
for (; i < l; i++) {
|
|
|
|
file = path.join(dir, list[i]);
|
|
|
|
files[path.basename(file)] = {
|
|
|
|
text: fs.readFileSync(file, 'utf8'),
|
|
|
|
html: fs.readFileSync(file.replace(/[^.]+$/, 'html'), 'utf8')
|
|
|
|
};
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
var main = function() {
|
|
|
|
if (!files) load();
|
2011-08-22 22:34:20 -05:00
|
|
|
|
2011-08-22 23:16:25 -05:00
|
|
|
var complete = 0
|
|
|
|
, keys = Object.keys(files)
|
|
|
|
, i_ = 0
|
|
|
|
, l_ = keys.length
|
|
|
|
, filename
|
|
|
|
, file
|
|
|
|
, text
|
|
|
|
, html;
|
2011-08-22 22:34:20 -05:00
|
|
|
|
2011-10-22 08:36:34 -05:00
|
|
|
main:
|
2011-08-22 23:16:25 -05:00
|
|
|
for (; i_ < l_; i_++) {
|
|
|
|
filename = keys[i_];
|
|
|
|
file = files[filename];
|
|
|
|
|
2011-10-22 08:36:34 -05:00
|
|
|
try {
|
2011-08-22 23:40:55 -05:00
|
|
|
text = marked(file.text).replace(/\s/g, '');
|
2011-08-22 23:16:25 -05:00
|
|
|
html = file.html.replace(/\s/g, '');
|
2011-10-22 08:36:34 -05:00
|
|
|
} catch(e) {
|
|
|
|
console.log('%s failed.', filename);
|
|
|
|
throw e;
|
2011-08-22 22:34:20 -05:00
|
|
|
}
|
|
|
|
|
2011-08-22 23:16:25 -05:00
|
|
|
var i = 0
|
|
|
|
, l = html.length;
|
|
|
|
|
|
|
|
for (; i < l; i++) {
|
2011-08-22 22:34:20 -05:00
|
|
|
if (text[i] !== html[i]) {
|
|
|
|
text = text.substring(
|
2011-10-22 08:36:34 -05:00
|
|
|
Math.max(i - 30, 0),
|
2011-08-22 22:34:20 -05:00
|
|
|
Math.min(i + 30, text.length));
|
|
|
|
html = html.substring(
|
2011-10-22 08:36:34 -05:00
|
|
|
Math.max(i - 30, 0),
|
2011-08-22 22:34:20 -05:00
|
|
|
Math.min(i + 30, html.length));
|
|
|
|
console.log(
|
2011-10-22 08:36:34 -05:00
|
|
|
'\n#%d. %s failed at offset %d. Near: "%s".\n',
|
2011-08-22 23:16:25 -05:00
|
|
|
i_ + 1, filename, i, text);
|
2011-10-22 08:36:34 -05:00
|
|
|
console.log('\nGot:\n%s\n',
|
2011-08-22 22:34:20 -05:00
|
|
|
pretty(text).trim() || text);
|
2011-10-22 08:36:34 -05:00
|
|
|
console.log('\nExpected:\n%s\n',
|
2011-08-22 22:34:20 -05:00
|
|
|
pretty(html).trim() || html);
|
2011-12-17 17:35:23 -06:00
|
|
|
if (BREAK_ON_ERROR) {
|
2011-08-22 22:34:20 -05:00
|
|
|
break main;
|
|
|
|
} else {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (i === l) {
|
|
|
|
complete++;
|
2011-08-22 23:16:25 -05:00
|
|
|
console.log('#%d. %s completed.', i_ + 1, filename);
|
2011-08-22 22:34:20 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
console.log('%d/%d tests completed successfully.', complete, l_);
|
|
|
|
};
|
|
|
|
|
2011-08-22 23:16:25 -05:00
|
|
|
main.bench = function(name, func) {
|
2012-01-02 23:59:13 -06:00
|
|
|
if (!files) {
|
|
|
|
load();
|
|
|
|
Object.keys(files).forEach(function(name) {
|
|
|
|
if (name.indexOf('gfm') === 0) delete files[name];
|
|
|
|
});
|
|
|
|
}
|
2011-08-22 23:16:25 -05:00
|
|
|
|
|
|
|
var start = Date.now()
|
|
|
|
, times = 1000
|
|
|
|
, keys = Object.keys(files)
|
|
|
|
, i = 0
|
|
|
|
, l = keys.length
|
|
|
|
, filename
|
|
|
|
, file;
|
|
|
|
|
|
|
|
while (times--) {
|
|
|
|
for (i = 0; i < l; i++) {
|
|
|
|
filename = keys[i];
|
|
|
|
file = files[filename];
|
|
|
|
func(file.text);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
console.log('%s completed in %dms.', name, Date.now() - start);
|
|
|
|
};
|
|
|
|
|
|
|
|
var bench = function() {
|
|
|
|
var marked = require('../');
|
|
|
|
main.bench('marked', marked);
|
|
|
|
|
|
|
|
var showdown = (function() {
|
|
|
|
var Showdown = require('showdown').Showdown;
|
|
|
|
var convert = new Showdown.converter();
|
|
|
|
return function(text) {
|
|
|
|
return convert.makeHtml(text);
|
|
|
|
};
|
|
|
|
})();
|
2011-10-22 08:36:34 -05:00
|
|
|
main.bench('showdown (reuse converter)', showdown);
|
|
|
|
|
|
|
|
var showdown_slow = (function() {
|
|
|
|
var Showdown = require('showdown').Showdown;
|
|
|
|
return function(text) {
|
|
|
|
var convert = new Showdown.converter();
|
|
|
|
return convert.makeHtml(text);
|
|
|
|
};
|
|
|
|
})();
|
|
|
|
main.bench('showdown (new converter)', showdown_slow);
|
2011-08-22 23:16:25 -05:00
|
|
|
|
2011-12-10 15:21:01 -06:00
|
|
|
var markdownjs = require('markdown');
|
2011-08-22 23:16:25 -05:00
|
|
|
main.bench('markdown-js', function(text) {
|
2011-12-10 15:21:01 -06:00
|
|
|
markdownjs.parse(text);
|
2011-08-22 23:16:25 -05:00
|
|
|
});
|
|
|
|
};
|
2011-08-22 22:34:20 -05:00
|
|
|
|
2011-10-22 08:36:34 -05:00
|
|
|
var time = function() {
|
|
|
|
var marked = require('../');
|
|
|
|
main.bench('marked', marked);
|
|
|
|
};
|
|
|
|
|
2011-08-22 23:40:55 -05:00
|
|
|
var old_bench = function() {
|
|
|
|
var text = fs.readFileSync(__dirname + '/main.md', 'utf8');
|
|
|
|
|
|
|
|
var benchmark = function(func, t) {
|
|
|
|
var start = new Date()
|
|
|
|
, i = t || 10000;
|
|
|
|
while (i--) func();
|
|
|
|
console.log('%s: %sms', func.name, new Date() - start);
|
|
|
|
};
|
|
|
|
|
|
|
|
var marked_ = require('../');
|
|
|
|
benchmark(function marked() {
|
|
|
|
marked_(text);
|
|
|
|
});
|
|
|
|
|
|
|
|
var showdown_ = (function() {
|
|
|
|
var Showdown = require('showdown').Showdown;
|
|
|
|
var convert = new Showdown.converter();
|
|
|
|
return function(str) {
|
|
|
|
return convert.makeHtml(str);
|
|
|
|
};
|
|
|
|
})();
|
|
|
|
benchmark(function showdown() {
|
|
|
|
showdown_(text);
|
|
|
|
});
|
|
|
|
|
2011-12-10 15:21:01 -06:00
|
|
|
var markdownjs_ = require('markdown');
|
2011-08-22 23:40:55 -05:00
|
|
|
benchmark(function markdownjs() {
|
2011-12-10 15:21:01 -06:00
|
|
|
markdownjs_.parse(text);
|
2011-08-22 23:40:55 -05:00
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
var old_test = function() {
|
|
|
|
var assert = require('assert')
|
|
|
|
, text = fs.readFileSync(__dirname + '/main.md', 'utf8');
|
|
|
|
|
|
|
|
var a = markdown(text)
|
|
|
|
, b = fs.readFileSync(__dirname + '/main.html', 'utf8');
|
|
|
|
|
|
|
|
console.log(a);
|
|
|
|
console.log('--------------------------------------------------------------');
|
|
|
|
console.log(b);
|
|
|
|
console.log('--------------------------------------------------------------');
|
|
|
|
|
|
|
|
a = a.replace(/\s+/g, '');
|
|
|
|
b = b.replace(/\s+/g, '');
|
|
|
|
|
|
|
|
assert.ok(a === b, 'Failed.');
|
|
|
|
console.log('Complete.');
|
|
|
|
};
|
|
|
|
|
2011-07-24 08:15:35 -05:00
|
|
|
/**
|
2011-08-22 22:34:20 -05:00
|
|
|
* Pretty print HTML
|
|
|
|
* Copyright (c) 2011, Christopher Jeffrey
|
2011-07-24 08:15:35 -05:00
|
|
|
*/
|
|
|
|
|
2011-08-22 22:34:20 -05:00
|
|
|
var pretty = (function() {
|
|
|
|
var indent = function(num) {
|
|
|
|
return Array((num >= 0 ? num : 0) + 1).join(' ');
|
|
|
|
};
|
|
|
|
|
|
|
|
var closing = {
|
|
|
|
base: true,
|
|
|
|
link: true,
|
|
|
|
meta: true,
|
|
|
|
hr: true,
|
|
|
|
br: true,
|
|
|
|
wbr: true,
|
|
|
|
img: true,
|
|
|
|
embed: true,
|
|
|
|
param: true,
|
|
|
|
source: true,
|
|
|
|
track: true,
|
|
|
|
area: true,
|
|
|
|
col: true,
|
|
|
|
input: true,
|
|
|
|
keygen: true,
|
|
|
|
command: true
|
|
|
|
};
|
|
|
|
|
|
|
|
var remove = /<(pre|textarea|title|p|li|a)(?:\s[^>]+)?>[\s\S]+?<\/\1>/g
|
|
|
|
, replace = /<!(\d+)%*\/>/g
|
|
|
|
, wrap = /([ \t]*)<p>([\s\S]+?)<\/p>/g;
|
|
|
|
|
|
|
|
return function(str) {
|
|
|
|
var hash = []
|
|
|
|
, out = []
|
|
|
|
, cap
|
|
|
|
, depth = 0
|
|
|
|
, text
|
|
|
|
, full
|
|
|
|
, tag
|
|
|
|
, name;
|
|
|
|
|
2011-10-22 08:36:34 -05:00
|
|
|
// temporarily remove elements before
|
2011-08-22 22:34:20 -05:00
|
|
|
// processing, also remove whitespace
|
|
|
|
str = str.replace(remove, function(element, name) {
|
|
|
|
element = element
|
|
|
|
.replace(/(<[^\/][^>]*>)\s+|\s+(<\/)/g, '$1$2')
|
|
|
|
.replace(/[\r\n]/g, '');
|
2011-10-22 08:36:34 -05:00
|
|
|
return '<!' + (hash.push(element) - 1)
|
2011-08-22 22:34:20 -05:00
|
|
|
+ (Array(element.length - 3).join('%')) + '/>';
|
|
|
|
});
|
|
|
|
|
|
|
|
// indent elements
|
|
|
|
str = str
|
|
|
|
.replace(/(>)\s+|\s+(<)/g, '$1$2')
|
|
|
|
.replace(/[\r\n]/g, '');
|
|
|
|
|
|
|
|
while (cap = /^([\s\S]*?)(<([^>]+)>)/.exec(str)) {
|
|
|
|
str = str.substring(cap[0].length);
|
|
|
|
text = cap[1];
|
|
|
|
full = cap[2];
|
|
|
|
tag = cap[3];
|
|
|
|
name = tag.split(' ')[0];
|
|
|
|
|
|
|
|
if (text) {
|
|
|
|
out.push(indent(depth) + text);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (name[0] !== '/') {
|
|
|
|
out.push(indent(depth) + full);
|
2011-10-22 08:36:34 -05:00
|
|
|
if (!closing[name]
|
|
|
|
&& name[0] !== '!'
|
|
|
|
&& name[0] !== '?'
|
2011-08-22 22:34:20 -05:00
|
|
|
&& tag[tag.length-1] !== '/') {
|
|
|
|
depth++;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
depth--;
|
|
|
|
out.push(indent(depth) + full);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
str = out.join('\n');
|
|
|
|
|
2011-10-22 08:36:34 -05:00
|
|
|
// restore the elements to
|
2011-08-22 22:34:20 -05:00
|
|
|
// their original locations
|
|
|
|
str = str.replace(replace, function($0, $1) {
|
|
|
|
return hash[$1];
|
|
|
|
});
|
2011-07-24 08:15:35 -05:00
|
|
|
|
2011-08-22 22:34:20 -05:00
|
|
|
// wrap paragraphs
|
|
|
|
str = str.replace(wrap, function($0, $1, $2) {
|
|
|
|
var indent = $1 + ' '
|
|
|
|
, text = indent + $2;
|
2011-07-24 08:15:35 -05:00
|
|
|
|
2011-08-22 22:34:20 -05:00
|
|
|
text = text
|
|
|
|
.replace(/[\t\r\n]+/g, '')
|
|
|
|
.replace(/(<\/[^>]+>|\/>)(?=\s*<\w)/g, '$1\n' + indent)
|
|
|
|
.replace(/(.{75,}?\s+(?![^<]+>))/g, '$1\n' + indent)
|
|
|
|
.replace(/([^<>\n]{50,}?)(<[^<]{15,}>)/g, '$1\n' + indent + '$2');
|
2011-07-24 08:15:35 -05:00
|
|
|
|
2011-08-22 22:34:20 -05:00
|
|
|
return $1 + '<p>\n' + text + '\n' + $1 + '</p>';
|
|
|
|
});
|
2011-07-24 08:15:35 -05:00
|
|
|
|
2011-08-22 22:34:20 -05:00
|
|
|
return str;
|
|
|
|
};
|
|
|
|
})();
|
2011-08-22 23:16:25 -05:00
|
|
|
|
|
|
|
if (!module.parent) {
|
|
|
|
if (~process.argv.indexOf('--bench')) {
|
|
|
|
bench();
|
2011-10-22 08:36:34 -05:00
|
|
|
} else if (~process.argv.indexOf('--time')) {
|
|
|
|
time();
|
2011-08-22 23:40:55 -05:00
|
|
|
} else if (~process.argv.indexOf('--old_bench')) {
|
|
|
|
old_bench();
|
|
|
|
} else if (~process.argv.indexOf('--old_test')) {
|
|
|
|
old_test();
|
2011-08-22 23:16:25 -05:00
|
|
|
} else {
|
|
|
|
main();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
module.exports = main;
|
|
|
|
}
|