Socket
Socket
Sign inDemoInstall

namp

Package Overview
Dependencies
1
Maintainers
1
Versions
33
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 0.1.4 to 0.1.6

Changes.markdown

51

bin/namp.js

@@ -7,24 +7,47 @@ #!/usr/bin/env node

, markdown = require('markdown').markdown
, fullpath = process.argv[2]
, nopt = require("nopt")
, stream
, opts
, buffer = ""
;
function convert(err, data) {
var md
, html
;
if (err) {
throw err;
opts = nopt(
{ "dialect": [ "Gruber", "Maruku"]
, "help": Boolean
}
);
md = data.toString('utf8');
html = markdown.toHTML(md);
if (opts.help) {
var name = process.argv[1].split('/').pop()
console.warn( require('util').format(
'usage: %s [--dialect=DIALECT] FILE\n\nValid dialects are Gruber (the default) or Maruku',
name
) );
process.exit(0);
}
if (!fullpath) {
console.error('try: ', process.argv[1].split('/').pop(), '/path/to/doc.md');
return;
var fullpath = opts.argv.remain[0];
if (fullpath && fullpath !== "-") {
stream = fs.createReadStream(fullpath);
} else {
stream = process.stdin;
}
stream.resume();
stream.setEncoding('utf8');
fs.readFile(fullpath, convert);
stream.on('error', function(error) {
console.error(error.toString());
process.exit(1);
});
stream.on('data', function(data) {
buffer += data;
});
stream.on('end', function() {
var html = markdown.toHTML(buffer, opts.dialect);
console.log(html);
});
}())

@@ -5,3 +5,3 @@ var fs = require('fs');

if (!err) {
var output = require("../lib/index").toHTML(data, {highlight: true } );
var output = require("../lib/index").toHTML(data, {highlight: true, smartyPants: true } );
fs.writeFileSync("SYNTAX.html", output.html);

@@ -8,0 +8,0 @@

@@ -7,3 +7,3 @@ Author: A noble spirit

Here's a list of current syntax options. Notations are provided for PHP Extras syntax, Maruku syntax, GFM, and NAMP dialects.
Here's a list of current syntax options. Notations are provided for PHP Extras syntax, Maruku syntax, GFM, and NAMP dialects. For most of these, you'll want to also check out the HTML source to see what's going on.

@@ -31,8 +31,8 @@ * * *

Inline (titles are optional):
![alt text](/path/img.jpg "Obviously, no image")
![alt text](http://gfhiryuu.tripod.com/random/green_dragon_sprite.gif "Random image")
Reference-style:
![alt text][id]
![alt text][id2]
[id]: /url/to/img.jpg "Obviously, no image"
[id2]: http://upload.wikimedia.org/wikipedia/en/math/b/8/b/b8b4326ebb88870f8cc97ab3f59a0867.png "Still, a random image"

@@ -60,5 +60,19 @@ ## HEADERS

1. Foo
2. Bar
1. Eggs
2. Milk
4. Cheese
3. Anything
Ordered, with paragraphs:
1. Eggs
Preferrably brown
2. Milk
Wait, I am lactose intolerant
5. Cheese
2. Wait, Cheese?
Unordered, with paragraphs:

@@ -79,3 +93,3 @@

2. Gorilla snack
* (or monkeys)
* (or, for monkeys)
3. Yellow

@@ -89,9 +103,9 @@ * Camel

> > And, they can be nested.
> > And, they can be nested.
> #### Headers in blockquotes
>
> * You can quote a list.
> * Etc.
> * Like this.
> 1. And nest one.

@@ -117,3 +131,3 @@

Code tags can also be "fenced" by ` ``` ` (GitHub-Flavored-Markdown)
Code blocks can also be "fenced" by ` ``` ` (GitHub-Flavored-Markdown)

@@ -132,5 +146,5 @@ ```

(Highlighting is enabled by default; you'll have to define your own CSS.)
(Highlighting is enabled by default; you'll have to define your own CSS that matches the highlight-js notation, though, which this document does not do!)
## Strikethrough
## STRIKETHROUGH

@@ -159,2 +173,13 @@ Hey, this is ~~terrible~~ great!

## PUNCTUATION
"check it out"
"
\"
`"should not curl"`
*"Wow"*
## TABLES (PHP Extras)

@@ -164,3 +189,3 @@ -----------------

|a |b |c
|--|--|--
|:---|---|---
|1 |2 |3

@@ -171,6 +196,6 @@

|:--|:--:|:--
|1 |2 |3
|1 |2 (or _two_) |[3]{: .threeClass}
|4 |5 | 6
{: #demo test="true"}
or

@@ -180,37 +205,47 @@ x |y |z

8 |9 |10
{: .table .table-striped .table-bordered .table-condensed}
alignment
Demonstrating alignment:
right|left | center
-----:|:-----|:------:
0001 | 2 | 003
0001 | 2 (or _two_) | 003
4 | 0005 | 6
## DEFINITION LISTS (PHP Extras)
(sadly, broken)
-----------------
Apple
: Pomaceous fruit of plants of the genus Malus in
the family Rosaceae.
: Pomaceous fruit of plants of the genus Malus in the family Rosaceae.
* List in dl
* Another **item**
* Wait, one more !
{: .listStyle}
: Okay, back to another dd.
Orange
: The fruit of an evergreen tree of the genus Citrus.
```python
print "Testing yet again"
```
It's extremly hard to come up with make believe text.
Pomegranate
: A deciduous shrub or small tree (Punica granatum),
native to Asia and _widely cultivated_ for its edible fruit. Anyway,
Blah blah blah.adsadsasd
: A deciduous shrub or small tree (Punica granatum), native to Asia and _widely cultivated_ for its edible fruit.
Anyway, Blah blah blah.adsadsasd.
Term 1
: This is a definition with two paragraphs. Lorem ipsum
dolor sit amet, consectetuer adipiscing elit. Aliquam
hendrerit mi posuere lectus.
: This is a definition with two paragraphs.
Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
Aliquam hendrerit mi posuere lectus.
: Second definition for term 1, also wrapped in a paragraph
because of the blank line preceding it.
because of the blank line preceding it. {: .test}
{: #TestingIDHere}
## ATTRIBUTES (Maruku) {: #myid .myclass}
## ATTRIBUTES (Maruku)
{: #myid .myclass}
-----------------

@@ -221,3 +256,2 @@

attributes!
{: #bigBlock tutorial=yes}

@@ -236,5 +270,5 @@

&amp; < "aaa"
&amp; < "aaa" &
## Boostrap tags
## Twitter Bootstrap tags

@@ -250,6 +284,7 @@ Note: This should be wrapped in a div that looks like this: `<div class='alert alert-success'>`.

## INLINE HTML
(sadly, broken)
-----------------
<p>
HTML is represented as is.<br>
HTML _should_ be represented as is.<br>
<del>The <strong>quick brown fox</strong> jumps over the lazy dog.</del>

@@ -259,3 +294,3 @@ </p>

<div>
Regularly Markdown syntax ignored in HTML.<br/>
Regularly Markdown syntax ignored in HTML.
[Google](http://www.google.co.jp/)

@@ -262,0 +297,0 @@ </div>

@@ -12,2 +12,3 @@ // Released under MIT license

var highlightEnabled = true; // always highlight by default
var smartyPantsEnabled = false; // support Smarty Pants translations
var documentMetaExists = false; // whether or not there's a document meta block

@@ -65,3 +66,3 @@

this.debug_indent = "";
}
};

@@ -87,3 +88,3 @@ /**

return md.toTree( source );
}
};

@@ -109,2 +110,4 @@ /**

highlightEnabled = false;
if (options.smartyPants === true)
smartyPantsEnabled = true;
}

@@ -150,4 +153,28 @@

return html;
};
// For Spidermonkey based engines
function mk_block_toSource() {
return "Markdown.mk_block( " +
uneval(this.toString()) +
", " +
uneval(this.trailing) +
", " +
uneval(this.lineNumber) +
" )";
}
// node
function mk_block_inspect() {
var util = require('util');
return "Markdown.mk_block( " +
util.inspect(this.toString()) +
", " +
util.inspect(this.trailing) +
", " +
util.inspect(this.lineNumber) +
" )";
}
var mk_block = Markdown.mk_block = function(block, trail, line) {

@@ -160,11 +187,4 @@ // Be helpful for default case in tests.

// To make it clear its not just a string
s.toSource = function() {
return "Markdown.mk_block( " +
uneval(block) +
", " +
uneval(trail) +
", " +
uneval(line) +
" )"
}
s.inspect = mk_block_inspect;
s.toSource = mk_block_toSource;

@@ -175,2 +195,8 @@ if (line != undefined)

return s;
};
function count_lines( str ) {
var n = 0, i = -1;
while ( ( i = str.indexOf('\n', i+1) ) !== -1) n++;
return n;
}

@@ -193,3 +219,3 @@

while ( ( m = re.exec(input) ) != null ) {
while ( ( m = re.exec(input) ) !== null ) {
blocks.push( mk_block( m[1], m[2], line_no ) );

@@ -200,3 +226,3 @@ line_no += helpers.count_lines( m[0] );

return blocks;
}
};

@@ -246,3 +272,3 @@ /**

return [];
}
};

@@ -253,3 +279,3 @@ Markdown.prototype.processInline = function processInline( block ) {

return this.dialect.inline.__call__.call( this, String( block ) );
}
};

@@ -264,5 +290,3 @@ /**

Markdown.prototype.toTree = function toTree( source, custom_root ) {
var blocks = source instanceof Array
? source
: this.split_blocks( source );
var blocks = source instanceof Array ? source : this.split_blocks( source );

@@ -286,7 +310,7 @@ // Make tree a member variable so its easier to mess with in extensions

finally {
if ( custom_root )
if ( custom_root ) {
this.tree = old_tree;
}
}
};

@@ -313,53 +337,11 @@ // Noop by default

return b;
}
};
Markdown.prototype.link = function( text ) {
// [link text](/path/to/img.jpg "Optional title")
// 1 2 3 4 <--- captures
var m = text.match( /^\[([\s\S]*?)\][ \t]*\([ \t]*(\S+)(?:[ \t]+(["'])(.*?)\3)?[ \t]*\)/ );
/**
* Markdown.dialects
*
* Namespace of built-in dialects.
**/
Markdown.dialects = {};
if ( m ) {
if ( m[2] && m[2][0] == '<' && m[2][m[2].length-1] == '>' )
m[2] = m[2].substring( 1, m[2].length - 1 );
// Process escapes only
m[2] = Markdown.dialects.Gruber.inline.__call__.call( this, m[2], /\\/ )[0];
var attrs = { href: m[2] || "" };
if ( m[4] !== undefined)
attrs.title = m[4];
var link = [ "link", attrs ];
Array.prototype.push.apply( link, Markdown.prototype.processInline( m[1] ) );
return [ m[0].length, link ];
}
// [Alt text][id]
// [Alt text] [id]
// [id]
m = text.match( /^\[[^~*_`]([\s\S]*?)\](?: ?\[(.*?)\])?/ );
if ( m ) {
// [id] case, text == id
if ( m[2] === undefined || m[2] === "" ) m[2] = m[1];
attrs = { ref: m[ 2 ].toLowerCase(), original: m[ 0 ] };
link = [ "link_ref", attrs ];
Array.prototype.push.apply( link, Markdown.prototype.processInline( m[1] ) );
// We can't check if the reference is known here as it likely wont be
// found till after. Check it in md tree->html tree conversion.
// Store the original so that conversion can revert if the ref isn't found.
return [
m[ 0 ].length,
link
];
}
// Just consume the '['
return [ 1, "[" ];
}
/**

@@ -375,7 +357,2 @@ * Markdown.dialects.Gruber

block: {
htmlBlock: function htmlBlock( block, next ) {
if ( block.match( /^\s*<\w/ ) && block.match( /<\/\s*\w+\s*>\s*$/ ) )
return [["__RAW", block.toString()]];
},
atxHeader: function atxHeader( block, next ) {

@@ -421,6 +398,4 @@ var m = block.match( /^(#{1,6})\s*(.*?)\s*#*\s*(?:\n|$)/ );

// 4 spaces + content
var m = block.match( re );
if ( !block.match( re ) ) return undefined;
if ( !m ) return undefined;
block_search:

@@ -430,3 +405,3 @@ do {

var b = this.loop_re_over_block(
re, block.valueOf(), function( m ) { ret.push( m[1] ) } );
re, block.valueOf(), function( m ) { ret.push( m[1] ); } );

@@ -440,6 +415,4 @@ if (b.length) {

// Check the next block - it might be code too
var m = next[0].match( re );
if ( !next[0].match( re ) ) break block_search;
if ( !m ) break block_search;
// Pull how how many blanks lines follow - minus two to account for .join

@@ -450,4 +423,5 @@ ret.push ( block.trailing.replace(/[^\n]/g, '').substring(2) );

}
else
else {
break block_search;
}
} while (true);

@@ -500,3 +474,3 @@

// Use a closure to hide a few variables.
var any_list = "[*+-]|\\d\\.",
var any_list = "[*+-]|\\d+\\.",
bullet_list = /[*+-]/,

@@ -541,4 +515,3 @@ number_list = /\d+\./,

is_str = typeof what == "string";
if (is_str && add_to.length > 1 && typeof add_to[add_to.length-1] == "string" )
{
if (is_str && add_to.length > 1 && typeof add_to[add_to.length-1] == "string" ) {
add_to[ add_to.length-1 ] += what;

@@ -611,3 +584,4 @@ }

loose = false,
ret = [ stack[0].list ];
ret = [ stack[0].list ],
i;

@@ -628,3 +602,3 @@ // Loop to search over block looking for inner block elements and loose lists

var nl = "",
l = lines[line_no].replace(/^\n/, function(n) { nl = n; return "" });
l = lines[line_no].replace(/^\n/, function(n) { nl = n; return ""; });

@@ -662,9 +636,10 @@ // TODO: really should cache this

// wanted_depth deserves.
var found = stack.some(function(s, i) {
if ( s.indent != m[1] ) return false;
list = s.list; // Found the level we want
stack.splice(i+1); // Remove the others
//print("found");
return true; // And stop looping
});
var found = false;
for (i = 0; i < stack.length; i++) {
if ( stack[ i ].indent != m[1] ) continue;
list = stack[ i ].list;
stack.splice( i+1 );
found = true;
break;
}

@@ -714,3 +689,3 @@ if (!found) {

// Make sure all listitems up the stack are paragraphs
stack.forEach( paragraphify, this );
forEach( stack, paragraphify, this);

@@ -734,3 +709,3 @@ last_li.push.apply( last_li, this.toTree( contained, [] ) );

// Make sure all listitems up the stack are paragraphs
stack.forEach( paragraphify , this );
forEach( stack, paragraphify, this);

@@ -744,3 +719,3 @@ loose = true;

return ret;
}
};
})(),

@@ -772,3 +747,3 @@

var b = next.shift();
block += block.trailing + b;
block = new String(block + block.trailing + b);
block.trailing = b.trailing;

@@ -831,28 +806,24 @@ }

}
}
};
Markdown.dialects.Gruber.inline = {
__call__: function inline( text, patterns ) {
// Hmmm - should this function be directly in Md#processInline, or
// conversely, should Md#processBlock be moved into block.__call__ too
var out = [ ],
m,
// Look for the next occurange of a special character/pattern
re = new RegExp( "([\\s\\S]*?)(" + (patterns.source || patterns) + ")", "g" ),
__oneElement__: function oneElement( text, patterns_or_re, previous_nodes ) {
var m,
res,
lastIndex = 0;
//D:var self = this;
//D:self.debug("processInline:", uneval(text) );
function add(x) {
//D:self.debug(" adding output", uneval(x));
if (typeof x == "string" && typeof out[out.length-1] == "string")
out[ out.length-1 ] += x;
else
out.push(x);
patterns_or_re = patterns_or_re || Markdown.dialects.Gruber.inline.__patterns__;
var re = new RegExp( "([\\s\\S]*?)(" + (patterns_or_re.source || patterns_or_re) + ")" );
m = re.exec( text );
if (!m) {
// Just boring text
return [ text.length, text ];
}
else if ( m[1] ) {
// Some un-interesting text matched. Return that first
return [ m[1].length, m[1] ];
}
while ( ( m = re.exec(text) ) != null) {
if ( m[1] ) add( m[1] ); // Some un-interesting text matched
else m[1] = { length: 0 }; // Or there was none, but make m[1].length == 0
var res;

@@ -862,20 +833,27 @@ if ( m[2] in this.dialect.inline ) {

this,
text.substr( m.index + m[1].length ), m, out );
text.substr( m.index ), m, previous_nodes || [] );
}
// Default for now to make dev easier. just slurp special and output it.
res = res || [ m[2].length, m[2] ];
return res;
},
var len = res.shift();
// Update how much input was consumed
re.lastIndex += ( len - m[2].length );
__call__: function inline( text, patterns ) {
// Add children
res.forEach(add);
var out = [],
res;
lastIndex = re.lastIndex;
function add(x) {
//D:self.debug(" adding output", uneval(x));
if (typeof x == "string" && typeof out[out.length-1] == "string")
out[ out.length-1 ] += x;
else
out.push(x);
}
// Add last 'boring' chunk
if ( text.length > lastIndex )
add( text.substr( lastIndex ) );
while ( text.length > 0 ) {
res = Markdown.dialects.Gruber.inline.__oneElement__.call(this, text, patterns, out );
text = text.substr( res.shift() );
forEach(res, add )
}

@@ -885,2 +863,7 @@ return out;

// These characters are intersting elsewhere, so have rules for them so that
// chunks of plain text blocks don't include them
"]": function () {},
"}": function () {},
"\\": function escaped( text ) {

@@ -897,2 +880,6 @@ // [ length of input processed, node/children to add... ]

"![": function image( text ) {
// Unlike images, alt text is plain text only. no other elements are
// allowed in there
// ![Alt text](/path/to/img.jpg "Optional title")

@@ -906,3 +893,3 @@ // 1 2 3 4 <--- captures

m[2] == this.dialect.inline.__call__.call( this, m[2], /\\/ )[0];
m[2] = this.dialect.inline.__call__.call( this, m[2], /\\/ )[0];

@@ -922,3 +909,3 @@ var attrs = { alt: m[1], href: m[2] || "" };

// found till after. Check it in md tree->hmtl tree conversion
return [ m[0].length, [ "img_ref", { alt: m[1], ref: m[2].toLowerCase(), text: m[0] } ] ];
return [ m[0].length, [ "img_ref", { alt: m[1], ref: m[2].toLowerCase(), original: m[0] } ] ];
}

@@ -930,4 +917,95 @@

"[": Markdown.prototype.link,
"[": function link( text ) {
var orig = String(text);
// Inline content is possible inside `link text`
var res = Markdown.DialectHelpers.inline_until_char.call( this, text.substr(1), ']' );
// No closing ']' found. Just consume the [
if ( !res ) return [ 1, '[' ];
var consumed = 1 + res[ 0 ],
children = res[ 1 ],
link,
attrs;
// At this point the first [...] has been parsed. See what follows to find
// out which kind of link we are (reference or direct url)
text = text.substr( consumed );
// [link text](/path/to/img.jpg "Optional title")
// 1 2 3 <--- captures
// This will capture up to the last paren in the block. We then pull
// back based on if there a matching ones in the url
// ([here](/url/(test))
// The parens have to be balanced
var m = text.match( /^\s*\([ \t]*(\S+)(?:[ \t]+(["'])(.*?)\2)?[ \t]*\)/ );
if ( m ) {
var url = m[1];
consumed += m[0].length;
if ( url && url[0] == '<' && url[url.length-1] == '>' )
url = url.substring( 1, url.length - 1 );
// If there is a title we don't have to worry about parens in the url
if ( !m[3] ) {
var open_parens = 1; // One open that isn't in the capture
for (var len = 0; len < url.length; len++) {
switch ( url[len] ) {
case '(':
open_parens++;
break;
case ')':
if ( --open_parens == 0) {
consumed -= url.length - len;
url = url.substring(0, len);
}
break;
}
}
}
// Process escapes only
url = Markdown.dialects.Gruber.inline.__call__.call( this, url, /\\/ )[0];
attrs = { href: url || "" };
if ( m[3] !== undefined)
attrs.title = m[3];
link = [ "link", attrs ].concat( children );
return [ consumed, link ];
}
// [Alt text][id]
// [Alt text] [id]
m = text.match( /^\s*\[(.*?)\]/ );
if ( m ) {
consumed += m[ 0 ].length;
// [links][] uses links as its reference
attrs = { ref: ( m[ 1 ] || String(children) ).toLowerCase(), original: orig.substr( 0, consumed ) };
link = [ "link_ref", attrs ].concat( children );
// We can't check if the reference is known here as it likely wont be
// found till after. Check it in md tree->hmtl tree conversion.
// Store the original so that conversion can revert if the ref isn't found.
return [ consumed, link ];
}
// [id]
// Only if id is plain (no formatting.)
if ( children.length == 1 && typeof children[0] == "string" ) {
attrs = { ref: children[0].toLowerCase(), original: orig.substr( 0, consumed ) };
link = [ "link_ref", attrs, children[0] ];
return [ consumed, link ];
}
// Just consume the '['
return [ 1, "[" ];
},
"<": function autoLink( text ) {

@@ -962,10 +1040,71 @@ var m;

}
},
" \n": function lineBreak( text ) {
return [ 3, [ "linebreak" ] ];
}
};
// Meta Helper/generator method for em and strong handling
function strong_em( tag, md ) {
var state_slot = tag + "_state",
other_slot = tag == "strong" ? "em_state" : "strong_state";
function CloseTag(len) {
this.len_after = len;
this.name = "close_" + md;
}
return function ( text, orig_match ) {
if (this[state_slot][0] == md) {
// Most recent em is of this type
//D:this.debug("closing", md);
this[state_slot].shift();
// "Consume" everything to go back to the recrusion in the else-block below
return[ text.length, new CloseTag(text.length-md.length) ];
}
else {
// Store a clone of the em/strong states
var other = this[other_slot].slice(),
state = this[state_slot].slice();
this[state_slot].unshift(md);
//D:this.debug_indent += " ";
// Recurse
var res = this.processInline( text.substr( md.length ) );
//D:this.debug_indent = this.debug_indent.substr(2);
var last = res[res.length - 1];
//D:this.debug("processInline from", tag + ": ", uneval( res ) );
var check = this[state_slot].shift();
if (last instanceof CloseTag) {
res.pop();
// We matched! Huzzah.
var consumed = text.length - last.len_after;
return [ consumed, [ tag ].concat(res) ];
}
else {
// Restore the state of the other kind. We might have mistakenly closed it.
this[other_slot] = other;
this[state_slot] = state;
// We can't reuse the processed result as it could have wrong parsing contexts in it.
return [ md.length, md ];
}
}
} // End returned function
}
Markdown.dialects.Gruber.inline["**"] = helpers.strong_em("strong", "**");
Markdown.dialects.Gruber.inline["__"] = helpers.strong_em("strong", "__");
Markdown.dialects.Gruber.inline["*"] = helpers.strong_em("em", "*");
Markdown.dialects.Gruber.inline["_"] = helpers.strong_em("em", "_");
Markdown.dialects.Gruber.inline["**"] = strong_em("strong", "**");
Markdown.dialects.Gruber.inline["__"] = strong_em("strong", "__");
Markdown.dialects.Gruber.inline["*"] = strong_em("em", "*");
Markdown.dialects.Gruber.inline["_"] = strong_em("em", "_");

@@ -981,3 +1120,3 @@

d.__order__ = ord;
}
};

@@ -989,3 +1128,4 @@ // Build patterns for inline matcher

for ( var i in d ) {
if (i == "__call__") continue;
// __foo__ is reserved and not a pattern
if ( i.match( /^__.*__$/) ) continue;
var l = i.replace( /([\\.*+?|()\[\]{}])/g, "\\$1" )

@@ -997,2 +1137,3 @@ .replace( /\n/, "\\n" );

patterns = patterns.join("|");
d.__patterns__ = patterns;
//print("patterns:", uneval( patterns ) );

@@ -1002,7 +1143,34 @@

d.__call__ = function(text, pattern) {
if (pattern != undefined)
if (pattern != undefined) {
return fn.call(this, text, pattern);
}
else
{
return fn.call(this, text, patterns);
}
};
};
Markdown.DialectHelpers = {};
Markdown.DialectHelpers.inline_until_char = function( text, want ) {
var consumed = 0,
nodes = [];
while ( true ) {
if ( text[ consumed ] == want ) {
// Found the character we were looking for
consumed++;
return [ consumed, nodes ];
}
if ( consumed >= text.length ) {
// No closing char found. Abort.
return null;
}
res = Markdown.dialects.Gruber.inline.__oneElement__.call(this, text.substr( consumed ) );
consumed += res[ 0 ];
// Add any returned nodes.
nodes.push.apply( nodes, res.slice( 1 ) );
}
}

@@ -1012,9 +1180,9 @@

Markdown.subclassDialect = function( d ) {
function Block() {};
function Block() {}
Block.prototype = d.block;
function Inline() {};
function Inline() {}
Inline.prototype = d.inline;
return { block: new Block(), inline: new Inline() };
}
};

@@ -1026,2 +1194,67 @@ Markdown.buildBlockOrder ( Markdown.dialects.Gruber.block );

Markdown.dialects.Maruku.processMetaHash = function processMetaHash( meta_string ) {
var meta = split_meta_hash( meta_string ),
attr = {};
for ( var i = 0; i < meta.length; ++i ) {
// id: #foo
if ( /^#/.test( meta[ i ] ) ) {
attr.id = meta[ i ].substring( 1 );
}
// class: .foo
else if ( /^\./.test( meta[ i ] ) ) {
// if class already exists, append the new one
if ( attr['class'] ) {
attr['class'] = attr['class'] + meta[ i ].replace( /./, " " );
}
else {
attr['class'] = meta[ i ].substring( 1 );
}
}
// attribute: foo=bar
else if ( /\=/.test( meta[ i ] ) ) {
var s = meta[ i ].split( /\=/ );
attr[ s[ 0 ] ] = s[ 1 ];
}
}
return attr;
}
function split_meta_hash( meta_string ) {
var meta = meta_string.split( "" ),
parts = [ "" ],
in_quotes = false;
while ( meta.length ) {
var letter = meta.shift();
switch ( letter ) {
case " " :
// if we're in a quoted section, keep it
if ( in_quotes ) {
parts[ parts.length - 1 ] += letter;
}
// otherwise make a new part
else {
parts.push( "" );
}
break;
case "'" :
case '"' :
// reverse the quotes and move straight on
in_quotes = !in_quotes;
break;
case "\\" :
// shift off the next letter to be used straight away.
// it was escaped so we'll keep it whatever it is
letter = meta.shift();
default :
parts[ parts.length - 1 ] += letter;
break;
}
}
return parts;
}
Markdown.dialects.Maruku.block.document_meta = function document_meta( block, next ) {

@@ -1051,3 +1284,3 @@ // we're only interested in the first block

return [];
}
};

@@ -1060,7 +1293,9 @@ Markdown.dialects.Maruku.block.block_meta = function block_meta( block, next ) {

// process the meta hash
var attr = process_meta_hash( m[ 2 ] );
var attr = Markdown.dialects.Maruku.processMetaHash( m[ 2 ] );
var hash;
// if we matched ^ then we need to apply meta to the previous block
if ( m[ 1 ] === "" ) {
var node = this.tree[ this.tree.length - 1 ],
var node = this.tree[ this.tree.length - 1 ];
hash = extract_attr( node );

@@ -1091,3 +1326,3 @@

// get or make the attributes hash
var hash = extract_attr( result[ 0 ] );
hash = extract_attr( result[ 0 ] );
if ( !hash ) {

@@ -1104,8 +1339,9 @@ hash = {};

return result;
}
};
Markdown.dialects.Maruku.block.definition_list = function definition_list( block, next ) {
// one or more terms followed by one or more definitions, in a single block
var tight = /^((?:[^\s:].*\n)+):\s+([^]+)$/,
list = [ "dl" ];
var tight = /^((?:[^\s:].*\n)+):\s+([\s\S]+)$/,
list = [ "dl" ],
i;

@@ -1128,7 +1364,7 @@ // see if we're dealing with a tight or loose block

for ( var i = 0; i < terms.length; ++i ) {
for ( i = 0; i < terms.length; ++i ) {
list.push( [ "dt", terms[ i ] ] );
}
for ( var i = 0; i < defns.length; ++i ) {
for ( i = 0; i < defns.length; ++i ) {
// run inline processing over the definition

@@ -1144,3 +1380,3 @@ list.push( [ "dd" ].concat( this.processInline( defns[ i ].replace( /(\n)\s+/, "$1" ) ) ) );

return [ list ];
}
};

@@ -1168,3 +1404,4 @@ Markdown.dialects.Maruku.inline[ "{:" ] = function inline_meta( text, matches, out ) {

// attach the attributes to the preceeding element
var meta = process_meta_hash( m[ 1 ] ),
var meta = Markdown.dialects.Maruku.processMetaHash( m[ 1 ] ),
attr = extract_attr( before );

@@ -1183,3 +1420,3 @@

return [ m[ 0 ].length, "" ];
}
};

@@ -1189,3 +1426,2 @@ Markdown.buildBlockOrder ( Markdown.dialects.Maruku.block );

Markdown.dialects.GFM = Markdown.subclassDialect( Markdown.dialects.Maruku );

@@ -1268,25 +1504,21 @@

if ( !m ) {
return Markdown.prototype.link( text );
return Markdown.dialects.Gruber.inline["["]( text );
}
if ( m )
{
// attach the attributes to the preceeding element
var meta = process_meta_hash( m[ 2 ] ),
attr = extract_attr( m[ 1 ] );
// attach the attributes to the preceeding element
var meta = Markdown.dialects.Maruku.processMetaHash( m[ 2 ] ),
attr = extract_attr( m[ 1 ] );
if ( !attr ) {
attr = {};
}
if ( !attr ) {
attr = {};
}
for ( var k in meta ) {
attr[k] = meta[k];
}
// cut out the string and replace it with span + attribute
var span = [ "span", attr ];
Array.prototype.push.apply( span, this.processInline( m[1] ) );
return [ m[0].length, span ];
for ( var k in meta ) {
attr[k] = meta[k];
}
// cut out the string and replace it with span + attribute
var span = [ "span", attr ];
Array.prototype.push.apply( span, this.processInline( m[1] ) );
return [ m[0].length, span ];
}

@@ -1352,4 +1584,4 @@

var tHeaders = lines[0];
var tableRERow = /^|.+/; // lazy.
var tableRERow = /^\|.+/; // lazy.
if (tHeaders.length) {

@@ -1382,3 +1614,3 @@ var tr = [ "tr" ]

for (var j = 1; j < rows.length; j++) {
tr.push( ["td", {align: alignAttr[j]}].concat(rows[j]) );
tr.push( ["td", {align: alignAttr[j]}].concat( this.processInline(rows[j]) ));
}

@@ -1394,6 +1626,20 @@ }

return [ table ];
if (lines[lines.length - 1].match(/^{: /)) {
var meta = Markdown.dialects.Maruku.processMetaHash( lines[lines.length - 1] ),
attr = extract_attr( table );
if ( !attr ) {
attr = {};
table.splice( 1, 0, attr );
}
for ( var k in meta ) {
attr[ k ] = meta[ k ];
}
}
return [ ["table", table ] ];
}
Markdown.dialects.NAMP.block.table2 = function table1_maker( block, next ) {
Markdown.dialects.NAMP.block.table2 = function table2_maker( block, next ) {
var tableRE = /^[ ]{0,3}(\S.*[|].*)\n[ ]{0,3}([-:]+[ ]*[|][-| :]*)\n/;

@@ -1409,4 +1655,2 @@

var tableRERow = /^[^{:]/; // lazy.
var metadataRE = /^{:/;
var metadata = "";

@@ -1440,9 +1684,6 @@ if (tHeaders.length) {

for (var j = 0; j < rows.length; j++) {
tr.push( ["td", {align: alignAttr[j]}].concat(rows[j]) );
tr.push( ["td", {align: alignAttr[j]}].concat( this.processInline(rows[j]) ));
}
table.push(tr);
}
else if ( (r = lines[i].match(metadataRE ) ) ) {
metadata = lines[i];
}
}

@@ -1454,2 +1695,16 @@ }

if (lines[lines.length - 1].match(/^{: /)) {
var meta = Markdown.dialects.Maruku.processMetaHash( lines[lines.length - 1] ),
attr = extract_attr( table );
if ( !attr ) {
attr = {};
table.splice( 1, 0, attr );
}
for ( var k in meta ) {
attr[ k ] = meta[ k ];
}
}
return [ table ];

@@ -1461,8 +1716,26 @@ }

var isArray = Array.isArray || function(obj) {
return Object.prototype.toString.call(obj) == '[object Array]';
};
var forEach;
// Don't mess with Array.prototype. Its not friendly
if ( Array.prototype.forEach ) {
forEach = function( arr, cb, thisp ) {
return arr.forEach( cb, thisp );
};
}
else {
forEach = function(arr, cb, thisp) {
for (var i = 0; i < arr.length; i++) {
cb.call(thisp || arr, arr[i], i, arr);
}
}
}
function extract_attr( jsonml ) {
return helpers.isArray(jsonml)
return isArray(jsonml)
&& jsonml.length > 1
&& typeof jsonml[ 1 ] === "object"
&& !( helpers.isArray(jsonml[ 1 ]) )
&& !( isArray(jsonml[ 1 ]) )
? jsonml[ 1 ]

@@ -1472,67 +1745,4 @@ : undefined;

function process_meta_hash( meta_string ) {
var meta = split_meta_hash( meta_string ),
attr = {};
for ( var i = 0; i < meta.length; ++i ) {
// id: #foo
if ( /^#/.test( meta[ i ] ) ) {
attr.id = meta[ i ].substring( 1 );
}
// class: .foo
else if ( /^\./.test( meta[ i ] ) ) {
// if class already exists, append the new one
if ( attr['class'] ) {
attr['class'] = attr['class'] + meta[ i ].replace( /./, " " );
}
else {
attr['class'] = meta[ i ].substring( 1 );
}
}
// attribute: foo=bar
else if ( /=/.test( meta[ i ] ) ) {
var s = meta[ i ].split( /=/ );
attr[ s[ 0 ] ] = s[ 1 ];
}
}
return attr;
}
function split_meta_hash( meta_string ) {
var meta = meta_string.split( "" ),
parts = [ "" ],
in_quotes = false;
while ( meta.length ) {
var letter = meta.shift();
switch ( letter ) {
case " " :
// if we're in a quoted section, keep it
if ( in_quotes ) {
parts[ parts.length - 1 ] += letter;
}
// otherwise make a new part
else {
parts.push( "" );
}
break;
case "'" :
case '"' :
// reverse the quotes and move straight on
in_quotes = !in_quotes;
break;
case "\\" :
// shift off the next letter to be used straight away.
// it was escaped so we'll keep it whatever it is
letter = meta.shift();
default :
parts[ parts.length - 1 ] += letter;
break;
}
}
return parts;
}
/**

@@ -1573,10 +1783,10 @@ * renderJsonML( jsonml[, options] ) -> String

return content.join( "\n\n" );
}
};
function escapeHTML( text ) {
return text.replace( /&/g, "&amp;" )
.replace( /</g, "&lt;" )
.replace( />/g, "&gt;" )
.replace( /"/g, "&quot;" )
.replace( /'/g, "&#39;" );
.replace( /</g, "&lt;" )
.replace( />/g, "&gt;" )
.replace( /"/g, "&quot;" )
.replace( /'/g, "&#39;" );
}

@@ -1604,5 +1814,2 @@

}
if ( jsonml[0] == "__RAW" ) {
return jsonml[1];
}

@@ -1626,10 +1833,13 @@ var tag = jsonml.shift(),

if (tag == 'br')
return "<br />";
// be careful about adding whitespace here for inline elements
if ( tag == "img" || tag == "br" || tag == "hr" ) {
return "<"+ tag + tag_attrs + "/>";
}
else {
return "<"+ tag + tag_attrs + ">" + content.join( "" ) + "</" + tag + ">";
}
}
function convert_tree_to_html( tree, references, options ) {
var i;
options = options || {};

@@ -1648,3 +1858,3 @@

jsonml[ 1 ] = {};
for ( var i in attrs ) {
for ( i in attrs ) {
jsonml[ 1 ][ i ] = attrs[ i ];

@@ -1659,3 +1869,3 @@ }

}
//console.log(jsonml[ 0 ] );
// convert this node

@@ -1685,12 +1895,5 @@ switch ( jsonml[ 0 ] ) {

jsonml[ 0 ] = "pre";
var i = attrs ? 2 : 1;
i = attrs ? 2 : 1;
var code = [ "code" ];
code.push.apply( code, jsonml.splice( i ) );
if (attrs !== undefined && attrs.lang !== undefined)
code.push( [ attrs.lang ] );
jsonml[ i ] = code;

@@ -1713,2 +1916,3 @@ break;

jsonml[ 0 ] = "div";
break;
case "link":

@@ -1741,6 +1945,30 @@ jsonml[ 0 ] = "a";

break;
case "img_ref":
jsonml[ 0 ] = "img";
// grab this ref and clean up the attribute node
var ref = references[ attrs.ref ];
// if the reference exists, make the link
if ( ref ) {
delete attrs.ref;
// add in the href and title, if present
attrs.src = ref.href;
if ( ref.title ) {
attrs.title = ref.title;
}
// get rid of the unneeded original text
delete attrs.original;
}
// the reference doesn't exist, so revert to plain text
else {
return attrs.original;
}
break;
}
// convert all the children
var i = 1;
i = 1;

@@ -1747,0 +1975,0 @@ // deal with the attribute node, if it exists

{
"name" : "namp",
"version" : "0.1.4",
"version" : "0.1.6",
"description" : "Markdown parser for Node, with Maruku, GFM, and PHP Extras support, plus more.",

@@ -5,0 +5,0 @@ "keywords" : [ "markdown", "maruku", "gfm", "text processing", "ast" ],

@@ -1,28 +0,28 @@

var markdown = require('Markdown');
var markdown = require("../lib/markdown"),
test = require("tap").test;
// var markdown = require('Markdown');
function clone_array( input ) {
eval( "var tmp = " + input.toSource() );
return tmp;
// Helper method. Since the objects are plain round trip through JSON to get
// a clone
return JSON.parse( JSON.stringify( input ) );
}
tests = {
test_arguments_untouched: function() {
var input = "A [link][id] by id.\n\n[id]: http://google.com",
tree = markdown.parse( input ),
clone = clone_array( tree );
test("arguments untouched", function(t) {
var input = "A [link][id] by id.\n\n[id]: http://google.com",
tree = markdown.parse( input ),
clone = clone_array( tree );
var output = markdown.toHTML( tree );
var output = markdown.toHTML( tree );
asserts.same( tree, clone, "tree isn't modified" );
// We had a problem where we would acidentally remove the references
// property from the root. We want to check the output is the same when
// called twice.
asserts.same( markdown.toHTML( tree ), output, "output is consistent" );
}
}
t.equivalent( tree, clone, "tree isn't modified" );
// We had a problem where we would accidentally remove the references
// property from the root. We want to check the output is the same when
// called twice.
t.equivalent( markdown.toHTML( tree ), output, "output is consistent" );
if (require.main === module) {
var asserts = require('test').asserts;
require('test').runner(tests);
}
t.end();
});

@@ -1,263 +0,266 @@

var Markdown = require('Markdown').Markdown,
var markdown = require("../lib/markdown"),
tap = require("tap"),
Markdown = markdown.Markdown,
mk_block = Markdown.mk_block;
var tests = {
meta: function(fn) {
return function() { fn( new Markdown ) }
}
};
tests = {
test_split_block: tests.meta(function(md) {
asserts.same(
md.split_blocks( "# h1 #\n\npara1\npara1L2\n \n\n\n\npara2\n" ),
[mk_block( "# h1 #", "\n\n", 1 ),
mk_block( "para1\npara1L2", "\n \n\n\n\n", 3 ),
mk_block( "para2", "\n", 9 )
],
"split_block should record trailing newlines");
/*
* This file contains tests that check various regressions on the individual
* parsers, rather than the parser as a whole.
*/
asserts.same(
md.split_blocks( "\n\n# heading #\n\npara\n" ),
[mk_block( "# heading #", "\n\n", 3 ),
mk_block( "para", "\n", 5 )
],
"split_block should ignore leading newlines");
}),
function test(name, cb) {
tap.test( name, function(t) {
cb(t, new Markdown );
t.end();
});
};
test_headers: tests.meta(function(md) {
var h1 = md.dialect.block.atxHeader( "# h1 #\n\n", [] ),
h2;
test("split_block", function(t, md) {
t.equivalent(
md.split_blocks( "# h1 #\n\npara1\npara1L2\n \n\n\n\npara2\n" ),
[mk_block( "# h1 #", "\n\n", 1 ),
mk_block( "para1\npara1L2", "\n \n\n\n\n", 3 ),
mk_block( "para2", "\n", 9 )
],
"split_block should record trailing newlines");
asserts.same(
h1,
md.dialect.block.setextHeader( "h1\n===\n\n", [] ),
"Atx and Setext style H1s should produce the same output" );
t.equivalent(
md.split_blocks( "\n\n# heading #\n\npara\n" ),
[mk_block( "# heading #", "\n\n", 3 ),
mk_block( "para", "\n", 5 )
],
"split_block should ignore leading newlines");
});
asserts.same(
md.dialect.block.atxHeader("# h1\n\n"),
h1,
"Closing # optional on atxHeader");
test("headers", function(t, md) {
t.equivalent(
md.dialect.block.setextHeader( "h1\n===\n\n", [] ),
[ [ 'header', { level: 1 }, 'h1' ] ],
"Atx and Setext style H1s should produce the same output" );
asserts.same(
h2 = md.dialect.block.atxHeader( "## h2\n\n", [] ),
[["header", {level: 2}, "h2"]],
"Atx h2 has right level");
t.equivalent(
md.dialect.block.atxHeader.call( md, "# h1\n\n"),
[ [ 'header', { level: 1 }, 'h1' ] ],
"Closing # optional on atxHeader");
asserts.same(
h2,
md.dialect.block.setextHeader( "h2\n---\n\n", [] ),
"Atx and Setext style H2s should produce the same output" );
t.equivalent(
h2 = md.dialect.block.atxHeader.call( md, "## h2\n\n", [] ),
[["header", {level: 2}, "h2"]],
"Atx h2 has right level");
}),
t.equivalent(
md.dialect.block.setextHeader.call( md, "h2\n---\n\n", [] ),
[["header", {level: 2}, "h2"]],
"Atx and Setext style H2s should produce the same output" );
});
test_code: tests.meta(function(md) {
var code = md.dialect.block.code,
next = [ mk_block("next") ];
test("code", function(t, md) {
var code = md.dialect.block.code,
next = [ mk_block("next") ];
asserts.same(
code.call( md, mk_block(" foo\n bar"), next ),
[["code_block", "foo\nbar" ]],
"Code block correct");
t.equivalent(
code.call( md, mk_block(" foo\n bar"), next ),
[["code_block", "foo\nbar" ]],
"Code block correct");
asserts.same(
next, [mk_block("next")],
"next untouched when its not code");
t.equivalent(
next, [mk_block("next")],
"next untouched when its not code");
next = [];
asserts.same(
code.call( md, mk_block(" foo\n bar"), next ),
[["code_block", "foo" ]],
"Code block correct for abutting para");
next = [];
t.equivalent(
code.call( md, mk_block(" foo\n bar"), next ),
[["code_block", "foo" ]],
"Code block correct for abutting para");
asserts.same(
next, [mk_block(" bar")],
"paragraph put back into next block");
t.equivalent(
next, [mk_block(" bar")],
"paragraph put back into next block");
asserts.same(
code.call( md, mk_block(" foo"), [mk_block(" bar"), ] ),
[["code_block", "foo\n\nbar" ]],
"adjacent code blocks ");
t.equivalent(
code.call( md, mk_block(" foo"), [mk_block(" bar"), ] ),
[["code_block", "foo\n\nbar" ]],
"adjacent code blocks ");
asserts.same(
code.call( md, mk_block(" foo","\n \n \n"), [mk_block(" bar"), ] ),
[["code_block", "foo\n\n\nbar" ]],
"adjacent code blocks preserve correct number of empty lines");
t.equivalent(
code.call( md, mk_block(" foo","\n \n \n"), [mk_block(" bar"), ] ),
[["code_block", "foo\n\n\nbar" ]],
"adjacent code blocks preserve correct number of empty lines");
}),
});
test_bulletlist: tests.meta(function(md) {
var bl = function() { return md.dialect.block.lists.apply(md, arguments) };
test( "bulletlist", function(t, md) {
var bl = function() { return md.dialect.block.lists.apply(md, arguments) };
asserts.same(
bl( mk_block("* foo\n* bar"), [] ),
[ [ "bulletlist", [ "listitem", "foo" ], [ "listitem", "bar" ] ] ],
"single line bullets");
t.equivalent(
bl( mk_block("* foo\n* bar"), [] ),
[ [ "bulletlist", [ "listitem", "foo" ], [ "listitem", "bar" ] ] ],
"single line bullets");
asserts.same(
bl( mk_block("* [text](url)" ), [] ),
[ [ "bulletlist", [ "listitem", [ "link", { href: "url" }, "text" ] ] ] ],
"link in bullet");
t.equivalent(
bl( mk_block("* [text](url)" ), [] ),
[ [ "bulletlist", [ "listitem", [ "link", { href: "url" }, "text" ] ] ] ],
"link in bullet");
asserts.same(
bl( mk_block("* foo\nbaz\n* bar\nbaz"), [] ),
[ [ "bulletlist", [ "listitem", "foo\nbaz" ], [ "listitem", "bar\nbaz" ] ] ],
"multiline lazy bullets");
t.equivalent(
bl( mk_block("* foo\nbaz\n* bar\nbaz"), [] ),
[ [ "bulletlist", [ "listitem", "foo\nbaz" ], [ "listitem", "bar\nbaz" ] ] ],
"multiline lazy bullets");
asserts.same(
bl( mk_block("* foo\n baz\n* bar\n baz"), [] ),
[ [ "bulletlist", [ "listitem", "foo\nbaz" ], [ "listitem", "bar\nbaz" ] ] ],
"multiline tidy bullets");
t.equivalent(
bl( mk_block("* foo\n baz\n* bar\n baz"), [] ),
[ [ "bulletlist", [ "listitem", "foo\nbaz" ], [ "listitem", "bar\nbaz" ] ] ],
"multiline tidy bullets");
asserts.same(
bl( mk_block("* foo\n baz"), [] ),
[ [ "bulletlist", [ "listitem", "foo\n baz" ] ] ],
"only trim 4 spaces from the start of the line");
t.equivalent(
bl( mk_block("* foo\n baz"), [] ),
[ [ "bulletlist", [ "listitem", "foo\n baz" ] ] ],
"only trim 4 spaces from the start of the line");
/* Test wrong: should end up with 3 nested lists here
asserts.same(
bl( mk_block(" * one\n * two\n * three" ), [] ),
[ [ "bulletlist", [ "listitem", "one" ], [ "listitem", "two" ], [ "listitem", "three" ] ] ],
"bullets can be indented up to three spaces");
*/
/* Test wrong: should end up with 3 nested lists here
t.equivalent(
bl( mk_block(" * one\n * two\n * three" ), [] ),
[ [ "bulletlist", [ "listitem", "one" ], [ "listitem", "two" ], [ "listitem", "three" ] ] ],
"bullets can be indented up to three spaces");
*/
asserts.same(
bl( mk_block(" * one"), [ mk_block(" two") ] ),
[ [ "bulletlist", [ "listitem", [ "para", "one" ], [ "para", "two" ] ] ] ],
"loose bullet lists can have multiple paragraphs");
t.equivalent(
bl( mk_block(" * one"), [ mk_block(" two") ] ),
[ [ "bulletlist", [ "listitem", [ "para", "one" ], [ "para", "two" ] ] ] ],
"loose bullet lists can have multiple paragraphs");
/* Case: no space after bullet - not a list
| *↵
|foo
*/
asserts.same(
bl( mk_block(" *\nfoo") ),
undefined,
"Space required after bullet to trigger list");
/* Case: no space after bullet - not a list
| *↵
|foo
*/
t.equivalent(
bl( mk_block(" *\nfoo") ),
undefined,
"Space required after bullet to trigger list");
/* Case: note the space after the bullet
| *␣
|foo
|bar
*/
asserts.same(
bl( mk_block(" * \nfoo\nbar"), [ ] ),
[ [ "bulletlist", [ "listitem", "foo\nbar" ] ] ],
"space+continuation lines");
/* Case: note the space after the bullet
| *␣
|foo
|bar
*/
t.equivalent(
bl( mk_block(" * \nfoo\nbar"), [ ] ),
[ [ "bulletlist", [ "listitem", "foo\nbar" ] ] ],
"space+continuation lines", {todo: true} );
/* Case I:
| * foo
| * bar
| * baz
*/
asserts.same(
bl( mk_block(" * foo\n" +
" * bar\n" +
" * baz"),
[] ),
[ [ "bulletlist",
[ "listitem",
"foo",
[ "bulletlist",
[ "listitem",
"bar",
[ "bulletlist",
[ "listitem", "baz" ]
]
/* Case I:
| * foo
| * bar
| * baz
*/
t.equivalent(
bl( mk_block(" * foo\n" +
" * bar\n" +
" * baz"),
[] ),
[ [ "bulletlist",
[ "listitem",
"foo",
[ "bulletlist",
[ "listitem",
"bar",
[ "bulletlist",
[ "listitem", "baz" ]
]
]
]
] ],
"Interesting indented lists I");
]
] ],
"Interesting indented lists I");
/* Case II:
| * foo
| * bar
| * baz
*/
asserts.same(
bl( mk_block(" * foo\n * bar\n * baz"), [] ),
[ [ "bulletlist",
[ "listitem",
"foo",
[ "bulletlist",
[ "listitem", "bar" ]
]
],
[ "listitem", "baz" ]
] ],
"Interesting indented lists II");
/* Case II:
| * foo
| * bar
| * baz
*/
t.equivalent(
bl( mk_block(" * foo\n * bar\n * baz"), [] ),
[ [ "bulletlist",
[ "listitem",
"foo",
[ "bulletlist",
[ "listitem", "bar" ]
]
],
[ "listitem", "baz" ]
] ],
"Interesting indented lists II");
/* Case III:
| * foo
| * bar
|* baz
| * fnord
*/
asserts.same(
bl( mk_block(" * foo\n * bar\n* baz\n * fnord"), [] ),
[ [ "bulletlist",
[ "listitem",
"foo",
[ "bulletlist",
[ "listitem", "bar" ],
[ "listitem", "baz" ],
[ "listitem", "fnord" ]
]
/* Case III:
| * foo
| * bar
|* baz
| * fnord
*/
t.equivalent(
bl( mk_block(" * foo\n * bar\n* baz\n * fnord"), [] ),
[ [ "bulletlist",
[ "listitem",
"foo",
[ "bulletlist",
[ "listitem", "bar" ],
[ "listitem", "baz" ],
[ "listitem", "fnord" ]
]
] ],
"Interesting indented lists III");
]
] ],
"Interesting indented lists III");
/* Case IV:
| * foo
|
| 1. bar
*/
asserts.same(
bl( mk_block(" * foo"), [ mk_block(" 1. bar\n") ] ),
[ [ "bulletlist",
["listitem", ["para", "foo"] ],
["listitem", ["para", "bar"] ]
] ],
"Different lists at same indent IV");
/* Case IV:
| * foo
|
| 1. bar
*/
t.equivalent(
bl( mk_block(" * foo"), [ mk_block(" 1. bar\n") ] ),
[ [ "bulletlist",
["listitem", ["para", "foo"] ],
["listitem", ["para", "bar"] ]
] ],
"Different lists at same indent IV");
/* Case V:
| * foo
| * bar
| * baz
*/
asserts.same(
bl( mk_block(" * foo\n * bar\n * baz"), [] ),
[ [ "bulletlist",
[ "listitem",
"foo",
[ "bulletlist",
["listitem", "bar"],
["listitem", "baz"],
]
/* Case V:
| * foo
| * bar
| * baz
*/
t.equivalent(
bl( mk_block(" * foo\n * bar\n * baz"), [] ),
[ [ "bulletlist",
[ "listitem",
"foo",
[ "bulletlist",
["listitem", "bar"],
["listitem", "baz"],
]
] ],
"Indenting Case V")
]
] ],
"Indenting Case V")
/* Case VI: deep nesting
|* one
| * two
| * three
| * four
*/
asserts.same(
bl( mk_block("* one\n * two\n * three\n * four"), [] ),
[ [ "bulletlist",
[ "listitem",
"one",
[ "bulletlist",
[ "listitem",
"two",
[ "bulletlist",
[ "listitem",
"three",
[ "bulletlist",
[ "listitem", "four" ]
]
/* Case VI: deep nesting
|* one
| * two
| * three
| * four
*/
t.equivalent(
bl( mk_block("* one\n * two\n * three\n * four"), [] ),
[ [ "bulletlist",
[ "listitem",
"one",
[ "bulletlist",
[ "listitem",
"two",
[ "bulletlist",
[ "listitem",
"three",
[ "bulletlist",
[ "listitem", "four" ]
]

@@ -268,81 +271,81 @@ ]

]
] ],
"deep nested lists VI")
]
] ],
"deep nested lists VI")
/* Case VII: This one is just fruity!
| * foo
| * bar
| * baz
|* HATE
| * flibble
| * quxx
| * nest?
| * where
| * am
| * i?
*/
asserts.same(
bl( mk_block(" * foo\n" +
" * bar\n" +
" * baz\n" +
"* HATE\n" +
" * flibble\n" +
" * quxx\n" +
" * nest?\n" +
" * where\n" +
" * am\n" +
" * i?"),
[] ),
[ [ "bulletlist",
[ "listitem",
"foo",
[ "bulletlist",
["listitem", "bar"],
["listitem", "baz"],
["listitem", "HATE"],
["listitem", "flibble"]
]
],
[ "listitem",
"quxx",
[ "bulletlist",
[ "listitem",
"nest?",
[ "bulletlist",
["listitem", "where"],
["listitem", "am"],
["listitem", "i?"]
]
/* Case VII: This one is just fruity!
| * foo
| * bar
| * baz
|* HATE
| * flibble
| * quxx
| * nest?
| * where
| * am
| * i?
*/
t.equivalent(
bl( mk_block(" * foo\n" +
" * bar\n" +
" * baz\n" +
"* HATE\n" +
" * flibble\n" +
" * quxx\n" +
" * nest?\n" +
" * where\n" +
" * am\n" +
" * i?"),
[] ),
[ [ "bulletlist",
[ "listitem",
"foo",
[ "bulletlist",
["listitem", "bar"],
["listitem", "baz"],
["listitem", "HATE"],
["listitem", "flibble"]
]
],
[ "listitem",
"quxx",
[ "bulletlist",
[ "listitem",
"nest?",
[ "bulletlist",
["listitem", "where"],
["listitem", "am"],
["listitem", "i?"]
]
]
]
] ],
"Indenting Case VII");
]
] ],
"Indenting Case VII");
/* Case VIII: Deep nesting + code block
| * one
| * two
| * three
| * four
|
| foo
*/
asserts.same(
bl( mk_block(" * one\n" +
" 1. two\n" +
" * three\n" +
" * four",
"\n\n"),
[ mk_block(" foo") ] ),
[ [ "bulletlist",
[ "listitem",
["para", "one"],
[ "numberlist",
[ "listitem",
["para", "two"],
[ "bulletlist",
[ "listitem",
[ "para", "three\n * four"],
["code_block", "foo"]
]
/* Case VIII: Deep nesting + code block
| * one
| * two
| * three
| * four
|
| foo
*/
t.equivalent(
bl( mk_block(" * one\n" +
" 1. two\n" +
" * three\n" +
" * four",
"\n\n"),
[ mk_block(" foo") ] ),
[ [ "bulletlist",
[ "listitem",
["para", "one"],
[ "numberlist",
[ "listitem",
["para", "two"],
[ "bulletlist",
[ "listitem",
[ "para", "three\n * four"],
["code_block", "foo"]
]

@@ -352,161 +355,173 @@ ]

]
] ],
"Case VIII: Deep nesting and code block");
]
] ],
"Case VIII: Deep nesting and code block");
}),
});
test_horizRule: tests.meta(function(md) {
var hr = md.dialect.block.horizRule,
strs = ["---", "_ __", "** ** **", "--- "];
strs.forEach( function(s) {
asserts.same(
hr.call( md, mk_block(s), [] ),
[ [ "hr" ] ],
"simple hr from " + uneval(s));
});
}),
test( "horizRule", function(t, md) {
var hr = md.dialect.block.horizRule,
strs = ["---", "_ __", "** ** **", "--- "];
strs.forEach( function(s) {
t.equivalent(
hr.call( md, mk_block(s), [] ),
[ [ "hr" ] ],
"simple hr from " + require('util').inspect(s));
});
});
test_blockquote: tests.meta(function(md) {
var bq = md.dialect.block.blockquote;
asserts.same(
bq.call( md, mk_block("> foo\n> bar"), [] ),
[ ["blockquote", ["para", "foo\nbar"] ] ],
"simple blockquote");
test( "blockquote", function(t, md) {
var bq = md.dialect.block.blockquote;
t.equivalent(
bq.call( md, mk_block("> foo\n> bar"), [] ),
[ ["blockquote", ["para", "foo\nbar"] ] ],
"simple blockquote");
// Note: this tests horizRule as well through block processing.
asserts.same(
bq.call( md, mk_block("> foo\n> bar\n>\n>- - - "), [] ),
[ ["blockquote",
["para", "foo\nbar"],
["hr"]
] ],
"blockquote with interesting content");
// Note: this tests horizRule as well through block processing.
t.equivalent(
bq.call( md, mk_block("> foo\n> bar\n>\n>- - - "), [] ),
[ ["blockquote",
["para", "foo\nbar"],
["hr"]
] ],
"blockquote with interesting content");
}),
});
test_referenceDefn: tests.meta(function(md) {
var rd = md.dialect.block.referenceDefn;
test( "referenceDefn", function(t, md) {
var rd = md.dialect.block.referenceDefn;
[ '[id]: http://example.com/ "Optional Title Here"',
"[id]: http://example.com/ 'Optional Title Here'",
'[id]: http://example.com/ (Optional Title Here)'
].forEach( function(s) {
md.tree = ["markdown"];
[ '[id]: http://example.com/ "Optional Title Here"',
"[id]: http://example.com/ 'Optional Title Here'",
'[id]: http://example.com/ (Optional Title Here)'
].forEach( function(s) {
md.tree = ["markdown"];
asserts.same(rd.call( md, mk_block(s) ), [], "ref processed");
t.equivalent(rd.call( md, mk_block(s) ), [], "ref processed");
asserts.same(md.tree[ 1 ].references,
{ "id": { href: "http://example.com/", title: "Optional Title Here" } },
"reference extracted");
});
t.equivalent(md.tree[ 1 ].references,
{ "id": { href: "http://example.com/", title: "Optional Title Here" } },
"reference extracted");
});
// Check a para abbuting a ref works right
md.tree = ["markdown"];
var next = [];
asserts.same(rd.call( md, mk_block("[id]: example.com\npara"), next ), [], "ref processed");
asserts.same(md.tree[ 1 ].references, { "id": { href: "example.com" } }, "reference extracted");
asserts.same(next, [ mk_block("para") ], "paragraph put back into blocks");
// Check a para abbuting a ref works right
md.tree = ["markdown"];
var next = [];
t.equivalent(rd.call( md, mk_block("[id]: example.com\npara"), next ), [], "ref processed");
t.equivalent(md.tree[ 1 ].references, { "id": { href: "example.com" } }, "reference extracted");
t.equivalent(next, [ mk_block("para") ], "paragraph put back into blocks");
}),
});
test_inline_br: tests.meta(function(md) {
asserts.same(
md.processInline("foo \n\\[bar"),
[ "foo", ["linebreak"], "[bar" ], "linebreak+escape");
}),
test( "inline_br", function(t, md) {
t.equivalent(
md.processInline("foo \n\\[bar"),
[ "foo", ["linebreak"], "[bar" ], "linebreak+escape");
});
test_inline_escape: tests.meta(function(md) {
asserts.same( md.processInline("\\bar"), [ "\\bar" ], "invalid escape" );
asserts.same( md.processInline("\\*foo*"), [ "*foo*" ], "escaped em" );
}),
test( "inline_escape", function(t, md) {
t.equivalent( md.processInline("\\bar"), [ "\\bar" ], "invalid escape" );
t.equivalent( md.processInline("\\*foo*"), [ "*foo*" ], "escaped em" );
});
test_inline_code: tests.meta(function(md) {
asserts.same( md.processInline("`bar`"), [ ["inlinecode", "bar" ] ], "code I" );
asserts.same( md.processInline("``b`ar``"), [ ["inlinecode", "b`ar" ] ], "code II" );
asserts.same( md.processInline("```bar``` baz"), [ ["inlinecode", "bar" ], " baz" ], "code III" );
}),
test( "inline_code", function(t, md) {
t.equivalent( md.processInline("`bar`"), [ ["inlinecode", "bar" ] ], "code I" );
t.equivalent( md.processInline("``b`ar``"), [ ["inlinecode", "b`ar" ] ], "code II" );
t.equivalent( md.processInline("```bar``` baz"), [ ["inlinecode", "bar" ], " baz" ], "code III" );
});
test_inline_strong_em: tests.meta(function(md) {
// Yay for horrible edge cases >_<
asserts.same( md.processInline("foo *abc* bar"), [ "foo ", ["em", "abc" ], " bar" ], "strong/em I" );
asserts.same( md.processInline("*abc `code`"), [ "*abc ", ["inlinecode", "code" ] ], "strong/em II" );
asserts.same( md.processInline("*abc**def* after"), [ ["em", "abc**def" ], " after" ], "strong/em III" );
asserts.same( md.processInline("*em **strong * wtf**"), [ ["em", "em **strong " ], " wtf**" ], "strong/em IV" );
asserts.same( md.processInline("*foo _b*a*r baz"), [ [ "em", "foo _b" ], "a*r baz" ], "strong/em V" );
}),
test( "inline_strong_em", function(t, md) {
// Yay for horrible edge cases >_<
t.equivalent( md.processInline("foo *abc* bar"), [ "foo ", ["em", "abc" ], " bar" ], "strong/em I" );
t.equivalent( md.processInline("*abc `code`"), [ "*abc ", ["inlinecode", "code" ] ], "strong/em II" );
t.equivalent( md.processInline("*abc**def* after"), [ ["em", "abc**def" ], " after" ], "strong/em III" );
t.equivalent( md.processInline("*em **strong * wtf**"), [ ["em", "em **strong " ], " wtf**" ], "strong/em IV" );
t.equivalent( md.processInline("*foo _b*a*r baz"), [ [ "em", "foo _b" ], "a*r baz" ], "strong/em V" );
});
test_inline_img: tests.meta(function(md) {
test( "inline_img", function(t, md) {
asserts.same( md.processInline( "![alt] (url)" ),
[ [ "img", { href: "url", alt: "alt" } ] ],
"inline img I" );
t.equivalent( md.processInline( "![alt] (url)" ),
[ [ "img", { href: "url", alt: "alt" } ] ],
"inline img I" );
asserts.same( md.processInline( "![alt](url 'title')" ),
[ [ "img", { href: "url", alt: "alt", title: "title" } ] ],
"inline img II" );
t.equivalent( md.processInline( "![alt](url 'title')" ),
[ [ "img", { href: "url", alt: "alt", title: "title" } ] ],
"inline img II" );
asserts.same( md.processInline( "![alt] (url 'tit'le') after')" ),
[ [ "img", { href: "url", alt: "alt", title: "tit'le" } ], " after')" ],
"inline img III" );
t.equivalent( md.processInline( "![alt] (url 'tit'le') after')" ),
[ [ "img", { href: "url", alt: "alt", title: "tit'le" } ], " after')" ],
"inline img III" );
asserts.same( md.processInline( "![alt] (url \"title\")" ),
[ [ "img", { href: "url", alt: "alt", title: "title" } ] ],
"inline img IV" );
t.equivalent( md.processInline( "![alt] (url \"title\")" ),
[ [ "img", { href: "url", alt: "alt", title: "title" } ] ],
"inline img IV" );
asserts.same( md.processInline( "![alt][id]" ),
[ [ "img_ref", { ref: "id", alt: "alt", text: "![alt][id]" } ] ],
"ref img I" );
t.equivalent( md.processInline( '![Alt text](/path/to/img\\\\.jpg "Optional title")' ),
[ [ "img", { href: "/path/to/img\\.jpg", alt: "Alt text", title: "Optional title" } ] ],
"inline img IV" );
asserts.same( md.processInline( "![alt] [id]" ),
[ [ "img_ref", { ref: "id", alt: "alt", text: "![alt] [id]" } ] ],
"ref img II" );
}),
t.equivalent( md.processInline( "![alt][id]" ),
[ [ "img_ref", { ref: "id", alt: "alt", original: "![alt][id]" } ] ],
"ref img I" );
test_inline_link: tests.meta(function(md) {
t.equivalent( md.processInline( "![alt] [id]" ),
[ [ "img_ref", { ref: "id", alt: "alt", original: "![alt] [id]" } ] ],
"ref img II" );
});
asserts.same( md.processInline( "[text] (url)" ),
[ [ "link", { href: "url" }, "text" ] ],
"inline link I" );
test( "inline_link", function(t, md) {
asserts.same( md.processInline( "[text](url 'title')" ),
[ [ "link", { href: "url", title: "title" }, "text" ] ],
"inline link II" );
t.equivalent( md.processInline( "[text] (url)" ),
[ [ "link", { href: "url" }, "text" ] ],
"inline link I" );
asserts.same( md.processInline( "[text](url 'tit'le') after')" ),
[ [ "link", { href: "url", title: "tit'le" }, "text" ], " after')" ],
"inline link III" );
t.equivalent( md.processInline( "[text](url 'title')" ),
[ [ "link", { href: "url", title: "title" }, "text" ] ],
"inline link II" );
asserts.same( md.processInline( "[text](url \"title\")" ),
[ [ "link", { href: "url", title: "title" }, "text" ] ],
"inline link IV" );
t.equivalent( md.processInline( "[text](url 'tit'le') after')" ),
[ [ "link", { href: "url", title: "tit'le" }, "text" ], " after')" ],
"inline link III" );
asserts.same( md.processInline( "[text][id]" ),
[ [ "link_ref", { ref: "id", original: "[text][id]" }, "text" ] ],
"ref link I" );
t.equivalent( md.processInline( "[text](url \"title\")" ),
[ [ "link", { href: "url", title: "title" }, "text" ] ],
"inline link IV" );
asserts.same( md.processInline( "[text] [id]" ),
[ [ "link_ref", { ref: "id", original: "[text] [id]" }, "text" ] ],
"ref link II" );
}),
t.equivalent( md.processInline( "[text][id]" ),
[ [ "link_ref", { ref: "id", original: "[text][id]" }, "text" ] ],
"ref link I" );
test_inline_autolink: tests.meta(function(md) {
t.equivalent( md.processInline( "[text] [id]" ),
[ [ "link_ref", { ref: "id", original: "[text] [id]" }, "text" ] ],
"ref link II" );
asserts.same( md.processInline( "<http://foo.com>" ),
[ [ "link", { href: "http://foo.com" }, "http://foo.com" ] ],
"autolink I" );
t.equivalent( md.processInline( "[to put it another way][SECTION 1] or even [link this](#SECTION-1)" ),
[
[ "link_ref",
{ ref: "section 1", original: "[to put it another way][SECTION 1]" },
"to put it another way"
],
" or even ",
[ "link",
{ href: "#SECTION-1" },
"link this"
],
],
"ref link II" );
});
asserts.same( md.processInline( "<mailto:foo@bar.com>" ),
[ [ "link", { href: "mailto:foo@bar.com" }, "foo@bar.com" ] ],
"autolink II" );
test( "inline_autolink", function(t, md) {
asserts.same( md.processInline( "<foo@bar.com>" ),
[ [ "link", { href: "mailto:foo@bar.com" }, "foo@bar.com" ] ],
"autolink III" );
}),
}
t.equivalent( md.processInline( "<http://foo.com>" ),
[ [ "link", { href: "http://foo.com" }, "http://foo.com" ] ],
"autolink I" );
t.equivalent( md.processInline( "<mailto:foo@bar.com>" ),
[ [ "link", { href: "mailto:foo@bar.com" }, "foo@bar.com" ] ],
"autolink II" );
if (require.main === module) {
var asserts = require('test').asserts;
require('test').runner(tests);
}
t.equivalent( md.processInline( "<foo@bar.com>" ),
[ [ "link", { href: "mailto:foo@bar.com" }, "foo@bar.com" ] ],
"autolink III" );
});

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

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

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc