From: Eduardo San Martin Morote Date: Thu, 29 Aug 2019 06:58:59 +0000 (+0200) Subject: wip X-Git-Tag: v4.0.0-alpha.0~228^2~3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a729a6c5281532a81a237a6fab2aba3836fede4d;p=thirdparty%2Fvuejs%2Frouter.git wip --- diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..3662b370 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "typescript.tsdk": "node_modules/typescript/lib" +} \ No newline at end of file diff --git a/__tests__/ssr/basic.spec.js b/__tests__/ssr/basic.spec.js new file mode 100644 index 00000000..d768414d --- /dev/null +++ b/__tests__/ssr/basic.spec.js @@ -0,0 +1,139 @@ +/** @type {import('vue').VueConstructor} */ +// @ts-ignore +const Vue = require('vue') +const Router = require('../../src').default +const { components, isMocha } = require('../utils') +const { createRenderer } = require('vue-server-renderer') + +describe.skip('SSR: basicRenderer', () => { + Vue.use(Router) + + function createRouter() { + // TODO: a more complex routing that can be used for most tests + return new Router({ + mode: 'history', + routes: [ + { + path: '/', + component: components.Home, + }, + { + path: '/foo', + component: components.Foo, + }, + ], + }) + } + + function createApp() { + // create router instance + const router = createRouter() + + const app = new Vue({ + // @ts-ignore + router, + render: h => h('div', {}, [h('RouterView')]), + }) + + // return both the app and the router + return { app, router } + } + + function renderApp(context) { + return new Promise((resolve, reject) => { + const { app, router } = createApp() + + // set server-side router's location + router.push(context.url) + + // wait until router has resolved possible async components and hooks + // TODO: rename the promise one to isReady + router.onReady().then(() => { + // const matchedComponents = router.getMatchedComponents() + // no matched routes, reject with 404 + if (!matchedComponents.length) { + return reject({ code: 404 }) + } + + // the Promise should resolve to the app instance so it can be rendered + resolve(app) + }, reject) + }) + } + + it('should work', done => { + renderToString( + new Vue({ + template: ` +
+

yoyo

+
+ {{ test }} + + + + +
+ `, + data: { + test: 'hi', + isRed: true, + imageUrl: 'https://vuejs.org/images/logo.png', + }, + components: { + test: { + render() { + return this.$createElement('div', { class: ['a'] }, 'test') + }, + }, + testAsync(resolve) { + resolve({ + render() { + return this.$createElement( + 'span', + { class: ['b'] }, + 'testAsync' + ) + }, + }) + }, + }, + }), + (err, result) => { + expect(err).toBeNull() + expect(result).toContain( + '
' + + '

yoyo

' + + '
' + + 'hi ' + + ' ' + + ' ' + + '
test
' + + 'testAsync' + + '
' + ) + done() + } + ) + }) + + // #5941 + it('should work peoperly when accessing $ssrContext in root component', done => { + let ssrContext + renderToString( + new Vue({ + template: ` +
+ `, + created() { + ssrContext = this.$ssrContext + }, + }), + err => { + expect(err).toBeNull() + expect(ssrContext).toBeUndefined() + done() + } + ) + }) +}) diff --git a/package.json b/package.json index a5938079..cfa1d1a9 100644 --- a/package.json +++ b/package.json @@ -44,6 +44,7 @@ "ts-node": "^8.3.0", "typescript": "^3.5.3", "vue": "^2.6.10", + "vue-server-renderer": "^2.6.10", "vue-template-compiler": "^2.6.10", "webpack": "^4.39.2", "webpack-cli": "^3.3.7", diff --git a/src/index.ts b/src/index.ts index 11a399bb..7c596c08 100644 --- a/src/index.ts +++ b/src/index.ts @@ -72,23 +72,37 @@ export { plugin, } +// TODO: refactor somewhere else +const inBrowser = typeof window !== 'undefined' + +const HistoryMode = { + history: HTML5History, + hash: HashHistory, + abstract: AbstractHistory, +} + export default class VueRouter extends Router { static install = plugin static version = '__VERSION__' // TODO: handle mode in a retro compatible way - constructor(options: RouterOptions & { mode: 'string' }) { + constructor( + options: Partial + ) { + let { mode } = options + if (!inBrowser) mode = 'abstract' super({ - history: new HTML5History(), ...options, + routes: options.routes || [], + history: new HistoryMode[mode || 'hash'](), }) } } declare global { interface Window { - Vue?: VueConstructor + Vue: VueConstructor } } -if (window.Vue) window.Vue.use(VueRouter) +if (typeof window !== 'undefined' && window.Vue) window.Vue.use(VueRouter) diff --git a/src/router.ts b/src/router.ts index 8480559d..fb5310f9 100644 --- a/src/router.ts +++ b/src/router.ts @@ -135,12 +135,18 @@ export class Router { }) } + resolve(to: RouteLocation, currentLocation?: RouteLocationNormalized/*, append?: boolean */) { + if (typeof to === 'string') return this.resolveLocation(this.history.utils.normalizeLocation(to), currentLocation) + return this.resolveLocation(to) + } + resolveLocation( location: MatcherLocation & Required, - currentLocation: RouteLocationNormalized, + currentLocation?: RouteLocationNormalized, redirectedFrom?: RouteLocationNormalized // ensure when returning that the redirectedFrom is a normalized location ): RouteLocationNormalized { + currentLocation = currentLocation || this.currentRoute const matchedRoute = this.matcher.resolve(location, currentLocation) if ('redirect' in matchedRoute) { @@ -216,6 +222,25 @@ export class Router { } } + /** + * Get an array of matched components for a location. TODO: check if the array should contain plain components + * instead of functions that return promises for lazy loaded components + * @param to location to geth matched components from. If not provided, uses current location instead + */ + // getMatchedComponents( + // to?: RouteLocation | RouteLocationNormalized + // ): RouteComponent[] { + // const location = to + // ? typeof to !== 'string' && 'matched' in to + // ? to + // : this.resolveLocation(typeof to === 'string' ? this.history.utils.normalizeLocation(to) : to) + // : this.currentRoute + // if (!location) return [] + // return location.matched.map(m => + // Object.keys(m.components).map(name => m.components[name]) + // ) + // } + /** * Trigger a navigation, adding an entry to the history stack. Also apply all navigation * guards first diff --git a/yarn.lock b/yarn.lock index 9e85cce9..7f2c80df 100644 --- a/yarn.lock +++ b/yarn.lock @@ -709,6 +709,11 @@ ansi-regex@^4.0.0, ansi-regex@^4.1.0: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== +ansi-styles@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" + integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4= + ansi-styles@^3.2.0, ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" @@ -1256,6 +1261,17 @@ chalk@2.4.2, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.3.0, chalk@^2.4.2: escape-string-regexp "^1.0.5" supports-color "^5.3.0" +chalk@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" + integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= + dependencies: + ansi-styles "^2.2.1" + escape-string-regexp "^1.0.2" + has-ansi "^2.0.0" + strip-ansi "^3.0.0" + supports-color "^2.0.0" + chokidar@^2.0.2, chokidar@^2.1.6: version "2.1.6" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.6.tgz#b6cad653a929e244ce8a834244164d241fa954c5" @@ -2020,7 +2036,7 @@ escape-html@~1.0.3: resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= -escape-string-regexp@1.0.5, escape-string-regexp@^1.0.5: +escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= @@ -2625,6 +2641,13 @@ har-validator@~5.1.0: ajv "^6.5.5" har-schema "^2.0.0" +has-ansi@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" + integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE= + dependencies: + ansi-regex "^2.0.0" + has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" @@ -2686,6 +2709,11 @@ hash-base@^3.0.0: inherits "^2.0.1" safe-buffer "^5.0.1" +hash-sum@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/hash-sum/-/hash-sum-1.0.2.tgz#33b40777754c6432573c120cc3808bbd10d47f04" + integrity sha1-M7QHd3VMZDJXPBIMw4CLvRDUfwQ= + hash.js@^1.0.0, hash.js@^1.0.3: version "1.1.7" resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" @@ -3890,11 +3918,36 @@ locate-path@^3.0.0: p-locate "^3.0.0" path-exists "^3.0.0" +lodash._reinterpolate@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" + integrity sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0= + lodash.sortby@^4.7.0: version "4.7.0" resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" integrity sha1-7dFMgk4sycHgsKG0K7UhBRakJDg= +lodash.template@^4.4.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-4.5.0.tgz#f976195cf3f347d0d5f52483569fe8031ccce8ab" + integrity sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A== + dependencies: + lodash._reinterpolate "^3.0.0" + lodash.templatesettings "^4.0.0" + +lodash.templatesettings@^4.0.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz#e481310f049d3cf6d47e912ad09313b154f0fb33" + integrity sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ== + dependencies: + lodash._reinterpolate "^3.0.0" + +lodash.uniq@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" + integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= + lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.3, lodash@^4.17.4: version "4.17.15" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" @@ -5250,7 +5303,7 @@ resolve@1.11.1: dependencies: path-parse "^1.0.6" -resolve@1.x, resolve@^1.10.0, resolve@^1.11.0, resolve@^1.11.1, resolve@^1.3.2: +resolve@1.x, resolve@^1.10.0, resolve@^1.11.0, resolve@^1.11.1, resolve@^1.2.0, resolve@^1.3.2: version "1.12.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.12.0.tgz#3fc644a35c84a48554609ff26ec52b66fa577df6" integrity sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w== @@ -5467,6 +5520,11 @@ send@0.17.1: range-parser "~1.2.1" statuses "~1.5.0" +serialize-javascript@^1.3.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-1.8.0.tgz#9515fc687232e2321aea1ca7a529476eb34bb480" + integrity sha512-3tHgtF4OzDmeKYj6V9nSyceRS0UJ3C7VqyD2Yj28vC/z2j6jG5FmFGahOKMD9CrglxTm3tETr87jEypaYV8DUg== + serialize-javascript@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-1.7.0.tgz#d6e0dfb2a3832a8c94468e6eb1db97e55a192a65" @@ -5649,6 +5707,11 @@ source-map-url@^0.4.0: resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM= +source-map@0.5.6: + version "0.5.6" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412" + integrity sha1-dc449SvwczxafwwRjYEzSiu19BI= + source-map@^0.5.0, source-map@^0.5.6: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" @@ -5900,6 +5963,11 @@ supports-color@6.1.0, supports-color@^6.1.0: dependencies: has-flag "^3.0.0" +supports-color@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" + integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= + supports-color@^5.3.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" @@ -6356,6 +6424,20 @@ vm-browserify@^1.0.1: resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.0.tgz#bd76d6a23323e2ca8ffa12028dc04559c75f9019" integrity sha512-iq+S7vZJE60yejDYM0ek6zg308+UZsdtPExWP9VZoCFCz1zkJoXFnAX7aZfd/ZwrkidzdUZL0C/ryW+JwAiIGw== +vue-server-renderer@^2.6.10: + version "2.6.10" + resolved "https://registry.yarnpkg.com/vue-server-renderer/-/vue-server-renderer-2.6.10.tgz#cb2558842ead360ae2ec1f3719b75564a805b375" + integrity sha512-UYoCEutBpKzL2fKCwx8zlRtRtwxbPZXKTqbl2iIF4yRZUNO/ovrHyDAJDljft0kd+K0tZhN53XRHkgvCZoIhug== + dependencies: + chalk "^1.1.3" + hash-sum "^1.0.2" + he "^1.1.0" + lodash.template "^4.4.0" + lodash.uniq "^4.5.0" + resolve "^1.2.0" + serialize-javascript "^1.3.0" + source-map "0.5.6" + vue-template-compiler@^2.6.10: version "2.6.10" resolved "https://registry.yarnpkg.com/vue-template-compiler/-/vue-template-compiler-2.6.10.tgz#323b4f3495f04faa3503337a82f5d6507799c9cc"