diff --git a/packages/linkifyjs/src/parser.mjs b/packages/linkifyjs/src/parser.mjs index 0deacc4..f854f75 100644 --- a/packages/linkifyjs/src/parser.mjs +++ b/packages/linkifyjs/src/parser.mjs @@ -191,6 +191,15 @@ export function init({ groups }) { tt(DomainDotTld, tk.SLASH, Url); tt(DomainDotTldColonPort, tk.SLASH, Url); + // A query string or fragment may also follow the domain (or port) directly, + // without a path slash (e.g. `example.com?q=1`, `example.com#frag`). Mirror + // how the `Url` state treats these tokens: `?` is non-accepting (a trailing + // `?` is trimmed), `#` is accepting. + tt(DomainDotTld, tk.QUERY, UrlNonaccept); + tt(DomainDotTld, tk.POUND, Url); + tt(DomainDotTldColonPort, tk.QUERY, UrlNonaccept); + tt(DomainDotTldColonPort, tk.POUND, Url); + // Note that domains that begin with schemes are treated slighly differently const SchemeColon = tt(Scheme, tk.COLON); // e.g., 'mailto:' const SlashSchemeColon = tt(SlashScheme, tk.COLON); // e.g., 'http:' diff --git a/test/spec/linkifyjs/parser.test.mjs b/test/spec/linkifyjs/parser.test.mjs index a07013c..d712849 100644 --- a/test/spec/linkifyjs/parser.test.mjs +++ b/test/spec/linkifyjs/parser.test.mjs @@ -12,6 +12,13 @@ const tests = [ ['google.com', [Url], ['google.com']], ['I like google.com the most', [Text, Url, Text], ['I like ', 'google.com', ' the most']], ['I like Google.com the most', [Text, Url, Text], ['I like ', 'Google.com', ' the most']], + // Query string / fragment directly after the domain (no path slash) (#516) + ['example.com?foo=bar', [Url], ['example.com?foo=bar']], + ['example.com?a=1&b=2', [Url], ['example.com?a=1&b=2']], + ['example.com:8080?x=1', [Url], ['example.com:8080?x=1']], + ['example.com#section', [Url], ['example.com#section']], + // A trailing `?` is sentence punctuation, not a query string, so it is trimmed + ['have you seen example.com?', [Text, Url, Text], ['have you seen ', 'example.com', '?']], [ 'there are two tests, brennan.com and nick.ca -- do they work?', [Text, Url, Text, Url, Text], @@ -75,8 +82,8 @@ const tests = [ ' ', 'goo.gl/0192n1', ' ', - 'google.com', - '?q=asda test ', + 'google.com?q=asda', + ' test ', 'bit.ly/0912j', ' ', 'www.bob.com',