From 3683bf3d29ed6cfb03552bd0be57800a14d33217 Mon Sep 17 00:00:00 2001 From: rolux Date: Thu, 31 May 2012 00:47:19 +0200 Subject: [PATCH] refactor HTML module; add functionality to Ox.parseMarkdown; add tests --- source/Ox/js/HTML.js | 188 ++++++++++++++++++++++++------------------- 1 file changed, 103 insertions(+), 85 deletions(-) diff --git a/source/Ox/js/HTML.js b/source/Ox/js/HTML.js index 654bb6a5..caf4e886 100644 --- a/source/Ox/js/HTML.js +++ b/source/Ox/js/HTML.js @@ -26,67 +26,50 @@ ].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: [ - [ - /]*?href="((\/|https?:\/\/|mailto:).+?)".*?>/gi, - '', - ], - [ - /<\/a>/gi, - '' - ] + a: [ + [ + /]*?href="((\/|https?:\/\/|mailto:).+?)".*?>/gi, + '', ], - img: [ - [ - /]*?src="((\/|https?:\/\/).+?)".*?>/gi, - '' - ] + [ + /<\/a>/gi, + '' + ] + ], + img: [ + [ + /]*?src="((\/|https?:\/\/).+?)".*?>/gi, + '' + ] + ], + rtl: [ + [ + //gi, + '
' ], - rtl: [ + [ + /<\/rtl>/gi, + '
' + ] + ], + '*': function(tag) { + return [ [ - //gi, - '
' - ], - [ - /<\/rtl>/gi, - '
' + new RegExp('', 'gi'), + '{0}' ] - ], - '*': function(tag) { - return [ - [ - new RegExp('', 'gi'), - '{0}' - ] - ]; - } - }, - 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); + } : '$1' + ); + } + + 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") -> example > Ox.parseMarkdown('*foo* **bar** `baz` ``back`tick``') 'foo bar baz back`tick' + > Ox.parseMarkdown('') + 'http://example.com' > Ox.parseMarkdown('[example](http://example.com "example.com")') 'example' > Ox.parseMarkdown('[example](http://example.com?foo=bar&bar=baz)') 'example' + > Ox(Ox.parseMarkdown('')).startsWith('mail@example.com' */ 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 '
'
-                        + b + '\n
'; + function(match, classname, code) { + return '
' + code + '\n
'; } ) .replace( /(^|[^\\])(`+)([^\r]*?[^`])\2(?!`)/gm, - function(match, a, b, c, d) { - return a + '' - + Ox.encodeHTMLEntities(c.trim()) + ''; + function(match, prev, backticks, code, next) { + return prev + '' + + Ox.encodeHTMLEntities(code.trim()) + ''; } ) .replace( /(\[((?:\[[^\]]*\]|[^\[\]])*)\]\([ \t]*()?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g, - function(match, a, b, c, d, e, f, g) { - return '' + b + ''; + function(match, all, text, id, url, rest, quote, title) { + return '' + text + ''; + } + ) + .replace( + /<((https?|ftp|dict):[^'">\s]+)>/gi, + '$1' + ) + .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));