Socket
Socket
Sign inDemoInstall

marked

Package Overview
Dependencies
Maintainers
1
Versions
178
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

marked - npm Package Compare versions

Comparing version 0.0.5 to 0.0.6

test/fix

136

lib/marked.js

@@ -14,9 +14,9 @@ /**

newline: /^\n+/,
block: /^ {4,}[^\n]*(?:\n {4,}[^\n]*)*/,
block: /^ {4,}[^\n]*(?:\n {4,}[^\n]*|\n)*(?=\n| *$)/,
hr: /^( *[\-*_]){3,} *\n/,
heading: /^ *(#{1,6}) *([^\n#]*) *#*/,
lheading: /^([^\n]+)\n *(=|-){3,}/,
hr: /^( ?[\-*_]){3,}/,
blockquote: /^ *>[^\n]*(?:\n *>[^\n]*)*/,
list: /^(?:( *)(\*|\+|-|\d+\.)[^\n]+(?:\n(?:\1 )+[^\n]+)*(?:\n+|$)){2,}/g,
html: /^<([^\/\s>]+)[^\n>]*>[^\n]*(?:\n[^\n]+)*\n?<\/\1>/,
list: /^( *)([*+-]|\d+\.) [^\0]+?(?:\n{2,}(?! )|\s*$)(?!\1\2|\1\d+\.)/,
html: /^(?:<!--[^\0]*?-->|<(\w+)[^\0]+?<\/\1>|<[^<>\n]+>) *(?:\n{2,}|\s*$)/,
text: /^[^\n]+/

@@ -50,9 +50,6 @@ };

// experimental
//str = str.replace(/(^|\n) +(\n|$)/g, '$1$2');
// grab link definitons
str = str.replace(
/^ {0,3}\[([^\]]+)\]: *([^ ]+)(?: +"([^"]+)")? *(?:\n|$)/gm,
function(_, id, href, title) {
/^ {0,3}\[([^\]]+)\]: *([^ ]+)(?: +"([^\n]+)")? *$/gm,
function(__, id, href, title) {
links[id] = {

@@ -72,2 +69,4 @@ href: href,

block.token = function(str, tokens) {
str = str.replace(/^ +$/gm, '');
var rules = block

@@ -77,3 +76,4 @@ , keys = block.keys

, key
, cap;
, cap
, loose;

@@ -131,11 +131,11 @@ var scan = function() {

});
// get each top-level
// item in the list
loose = /\n *\n *(?:[*+-]|\d+\.)/.test(cap[0]);
// get each top-level item
cap = cap[0].match(
/^( *)(\*|\+|-|\d+\.)[^\n]+(?:\n(?:\1 )+[^\n]+)*/gm
);
/^( *)([*+-]|\d+\.)[^\n]*(?:\n(?!\1(?:\2|\d+\.))[^\n]*)*/gm
);
each(cap, function(item) {
// remove the list items sigil
// so its seen as the next token
item = item.replace(/^ *(\*|\+|-|\d+\.) */, '');
item = item.replace(/^ *([*+-]|\d+\.) */, '');
// outdent whatever the

@@ -149,3 +149,5 @@ // list item contains, hacky

tokens.push({
type: 'list_item_start'
type: loose
? 'loose_item_start'
: 'list_item_start'
});

@@ -189,10 +191,12 @@ block.token(item, tokens);

var inline = {
escape: /^\\([\\`*{}\[\]()#+\-.!])/,
escape: /^\\([\\`*{}\[\]()#+\-.!_])/,
autolink: /^<([^ >]+(@|:\/)[^ >]+)>/,
tag: /^<[^\n>]+>/,
link: /^!?\[([^\]]+)\]\(([^\)]+)\)/,
reflink: /^!?\[([^\]]+)\]\[([^\]]+)\]/,
strong: /^__([\s\S]+?)__|^\*\*([\s\S]+?)\*\*/,
tag: /^<!--[^\0]*?-->|^<[^\n>]+>/,
link: /^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]\s*\(([^\)]*)\)/,
reflink: /^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]\s*\[([^\]]*)\]/,
nolink: /^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/,
strong: /^__([^\0]+?)__(?!_)|^\*\*([^\0]+?)\*\*(?!\*)/,
em: /^_([^_]+)_|^\*([^*]+)\*/,
code: /^`([^`]+)`|^``([\s\S]+?)``/
code: /^`([^`]+)`|^``([^\0]+?)``/,
text: /^/
};

@@ -206,28 +210,29 @@

'reflink',
'nolink',
'strong',
'em',
'code'
'code',
'text'
];
// hacky, but performant
inline.text = (function(rules) {
var keys = rules.keys
, i = 0
, l = keys.length
, body = [];
inline.text = (function() {
var body = [];
for (; i < l; i++) {
body.push(rules[keys[i]].source
.replace(/(^|[^\[])\^/g, '$1'));
}
(function push(rule) {
rule = inline[rule].source;
body.push(rule.replace(/(^|[^\[])\^/g, '$1'));
return push;
})
('escape')
('tag')
('nolink')
('strong')
('em')
('code');
keys.push('text');
return new
RegExp('^[^\\0]+?(?=' + body.join('|') + '|$)');
})();
return new RegExp(
'^([\\s\\S]+?)(?='
+ body.join('|')
+ '|$)'
);
})(inline);
/**

@@ -271,13 +276,19 @@ * Inline Lexer

case 'reflink':
case 'nolink':
if (key !== 'link') {
link = (cap[2] || cap[1]).replace(/\s+/g, ' ');
link = links[link];
if (!link) {
out += cap[0][0];
str = cap[0].substring(1) + str;
break;
}
} else {
text = /^\s*<?([^\s]*?)>?(?:\s+"([^\n]+)")?\s*$/.exec(cap[2]);
link = {
href: text[1],
title: text[2]
};
}
if (cap[0][0] !== '!') {
if (key === 'reflink') {
link = links[cap[2]];
if (!link) throw new
Error('Undefined Reference: ' + cap[2]);
} else {
link = {
href: cap[2],
title: cap[3]
};
}
out += '<a href="'

@@ -295,13 +306,2 @@ + escape(link.href)

} else {
if (key === 'reflink') {
link = links[cap[2]];
if (!link) throw new
Error('Undefined Reference: ' + cap[2]);
} else {
text = /^([^\s]+)\s*(.+)?$/.exec(cap[2]);
link = {
href: text[1],
title: text[2]
};
}
out += '<img src="'

@@ -348,3 +348,3 @@ + escape(link.href)

case 'text':
out += escape(cap[1]);
out += escape(cap[0]);
break;

@@ -404,5 +404,3 @@ default:

while (next().type !== 'list_item_end') {
// TODO incorporate paragraph
// list items here
body.push(token.type === 'text'
body.push(token.type === 'text'
? inline.lexer(token.text)

@@ -414,2 +412,10 @@ : tok());

+ '</li>';
case 'loose_item_start':
var body = [];
while (next().type !== 'list_item_end') {
body.push(tok());
}
return '<li>'
+ body.join(' ')
+ '</li>';
case 'html':

@@ -416,0 +422,0 @@ return inline.lexer(token.text);

@@ -5,3 +5,3 @@ {

"author": "Christopher Jeffrey",
"version": "0.0.5",
"version": "0.0.6",
"main": "./lib/marked.js",

@@ -8,0 +8,0 @@ "bin": { "marked": "./bin/marked" },

@@ -9,3 +9,3 @@ # marked

``` bash
$ node test/bench
$ node test --old_bench
marked: 6260ms

@@ -16,2 +16,4 @@ showdown: 21665ms

(Above is the old benchmark, try `node test --bench` for the new ones.)
The point of marked was to create a markdown compiler where it was possible to

@@ -24,2 +26,6 @@ frequently parse huge chunks of markdown without having to worry about

marked more or less passes the official markdown test suite in its
entirety. This is important because a surprising number of markdown compilers
cannot pass more than a few tests.
## Install

@@ -47,5 +53,2 @@

This parser was written in one night, so there's still a lot on the todo list.
There may also be some bugs.
- Implement GFM features.

@@ -58,10 +61,2 @@ - Possibly add some

be possible.
- Find a better way of testing. Create a test suite from scratch because most
markdown compilers don't appear to be working properly in every aspect (but
it's hard to tell because the markdown "spec" is so vague).
- Recognize and parse paragraph list items better. This may be the most
important task. Currently, list items are parsed strictly, it's not possible
to have "loose list items" as they're known.
- Add an explicit pretty printing and minification feature.
I've still just begun to write this. I expect I will be updating it frequently.

@@ -0,22 +1,324 @@

#!/usr/bin/env node
var fs = require('fs')
, path = require('path')
, marked = require('marked')
, dir = __dirname + '/tests';
var breakOnError = true;
var files;
var load = function() {
files = {};
var list = fs
.readdirSync(dir)
//.concat('/../main.md')
.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);
});
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();
var complete = 0
, keys = Object.keys(files)
, i_ = 0
, l_ = keys.length
, filename
, file
, text
, html;
main:
for (; i_ < l_; i_++) {
filename = keys[i_];
file = files[filename];
// this was messing with
// `node test | less` on sakura
try {
text = marked(file.text).replace(/\s/g, '');
html = file.html.replace(/\s/g, '');
} catch(e) {
console.log('%s failed.', filename);
throw e;
}
var i = 0
, l = html.length;
for (; i < l; i++) {
if (text[i] !== html[i]) {
text = text.substring(
Math.max(i - 30, 0),
Math.min(i + 30, text.length));
html = html.substring(
Math.max(i - 30, 0),
Math.min(i + 30, html.length));
console.log(
'\n#%d. %s failed at offset %d. Near: "%s".\n',
i_ + 1, filename, i, text);
console.log('\nGot:\n%s\n',
pretty(text).trim() || text);
console.log('\nExpected:\n%s\n',
pretty(html).trim() || html);
if (breakOnError) {
break main;
} else {
break;
}
}
}
if (i === l) {
complete++;
console.log('#%d. %s completed.', i_ + 1, filename);
}
}
console.log('%d/%d tests completed successfully.', complete, l_);
};
main.bench = function(name, func) {
if (!files) load();
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);
/**
* There's two ways to benchmark showdown here.
* The first way is to create a new converter
* every time, this will renew any closured
* variables. It is the "proper" way of using
* showdown. However, for this benchmark,
* I will use the completely improper method
* which is must faster, just to be fair.
*/
var showdown = (function() {
var Showdown = require('showdown').Showdown;
var convert = new Showdown.converter();
return function(text) {
return convert.makeHtml(text);
};
})();
main.bench('showdown', showdown);
var markdownjs = require('markdown-js');
main.bench('markdown-js', function(text) {
markdownjs.toHTML(text);
});
};
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);
});
var markdownjs_ = require('markdown-js');
benchmark(function markdownjs() {
markdownjs_.toHTML(text);
});
};
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.');
};
/**
* Test
* Pretty print HTML
* Copyright (c) 2011, Christopher Jeffrey
*/
var marked = require('../')
, assert = require('assert')
, fs = require('fs')
, text = fs.readFileSync(__dirname + '/in.md', 'utf8');
var pretty = (function() {
var indent = function(num) {
return Array((num >= 0 ? num : 0) + 1).join(' ');
};
var a = marked(text)
, b = fs.readFileSync(__dirname + '/out.html', 'utf8');
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
};
console.log(a);
console.log('----------------------------------------------------------------');
console.log(b);
console.log('----------------------------------------------------------------');
var remove = /<(pre|textarea|title|p|li|a)(?:\s[^>]+)?>[\s\S]+?<\/\1>/g
, replace = /<!(\d+)%*\/>/g
, wrap = /([ \t]*)<p>([\s\S]+?)<\/p>/g;
a = a.replace(/\s+/g, '');
b = b.replace(/\s+/g, '');
return function(str) {
var hash = []
, out = []
, cap
, depth = 0
, text
, full
, tag
, name;
assert.ok(a === b, 'Failed.');
console.log('Complete.');
// temporarily remove elements before
// processing, also remove whitespace
str = str.replace(remove, function(element, name) {
element = element
.replace(/(<[^\/][^>]*>)\s+|\s+(<\/)/g, '$1$2')
.replace(/[\r\n]/g, '');
return '<!' + (hash.push(element) - 1)
+ (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);
if (!closing[name]
&& name[0] !== '!'
&& name[0] !== '?'
&& tag[tag.length-1] !== '/') {
depth++;
}
} else {
depth--;
out.push(indent(depth) + full);
}
}
str = out.join('\n');
// restore the elements to
// their original locations
str = str.replace(replace, function($0, $1) {
return hash[$1];
});
// wrap paragraphs
str = str.replace(wrap, function($0, $1, $2) {
var indent = $1 + ' '
, text = indent + $2;
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');
return $1 + '<p>\n' + text + '\n' + $1 + '</p>';
});
return str;
};
})();
if (!module.parent) {
if (~process.argv.indexOf('--bench')) {
bench();
} else if (~process.argv.indexOf('--old_bench')) {
old_bench();
} else if (~process.argv.indexOf('--old_test')) {
old_test();
} else {
main();
}
} else {
module.exports = main;
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc