From: Eduardo San Martin Morote Date: Thu, 4 Apr 2019 17:37:44 +0000 (+0200) Subject: more matching X-Git-Tag: v4.0.0-alpha.0~468 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=bc1905bbaf87cdea7e1fc5347fc43b552100ba7d;p=thirdparty%2Fvuejs%2Frouter.git more matching --- diff --git a/explorations/html5.ts b/explorations/html5.ts index dff41b04..fa922ca6 100644 --- a/explorations/html5.ts +++ b/explorations/html5.ts @@ -55,6 +55,6 @@ r.push({ }, }) -r.push({ - hash: '#hey', -}) +// r.push({ +// hash: '#hey', +// }) diff --git a/src/history/base.ts b/src/history/base.ts index 35833b0e..763d936f 100644 --- a/src/history/base.ts +++ b/src/history/base.ts @@ -3,6 +3,7 @@ import { HistoryLocation, NavigationCallback, RemoveListener, + HistoryURL, } from '../types/index' export default abstract class BaseHistory { @@ -33,6 +34,13 @@ export default abstract class BaseHistory { */ abstract listen(callback: NavigationCallback): RemoveListener + /** + * Transforms a URL into an object + * @param location location to normalize + * @param currentLocation current location, to reuse params and location + */ + abstract parseURL(location: HistoryLocation): HistoryURL + /** * ensure the current location matches the external source * For example, in HTML5 and hash history, that would be diff --git a/src/history/html5.ts b/src/history/html5.ts index c549532e..7134646c 100644 --- a/src/history/html5.ts +++ b/src/history/html5.ts @@ -5,6 +5,7 @@ import { NavigationCallback, HistoryState, NavigationType, + HistoryURL, } from '../types/index' const cs = consola.withTag('html5') @@ -116,6 +117,45 @@ export default class HTML5History extends BaseHistory { return teardown } + parseURL(location: string): HistoryURL { + let path = '', + search: HistoryURL['search'] = {}, + searchString = '', + hash = '' + + // Could use URL and URLSearchParams but IE 11 doesn't support it + const searchPos = location.indexOf('?') + const hashPos = location.indexOf(location, searchPos > -1 ? searchPos : 0) + if (searchPos > -1) { + path = location.slice(0, searchPos) + searchString = location.slice( + searchPos + 1, + hashPos > -1 ? hashPos : location.length - 1 + ) + + // TODO: properly do this in a util function + search = searchString.split('&').reduce((search, entry) => { + const [key, value] = entry.split('=') + search[key] = value + return search + }, search) + } + + if (hashPos > -1) { + path = path || location.slice(0, hashPos) + hash = location.slice(hashPos, location.length - 1) + } + + path = path || location + + return { + path, + // TODO: transform searchString + search, + hash, + } + } + destroy() { for (const teardown of this._teardowns) teardown() this._teardowns = [] diff --git a/src/index.ts b/src/index.ts index 2df39368..61adf906 100644 --- a/src/index.ts +++ b/src/index.ts @@ -30,9 +30,10 @@ export class Router { */ push(to: RouterLocation) { // TODO: resolve URL - const path = this.matcher.resolve(to, this.currentRoute) + const location = this.matcher.resolve(to, this.currentRoute) // TODO: call hooks, guards - this.history.push(path) + this.history.push(location.fullPath) + this.currentRoute = location } getRouteRecord(location: RouterLocation) {} diff --git a/src/matcher.ts b/src/matcher.ts index a47ac7ed..fbb36468 100644 --- a/src/matcher.ts +++ b/src/matcher.ts @@ -34,18 +34,6 @@ export class RouterMatcher { this.matchers = routes.map(generateMatcher) } - /** - * Normalize a RouterLocation into an object that is easier to handle - * @param location location to normalize - * @param currentLocation current location, to reuse params and location - */ - normalize( - location: Readonly, - currentLocation: Readonly - ): RouterLocationNormalized { - return {} as RouterLocationNormalized - } - /** * Transforms a RouterLocation object into a URL string. If a string is * passed, it returns the string itself @@ -53,15 +41,31 @@ export class RouterMatcher { */ resolve( location: Readonly, - currentLocation: RouterLocationNormalized - ): string { - if (typeof location === 'string') return location + currentLocation: Readonly + ): RouterLocationNormalized { + if (typeof location === 'string') + return { + path: location, + fullPath: location, + // TODO: resolve params, query and hash + params: {}, + query: {}, + hash: '', + } if ('path' in location) { // TODO: warn missing params - return ( - location.path + stringifyQuery(location.query) + (location.hash || '') - ) + // TODO: extract query and hash? warn about presence + return { + path: location.path, + query: location.query || {}, + hash: location.hash || '', + params: {}, + fullPath: + location.path + + stringifyQuery(location.query) + + (location.hash || ''), + } } let matcher: RouteMatcher | void @@ -74,9 +78,7 @@ export class RouterMatcher { m => m.record.name === currentLocation.name ) } else { - matcher = this.matchers.find( - m => m.record.path === currentLocation.path - ) + matcher = this.matchers.find(m => m.re.test(currentLocation.path)) } // return '/using current location' } else { @@ -85,9 +87,19 @@ export class RouterMatcher { if (!matcher) { // TODO: error - throw new Error('No match for' + location) + throw new Error( + 'No match for' + JSON.stringify({ ...currentLocation, ...location }) + ) } - return matcher.resolve(location.params || {}) + // TODO: try catch to show missing params + const fullPath = matcher.resolve(location.params || {}) + return { + path: fullPath, // TODO: extract path path, query, hash + fullPath, + query: {}, + params: {}, + hash: '', + } } } diff --git a/src/types/index.ts b/src/types/index.ts index 9a0cc59c..ea5c8070 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -46,13 +46,19 @@ export type RouterLocation = export interface RouterLocationNormalized { path: string + fullPath: string name?: string params: RouteParams query: TODO - hash: TODO + hash: string } export type HistoryLocation = string +export interface HistoryURL { + path: string + search: Record + hash: string +} // pushState clones the state passed and do not accept everything // it doesn't accept symbols, nor functions. It also ignores Symbols as keys @@ -81,6 +87,7 @@ export const START_LOCATION_NORMALIZED: RouterLocationNormalized = { params: {}, query: {}, hash: '', + fullPath: '/', } export enum NavigationType {