refactor HTML module; add functionality to Ox.parseMarkdown; add tests
This commit is contained in:
parent
d6b86b518b
commit
3683bf3d29
1 changed files with 103 additions and 85 deletions
|
@ -26,31 +26,6 @@
|
|||
].join('|') + ')\\/?>', 'gi')
|
||||
},
|
||||
replace = {
|
||||
mail: [
|
||||
/\b([0-9A-Z\.\+\-_]+@(?:[0-9A-Z\-]+\.)+[A-Z]{2,6})\b/gi, '$1'
|
||||
/*
|
||||
function(match, mail) {
|
||||
return Ox.encodeEmailAddress(mail);
|
||||
}
|
||||
*/
|
||||
],
|
||||
namedEntity: [
|
||||
new RegExp('(' + Ox.values(htmlEntities).join('|') + ')', 'g'),
|
||||
function(match) {
|
||||
return Ox.keyOf(htmlEntities, match);
|
||||
}
|
||||
],
|
||||
numericEntity: [
|
||||
/&#([0-9A-FX]+);/gi,
|
||||
function(match, code) {
|
||||
return Ox.char(
|
||||
/^X/i.test(code)
|
||||
? parseInt(code.slice(1), 16)
|
||||
: parseInt(code, 10)
|
||||
);
|
||||
}
|
||||
],
|
||||
tag: {
|
||||
a: [
|
||||
[
|
||||
/<a [^<>]*?href="((\/|https?:\/\/|mailto:).+?)".*?>/gi,
|
||||
|
@ -86,7 +61,15 @@
|
|||
];
|
||||
}
|
||||
},
|
||||
url: [
|
||||
salt = Ox.range(2).map(function(){
|
||||
return Ox.range(16).map(function() {
|
||||
return Ox.char(65 + Ox.random(26));
|
||||
}).join('');
|
||||
});
|
||||
|
||||
function addLinks(string, obfuscate) {
|
||||
return string
|
||||
.replace(
|
||||
/\b((https?:\/\/|www\.).+?)([\.,:;!\?\)\]]*?(\s|$))/gi,
|
||||
function(match, url, prefix, end) {
|
||||
prefix = prefix.toLowerCase() == 'www.' ? 'http://' : '';
|
||||
|
@ -95,13 +78,34 @@
|
|||
{end: end, prefix: prefix, url: url}
|
||||
);
|
||||
}
|
||||
]
|
||||
},
|
||||
salt = Ox.range(2).map(function(){
|
||||
return Ox.range(16).map(function() {
|
||||
return Ox.char(65 + Ox.random(26));
|
||||
}).join('');
|
||||
});
|
||||
)
|
||||
.replace(
|
||||
/\b([0-9A-Z\.\+\-_]+@(?:[0-9A-Z\-]+\.)+[A-Z]{2,6})\b/gi,
|
||||
obfuscate ? function(match, mail) {
|
||||
return Ox.encodeEmailAddress(mail);
|
||||
} : '<a href="mailto:$1">$1</a>'
|
||||
);
|
||||
}
|
||||
|
||||
function decodeHTMLEntities(string) {
|
||||
return string
|
||||
.replace(
|
||||
new RegExp('(' + Ox.values(htmlEntities).join('|') + ')', 'g'),
|
||||
function(match) {
|
||||
return Ox.keyOf(htmlEntities, match);
|
||||
}
|
||||
)
|
||||
.replace(
|
||||
/&#([0-9A-FX]+);/gi,
|
||||
function(match, code) {
|
||||
return Ox.char(
|
||||
/^X/i.test(code)
|
||||
? parseInt(code.slice(1), 16)
|
||||
: parseInt(code, 10)
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// Splits a string into text (even indices) and tags (odd indices), ignoring
|
||||
// tags with starting positions that are included in the ignore array
|
||||
|
@ -136,11 +140,6 @@
|
|||
@*/
|
||||
Ox.addLinks = function(string, isHTML) {
|
||||
var isLink = false;
|
||||
function replaceString(string) {
|
||||
return string
|
||||
.replace(replace.mail[0], replace.mail[1])
|
||||
.replace(replace.url[0], replace.url[1]);
|
||||
}
|
||||
return isHTML
|
||||
? splitHTMLTags(string).map(function(string, i) {
|
||||
var isTag = i % 2;
|
||||
|
@ -151,9 +150,9 @@
|
|||
isLink = false;
|
||||
}
|
||||
}
|
||||
return isTag || isLink ? string : replaceString(string);
|
||||
return isTag || isLink ? string : addLinks(string);
|
||||
}).join('')
|
||||
: Ox.normalizeHTML(replaceString(string));
|
||||
: Ox.normalizeHTML(addLinks(string));
|
||||
};
|
||||
|
||||
/*@
|
||||
|
@ -224,9 +223,7 @@
|
|||
Ox.decodeHTMLEntities = function(string, decodeAll) {
|
||||
return decodeAll
|
||||
? Ox.decodeHTMLEntities(Ox.normalizeHTML(string))
|
||||
: String(string)
|
||||
.replace(replace.namedEntity[0], replace.namedEntity[1])
|
||||
.replace(replace.numericEntity[0], replace.numericEntity[1]);
|
||||
: decodeHTMLEntities(string);
|
||||
};
|
||||
|
||||
/*@
|
||||
|
@ -360,10 +357,20 @@
|
|||
[example](http://example.com "example.com") -> <a href="http://example.com" title="example.com">example</a>
|
||||
> Ox.parseMarkdown('*foo* **bar** `baz` ``back`tick``')
|
||||
'<em>foo</em> <strong>bar</strong> <code>baz</code> <code>back`tick</code>'
|
||||
> Ox.parseMarkdown('<http://example.com>')
|
||||
'<a href="http://example.com">http://example.com</a>'
|
||||
> Ox.parseMarkdown('[example](http://example.com "example.com")')
|
||||
'<a href="http://example.com" title="example.com">example</a>'
|
||||
> Ox.parseMarkdown('[example](http://example.com?foo=bar&bar=baz)')
|
||||
'<a href="http://example.com?foo=bar&bar=baz">example</a>'
|
||||
> Ox(Ox.parseMarkdown('<mail@example.com>')).startsWith('<a href="')
|
||||
true
|
||||
> Ox(Ox.parseMarkdown('<mail@example.com>')).endsWith('</a>')
|
||||
true
|
||||
> Ox(Ox.parseMarkdown('<mail@example.com>')).count(':')
|
||||
1
|
||||
> Ox(Ox.parseMarkdown('<mail@example.com>')).decodeHTMLEntities()
|
||||
'<a href="mailto:mail@example.com">mail@example.com</a>'
|
||||
*/
|
||||
Ox.parseMarkdown = function(string) {
|
||||
// see https://github.com/coreyti/showdown/blob/master/src/showdown.js
|
||||
|
@ -379,24 +386,35 @@
|
|||
)
|
||||
.replace(
|
||||
/\n```(.*)\n([^`]+)\n```/g,
|
||||
function(match, a, b) {
|
||||
return '<pre><code' + (a ? ' class="' + a + '"' : '') + '>'
|
||||
+ b + '\n</code></pre>';
|
||||
function(match, classname, code) {
|
||||
return '<pre><code'
|
||||
+ (classname ? ' class="' + classname + '"' : '')
|
||||
+ '>' + code + '\n</code></pre>';
|
||||
}
|
||||
)
|
||||
.replace(
|
||||
/(^|[^\\])(`+)([^\r]*?[^`])\2(?!`)/gm,
|
||||
function(match, a, b, c, d) {
|
||||
return a + '<code>'
|
||||
+ Ox.encodeHTMLEntities(c.trim()) + '</code>';
|
||||
function(match, prev, backticks, code, next) {
|
||||
return prev + '<code>'
|
||||
+ Ox.encodeHTMLEntities(code.trim()) + '</code>';
|
||||
}
|
||||
)
|
||||
.replace(
|
||||
/(\[((?:\[[^\]]*\]|[^\[\]])*)\]\([ \t]*()<?(.*?)>?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g,
|
||||
function(match, a, b, c, d, e, f, g) {
|
||||
return '<a href="' + Ox.encodeHTMLEntities(d) + '"' + (
|
||||
g ? ' title="' + Ox.encodeHTMLEntities(g) + '"' : ''
|
||||
) + '>' + b + '</a>';
|
||||
function(match, all, text, id, url, rest, quote, title) {
|
||||
return '<a href="' + Ox.encodeHTMLEntities(url) + '"' + (
|
||||
title ? ' title="' + Ox.encodeHTMLEntities(title) + '"' : ''
|
||||
) + '>' + text + '</a>';
|
||||
}
|
||||
)
|
||||
.replace(
|
||||
/<((https?|ftp|dict):[^'">\s]+)>/gi,
|
||||
'<a href=\"$1\">$1</a>'
|
||||
)
|
||||
.replace(
|
||||
/<(?:mailto:)?([-.\w]+\@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)>/gi,
|
||||
function(match, mail) {
|
||||
return Ox.encodeEmailAddress(mail);
|
||||
}
|
||||
);
|
||||
};
|
||||
|
@ -447,7 +465,7 @@
|
|||
});
|
||||
}
|
||||
tags.forEach(function(tag) {
|
||||
var array = replace.tag[tag] || replace.tag['*'](tag);
|
||||
var array = replace[tag] || replace['*'](tag);
|
||||
Ox.forEach(array, function(value) {
|
||||
html = html.replace(value[0], function() {
|
||||
matches.push(Ox.formatString(value[1], arguments));
|
||||
|
|
Loading…
Reference in a new issue