]> git.ipfire.org Git - thirdparty/vuejs/router.git/commitdiff
fix(hash): allow base tag different from base parameter
authorEduardo San Martin Morote <posva13@gmail.com>
Mon, 4 Jan 2021 12:06:47 +0000 (13:06 +0100)
committerEduardo San Martin Morote <posva13@gmail.com>
Mon, 4 Jan 2021 12:06:47 +0000 (13:06 +0100)
Fix #685

__tests__/history/html5.spec.ts
docs/api/index.md
e2e/hash/index.ts
e2e/specs/hash.js
src/history/hash.ts
src/history/html5.ts

index c92ce0d62cba89bbd88e0be39dad8d19c0ff3e46..7df3b381966410c4f8a95a49f6f506af9be1e903 100644 (file)
@@ -95,7 +95,7 @@ describe('History HTMl5', () => {
 
   it('calls push with hash part of the url with a base', () => {
     dom.reconfigure({ url: 'file:///usr/etc/index.html' })
-    let history = createWebHistory('/usr/etc/index.html#/')
+    let history = createWebHistory('#')
     let spy = jest.spyOn(window.history, 'pushState')
     history.push('/foo')
     expect(spy).toHaveBeenCalledWith(
index bd00d1cd853a4ff2275c0371ca2905e55e06ddaf..ebab310f45a54b63f9f70d62fe69bfe010eeccc5 100644 (file)
@@ -227,10 +227,9 @@ export declare function createWebHashHistory(base?: string): RouterHistory
 
 ### Parameters
 
-| Parameter | Type     | Description                                                                                                                                                                                                                                                                                                                                                  |
-| --------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
-| base      | `string` | optional base to provide. Defaults to `location.pathname` or `/` if at root. If there is a `<base>` tag in the `head`, its value will be ignored in favor of this parameter **but note it affects all the history.pushState() calls**, meaning that if you use a `<base>` tag, its `href` value **has to match this parameter** (ignoring anything after the |
-| `#`)      |
+| Parameter | Type     | Description                                                                                                                                                                                                                                                                                                                                                       |
+| --------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| base      | `string` | optional base to provide. Defaults to `location.pathname + location.search`. If there is a `<base>` tag in the `head`, its value will be ignored in favor of this parameter **but note it affects all the history.pushState() calls**, meaning that if you use a `<base>` tag, its `href` value **has to match this parameter** (ignoring anything after the `#`) |
 
 ### Examples
 
index ebf448c0535c9c5d75fe19343f0da2f64972f9c8..bc154a87c5eee6f0e4d95b8bfa539435a80f514b 100644 (file)
@@ -20,7 +20,7 @@ const Unicode: RouteComponent = {
 const router = createRouter({
   // keep a trailing slash in this specific case because we are using a hash
   // history
-  history: createWebHashHistory('/' + __dirname + '/#/'),
+  history: createWebHashHistory(),
   routes: [
     { path: '/', component: Home },
     { path: '/redirect', name: 'redirect', redirect: '/foo' },
index 33b38f6cfe6f1e5dcc5ddd5a0f5276bbf79b12b7..4b82b6844ef2c3f22accb493ed37eb806830e937 100644 (file)
@@ -62,6 +62,7 @@ module.exports = {
       .execute(function () {
         window.history.replaceState(history.state, '', '/hash/#/foo')
       })
+      .assert.urlEquals(baseURL + '/foo')
       .click('li:nth-child(3) a')
       .assert.urlEquals(baseURL + '/bar')
       .back()
index 9768b077a4958814e1b891e1274feb8fa1b7958f..6e4f5046e64aa1956e739d68e0f49740fac282f0 100644 (file)
@@ -6,8 +6,8 @@ import { warn } from '../warning'
  * Creates a hash history. Useful for web applications with no host (e.g.
  * `file://`) or when configuring a server to handle any URL is not possible.
  *
- * @param base - optional base to provide. Defaults to `location.pathname` or
- * `/` if at root. If there is a `<base>` tag in the `head`, its value will be
+ * @param base - optional base to provide. Defaults to `location.pathname +
+ * location.search` If there is a `<base>` tag in the `head`, its value will be
  * ignored in favor of this parameter **but note it affects all the
  * history.pushState() calls**, meaning that if you use a `<base>` tag, it's
  * `href` value **has to match this parameter** (ignoring anything after the
@@ -32,7 +32,7 @@ export function createWebHashHistory(base?: string): RouterHistory {
   // Make sure this implementation is fine in terms of encoding, specially for IE11
   // for `file://`, directly use the pathname and ignore the base
   // location.pathname contains an initial `/` even at the root: `https://example.com`
-  base = location.host ? base || location.pathname : ''
+  base = location.host ? base || location.pathname + location.search : ''
   // allow the user to provide a `#` in the middle: `/base/#/app`
   if (base.indexOf('#') < 0) base += '#'
 
index 0f91b8daa9412234e23d4f63b2d927a93e027a2a..c17dc08b1b8b13887d5e19c4cb367fb4c441bef7 100644 (file)
@@ -202,11 +202,21 @@ function useHistoryStateNavigation(base: string) {
     state: StateEntry,
     replace: boolean
   ): void {
-    // when the base has a `#`, only use that for the URL
+    /**
+     * if a base tag is provided and we are on a normal domain, we have to
+     * respect the provided `base` attribute because pushState() will use it and
+     * potentially erase anything before the `#` like at
+     * https://github.com/vuejs/vue-router-next/issues/685 where a base of
+     * `/folder/#` but a base of `/` would erase the `/folder/` section. If
+     * there is no host, the `<base>` tag makes no sense and if there isn't a
+     * base tag we can just use everything after the `#`.
+     */
     const hashIndex = base.indexOf('#')
     const url =
       hashIndex > -1
-        ? base.slice(hashIndex) + to
+        ? (location.host && document.querySelector('base')
+            ? base
+            : base.slice(hashIndex)) + to
         : createBaseLocation() + base + to
     try {
       // BROWSER QUIRK