From 98a12b8773f0845f89f83035a767f129f0aa77fa Mon Sep 17 00:00:00 2001 From: Luigi Pinca Date: Fri, 14 May 2021 12:32:59 +0200 Subject: [PATCH] [fix] Special case the `file:` protocol Fixes #203 --- index.js | 13 +++++++++---- test/test.js | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 4 deletions(-) diff --git a/index.js b/index.js index 72b27c0..94e357e 100644 --- a/index.js +++ b/index.js @@ -33,7 +33,7 @@ var rules = [ ['#', 'hash'], // Extract from the back. ['?', 'query'], // Extract from the back. function sanitize(address) { // Sanitize what is left of the address - return address.replace('\\', '/'); + return address.replace(/\\/g, '/'); }, ['/', 'pathname'], // Extract from the back. ['@', 'auth', 1], // Extract from the front. @@ -224,7 +224,9 @@ function Url(address, location, parser) { // When the authority component is absent the URL starts with a path // component. // - if (!extracted.slashes) instructions[3] = [/(.*)/, 'pathname']; + if (!extracted.slashes || url.protocol === 'file:') { + instructions[3] = [/(.*)/, 'pathname']; + } for (; i < instructions.length; i++) { instruction = instructions[i]; @@ -288,7 +290,10 @@ function Url(address, location, parser) { // Default to a / for pathname if none exists. This normalizes the URL // to always have a / // - if (url.pathname.charAt(0) !== '/' && url.hostname) { + if ( + url.pathname.charAt(0) !== '/' + && (url.hostname || url.protocol === 'file:') + ) { url.pathname = '/' + url.pathname; } @@ -430,7 +435,7 @@ function toString(stringify) { if (protocol && protocol.charAt(protocol.length - 1) !== ':') protocol += ':'; - var result = protocol + (url.slashes ? '//' : ''); + var result = protocol + (url.slashes || url.protocol === 'file:' ? '//' : ''); if (url.username) { result += url.username; diff --git a/test/test.js b/test/test.js index eec3937..38290ed 100644 --- a/test/test.js +++ b/test/test.js @@ -438,6 +438,48 @@ describe('url-parse', function () { data.set('protocol', 'https:'); assume(data.href).equals('https://google.com/foo'); }); + + it('handles the file: protocol', function () { + var slashes = ['', '/', '//', '///', '////', '/////']; + var data; + var url; + + for (var i = 0; i < slashes.length; i++) { + data = parse('file:' + slashes[i]); + assume(data.protocol).equals('file:'); + assume(data.pathname).equals('/'); + assume(data.href).equals('file:///'); + } + + url = 'file:///Users/foo/BAR/baz.pdf'; + data = parse(url); + assume(data.protocol).equals('file:'); + assume(data.pathname).equals('/Users/foo/BAR/baz.pdf'); + assume(data.href).equals(url); + + url = 'file:///foo/bar?baz=qux#hash'; + data = parse(url); + assume(data.protocol).equals('file:'); + assume(data.hash).equals('#hash'); + assume(data.query).equals('?baz=qux'); + assume(data.pathname).equals('/foo/bar'); + assume(data.href).equals(url); + + data = parse('file://c:\\foo\\bar\\'); + assume(data.protocol).equals('file:'); + assume(data.pathname).equals('/c:/foo/bar/'); + assume(data.href).equals('file:///c:/foo/bar/'); + + data = parse('foo/bar', 'file:///baz'); + assume(data.protocol).equals('file:'); + assume(data.pathname).equals('/foo/bar'); + assume(data.href).equals('file:///foo/bar'); + + data = parse('foo/bar', 'file:///baz/'); + assume(data.protocol).equals('file:'); + assume(data.pathname).equals('/baz/foo/bar'); + assume(data.href).equals('file:///baz/foo/bar'); + }); }); describe('ip', function () {