Skip to content

Commit

Permalink
Un-deprecate top-level createLocation
Browse files Browse the repository at this point in the history
Also, add ability to pass an object as the first argument to
createLocation that specifies pathname, search, and hash properties of
the resulting location object.
  • Loading branch information
mjackson committed Oct 11, 2015
1 parent fdd42c6 commit 3f1d596
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 84 deletions.
13 changes: 10 additions & 3 deletions docs/Location.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,18 @@ Support for query string parsing is provided using the [`useQueries` module](Que

### Programmatic Creation

You may occasionally need to create a `location` object, either for testing or when using `history` in a stateless, non-DOM environment (i.e. a server). `history` objects have a `createLocation` method for this purpose.
You may occasionally need to create a `location` object, either for testing or when using `history` in a stateless, non-DOM environment (i.e. a server). In these cases, you can use the `createLocation` method directly:

```js
import { createHistory } from 'history'
import { createLocation } from 'history'

const history = createHistory()
const location = createLocation('/a/path?a=query', { the: 'state' })
```

Alternatively, you can use a `history` object's `createLocation` method:

```js
const location = history.createLocation('/a/path?a=query', { the: 'state' })
```

`location` objects created in this way will get a default `key` property that is generated using `history.createKey()`.
44 changes: 33 additions & 11 deletions modules/__tests__/Location-test.js
Original file line number Diff line number Diff line change
@@ -1,27 +1,23 @@
/*eslint-env mocha */
import expect from 'expect'
import createHistory from '../createHistory'
import createLocation from '../createLocation'
import { POP } from '../Actions'

describe('a location', function () {
let createLocation
beforeEach(function () {
createLocation = createHistory().createLocation
})

it('knows its pathname', function () {
let location = createLocation('/home?the=query#the-hash')
expect(location.pathname).toEqual('/home')
})

it('knows its hash', function () {
it('knows its search string', function () {
let location = createLocation('/home?the=query#the-hash')
expect(location.hash).toEqual('#the-hash')
expect(location.search).toEqual('?the=query')
})

it('knows its search string', function () {
it('knows its hash', function () {
let location = createLocation('/home?the=query#the-hash')
expect(location.search).toEqual('?the=query')
expect(location.hash).toEqual('#the-hash')
})

it('has null state by default', function () {
Expand All @@ -34,8 +30,34 @@ describe('a location', function () {
expect(location.action).toBe(POP)
})

it('has a key by default', function () {
it('has a null key by default', function () {
let location = createLocation()
expect(location.key).toExist()
expect(location.key).toBe(null)
})

describe('created by a history object', function () {
let history
beforeEach(function () {
history = createHistory()
})

it('has a key by default', function () {
let location = history.createLocation()
expect(location.key).toExist()
})
})
})

describe('creating a location with an object', function () {
it('puts the pathname, search, and hash in the proper order', function () {
let location = createLocation({
pathname: '/the/path',
search: '?the=query',
hash: '#the-hash'
})

expect(location.pathname).toEqual('/the/path')
expect(location.search).toEqual('?the=query')
expect(location.hash).toEqual('#the-hash')
})
})
47 changes: 3 additions & 44 deletions modules/createHistory.js
Original file line number Diff line number Diff line change
@@ -1,29 +1,14 @@
import warning from 'warning'
import deepEqual from 'deep-equal'
import { loopAsync } from './AsyncUtils'
import { PUSH, REPLACE, POP } from './Actions'
import _createLocation from './createLocation'
import runTransitionHook from './runTransitionHook'
import deprecate from './deprecate'

function createRandomKey(length) {
return Math.random().toString(36).substr(2, length)
}

function extractPath(string) {
let 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)
}

function locationsAreEqual(a, b) {
return a.pathname === b.pathname &&
a.search === b.search &&
Expand Down Expand Up @@ -173,34 +158,8 @@ function createHistory(options={}) {
return path
}

function createLocation(path='/', state=null, action=POP, key=createKey()) {
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,
state,
action,
key
}
function createLocation(path, state, action, key=createKey()) {
return _createLocation(path, state, action, key)
}

// deprecated
Expand Down
51 changes: 26 additions & 25 deletions modules/createLocation.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import warning from 'warning'
import deprecate from './deprecate'
import { POP } from './Actions'

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

if (match == null)
return string
Expand All @@ -18,27 +17,32 @@ function extractPath(string) {
}

function createLocation(path='/', state=null, action=POP, key=null) {
path = extractPath(path)

let pathname = path
let search = ''
let hash = ''

let hashIndex = pathname.indexOf('#')
if (hashIndex !== -1) {
hash = pathname.substring(hashIndex)
pathname = pathname.substring(0, hashIndex)
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)
}

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 || ''
}

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

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

return {
pathname,
search,
Expand All @@ -49,7 +53,4 @@ function createLocation(path='/', state=null, action=POP, key=null) {
}
}

export default deprecate(
createLocation,
'Calling createLocation statically is deprecated; instead call the history.createLocation method - see docs/Location.md'
)
export default createLocation
2 changes: 1 addition & 1 deletion modules/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export createHistory from './createBrowserHistory'
export createHashHistory from './createHashHistory'
export createMemoryHistory from './createMemoryHistory'
export createLocation from './createLocation'

export useBasename from './useBasename'
export useBeforeUnload from './useBeforeUnload'
Expand All @@ -9,6 +10,5 @@ export useQueries from './useQueries'
export Actions from './Actions'

// deprecated
export createLocation from './createLocation'
export enableBeforeUnload from './enableBeforeUnload'
export enableQueries from './enableQueries'

0 comments on commit 3f1d596

Please sign in to comment.