Skip to content

Commit

Permalink
fix(hash): only decode path (#2711)
Browse files Browse the repository at this point in the history
Fix #2708
  • Loading branch information
posva authored Apr 12, 2019
1 parent 8009b9c commit a775fb1
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 8 deletions.
4 changes: 4 additions & 0 deletions examples/basic/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,11 @@ new Vue({
<a>/bar</a>
</router-link>
<li><router-link to="/é">/é</router-link></li>
<li><router-link to="/é?t=%25ñ">/é?t=%ñ</router-link></li>
<li><router-link to="/é#%25ñ">/é#%25ñ</router-link></li>
</ul>
<pre id="query-t">{{ $route.query.t }}</pre>
<pre id="hash">{{ $route.hash }}</pre>
<router-view class="view"></router-view>
</div>
`
Expand Down
10 changes: 8 additions & 2 deletions examples/hash-mode/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Vue.use(VueRouter)
const Home = { template: '<div>home</div>' }
const Foo = { template: '<div>foo</div>' }
const Bar = { template: '<div>bar</div>' }
const Unicode = { template: '<div>unicode</div>' }
const Unicode = { template: '<div>unicode: {{ $route.params.unicode }}</div>' }

// 3. Create the router
const router = new VueRouter({
Expand All @@ -20,7 +20,8 @@ const router = new VueRouter({
{ path: '/', component: Home }, // all paths are defined without the hash.
{ path: '/foo', component: Foo },
{ path: '/bar', component: Bar },
{ path: '/é', component: Unicode }
{ path: '/é', component: Unicode },
{ path: '/é/:unicode', component: Unicode }
]
})

Expand All @@ -38,7 +39,12 @@ new Vue({
<li><router-link to="/bar">/bar</router-link></li>
<router-link tag="li" to="/bar">/bar</router-link>
<li><router-link to="/é">/é</router-link></li>
<li><router-link to="/é/ñ">/é/ñ</router-link></li>
<li><router-link to="/é/ñ?t=%25ñ">/é/ñ?t=%ñ</router-link></li>
<li><router-link to="/é/ñ#é">/é/ñ#é</router-link></li>
</ul>
<pre id="query-t">{{ $route.query.t }}</pre>
<pre id="hash">{{ $route.hash }}</pre>
<router-view class="view"></router-view>
</div>
`
Expand Down
20 changes: 18 additions & 2 deletions src/history/hash.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,25 @@ function ensureSlash (): boolean {
export function getHash (): string {
// We can't use window.location.hash here because it's not
// consistent across browsers - Firefox will pre-decode it!
const href = window.location.href
let href = window.location.href
const index = href.indexOf('#')
return index === -1 ? '' : decodeURI(href.slice(index + 1))
// empty path
if (index < 0) return ''

href = href.slice(index + 1)
// decode the hash but not the search or hash
// as search(query) is already decoded
// https://github.com/vuejs/vue-router/issues/2708
const searchIndex = href.indexOf('?')
if (searchIndex < 0) {
const hashIndex = href.indexOf('#')
if (hashIndex > -1) href = decodeURI(href.slice(0, hashIndex)) + href.slice(hashIndex)
else href = decodeURI(href)
} else {
if (searchIndex > -1) href = decodeURI(href.slice(0, searchIndex)) + href.slice(searchIndex)
}

return href
}

function getUrl (path) {
Expand Down
4 changes: 2 additions & 2 deletions test/e2e/specs/basic.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ module.exports = {
browser
.url('http://localhost:8080/basic/')
.waitForElementVisible('#app', 1000)
.assert.count('li', 5)
.assert.count('li a', 5)
.assert.count('li', 7)
.assert.count('li a', 7)
// assert correct href with base
.assert.attributeContains('li:nth-child(1) a', 'href', '/basic/')
.assert.attributeContains('li:nth-child(2) a', 'href', '/basic/foo')
Expand Down
21 changes: 19 additions & 2 deletions test/e2e/specs/hash-mode.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@ module.exports = {
browser
.url('http://localhost:8080/hash-mode/')
.waitForElementVisible('#app', 1000)
.assert.count('li', 5)
.assert.count('li a', 4)
.assert.count('li', 8)
.assert.count('li a', 7)
.assert.attributeContains('li:nth-child(1) a', 'href', '/hash-mode/#/')
.assert.attributeContains('li:nth-child(2) a', 'href', '/hash-mode/#/foo')
.assert.attributeContains('li:nth-child(3) a', 'href', '/hash-mode/#/bar')
.assert.attributeContains('li:nth-child(5) a', 'href', '/hash-mode/#/%C3%A9')
.assert.attributeContains('li:nth-child(6) a', 'href', '/hash-mode/#/%C3%A9/%C3%B1')
.assert.attributeContains('li:nth-child(7) a', 'href', '/hash-mode/#/%C3%A9/%C3%B1?t=%25%C3%B1')
.assert.containsText('.view', 'home')

.click('li:nth-child(2) a')
Expand All @@ -31,9 +33,24 @@ module.exports = {
.url('http://localhost:8080/hash-mode/#/foo')
.waitForElementVisible('#app', 1000)
.assert.containsText('.view', 'foo')
// direct visit encoded unicode
.url('http://localhost:8080/hash-mode/#/%C3%A9')
.waitForElementVisible('#app', 1000)
.assert.containsText('.view', 'unicode')
// direct visit raw unicode
.url('http://localhost:8080/hash-mode/#/%C3%A9/%C3%B1')
.waitForElementVisible('#app', 1000)
.assert.containsText('.view', 'unicode: ñ')
// TODO: Doesn't seem to work on PhantomJS
// .click('li:nth-child(7)')
// .assert.urlEquals('http://localhost:8080/hash-mode/#/%C3%A9/%C3%B1?t=%25')
// .assert.containsText('.view', 'unicode: ñ')
// .assert.containsText('#query-t', '%')
// direct visit
.url('http://localhost:8080/hash-mode/#/%C3%A9/%C3%B1?t=%25')
.waitForElementVisible('#app', 1000)
.assert.containsText('.view', 'unicode: ñ')
.assert.containsText('#query-t', '%')
.end()
}
}

0 comments on commit a775fb1

Please sign in to comment.