Skip to content

Commit e7f1c9e

Browse files
committed
Add support for reference links.
1 parent 067da3d commit e7f1c9e

2 files changed

Lines changed: 19 additions & 11 deletions

File tree

src/index.js

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,17 @@ function trim(str) {
4545

4646
export default function parse(md) {
4747
// eslint-disable-next-line
48-
let tokenizer = /(?:^```(\w*)\n([\s\S]*?)\n```$)|((?:(?:^|\n+)(?:\t| {2,}).+)+\n*)|((?:(?:^|\n)([>*+-]|\d+\.)\s+.*)+)|(?:\!\[([^\]]*?)\]\(([^\)]+?)\))|(\[)|(?:\]\(([^\)]+?)\)|(?:(?:^|\n+)([^\s].*)\n(\-{3,}|={3,})(?:\n+|$))|(?:(?:^|\n+)(#{1,3})\s*(.+)(?:\n+|$))|(?:`([^`].*?)`)|( \n\n*|\n{2,}|__|\*\*|[_*]))/gm,
48+
let tokenizer = /(?:^```(\w*)\n([\s\S]*?)\n```$)|((?:(?:^|\n+)(?:\t| {2,}).+)+\n*)|((?:(?:^|\n)([>*+-]|\d+\.)\s+.*)+)|(?:\!\[([^\]]*?)\]\(([^\)]+?)\))|(\[)|(\](?:\(([^\)]+?)\))?)|(?:(?:^|\n+)([^\s].*)\n(\-{3,}|={3,})(?:\n+|$))|(?:(?:^|\n+)(#{1,3})\s*(.+)(?:\n+|$))|(?:`([^`].*?)`)|( \n\n*|\n{2,}|__|\*\*|[_*])/gm,
4949
context = [],
5050
out = '',
5151
last = 0,
52+
links = {},
5253
chunk, prev, token, inner, t;
5354

54-
md = trim(md);
55+
md = trim(md).replace(/^\[(.+?)\]:\s*(.+)$/gm, (s, name, url) => {
56+
links[name.toLowerCase()] = url;
57+
return '';
58+
});
5559

5660
while ( (token=tokenizer.exec(md)) ) {
5761
prev = md.substring(last, token.index);
@@ -84,24 +88,24 @@ export default function parse(md) {
8488
}
8589
// Links:
8690
else if (token[9]) {
87-
out = out.replace('<a>', `<a href="${encodeAttr(token[9])}">`);
91+
out = out.replace('<a>', `<a href="${encodeAttr(token[10] || links[prev.toLowerCase()])}">`);
8892
chunk = '</a>';
8993
}
9094
else if (token[8]) {
9195
chunk = '<a>';
9296
}
9397
// Headings:
94-
else if (token[10] || token[12]) {
95-
t = 'h' + (token[12] ? token[12].length : (token[11][0]==='='?1:2));
96-
chunk = '\n\n<'+t+'>' + parse(token[10] || token[13]) + '</'+t+'>\n';
98+
else if (token[11] || token[13]) {
99+
t = 'h' + (token[13] ? token[13].length : (token[12][0]==='='?1:2));
100+
chunk = '\n\n<'+t+'>' + parse(token[11] || token[14]) + '</'+t+'>\n';
97101
}
98102
// `code`:
99-
else if (token[14]) {
100-
chunk = '<code>'+token[14]+'</code>';
103+
else if (token[15]) {
104+
chunk = '<code>'+token[15]+'</code>';
101105
}
102106
// Inline formatting: *em*, **strong** & friends
103-
else if (token[15]) {
104-
chunk = tag(context, token[15]);
107+
else if (token[16]) {
108+
chunk = tag(context, token[16]);
105109
}
106110
out += prev;
107111
out += chunk;

test/index.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ describe('snarkdown()', () => {
4343
expect(snarkdown('[Snarkdown](http://github.com/developit/snarkdown)')).to.equal('<a href="http://github.com/developit/snarkdown">Snarkdown</a>');
4444
});
4545

46-
it('parses internal links', () => {
46+
it('parses anchor links', () => {
4747
expect(snarkdown('[Example](#example)')).to.equal('<a href="#example">Example</a>');
4848
});
4949

@@ -56,6 +56,10 @@ describe('snarkdown()', () => {
5656
expect(snarkdown('[![](toc.png)](#toc)')).to.equal('<a href="#toc"><img src="toc.png" alt=""></a>');
5757
expect(snarkdown('[![a](a.png)](#a) [![b](b.png)](#b)')).to.equal('<a href="#a"><img src="a.png" alt="a"></a> <a href="#b"><img src="b.png" alt="b"></a>');
5858
});
59+
60+
it('parses reference links', () => {
61+
expect(snarkdown('\nhello [World]!\n[world]: http://world.com')).to.equal('hello <a href="http://world.com">World</a>!');
62+
});
5963
});
6064

6165
describe('lists', () => {

0 commit comments

Comments
 (0)