diff --git a/lib/utils.js b/lib/utils.js index a396ea8..86a8a10 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -1,4 +1,4 @@ -var URL = require('url') +var WHATWGURL = require('url').URL , namespaces = require('./namespaces') ; @@ -55,13 +55,18 @@ function safeTrim (val) { exports.safeTrim = safeTrim; /* - * Expose require('url').resolve, safely returning if either parameter - * isn't provided + * Resolve a URL against a base URL, returning the original pathUrl if + * either parameter isn't provided or if the URL is not resolvable (e.g. + * tag: URIs and other non-http schemes that the URL constructor rejects). * @private */ function resolve (baseUrl, pathUrl) { if (!baseUrl || !pathUrl) return pathUrl; - return URL.resolve(baseUrl, pathUrl); + try { + return new WHATWGURL(pathUrl, baseUrl).href; + } catch (e) { + return pathUrl; + } } exports.resolve = resolve; @@ -72,8 +77,11 @@ exports.resolve = resolve; */ function isAbsoluteUrl (uri) { if (!uri || typeof uri !== 'string') return false; - var parts = URL.parse(uri); - return Boolean(parts.host); + try { + return Boolean(new WHATWGURL(uri).host); + } catch (e) { + return false; + } } exports.isAbsoluteUrl = isAbsoluteUrl; @@ -130,14 +138,14 @@ function reresolve (node, baseurl) { if (level[el].constructor.name === 'Object') { if (el == 'logo' || el == 'icon' || el == 'link') { if ('#' in level[el]) { - level[el]['#'] = URL.resolve(baseurl, level[el]['#']); + level[el]['#'] = resolve(baseurl, level[el]['#']); } } else if (el == 'image') { if ('url' in level[el] && level[el]['url'].constructor.name === 'Object' && '#' in level[el]['url']) { - level[el]['url']['#'] = URL.resolve(baseurl, level[el]['url']['#']); + level[el]['url']['#'] = resolve(baseurl, level[el]['url']['#']); } if ('link' in level[el] && level[el]['link'].constructor.name === 'Object' && '#' in level[el]['link']) { - level[el]['link']['#'] = URL.resolve(baseurl, level[el]['link']['#']); + level[el]['link']['#'] = resolve(baseurl, level[el]['link']['#']); } } if ('@' in level[el]) { @@ -145,7 +153,7 @@ function reresolve (node, baseurl) { attrs.forEach(function (name) { if (name == 'href' || name == 'src' || name == 'uri') { if ('string' === typeof level[el]['@'][name]) { - level[el]['@'][name] = URL.resolve(baseurl, level[el]['@'][name]); + level[el]['@'][name] = resolve(baseurl, level[el]['@'][name]); } } }); diff --git a/package-lock.json b/package-lock.json index ea28dc9..2a36787 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,7 +17,7 @@ "lodash.uniq": "^4.5.0", "mri": "^1.1.5", "readable-stream": "^2.3.7", - "sax": "^1.2.4" + "sax": ">=1.2.4 <1.4.4" }, "bin": { "feedparser": "bin/feedparser.js" @@ -69,7 +69,6 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.1.tgz", "integrity": "sha512-add7dgA5ppRPxCFJoAGfMDi7PIBXq1RtGo7BhbLaxwrXPOmw8gq48Y9ozT01hUKy9byMjlR20EJhu5zlkErEkg==", "dev": true, - "peer": true, "bin": { "acorn": "bin/acorn" }, diff --git a/test/feeds/atom-with-tag-uri-links.xml b/test/feeds/atom-with-tag-uri-links.xml new file mode 100644 index 0000000..cef709f --- /dev/null +++ b/test/feeds/atom-with-tag-uri-links.xml @@ -0,0 +1,10 @@ + + + Test Feed + + + Test Entry + + tag:mefi.social,2024-01-26:objectId=20368395 + + diff --git a/test/link.js b/test/link.js index de590bf..52d56ca 100644 --- a/test/link.js +++ b/test/link.js @@ -15,4 +15,36 @@ describe('links', function(){ }); }); + it('should not throw or emit a deprecation warning for tag: URI links (issue #295)', function (done) { + var tagUriFeed = __dirname + '/feeds/atom-with-tag-uri-links.xml'; + var items = []; + var sawDeprecation = false; + var origEmit = process.emit; + process.emit = function(event, warning) { + if (event === 'warning' && warning && warning.name === 'DeprecationWarning') { + sawDeprecation = true; + } + return origEmit.apply(process, arguments); + }; + fs.createReadStream(tagUriFeed).pipe(new FeedParser()) + .on('readable', function () { + var stream = this, item; + while ((item = stream.read()) !== null) { + items.push(item); + } + }) + .on('end', function () { + process.emit = origEmit; + assert.equal(items.length, 1); + assert.equal(items[0].link, 'tag:mefi.social,2024-01-26:objectId=20368395'); + assert.equal(sawDeprecation, false, 'Should not emit a DEP0170 deprecation warning'); + done(); + }) + .on('error', function (err) { + process.emit = origEmit; + assert.ifError(err); + done(err); + }); + }); + });