]> git.ipfire.org Git - thirdparty/vuejs/router.git/commitdiff
refactor: remove old history files
authorEduardo San Martin Morote <posva13@gmail.com>
Sat, 12 Oct 2019 15:04:16 +0000 (17:04 +0200)
committerEduardo San Martin Morote <posva13@gmail.com>
Sat, 12 Oct 2019 15:04:16 +0000 (17:04 +0200)
src/history/base.ts [deleted file]
src/history/hash.ts [deleted file]
src/history/utils.ts [deleted file]

diff --git a/src/history/base.ts b/src/history/base.ts
deleted file mode 100644 (file)
index 5c878fa..0000000
+++ /dev/null
@@ -1,115 +0,0 @@
-import * as utils from './utils'
-import { ListenerRemover } from '../types'
-
-export type HistoryQuery = Record<string, string | string[]>
-// TODO: is it reall worth allowing null to form queries like ?q&b&c
-// When parsing using URLSearchParams, `q&c=` yield an empty string for q and c
-export type RawHistoryQuery = Record<string, string | string[] | null>
-
-export interface HistoryLocation {
-  // pathname section
-  path: string
-  // search string parsed
-  query?: RawHistoryQuery
-  // hash with the #
-  hash?: string
-}
-export interface HistoryLocationNormalized extends Required<HistoryLocation> {
-  // full path (like href)
-  fullPath: string
-  query: HistoryQuery
-}
-
-// pushState clones the state passed and do not accept everything
-// it doesn't accept symbols, nor functions as values. It also ignores Symbols as keys
-type HistoryStateValue =
-  | string
-  | number
-  | boolean
-  | null
-  | HistoryState
-  | HistoryStateArray
-export interface HistoryState {
-  [x: number]: HistoryStateValue
-  [x: string]: HistoryStateValue
-}
-interface HistoryStateArray extends Array<HistoryStateValue> {}
-// export type HistoryState = Record<string | number, string | number | boolean | undefined | null |
-
-export const START: HistoryLocationNormalized = {
-  fullPath: '/',
-  path: '/',
-  query: {},
-  hash: '',
-}
-
-export enum NavigationDirection {
-  // NOTE: is it better to have strings?
-  back = 'back',
-  forward = 'forward',
-}
-
-export interface NavigationCallback {
-  (
-    to: HistoryLocationNormalized,
-    from: HistoryLocationNormalized,
-    info: { direction: NavigationDirection }
-  ): void
-}
-
-// TODO: should BaseHistory be just an interface instead?
-
-export abstract class BaseHistory {
-  // previousState: object
-  location: HistoryLocationNormalized = START
-  base: string = ''
-  paused: boolean = false
-  utils = utils
-
-  /**
-   * Sync source with a different location.
-   * Adds an entry to the history
-   * @param to URL to go to
-   */
-  abstract push(to: HistoryLocation, data?: any): void
-
-  /**
-   * Syncs source with a different location
-   * Replaces current entry in the history
-   * @param to URL to go to
-   */
-  abstract replace(to: HistoryLocation): void
-
-  /**
-   * Goes back in history log. Should trigger any listener added via
-   * `listen`. If we are on the first entry, behaviour may change depending
-   * on implementation
-   * @param triggerListeners should default to true. If false, won't trigger listeners added via .listen()
-   */
-  abstract back(triggerListeners?: boolean): void
-
-  /**
-   * Goes forward in history log. Should trigger any listener added via
-   * `listen`. If we are on the last entry, behaviour may change depending
-   * on implementation
-   * @param triggerListeners should default to true. If false, won't trigger listeners added via .listen()
-   */
-  abstract forward(triggerListeners?: boolean): void
-
-  /**
-   * Notifies back whenever the location changes due to user interactions
-   * outside of the applicaiton. For example, going back/forward on a
-   * web browser
-   * @param callback callback to be called whenever the route changes
-   * @returns
-   */
-  abstract listen(callback: NavigationCallback): ListenerRemover
-
-  /**
-   * ensure the current location matches the external source
-   * For example, in HTML5 and hash history, that would be
-   * location.pathname
-   * TODO: is this necessary?
-   */
-  abstract ensureLocation(): void
-}
diff --git a/src/history/hash.ts b/src/history/hash.ts
deleted file mode 100644 (file)
index dae2686..0000000
+++ /dev/null
@@ -1,174 +0,0 @@
-import consola from '../consola'
-import { BaseHistory, HistoryLocationNormalized, HistoryLocation } from './base'
-import { NavigationCallback, HistoryState, NavigationDirection } from './base'
-
-const cs = consola.withTag('hash')
-
-// TODO: implement the mock instead
-/* istanbul ignore next */
-// @ts-ignore otherwise fails after rollup replacement plugin
-if (process.env.NODE_ENV === 'test') cs.mockTypes(() => jest.fn())
-
-type HashChangeHandler = (this: Window, ev: HashChangeEvent) => any
-
-/**
- * TODO: currently, we cannot prevent a hashchange, we could pass a callback to restore previous navigation on the listener. But we will face the same problems as with HTML5: go(-n) can leads to unexpected directions. We could save a copy of the history and the state, pretty much polyfilling the state stack
- */
-
-interface PauseState {
-  currentLocation: HistoryLocationNormalized
-  // location we are going to after pausing
-  to: HistoryLocationNormalized
-}
-
-export class HashHistory extends BaseHistory {
-  // private history = window.history
-  private _hashChangeHandler: HashChangeHandler
-  private _listeners: NavigationCallback[] = []
-  private _teardowns: Array<() => void> = []
-
-  // TODO: should it be a stack? a Dict. Check if the popstate listener
-  // can trigger twice
-  private pauseState: PauseState | null = null
-
-  constructor() {
-    super()
-    // const to = this.createCurrentLocation()
-    // replace current url to ensure leading slash
-    // this.history.replaceState(buildState(null, to, null), '', to.fullPath)
-    // we cannot use window.location.hash because some browsers
-    // predecode it
-    this.location = this.utils.normalizeLocation(
-      getFullPath(window.location.href)
-    )
-    this._hashChangeHandler = this.setupHashListener()
-  }
-
-  // TODO: is this necessary
-  ensureLocation() {}
-
-  replace(location: HistoryLocation) {
-    const to = this.utils.normalizeLocation(location)
-    // this.pauseListeners(to)
-    const hashIndex = window.location.href.indexOf('#')
-    // set it before to make sure we can skip the listener with a simple check
-    this.location = to
-    window.location.replace(
-      window.location.href.slice(0, hashIndex < 0 ? 0 : hashIndex) +
-        '#' +
-        to.fullPath
-    )
-  }
-
-  push(location: HistoryLocation, data?: HistoryState) {
-    const to = this.utils.normalizeLocation(location)
-    // set it before to make sure we can skip the listener with a simple check
-    this.location = to
-    window.location.hash = '#' + to.fullPath
-  }
-
-  back(triggerListeners: boolean = true) {
-    // TODO: check if we can go back
-    // const previvousLocation = this.history.state
-    //   .back as HistoryLocationNormalized
-    if (!triggerListeners) this.pauseListeners(this.location)
-    window.history.back()
-  }
-
-  forward(triggerListeners: boolean = true) {}
-
-  listen(callback: NavigationCallback) {
-    // settup the listener and prepare teardown callbacks
-    this._listeners.push(callback)
-
-    const teardown = () => {
-      this._listeners.splice(this._listeners.indexOf(callback), 1)
-    }
-
-    this._teardowns.push(teardown)
-    return teardown
-  }
-
-  /**
-   * Remove all listeners attached to the history and cleanups the history
-   * instance
-   */
-  destroy() {
-    for (const teardown of this._teardowns) teardown()
-    this._teardowns = []
-    if (this._hashChangeHandler)
-      window.removeEventListener('hashchange', this._hashChangeHandler)
-  }
-
-  /**
-   * Setups the popstate event listener. It's important to setup only
-   * one to ensure the same parameters are passed to every listener
-   */
-  private setupHashListener() {
-    const handler: HashChangeHandler = ({ oldURL, newURL }) => {
-      // TODO: assert oldURL === this.location.fullPath
-      cs.info('hashchange fired', {
-        location: this.location.fullPath,
-        oldURL,
-        newURL,
-      })
-
-      // TODO: handle go(-2) and go(2) (skipping entries)
-
-      const from = this.location
-
-      const targetTo = getFullPath(newURL)
-
-      if (from.fullPath === targetTo) {
-        cs.info('ignored because internal navigation')
-        return
-      }
-      // we have the state from the old entry, not the current one being removed
-      // TODO: correctly parse pathname
-      // TODO: ensure newURL value is consistent
-      // handle encoding
-      const to = this.utils.normalizeLocation(targetTo)
-      this.location = to
-
-      if (
-        this.pauseState &&
-        this.pauseState.to &&
-        this.pauseState.to.fullPath === to.fullPath
-      ) {
-        cs.info('Ignored beacuse paused')
-        // reset pauseState
-        this.pauseState = null
-        return
-      }
-
-      // call all listeners
-      const navigationInfo = {
-        // TODO: should we do an unknown direction?
-        direction: NavigationDirection.forward,
-      }
-      this._listeners.forEach(listener =>
-        listener(this.location, from, navigationInfo)
-      )
-    }
-
-    // settup the listener and prepare teardown callbacks
-    window.addEventListener('hashchange', handler)
-    return handler
-  }
-
-  private pauseListeners(to: HistoryLocationNormalized) {
-    this.pauseState = {
-      currentLocation: this.location,
-      to,
-    }
-  }
-}
-
-function getFullPath(href: string): string {
-  const hashIndex = href.indexOf('#')
-  // if no hash is present, we normalize it to the version without the hash
-  const fullPath = hashIndex < 0 ? '' : href.slice(hashIndex + 1)
-
-  // ensure leading slash
-  return fullPath.indexOf('/') < 0 ? '/' + fullPath : fullPath
-}
diff --git a/src/history/utils.ts b/src/history/utils.ts
deleted file mode 100644 (file)
index f62f2ae..0000000
+++ /dev/null
@@ -1,186 +0,0 @@
-import {
-  HistoryLocationNormalized,
-  HistoryQuery,
-  HistoryLocation,
-  RawHistoryQuery,
-} from './base'
-
-const PERCENT_RE = /%/g
-
-/**
- * Transforms a URL into an object
- * @param location location to normalize
- * @param currentLocation current location, to reuse params and location
- */
-export function parseURL(location: string): HistoryLocationNormalized {
-  let path = '',
-    query: HistoryQuery = {},
-    searchString = '',
-    hash = ''
-
-  // Could use URL and URLSearchParams but IE 11 doesn't support it
-  const searchPos = location.indexOf('?')
-  const hashPos = location.indexOf('#', searchPos > -1 ? searchPos : 0)
-  if (searchPos > -1) {
-    path = location.slice(0, searchPos)
-    searchString = location.slice(
-      searchPos + 1,
-      hashPos > -1 ? hashPos : location.length
-    )
-
-    query = normalizeQuery(parseQuery(searchString))
-  }
-
-  if (hashPos > -1) {
-    path = path || location.slice(0, hashPos)
-    hash = location.slice(hashPos, location.length)
-  }
-
-  path = path || location
-
-  return {
-    fullPath: location,
-    path,
-    query,
-    hash,
-  }
-}
-
-function safeDecodeUriComponent(value: string): string {
-  try {
-    value = decodeURIComponent(value)
-  } catch (err) {
-    // TODO: handling only URIError?
-    console.warn(
-      `[vue-router] error decoding query "${value}". Keeping the original value.`
-    )
-  }
-
-  return value
-}
-
-function safeEncodeUriComponent(value: string): string {
-  try {
-    value = encodeURIComponent(value)
-  } catch (err) {
-    // TODO: handling only URIError?
-    console.warn(
-      `[vue-router] error encoding query "${value}". Keeping the original value.`
-    )
-  }
-
-  return value
-}
-
-/**
- * Transform a queryString into a query object. Accept both, a version with the leading `?` and without
- * Should work as URLSearchParams
- * @param search
- */
-export function parseQuery(search: string): HistoryQuery {
-  const hasLeadingIM = search[0] === '?'
-  const query: HistoryQuery = {}
-  // avoid creating an object with an empty key and empty value
-  // because of split('&')
-  if (search === '' || search === '?') return query
-  const searchParams = (hasLeadingIM ? search.slice(1) : search).split('&')
-  for (let i = 0; i < searchParams.length; ++i) {
-    let [key, value] = searchParams[i].split('=')
-    key = safeDecodeUriComponent(key)
-    value = safeDecodeUriComponent(value)
-    if (key in query) {
-      // an extra variable for ts types
-      let currentValue = query[key]
-      if (!Array.isArray(currentValue)) {
-        currentValue = query[key] = [currentValue]
-      }
-      currentValue.push(value)
-    } else {
-      query[key] = value
-    }
-  }
-  return query
-}
-
-/**
- * Stringify a URL object
- * @param location
- */
-export function stringifyURL(location: HistoryLocation): string {
-  let url = location.path
-  let query = location.query ? stringifyQuery(location.query) : ''
-
-  return url + (query && '?' + query) + (location.hash || '')
-}
-
-/**
- * Stringify an object query. Works like URLSearchParams. Doesn't prepend a `?`
- * @param query
- */
-export function stringifyQuery(query: RawHistoryQuery): string {
-  let search = ''
-  // TODO: util function?
-  for (const key in query) {
-    if (search.length > 1) search += '&'
-    const value = query[key]
-    if (value === null) {
-      // TODO: should we just add the empty string value?
-      search += key
-      continue
-    }
-    let encodedKey = safeEncodeUriComponent(key)
-    let values: string[] = Array.isArray(value) ? value : [value]
-    values = values.map(safeEncodeUriComponent)
-
-    search += `${encodedKey}=${values[0]}`
-    for (let i = 1; i < values.length; i++) {
-      search += `&${encodedKey}=${values[i]}`
-    }
-  }
-
-  return search
-}
-
-export function normalizeQuery(query: RawHistoryQuery): HistoryQuery {
-  // TODO: implem
-  const normalizedQuery: HistoryQuery = {}
-  for (const key in query) {
-    const value = query[key]
-    if (value === null) normalizedQuery[key] = ''
-    else normalizedQuery[key] = value
-  }
-  return normalizedQuery
-}
-
-/**
- * Prepare a URI string to be passed to pushState
- * @param uri
- */
-export function prepareURI(uri: string) {
-  // encode the % symbol so it also works on IE
-  return uri.replace(PERCENT_RE, '%25')
-}
-
-// use regular decodeURI
-// Use a renamed export instead of global.decodeURI
-// to support node and browser at the same time
-const originalDecodeURI = decodeURI
-export { originalDecodeURI as decodeURI }
-
-/**
- * Normalize a History location into an object that looks like
- * the one at window.location
- * @param location
- */
-export function normalizeLocation(
-  location: string | HistoryLocation
-): HistoryLocationNormalized {
-  if (typeof location === 'string') return parseURL(location)
-  else
-    return {
-      fullPath: stringifyURL(location),
-      path: location.path,
-      query: location.query ? normalizeQuery(location.query) : {},
-      hash: location.hash || '',
-    }
-}