Skip to content

Commit

Permalink
Fix useQueries handling of hash
Browse files Browse the repository at this point in the history
Fixes #93
  • Loading branch information
mjackson committed Oct 11, 2015
1 parent 3f1d596 commit 8d4ece5
Show file tree
Hide file tree
Showing 6 changed files with 108 additions and 55 deletions.
8 changes: 8 additions & 0 deletions modules/__tests__/describeQueries.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,14 @@ function describeQueries(createHistory) {
history.createPath('/the/path/', { the: 'query' })
).toEqual('/the/path/?STRINGIFY_QUERY')
})

describe('when the path contains a hash', function () {
it('puts the query before the hash', function () {
expect(
history.createPath('/the/path#the-hash', { the: 'query' })
).toEqual('/the/path?STRINGIFY_QUERY#the-hash')
})
})
})

describe('in createHref', function () {
Expand Down
17 changes: 15 additions & 2 deletions modules/createHistory.js
Original file line number Diff line number Diff line change
Expand Up @@ -151,11 +151,24 @@ function createHistory(options={}) {
}

function createPath(path) {
return path
if (path == null || typeof path === 'string')
return path

const { pathname, search, hash } = path

let result = pathname

if (search)
result += search

if (hash)
result += hash

return result
}

function createHref(path) {
return path
return createPath(path)
}

function createLocation(path, state, action, key=createKey()) {
Expand Down
46 changes: 6 additions & 40 deletions modules/createLocation.js
Original file line number Diff line number Diff line change
@@ -1,47 +1,13 @@
import warning from 'warning'
import { POP } from './Actions'

function extractPath(string) {
const match = string.match(/https?:\/\/[^\/]*/)

if (match == null)
return string

warning(
false,
'Location path must be pathname + query string only, not a fully qualified URL like "%s"',
string
)

return string.substring(match[0].length)
}
import parsePath from './parsePath'

function createLocation(path='/', state=null, action=POP, key=null) {
let pathname, search, hash
if (typeof path === 'string') {
pathname = extractPath(path)
search = ''
hash = ''

let hashIndex = pathname.indexOf('#')
if (hashIndex !== -1) {
hash = pathname.substring(hashIndex)
pathname = pathname.substring(0, hashIndex)
}
if (typeof path === 'string')
path = parsePath(path)

let searchIndex = pathname.indexOf('?')
if (searchIndex !== -1) {
search = pathname.substring(searchIndex)
pathname = pathname.substring(0, searchIndex)
}

if (pathname === '')
pathname = '/'
} else {
pathname = path.pathname || '/'
search = path.search || ''
hash = path.hash || ''
}
const pathname = path.pathname || '/'
const search = path.search || ''
const hash = path.hash || ''

return {
pathname,
Expand Down
45 changes: 45 additions & 0 deletions modules/parsePath.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import warning from 'warning'

function extractPath(string) {
const match = string.match(/https?:\/\/[^\/]*/)

if (match == null)
return string

warning(
false,
'A path must be pathname + search + hash only, not a fully qualified URL like "%s"',
string
)

return string.substring(match[0].length)
}

function parsePath(path) {
let pathname = extractPath(path)
let search = ''
let hash = ''

let hashIndex = pathname.indexOf('#')
if (hashIndex !== -1) {
hash = pathname.substring(hashIndex)
pathname = pathname.substring(0, hashIndex)
}

let searchIndex = pathname.indexOf('?')
if (searchIndex !== -1) {
search = pathname.substring(searchIndex)
pathname = pathname.substring(0, searchIndex)
}

if (pathname === '')
pathname = '/'

return {
pathname,
search,
hash
}
}

export default parsePath
14 changes: 13 additions & 1 deletion modules/useBasename.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import runTransitionHook from './runTransitionHook'
import parsePath from './parsePath'

function useBasename(createHistory) {
return function (options={}) {
Expand All @@ -22,7 +23,18 @@ function useBasename(createHistory) {
}

function prependBasename(path) {
return basename ? basename + path : path
if (!basename)
return path

if (typeof path === 'string')
path = parsePath(path)

const pathname = basename + path.pathname

return {
...path,
pathname
}
}

// Override all read methods with basename-aware versions.
Expand Down
33 changes: 21 additions & 12 deletions modules/useQueries.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import qs from 'qs'
import runTransitionHook from './runTransitionHook'
import parsePath from './parsePath'

function defaultStringifyQuery(query) {
return qs.stringify(query, { arrayFormat: 'brackets' })
Expand Down Expand Up @@ -31,12 +32,20 @@ function useQueries(createHistory) {
return location
}

function appendQuery(pathname, query) {
function appendQuery(path, query) {
let queryString
if (query && (queryString = stringifyQuery(query)) !== '')
return pathname + (pathname.indexOf('?') === -1 ? '?' : '&') + queryString
if (!query || (queryString = stringifyQuery(query)) === '')
return path

return pathname
if (typeof path === 'string')
path = parsePath(path)

const search = path.search + (path.search ? '&' : '?') + queryString

return {
...path,
search
}
}

// Override all read methods with query-aware versions.
Expand All @@ -53,20 +62,20 @@ function useQueries(createHistory) {
}

// Override all write methods with query-aware versions.
function pushState(state, pathname, query) {
return history.pushState(state, appendQuery(pathname, query))
function pushState(state, path, query) {
return history.pushState(state, appendQuery(path, query))
}

function replaceState(state, pathname, query) {
return history.replaceState(state, appendQuery(pathname, query))
function replaceState(state, path, query) {
return history.replaceState(state, appendQuery(path, query))
}

function createPath(pathname, query) {
return history.createPath(appendQuery(pathname, query))
function createPath(path, query) {
return history.createPath(appendQuery(path, query))
}

function createHref(pathname, query) {
return history.createHref(appendQuery(pathname, query))
function createHref(path, query) {
return history.createHref(appendQuery(path, query))
}

function createLocation() {
Expand Down

0 comments on commit 8d4ece5

Please sign in to comment.