diff --git a/ImageResolver.js b/ImageResolver.js index a02cc76..6a5ad72 100644 --- a/ImageResolver.js +++ b/ImageResolver.js @@ -48,18 +48,40 @@ window.ImageResolver = (function(){ clbk(null); }; + ImageResolver.prototype.iterateFilters = function(filters, url, dom){ + if (filters.length){ + var result; + for (var i = 0; i < filters.length; i++){ + result = filters[i].directResolve(url, dom); + if (result !== null){ + return result; + } + } + return null; + } else { + return null; + } + }; + ImageResolver.prototype.resolve = function(url, clbk) { var filters = this.filters; this.next(filters, url, clbk); return this; }; + ImageResolver.prototype.directResolve = function(url, dom) { + var filters = this.filters; + return this.iterateFilters(filters, url, dom); + }; + return new ImageResolver(); })(); /** * Plugins + * + * NOTE THAT NOT ALL OF THEM HAVE DIRECT RESOLUTION */ /** @@ -77,6 +99,14 @@ FileExtensionResolver.prototype.resolve = function(url, clbk) { clbk(null); }; +FileExtensionResolver.prototype.directResolve = function(url, dom) { + var pathname = URI(url).pathname(); + if (pathname.match(/(png|jpg|jpeg|gif|bmp|svg)$/i)) { + return url; + } + return null; +}; + /** * Imgur page */ @@ -91,6 +121,14 @@ ImgurPageResolver.prototype.resolve = function(url, clbk) { clbk(null); }; +ImgurPageResolver.prototype.directResolve = function(url, dom) { + var matches = url.match(/http:\/\/(i\.)*imgur.com\/(gallery\/){0,1}(.*)/); + if (matches && matches.length && (-1 === matches[matches.length-1].indexOf('/'))) { + return 'http://i.imgur.com/' + matches[matches.length-1] + '.jpg' ; //@FIXME : image can be gif or png + } + return null; +}; + /** * Imgur album */ @@ -143,6 +181,18 @@ NineGagResolver.prototype.resolve = function(url, clbk) { clbk(null); }; +NineGagResolver.prototype.directResolve = function(url, dom) { + var matches = url.match(/http:\/\/9gag.com\/gag\/(.*)/) || []; + var id; + var image; + if (matches.length) { + id = matches[1]; + image = 'http://d24w6bsrhbeh9d.cloudfront.net/photo/' + id + '_700b.jpg'; + return image; + } + return null; +}; + /** * Instagram page */ @@ -158,6 +208,17 @@ InstagramResolver.prototype.resolve = function(url, clbk) { clbk(null); }; +InstagramResolver.prototype.directResolve = function(url, dom) { + var id = url.match(/http:\/\/instagr(\.am|am\.com)\/p\/([^\/]+)/); + if (id && id.length > 1) { + url = 'http://instagram.com/p/' + id[2] + '/media/?size=l'; + return url; + } + return null; +}; + + + /** * Flickr photo page */ @@ -265,96 +326,100 @@ WebpageResolver.prototype._score = function(image) { return score; }; -WebpageResolver.prototype.resolve = function(url, clbk) { - var self = this; - ImageResolver.fetch( - url, - function(html) { - var images = html.match(/]*)>/g) || []; - var image; - var candidates = []; - var significant_surface = 16*16; - var significant_surface_count = 0; - var tag; - var src; - var surface; - for (var i=0,l=images.length; i significant_surface) { - significant_surface_count++; - } - candidates.push({ - url: src, - surface: surface, - score: self._score(tag) - }); - } +WebpageResolver.prototype._resolveImageLazily = function(url, html) { + var images = html.match(/]*)>/g) || []; + var image; + var candidates = []; + var significant_surface = 16*16; + var significant_surface_count = 0; + var tag; + var src; + var surface; + for (var i=0,l=images.length; i= 0); - }); - if (!candidates.length) { - clbk(null); - return; + if (tag.attributes['data-lazy-src']) { + src = tag.attributes['data-lazy-src']; + } + if (!src){ + continue; } - //Sort candidates by size, or score - if (significant_surface_count > 0) { - candidates = candidates.sort(function(a,b){ - return b.surface - a.surface; - }); + // Compute surface area, even when only 1 dimension is specified + if (tag.attributes.width) { + if (tag.attributes.height) { + surface = parseInt(tag.attributes.width, 10) * parseInt(tag.attributes.height,10); + } else { + surface = parseInt(tag.attributes.width, 10); + } } else { - candidates = candidates.sort(function(a,b){ - return b.score - a.score; - }); + if (tag.attributes.height) { + surface = parseInt(tag.attributes.height,10); + } else { + surface = 0; + } } - image = candidates[0].url; - //Resolve relative url - if (!image.match(/^http/)) { - var uri = new URI(image); - image = uri.absoluteTo(url); + if (surface > significant_surface) { + significant_surface_count++; } - clbk(image); + candidates.push({ + url: src, + surface: surface, + score: this._score(tag) + }); + } + } + + if (!candidates.length) { + return null + } + + //Remove scores below 0 + candidates = candidates.filter(function(item){ + return (item.score >= 0); + }); + if (!candidates.length) { + return null; + } + + //Sort candidates by size, or score + if (significant_surface_count > 0) { + candidates = candidates.sort(function(a,b){ + return b.surface - a.surface; + }); + } else { + candidates = candidates.sort(function(a,b){ + return b.score - a.score; + }); + } + image = candidates[0].url; + //Resolve relative url + if (!image.match(/^http/)) { + var uri = new URI(image); + image = uri.absoluteTo(url); + } + + return image; +}; + +WebpageResolver.prototype.resolve = function(url, clbk) { + self = this; + ImageResolver.fetch( + url, + function(html) { + clbk(self._resolveImageLazily(url, html)); return; }, function() { @@ -364,97 +429,107 @@ WebpageResolver.prototype.resolve = function(url, clbk) { ); }; +WebpageResolver.prototype.directResolve = function(url, dom) { + return this._resolveImageLazily(url, dom.documentElement.innerHTML) +}; + + /** * Opengraph meta tags */ function OpengraphResolver() { } -OpengraphResolver.prototype.resolve = function(url, clbk) { - var self = this; - ImageResolver.fetch( - url, - function(html) { - // @TODO : add - var meta = html.match(/<(meta|link)([^>]*)>/g) || []; - var tag; - var images = []; - var image = null; - var tags = [ - // Facebook, Google+ - { - type: "facebook", - attribute : "property", - name : "og:image", - value : "content" - }, - // Old Facebook - { - type: "facebook", - attribute : "rel", - name : "image_src", - value : "href" - }, - // Old Twitter card - { - type: "twitter", - attribute : "name", - name : "twitter:image", - value : "value" - }, - // New Twitter card - { - type: "twitter", - attribute : "name", - name : "twitter:image", - value : "content" - } - ]; - - for (var i=0,l=meta.length; i + var meta = html.match(/<(meta|link)([^>]*)>/g) || []; + var tag; + var images = []; + var image = null; + var tags = [ + // Facebook, Google+ + { + type: "facebook", + attribute : "property", + name : "og:image", + value : "content" + }, + // Old Facebook + { + type: "facebook", + attribute : "rel", + name : "image_src", + value : "href" + }, + // Old Twitter card + { + type: "twitter", + attribute : "name", + name : "twitter:image", + value : "value" + }, + // New Twitter card + { + type: "twitter", + attribute : "name", + name : "twitter:image", + value : "content" + } + ]; + + for (var i=0,l=meta.length; i 1) { - for (i=0, l=images.length; i 1) { + for (i=0, l=images.length; i +If you already have access to the DOM of the page you can call directResolve, thus avoiding the extra GET request for the html code neccesary in some of the plugins. Furthermore, this gives a direct result without needing any callback. Note that this won't work in plugins requiring more ajax calls than the original html fetch. + + + + + Dependencies ------------