|
|
@ -12,14 +12,110 @@ |
|
|
|
// - fractionals 1/2, 1/4, 3/4 -> ½, ¼, ¾
|
|
|
|
// - miltiplication 2 x 4 -> 2 × 4
|
|
|
|
|
|
|
|
var assign = require('./common/utils').assign; |
|
|
|
var defaults = require('./defaults_typographer'); |
|
|
|
var Ruler = require('./ruler'); |
|
|
|
|
|
|
|
var Autolinker = require('autolinker'); |
|
|
|
|
|
|
|
|
|
|
|
var assign = require('./common/utils').assign; |
|
|
|
var escapeHtml = require('./helpers').escapeHtml; |
|
|
|
var defaults = require('./defaults_typographer'); |
|
|
|
var Ruler = require('./ruler'); |
|
|
|
|
|
|
|
|
|
|
|
var links = []; |
|
|
|
var autolinker = new Autolinker({ |
|
|
|
stripPrefix: false, |
|
|
|
replaceFn: function (autolinker, match) { |
|
|
|
// Only collect matched strings but don't change anything.
|
|
|
|
var url; |
|
|
|
if (match.getType() === 'url') { |
|
|
|
url = match.getUrl(); |
|
|
|
if (/^(http|https|ftp|git)/.test(url)) { |
|
|
|
links.push(url); |
|
|
|
} |
|
|
|
} |
|
|
|
return false; |
|
|
|
} |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
var rules = []; |
|
|
|
|
|
|
|
|
|
|
|
rules.push(function linkify(t, state) { |
|
|
|
var i, token, text, nodes, ln, pos, level, |
|
|
|
tokens = state.tokens; |
|
|
|
|
|
|
|
if (!t.options.linkify) { return; } |
|
|
|
|
|
|
|
for (i = tokens.length - 1; i >= 0; i--) { |
|
|
|
token = tokens[i]; |
|
|
|
|
|
|
|
// Skip content of links
|
|
|
|
if (token.type === 'link_close') { |
|
|
|
i--; |
|
|
|
while (tokens[i].type !== 'link_open' && tokens[i].level !== token.level) { |
|
|
|
i--; |
|
|
|
} |
|
|
|
i--; |
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
if (token.type === 'text' && |
|
|
|
(token.content.indexOf('://') || |
|
|
|
token.content.indexOf('www'))) { |
|
|
|
text = token.content; |
|
|
|
links = []; |
|
|
|
autolinker.link(text); |
|
|
|
|
|
|
|
if (!links.length) { continue; } |
|
|
|
|
|
|
|
// Now split string to nodes
|
|
|
|
nodes = []; |
|
|
|
level = token.level; |
|
|
|
|
|
|
|
for (ln = 0; ln < links.length; ln++) { |
|
|
|
pos = text.indexOf(links[ln]); |
|
|
|
if (pos) { |
|
|
|
level = level; |
|
|
|
nodes.push({ |
|
|
|
type: 'text', |
|
|
|
content: text.slice(0, pos), |
|
|
|
level: level |
|
|
|
}); |
|
|
|
} |
|
|
|
nodes.push({ |
|
|
|
type: 'link_open', |
|
|
|
href: links[ln], |
|
|
|
title: '', |
|
|
|
level: level++ |
|
|
|
}); |
|
|
|
nodes.push({ |
|
|
|
type: 'text', |
|
|
|
content: escapeHtml(links[ln]), |
|
|
|
level: level |
|
|
|
}); |
|
|
|
nodes.push({ |
|
|
|
type: 'link_close', |
|
|
|
level: --level |
|
|
|
}); |
|
|
|
text = text.slice(pos + links[ln].length); |
|
|
|
} |
|
|
|
if (text.length) { |
|
|
|
nodes.push({ |
|
|
|
type: 'text', |
|
|
|
content: text, |
|
|
|
level: level |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
// replace cuttent node
|
|
|
|
state.tokens = tokens = [].concat(tokens.slice(0, i), nodes, tokens.slice(i + 1)); |
|
|
|
} |
|
|
|
} |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
rules.push(function single(t, state) { |
|
|
|
var i, token, text, |
|
|
|
tokens = state.tokens, |
|
|
|