diff --git a/source/Ox/js/HTML.js b/source/Ox/js/HTML.js index bf742c66..a4974b57 100644 --- a/source/Ox/js/HTML.js +++ b/source/Ox/js/HTML.js @@ -27,8 +27,12 @@ }, replace = { mail: [ - /\b([0-9A-Z\.\+\-_]+@(?:[0-9A-Z\-]+\.)+[A-Z]{2,6})\b/gi, - '$1' + /\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'), @@ -84,7 +88,7 @@ }, url: [ /\b((https?:\/\/|www\.).+?)([\.,:;!\?\)\]]*?(\s|$))/gi, - function(string, url, prefix, end) { + function(match, url, prefix, end) { prefix = prefix.toLowerCase() == 'www.' ? 'http://' : ''; return Ox.formatString( '{url}{end}', @@ -152,6 +156,24 @@ : Ox.normalizeHTML(replaceString(string)); }; + /*@ + Ox.encodeEmailAddress Returns obfuscated mailto: link + > Ox.encodeEmailAddress('mailto:foo@bar.com').indexOf(':') > -1 + true + @*/ + Ox.encodeEmailAddress = function(string) { + var parts = ['mailto:' + string, string].map(function(part) { + return Ox.map(part, function(char) { + var code = char.charCodeAt(0); + return char == ':' ? ':' + : '&#' + + (Math.random() < 0.5 ? code : 'x' + code.toString(16)) + + ';' + }); + }); + return '' + parts[1] + ''; + }; + /*@ Ox.encodeHTMLEntities Encodes HTML entities (string[, encodeAll]) -> String @@ -329,12 +351,62 @@ return Ox.$('
').html(html).html(); }; + /*@ + Ox.parseMarkdown Parses (a tiny subset of) Markdown. + \*foo\* -> foo + \*\*foo\*\* -> foo + \`foo\` -> foo + \`\`\`code\`\`\` ->
foo
+ [example](http://example.com "example.com") -> example + > Ox.parseMarkdown('*foo* **bar** `baz` ``back`tick``') + 'foo bar baz back`tick' + > Ox.parseMarkdown('[example](http://example.com "example.com")') + 'example' + > Ox.parseMarkdown('[example](http://example.com?foo=bar&bar=baz)') + 'example' + */ + Ox.parseMarkdown = function(string) { + // see https://github.com/coreyti/showdown/blob/master/src/showdown.js + return string.replace(/\r\n/g, '\n').replace(/\r/g, '\n') + .replace(/\n\n/g, '

') + .replace( + /(\*\*|__)(?=\S)([^\r]*?\S[*_]*)\1/g, + '$2' + ) + .replace( + /(\*|_)(?=\S)([^\r]*?\S)\1/g, + '$2' + ) + .replace( + /\n```(.*)\n([^`]+)\n```/g, + function(match, a, b) { + return '
'
+                        + Ox.encodeHTMLEntities(b) + '\n
'; + } + ) + .replace( + /(^|[^\\])(`+)([^\r]*?[^`])\2(?!`)/gm, + function(match, a, b, c, d) { + return a + '' + + Ox.encodeHTMLEntities(c.trim()) + ''; + } + ) + .replace( + /(\[((?:\[[^\]]*\]|[^\[\]])*)\]\([ \t]*()?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g, + function(match, a, b, c, d, e, f, g) { + return '' + b + ''; + } + ); + }; + /*@ Ox.sanitizeHTML Takes untrusted HTML and returns something trustworthy - > Ox.sanitizeHTML('http://foo.com, bar') - 'http://foo.com, bar' - > Ox.sanitizeHTML('http://foo.com/foo?bar, bar') - 'http://foo.com/foo?bar, bar' + > Ox.sanitizeHTML('http://foo.com, ...') + 'http://foo.com, ...' + > Ox.sanitizeHTML('http://foo.com/foo?bar&baz, ...') + 'http://foo.com/foo?bar&baz, ...' > Ox.sanitizeHTML('(see: www.foo.com)') '(see: www.foo.com)' > Ox.sanitizeHTML('foo@bar.com')