From 297fdec2f8794305f22138e370264fe30c058454 Mon Sep 17 00:00:00 2001 From: Sukka Date: Mon, 28 Oct 2019 17:08:35 +0800 Subject: [PATCH] fix: external link ignore mailto: & javascript: (#3812) * fix: external link ignore mailto: & javascript: Close #3796 * refactor: use startsWith instead of regex * refactor(external_link): use whatwg url * fix(external_link): handle whatwg url api Apply code suggestions from code review by @curbengh --- .../filter/after_post_render/external_link.js | 19 ++++++++--- .../filter/after_render/external_link.js | 17 +++++++--- test/scripts/filters/external_link.js | 32 ++++++++++++------- 3 files changed, 47 insertions(+), 21 deletions(-) diff --git a/lib/plugins/filter/after_post_render/external_link.js b/lib/plugins/filter/after_post_render/external_link.js index a056a5a525..43c8dd348e 100644 --- a/lib/plugins/filter/after_post_render/external_link.js +++ b/lib/plugins/filter/after_post_render/external_link.js @@ -1,15 +1,24 @@ 'use strict'; -const { parse } = require('url'); +const { URL } = require('url'); + +const urlObj = (str) => { + try { + return new URL(str); + } catch (err) { + return str; + } +}; const isExternal = (url, config) => { const exclude = Array.isArray(config.external_link.exclude) ? config.external_link.exclude : [config.external_link.exclude]; - const data = parse(url); + const data = urlObj(url); const host = data.hostname; - const sitehost = parse(config.url).hostname || config.url; + const sitehost = typeof urlObj(config.url) === 'object' ? urlObj(config.url).hostname : config.url; - if (!data.protocol || !sitehost) return false; + if (!sitehost || typeof data === 'string') return false; + if (data.origin === 'null') return false; if (exclude && exclude.length) { for (const i of exclude) { @@ -34,7 +43,7 @@ function externalLinkFilter(data) { }, config.external_link); } if (config.external_link === false || config.external_link.enable === false || - config.external_link.field !== 'post') return; + config.external_link.field !== 'post') return; data.content = data.content.replace(//gi, (str, hrefStr, href) => { if (/target=/gi.test(str) || !isExternal(href, config)) return str; diff --git a/lib/plugins/filter/after_render/external_link.js b/lib/plugins/filter/after_render/external_link.js index fd3d7b4ea8..d064bf13d5 100644 --- a/lib/plugins/filter/after_render/external_link.js +++ b/lib/plugins/filter/after_render/external_link.js @@ -1,6 +1,14 @@ 'use strict'; -const { parse } = require('url'); +const { URL } = require('url'); + +const urlObj = (str) => { + try { + return new URL(str); + } catch (err) { + return str; + } +}; /** * Check whether the link is external @@ -11,11 +19,12 @@ const { parse } = require('url'); const isExternal = (url, config) => { const exclude = Array.isArray(config.external_link.exclude) ? config.external_link.exclude : [config.external_link.exclude]; - const data = parse(url); + const data = urlObj(url); const host = data.hostname; - const sitehost = parse(config.url).hostname || config.url; + const sitehost = typeof urlObj(config.url) === 'object' ? urlObj(config.url).hostname : config.url; - if (!data.protocol || !sitehost) return false; + if (!sitehost || typeof data === 'string') return false; + if (data.origin === 'null') return false; if (exclude && exclude.length) { for (const i of exclude) { diff --git a/test/scripts/filters/external_link.js b/test/scripts/filters/external_link.js index b0d7d64c40..5eec7074fe 100644 --- a/test/scripts/filters/external_link.js +++ b/test/scripts/filters/external_link.js @@ -208,23 +208,27 @@ describe('External link - post', () => { '# External link test', '1. External link', 'Hexo', - '2. External link with "rel" Attribute', + '2. Link with hash (#), mailto: , javascript: shouldn\'t be processed', + 'Hexo', + 'Hexo', + 'Hexo', + '3. External link with "rel" Attribute', 'Hexo', 'Hexo', 'Hexo', 'Hexo', 'Hexo', 'Hexo', - '3. External link with Other Attributes', + '4. External link with Other Attributes', 'Hexo', 'Hexo', - '4. Internal link', + '5. Internal link', 'Link', - '5. Ignore links have "target" attribute', + '6. Ignore links have "target" attribute', 'Hexo', - '6. Ignore links don\'t have "href" attribute', + '7. Ignore links don\'t have "href" attribute', 'Anchor', - '7. Ignore links whose hostname is same as config', + '8. Ignore links whose hostname is same as config', 'Example Domain' ].join('\n'); @@ -235,23 +239,27 @@ describe('External link - post', () => { '# External link test', '1. External link', 'Hexo', - '2. External link with "rel" Attribute', + '2. Link with hash (#), mailto: , javascript: shouldn\'t be processed', + 'Hexo', + 'Hexo', + 'Hexo', + '3. External link with "rel" Attribute', 'Hexo', 'Hexo', 'Hexo', 'Hexo', 'Hexo', 'Hexo', - '3. External link with Other Attributes', + '4. External link with Other Attributes', 'Hexo', 'Hexo', - '4. Internal link', + '5. Internal link', 'Link', - '5. Ignore links have "target" attribute', + '6. Ignore links have "target" attribute', 'Hexo', - '6. Ignore links don\'t have "href" attribute', + '7. Ignore links don\'t have "href" attribute', 'Anchor', - '7. Ignore links whose hostname is same as config', + '8. Ignore links whose hostname is same as config', 'Example Domain' ].join('\n')); });