fix(app): lint all templates (#4175)

This commit is contained in:
Pim 2018-10-24 15:46:06 +02:00 committed by Pooya Parsa
parent 81b25ee2e2
commit 96bdcaba01
25 changed files with 304 additions and 220 deletions

View File

@ -6,5 +6,32 @@ module.exports = {
},
extends: [
'@nuxtjs'
]
],
overrides: [{
files: [ 'test/fixtures/*/.nuxt*/**' ],
rules: {
'vue/name-property-casing': ['error', 'kebab-case']
}
}, {
files: [ 'test/fixtures/*/.nuxt*/**/+(App|index).js' ],
rules: {
'import/order': 'ignore'
}
}, {
files: [ 'test/fixtures/*/.nuxt*/**/client.js' ],
rules: {
'no-console': ['error', { allow: ['error'] }]
}
}, {
files: [ 'test/fixtures/*/.nuxt*/**/router.js' ],
rules: {
'no-console': ['error', { allow: ['warn'] }]
}
}, {
files: [ 'test/fixtures/*/.nuxt*/**/*.html' ],
rules: {
'semi': ['error', 'always', { 'omitLastInOneLineBlock': true }],
'no-var': 'warn'
}
}]
}

View File

@ -13,7 +13,7 @@
"dev": "yarn build --watch",
"coverage": "codecov",
"lint": "eslint --ext .js,.mjs,.vue .",
"lint:app": "eslint-multiplexer eslint --ignore-path lib/app/.eslintignore 'test/fixtures/!(missing-plugin)/.nuxt!(-dev)/**' | eslint-multiplexer -b",
"lint:app": "eslint-multiplexer eslint --ignore-path packages/app/template/.eslintignore 'test/fixtures/!(missing-plugin)/.nuxt!(-dev)/**' | eslint-multiplexer -b",
"nuxt": "node -r esm ./packages/cli/bin/nuxt.js",
"test": "yarn test:fixtures && yarn test:unit",
"test:fixtures": "jest test/fixtures",

View File

@ -12,12 +12,14 @@ import '<%= relativeToBuild(resolvePath(c.src || c)) %>'
}
}).join('\n') %>
const layouts = { <%= Object.keys(layouts).map(key => `"_${key}": _${hash(key)}`).join(',') %> }
const layouts = { <%= Object.keys(layouts).map(key => `"_${key}": _${hash(key)}`).join(',') %> }<%= isTest ? '// eslint-disable-line' : '' %>
<% if (splitChunks.layouts) { %>let resolvedLayouts = {}<% } %>
export default {
<%= isTest ? '/* eslint-disable quotes, semi, indent, comma-spacing, key-spacing, object-curly-spacing, object-property-newline, arrow-parens */' : '' %>
head: <%= serialize(head).replace(/:\w+\(/gm, ':function(') %>,
<%= isTest ? '/* eslint-enable quotes, semi, indent, comma-spacing, key-spacing, object-curly-spacing, object-property-newline, arrow-parens */' : '' %>
render(h, props) {
<% if (loading) { %>const loadingEl = h('nuxt-loading', { ref: 'loading' })<% } %>
const layoutEl = h(this.layout || 'nuxt')
@ -35,7 +37,7 @@ export default {
}
}, [ templateEl ])
return h('div',{
return h('div', {
domProps: {
id: '<%= globals.id %>'
}
@ -48,10 +50,10 @@ export default {
layout: null,
layoutName: ''
}),
beforeCreate () {
beforeCreate() {
Vue.util.defineReactive(this, 'nuxt', this.$options.nuxt)
},
created () {
created() {
// Add this.$nuxt in child instances
Vue.prototype.<%= globals.nuxt %> = this
// add to window so we can listen when ready
@ -65,7 +67,7 @@ export default {
this.error = this.nuxt.error
},
<% if (loading) { %>
mounted () {
mounted() {
this.$loading = this.$refs.loading
},
watch: {
@ -74,7 +76,7 @@ export default {
<% } %>
methods: {
<% if (loading) { %>
errorChanged () {
errorChanged() {
if (this.nuxt.err && this.$loading) {
if (this.$loading.fail) this.$loading.fail()
if (this.$loading.finish) this.$loading.finish()
@ -82,7 +84,7 @@ export default {
},
<% } %>
<% if (splitChunks.layouts) { %>
setLayout (layout) {
setLayout(layout) {
<% if (debug) { %>
if(layout && typeof layout !== 'string') throw new Error('[nuxt] Avoid using non-string value as layout property.')
<% } %>
@ -92,7 +94,7 @@ export default {
this.layout = resolvedLayouts[_layout]
return this.layout
},
loadLayout (layout) {
loadLayout(layout) {
const undef = !layout
const inexisting = !(layouts['_' + layout] || resolvedLayouts['_' + layout])
let _layout = '_' + ((undef || inexisting) ? 'default' : layout)

View File

@ -1,6 +1,5 @@
import Vue from 'vue'
import middleware from './middleware'
import { createApp, NuxtError } from './index'
import {
applyAsyncData,
sanitizeComponent,
@ -16,6 +15,7 @@ import {
getQueryDiff,
globalHandleError
} from './utils'
import { createApp, NuxtError } from './index'
const noopData = () => { return {} }
const noopFetch = () => {}
@ -29,7 +29,7 @@ let router
// Try to rehydrate SSR data from window
const NUXT = window.<%= globals.context %> || {}
Object.assign(Vue.config, <%= serialize(vue.config) %>)
Object.assign(Vue.config, <%= serialize(vue.config) %>)<%= isTest ? '// eslint-disable-line' : '' %>
<% if (debug || mode === 'spa') { %>
// Setup global Vue error handler
@ -46,7 +46,7 @@ if (!Vue.config.$nuxt) {
if (typeof defaultErrorHandler === 'function') {
handled = defaultErrorHandler(err, vm, info, ...rest)
}
if (handled === true){
if (handled === true) {
return handled
}
@ -79,10 +79,10 @@ Vue.config.$nuxt.<%= globals.nuxt %> = true
// Create and mount App
createApp()
.then(mountApp)
.catch((err) => {
.then(mountApp)
.catch((err) => {
console.error('[nuxt] Error while initializing app', err)
})
})
function componentOption(component, key, ...args) {
if (!component || !component.options || !component.options[key]) {
@ -107,17 +107,17 @@ function mapTransitions(Components, to, from) {
// Combine transitions & prefer `leave` transitions of 'from' route
if (from && from.matched.length && from.matched[0].components.default) {
const from_transitions = componentTransitions(from.matched[0].components.default)
Object.keys(from_transitions)
.filter((key) => from_transitions[key] && key.toLowerCase().includes('leave'))
.forEach((key) => { transitions[key] = from_transitions[key] })
const fromTransitions = componentTransitions(from.matched[0].components.default)
Object.keys(fromTransitions)
.filter(key => fromTransitions[key] && key.toLowerCase().includes('leave'))
.forEach((key) => { transitions[key] = fromTransitions[key] })
}
return transitions
})
}
async function loadAsyncComponents (to, from, next) {
async function loadAsyncComponents(to, from, next) {
// Check if route path changed (this._pathChanged), only if the page is not an error (for validate())
this._pathChanged = !!app.nuxt.err || from.path !== to.path
this._queryChanged = JSON.stringify(to.query) !== JSON.stringify(from.query)
@ -138,7 +138,7 @@ async function loadAsyncComponents (to, from, next) {
const watchQuery = Component.options.watchQuery
if (watchQuery === true) return true
if (Array.isArray(watchQuery)) {
return watchQuery.some((key) => this._diffQuery[key])
return watchQuery.some(key => this._diffQuery[key])
}
return false
})
@ -150,10 +150,10 @@ async function loadAsyncComponents (to, from, next) {
// Call next()
next()
} catch (err) {
err = err || {}
const statusCode = (err.statusCode || err.status || (err.response && err.response.status) || 500)
this.error({ statusCode, message: err.message })
this.<%= globals.nuxt %>.$emit('routeChanged', to, from, err)
const error = err || {}
const statusCode = (error.statusCode || error.status || (error.response && error.response.status) || 500)
this.error({ statusCode, message: error.message })
this.<%= globals.nuxt %>.$emit('routeChanged', to, from, error)
next(false)
}
}
@ -182,8 +182,8 @@ function resolveComponents(router) {
})
}
function callMiddleware (Components, context, layout) {
let midd = <%= devalue(router.middleware) %>
function callMiddleware(Components, context, layout) {
let midd = <%= devalue(router.middleware) %><%= isTest ? '// eslint-disable-line' : '' %>
let unknownMiddleware = false
// If layout is undefined, only call global middleware
@ -212,7 +212,7 @@ function callMiddleware (Components, context, layout) {
return middlewareSeries(midd, context)
}
async function render (to, from, next) {
async function render(to, from, next) {
if (this._pathChanged === false && this._queryChanged === false) return next()
// Handle first render on SPA mode
if (to === from) _lastPaths = []
@ -337,21 +337,21 @@ async function render (to, from, next) {
Component._dataRefresh = false
// Check if Component need to be refreshed (call asyncData & fetch)
// Only if its slug has changed or is watch query changes
if (this._pathChanged && this._queryChanged || Component._path !== _lastPaths[i]) {
if ((this._pathChanged && this._queryChanged) || Component._path !== _lastPaths[i]) {
Component._dataRefresh = true
} else if (!this._pathChanged && this._queryChanged) {
const watchQuery = Component.options.watchQuery
if (watchQuery === true) {
Component._dataRefresh = true
} else if (Array.isArray(watchQuery)) {
Component._dataRefresh = watchQuery.some((key) => this._diffQuery[key])
Component._dataRefresh = watchQuery.some(key => this._diffQuery[key])
}
}
if (!this._hadError && this._isMounted && !Component._dataRefresh) {
return Promise.resolve()
}
let promises = []
const promises = []
const hasAsyncData = (
Component.options.asyncData &&
@ -368,7 +368,7 @@ async function render (to, from, next) {
.then((asyncDataResult) => {
applyAsyncData(Component, asyncDataResult)
<% if (loading) { %>
if(this.$loading.increase) {
if (this.$loading.increase) {
this.$loading.increase(loadingIncrease)
}
<% } %>
@ -408,10 +408,9 @@ async function render (to, from, next) {
next()
}
} catch (error) {
if (!error) {
error = {}
} else if (error.message === 'ERR_REDIRECT') {
} catch (err) {
const error = err || {}
if (error.message === 'ERR_REDIRECT') {
return this.<%= globals.nuxt %>.$emit('routeChanged', to, from, error)
}
_lastPaths = []
@ -434,7 +433,7 @@ async function render (to, from, next) {
}
// Fix components format in matched, it's due to code-splitting of vue-router
function normalizeComponents (to, ___) {
function normalizeComponents(to, ___) {
flatMapComponents(to, (Component, _, match, key) => {
if (typeof Component === 'object' && !Component.options) {
// Updated via vue-router resolveAsyncComponents()
@ -486,7 +485,7 @@ function fixPrepatch(to, ___) {
typeof instance.constructor.options.data === 'function'
) {
const newData = instance.constructor.options.data.call(instance)
for (let key in newData) {
for (const key in newData) {
Vue.set(instance.$data, key, newData[key])
}
}
@ -499,7 +498,7 @@ function fixPrepatch(to, ___) {
})
}
function nuxtReady (_app) {
function nuxtReady(_app) {
window.<%= globals.readyCallback %>Cbs.forEach((cb) => {
if (typeof cb === 'function') {
cb(_app)
@ -531,7 +530,7 @@ function getNuxtChildComponents($parent, $components = []) {
return $components
}
function hotReloadAPI (_app) {
function hotReloadAPI(_app) {
if (!module.hot) return
let $components = getNuxtChildComponents(_app.<%= globals.nuxt %>, [])
@ -539,7 +538,7 @@ function hotReloadAPI (_app) {
$components.forEach(addHotReload.bind(_app))
}
function addHotReload ($component, depth) {
function addHotReload($component, depth) {
if ($component.$vnode.data._hasHotReload) return
$component.$vnode.data._hasHotReload = true
@ -617,7 +616,7 @@ async function mountApp(__app) {
// Set global variables
app = __app.app
router = __app.router
<% if (store) { %>store = __app.store <% } %>
<% if (store) { %>store = __app.store<% } %>
// Resolve route components
const Components = await Promise.all(resolveComponents(router))

View File

@ -1,4 +1,4 @@
/*
/*<%= isTest ? ' @vue/component' : '' %>
** From https://github.com/egoist/vue-no-ssr
** With the authorization of @egoist
*/

View File

@ -1,8 +1,15 @@
<%= isTest ? '// @vue/component' : '' %>
export default {
name: 'nuxt-child',
functional: true,
props: ['keepAlive', 'keepAliveProps'],
render (h, { parent, data, props }) {
props: {
nuxtChildKey: {
type: String,
default: ''
},
keepAlive: Boolean
},
render(h, { parent, data, props }) {
data.nuxtChild = true
const _parent = parent
const transitions = parent.<%= globals.nuxt %>.nuxt.transitions
@ -17,14 +24,14 @@ export default {
}
data.nuxtChildDepth = depth
const transition = transitions[depth] || defaultTransition
let transitionProps = {}
const transitionProps = {}
transitionsKeys.forEach((key) => {
if (typeof transition[key] !== 'undefined') {
transitionProps[key] = transition[key]
}
})
let listeners = {}
const listeners = {}
listenersKeys.forEach((key) => {
if (typeof transition[key] === 'function') {
listeners[key] = transition[key].bind(_parent)
@ -43,7 +50,7 @@ export default {
let routerView = [
h('router-view', data)
]
if (typeof props.keepAlive !== 'undefined') {
if (props.keepAlive) {
routerView = [
h('keep-alive', { props: props.keepAliveProps }, routerView)
]

View File

@ -1,10 +1,10 @@
<template>
<div class="__nuxt-error-page">
<div class="error">
<svg xmlns="http://www.w3.org/2000/svg" width="90" height="90" fill="#DBE1EC" viewBox="0 0 48 48"><path d="M22 30h4v4h-4zm0-16h4v12h-4zm1.99-10C12.94 4 4 12.95 4 24s8.94 20 19.99 20S44 35.05 44 24 35.04 4 23.99 4zM24 40c-8.84 0-16-7.16-16-16S15.16 8 24 8s16 7.16 16 16-7.16 16-16 16z"/></svg>
<div class="__nuxt-error-page">
<div class="error">
<svg xmlns="http://www.w3.org/2000/svg" width="90" height="90" fill="#DBE1EC" viewBox="0 0 48 48"><path d="M22 30h4v4h-4zm0-16h4v12h-4zm1.99-10C12.94 4 4 12.95 4 24s8.94 20 19.99 20S44 35.05 44 24 35.04 4 23.99 4zM24 40c-8.84 0-16-7.16-16-16S15.16 8 24 8s16 7.16 16 16-7.16 16-16 16z" /></svg>
<div class="title">{{ message }}</div>
<p class="description" v-if="statusCode === 404">
<p v-if="statusCode === 404" class="description">
<nuxt-link class="error-link" to="/"><%= messages.back_to_home %></nuxt-link>
</p>
<% if(debug) { %>
@ -14,15 +14,20 @@
<div class="logo">
<a href="https://nuxtjs.org" target="_blank" rel="noopener"><%= messages.nuxtjs %></a>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'nuxt-error',
props: ['error'],
head () {
props: {
error: {
type: Object,
default: null
}
},
head() {
return {
title: this.message,
meta: [
@ -34,10 +39,10 @@ export default {
}
},
computed: {
statusCode () {
statusCode() {
return (this.error && this.error.statusCode) || 500
},
message () {
message() {
return this.error.message || `<%= messages.client_error %>`
}
}

View File

@ -1,7 +1,8 @@
<%= isTest ? '// @vue/component' : '' %>
export default {
name: 'nuxt-link',
functional: true,
render (h, { data, children }) {
render(h, { data, children }) {
return h('router-link', data, children)
}
}

View File

@ -1,10 +1,13 @@
<template>
<div class="nuxt-progress" :style="{
<div
class="nuxt-progress"
:style="{
'width': percent + '%',
'height': height,
'background-color': canSuccess ? color : failedColor,
'opacity': show ? 1 : 0
}"></div>
}"
/>
</template>
<script>
@ -12,20 +15,20 @@ import Vue from 'vue'
export default {
name: 'nuxt-loading',
data () {
data() {
return {
percent: 0,
show: false,
canSuccess: true,
throttle: <%= loading.throttle %>,
duration: <%= loading.duration %>,
throttle: <%= loading.throttle || 200 %>,
duration: <%= loading.duration || 1000 %>,
height: '<%= loading.height %>',
color: '<%= loading.color %>',
failedColor: '<%= loading.failedColor %>',
failedColor: '<%= loading.failedColor %>'
}
},
methods: {
start () {
start() {
this.canSuccess = true
if (this._throttle) {
clearTimeout(this._throttle)
@ -47,33 +50,33 @@ export default {
}, this.throttle)
return this
},
set (num) {
set(num) {
this.show = true
this.canSuccess = true
this.percent = Math.floor(num)
return this
},
get () {
get() {
return Math.floor(this.percent)
},
increase (num) {
increase(num) {
this.percent = this.percent + Math.floor(num)
return this
},
decrease (num) {
decrease(num) {
this.percent = this.percent - Math.floor(num)
return this
},
finish () {
finish() {
this.percent = 100
this.hide()
return this
},
pause () {
pause() {
clearInterval(this._timer)
return this
},
hide () {
hide() {
clearInterval(this._timer)
this._timer = null
clearTimeout(this._throttle)
@ -88,7 +91,7 @@ export default {
}, 500)
return this
},
fail () {
fail() {
this.canSuccess = false
return this
}

View File

@ -1,5 +1,6 @@
<%= isTest ? '// @vue/component' : '' %>
import Vue from 'vue'
import NuxtChild from './nuxt-child'
import { compile } from '../utils'
<% if (components.ErrorPage) { %>
<% if (('~@').includes(components.ErrorPage.charAt(0))) { %>
@ -10,12 +11,14 @@ import NuxtError from '<%= "../" + components.ErrorPage %>'
<% } else { %>
import NuxtError from './nuxt-error.vue'
<% } %>
import { compile } from '../utils'
import NuxtChild from './nuxt-child'
export default {
name: 'nuxt',
props: ['nuxtChildKey', 'keepAlive'],
props: {
nuxtChildKey: String,
keepAlive: Boolean
},
render(h) {
// If there is some error
if (this.nuxt.err) {
@ -31,11 +34,11 @@ export default {
props: this.$props
})
},
beforeCreate () {
beforeCreate() {
Vue.util.defineReactive(this, 'nuxt', this.$root.$options.nuxt)
},
computed: {
routerViewKey () {
routerViewKey() {
// If nuxtChildKey prop is given or current route has children
if (typeof this.nuxtChildKey !== 'undefined' || this.$route.matched.length > 1) {
return this.nuxtChildKey || compile(this.$route.matched[0].path)(this.$route.params)

View File

@ -11,8 +11,10 @@ import { setContext, getLocation, getRouteData } from './utils'
<% if (store) { %>import { createStore } from './store.js'<% } %>
/* Plugins */
<%= isTest ? '/* eslint-disable camelcase */' : '' %>
<% plugins.forEach((plugin) => { %>import <%= plugin.name %> from '<%= plugin.name %>' // Source: <%= relativeToBuild(plugin.src) %><%= (plugin.ssr===false) ? ' (ssr: false)' : '' %>
<% }) %>
<%= isTest ? '/* eslint-enable camelcase */' : '' %>
// Component: <no-ssr>
Vue.component(NoSSR.name, NoSSR)
@ -40,9 +42,9 @@ const defaultTransition = <%=
.replace('enterCancelled(', 'function(').replace('beforeLeave(', 'function(').replace('leave(', 'function(')
.replace('afterLeave(', 'function(').replace('leaveCancelled(', 'function(').replace('beforeAppear(', 'function(')
.replace('appear(', 'function(').replace('afterAppear(', 'function(').replace('appearCancelled(', 'function(')
%>
%><%= isTest ? '// eslint-disable-line' : '' %>
async function createApp (ssrContext) {
async function createApp(ssrContext) {
const router = await createRouter(ssrContext)
<% if (store) { %>
@ -56,7 +58,8 @@ async function createApp (ssrContext) {
<% } %>
<% } %>
// Create Root instance
// Create Root instance13:14:29: Error: can't open file '.eslintrc.js' (error 2: No such file or directory)
// here we inject the router and store to all child components,
// making them available everywhere as `this.$router` and `this.$store`.
const app = {
@ -65,7 +68,7 @@ async function createApp (ssrContext) {
nuxt: {
defaultTransition,
transitions: [ defaultTransition ],
setTransitions (transitions) {
setTransitions(transitions) {
if (!Array.isArray(transitions)) {
transitions = [ transitions ]
}
@ -84,7 +87,7 @@ async function createApp (ssrContext) {
},
err: null,
dateErr: null,
error (err) {
error(err) {
err = err || null
app.context._errored = !!err
if (typeof err === 'string') err = { statusCode: 500, message: err }
@ -124,6 +127,7 @@ async function createApp (ssrContext) {
beforeRenderFns: ssrContext ? ssrContext.beforeRenderFns : undefined
})
<% if (plugins.length) { %>
const inject = function (key, value) {
if (!key) throw new Error('inject(key, value) has no key provided')
if (!value) throw new Error('inject(key, value) has no value provided')
@ -142,13 +146,14 @@ async function createApp (ssrContext) {
Vue.use(() => {
if (!Vue.prototype.hasOwnProperty(key)) {
Object.defineProperty(Vue.prototype, key, {
get () {
get() {
return this.$root.$options[key]
}
})
}
})
}
<% } %>
<% if (store) { %>
if (process.client) {
@ -160,12 +165,14 @@ async function createApp (ssrContext) {
<% } %>
// Plugin execution
<%= isTest ? '/* eslint-disable camelcase */' : '' %>
<% plugins.filter(p => p.ssr).forEach((plugin) => { %>
if (typeof <%= plugin.name %> === 'function') await <%= plugin.name %>(app.context, inject)<% }) %>
<% if (plugins.filter(p => !p.ssr).length) { %>
if (process.client) { <% plugins.filter((p) => !p.ssr).forEach((plugin) => { %>
if (typeof <%= plugin.name %> === 'function') await <%= plugin.name %>(app.context, inject)<% }) %>
}<% } %>
<%= isTest ? '/* eslint-enable camelcase */' : '' %>
// If server-side, wait for async component to be resolved first
if (process.server && ssrContext && ssrContext.url) {
@ -186,8 +193,8 @@ async function createApp (ssrContext) {
return {
app,
router,
<% if(store) { %>store<% } %>
<% if(store) { %>store,<% } %>
router
}
}

View File

@ -1,3 +1,3 @@
<template>
<nuxt/>
<nuxt />
</template>

View File

@ -2,7 +2,7 @@
const files = require.context('@/<%= dir.middleware %>', false, /^\.\/(?!<%= ignorePrefix %>)[^.]+\.(<%= extensions %>)$/)
const filenames = files.keys()
function getModule (filename) {
function getModule(filename) {
const file = files(filename)
return file.default || file
}

View File

@ -1,32 +1,39 @@
import Vue from 'vue'
import Router from 'vue-router'
import { interopDefault } from './utils';
import { interopDefault } from './utils'
<% function recursiveRoutes(routes, tab, components) {
<% function recursiveRoutes(routes, tab, components, indentCount) {
let res = ''
const baseIndent = tab.repeat(indentCount)
const firstIndent = '\n' + tab.repeat(indentCount + 1)
const nextIndent = ',' + firstIndent
routes.forEach((route, i) => {
route._name = '_' + hash(route.component)
components.push({ _name: route._name, component: route.component, name: route.name, chunkName: route.chunkName })
// @see: https://router.vuejs.org/api/#router-construction-options
res += tab + '{\n'
res += tab + '\tpath: ' + JSON.stringify(route.path)
res += (route.component) ? ',\n\t' + tab + 'component: ' + (splitChunks.pages ? route._name : `() => ${route._name}.default || ${route._name}`) : ''
res += (route.redirect) ? ',\n\t' + tab + 'redirect: ' + JSON.stringify(route.redirect) : ''
res += (route.meta) ? ',\n\t' + tab + 'meta: ' + JSON.stringify(route.meta) : ''
res += (typeof route.props !== 'undefined') ? ',\n\t' + tab + 'props: ' + (typeof route.props === 'function' ? serialize(route.props) : JSON.stringify(route.props)) : ''
res += (typeof route.caseSensitive !== 'undefined') ? ',\n\t' + tab + 'caseSensitive: ' + JSON.stringify(route.caseSensitive) : ''
res += (route.alias) ? ',\n\t' + tab + 'alias: ' + JSON.stringify(route.alias) : ''
res += (route.pathToRegexpOptions) ? ',\n\t' + tab + 'pathToRegexpOptions: ' + JSON.stringify(route.pathToRegexpOptions) : ''
res += (route.name) ? ',\n\t' + tab + 'name: ' + JSON.stringify(route.name) : ''
res += (route.beforeEnter) ? ',\n\t' + tab + 'beforeEnter: ' + serialize(route.beforeEnter) : ''
res += (route.children) ? ',\n\t' + tab + 'children: [\n' + recursiveRoutes(routes[i].children, tab + '\t\t', components) + '\n\t' + tab + ']' : ''
res += '\n' + tab + '}' + (i + 1 === routes.length ? '' : ',\n')
res += '{'
res += firstIndent + 'path: ' + JSON.stringify(route.path)
res += (route.component) ? nextIndent + 'component: ' + (splitChunks.pages ? route._name : `() => ${route._name}.default || ${route._name}`) : ''
res += (route.redirect) ? nextIndent + 'redirect: ' + JSON.stringify(route.redirect) : ''
res += (route.meta) ? nextIndent + 'meta: ' + JSON.stringify(route.meta) : ''
res += (typeof route.props !== 'undefined') ? nextIndent + 'props: ' + (typeof route.props === 'function' ? serialize(route.props) : JSON.stringify(route.props)) : ''
res += (typeof route.caseSensitive !== 'undefined') ? nextIndent + 'caseSensitive: ' + JSON.stringify(route.caseSensitive) : ''
res += (route.alias) ? nextIndent + 'alias: ' + JSON.stringify(route.alias) : ''
res += (route.pathToRegexpOptions) ? nextIndent + 'pathToRegexpOptions: ' + JSON.stringify(route.pathToRegexpOptions) : ''
res += (route.name) ? nextIndent + 'name: ' + JSON.stringify(route.name) : ''
if (route.beforeEnter) {
if(isTest) { res += ',\n/* eslint-disable indent, semi */' }
res += (isTest ? firstIndent : nextIndent) + 'beforeEnter: ' + serialize(route.beforeEnter)
if(isTest) { res += firstIndent + '/* eslint-enable indent, semi */' }
}
res += (route.children) ? nextIndent + 'children: [' + recursiveRoutes(routes[i].children, tab, components, indentCount + 1) + ']' : ''
res += '\n' + baseIndent + '}' + (i + 1 === routes.length ? '' : ', ')
})
return res
}
const _components = []
const _routes = recursiveRoutes(router.routes, '\t\t', _components)
%> <%= uniqBy(_components, '_name').map((route) => {
const _routes = recursiveRoutes(router.routes, ' ', _components, 2)
%><%= uniqBy(_components, '_name').map((route) => {
if (!route.component) return ''
const path = relativeToBuild(route.component)
const chunkName = wChunk(route.chunkName)
@ -56,7 +63,7 @@ const scrollBehavior = function (to, from, savedPosition) {
if (to.matched.length < 2) {
// scroll to the top of the page
position = { x: 0, y: 0 }
} else if (to.matched.some((r) => r.components.default.options.scrollToTop)) {
} else if (to.matched.some(r => r.components.default.options.scrollToTop)) {
// if one of the children has scrollToTop option set to true
position = { x: 0, y: 0 }
}
@ -92,16 +99,16 @@ const scrollBehavior = function (to, from, savedPosition) {
}
<% } %>
export function createRouter () {
export function createRouter() {
return new Router({
mode: '<%= router.mode %>',
base: '<%= router.base %>',
linkActiveClass: '<%= router.linkActiveClass %>',
linkExactActiveClass: '<%= router.linkExactActiveClass %>',
scrollBehavior,
routes: [
<%= _routes %>
],
<%= isTest ? '/* eslint-disable quotes */' : '' %>
routes: [<%= _routes %>],
<%= isTest ? '/* eslint-enable quotes */' : '' %>
<% if (router.parseQuery) { %>parseQuery: <%= serialize(router.parseQuery).replace('parseQuery(', 'function(') %>,<% } %>
<% if (router.stringifyQuery) { %>stringifyQuery: <%= serialize(router.stringifyQuery).replace('stringifyQuery(', 'function(') %>,<% } %>
fallback: <%= router.fallback %>

View File

@ -1,18 +1,18 @@
import Vue from 'vue'
import { stringify } from 'querystring'
import Vue from 'vue'
import omit from 'lodash/omit'
import middleware from './middleware'
import { createApp, NuxtError } from './index'
import { applyAsyncData, sanitizeComponent, getMatchedComponents, getContext, middlewareSeries, promisify, urlJoin } from './utils'
import { createApp, NuxtError } from './index'
const debug = require('debug')('nuxt:render')
debug.color = 4 // force blue color
const isDev = <%= isDev %>
const noopApp = () => new Vue({ render: (h) => h('div') })
const noopApp = () => new Vue({ render: h => h('div') })
const createNext = (ssrContext) => (opts) => {
const createNext = ssrContext => (opts) => {
ssrContext.redirected = opts
// If nuxt generate
if (!ssrContext.res) {
@ -21,8 +21,9 @@ const createNext = (ssrContext) => (opts) => {
}
opts.query = stringify(opts.query)
opts.path = opts.path + (opts.query ? '?' + opts.query : '')
if (!opts.path.startsWith('http') && ('<%= router.base %>' !== '/' && !opts.path.startsWith('<%= router.base %>'))) {
opts.path = urlJoin('<%= router.base %>', opts.path)
const routerBase = '<%= router.base %>'
if (!opts.path.startsWith('http') && (routerBase !== '/' && !opts.path.startsWith(routerBase))) {
opts.path = urlJoin(routerBase, opts.path)
}
// Avoid loop redirect
if (opts.path === ssrContext.url) {
@ -59,7 +60,7 @@ export default async (ssrContext) => {
const beforeRender = async () => {
// Call beforeNuxtRender() methods
await Promise.all(ssrContext.beforeRenderFns.map((fn) => promisify(fn, { Components, nuxtState: ssrContext.nuxt })))
await Promise.all(ssrContext.beforeRenderFns.map(fn => promisify(fn, { Components, nuxtState: ssrContext.nuxt })))
<% if (store) { %>
// Add the state from the vuex store
ssrContext.nuxt.state = store.state
@ -67,7 +68,7 @@ export default async (ssrContext) => {
}
const renderErrorPage = async () => {
// Load layout for error page
let errLayout = (typeof NuxtError.layout === 'function' ? NuxtError.layout(app.context) : NuxtError.layout)
const errLayout = (typeof NuxtError.layout === 'function' ? NuxtError.layout(app.context) : NuxtError.layout)
ssrContext.nuxt.layout = errLayout || 'default'
await _app.loadLayout(errLayout)
_app.setLayout(errLayout)
@ -104,7 +105,7 @@ export default async (ssrContext) => {
/*
** Call global middleware (nuxt.config.js)
*/
let midd = <%= serialize(router.middleware).replace('middleware(', 'function(') %>
let midd = <%= serialize(router.middleware).replace('middleware(', 'function(') %><%= isTest ? '// eslint-disable-line' : '' %>
midd = midd.map((name) => {
if (typeof name === 'function') return name
if (typeof middleware[name] !== 'function') {
@ -186,12 +187,12 @@ export default async (ssrContext) => {
if (!Components.length) return render404Page()
// Call asyncData & fetch hooks on components matched by the route.
let asyncDatas = await Promise.all(Components.map((Component) => {
let promises = []
const asyncDatas = await Promise.all(Components.map((Component) => {
const promises = []
// Call asyncData(context)
if (Component.options.asyncData && typeof Component.options.asyncData === 'function') {
let promise = promisify(Component.options.asyncData, app.context)
const promise = promisify(Component.options.asyncData, app.context)
promise.then((asyncDataResult) => {
ssrContext.asyncData[Component.cid] = asyncDataResult
applyAsyncData(Component)
@ -205,8 +206,7 @@ export default async (ssrContext) => {
// Call fetch(context)
if (Component.options.fetch) {
promises.push(Component.options.fetch(app.context))
}
else {
} else {
promises.push(null)
}

View File

@ -81,7 +81,7 @@ export const createStore = storeData instanceof Function ? storeData : () => {
}
// Dynamically require module
function getModule (filename) {
function getModule(filename) {
const file = files(filename)
const module = file.default || file
if (module.commit) {
@ -93,7 +93,7 @@ function getModule (filename) {
return module
}
function getModuleNamespace (storeData, namePath, forAppend = false) {
function getModuleNamespace(storeData, namePath, forAppend = false) {
if (namePath.length === 1) {
if (forAppend) {
return storeData
@ -107,7 +107,7 @@ function getModuleNamespace (storeData, namePath, forAppend = false) {
return getModuleNamespace(storeData.modules[namespace], namePath, forAppend)
}
function appendModule (module, filename, name) {
function appendModule(module, filename, name) {
const file = files(filename)
module.appends = module.appends || []
module.appends.push(name)

View File

@ -20,7 +20,7 @@ export function globalHandleError(error) {
}
export function interopDefault(promise) {
return promise.then(m => m.default || m);
return promise.then(m => m.default || m)
}
export function applyAsyncData(Component, asyncData) {
@ -99,7 +99,8 @@ export function resolveRouteComponents(route) {
if (typeof Component === 'function' && !Component.options) {
Component = await Component()
}
return match.components[key] = sanitizeComponent(Component)
match.components[key] = sanitizeComponent(Component)
return match.components[key]
})
)
}
@ -117,7 +118,6 @@ export async function getRouteData(route) {
}
export async function setContext(app, context) {
const route = (context.to ? context.to : context.route)
// If context not defined, create it
if (!app.context) {
app.context = {
@ -129,7 +129,7 @@ export async function setContext(app, context) {
payload: context.payload,
error: context.error,
base: '<%= router.base %>',
env: <%= JSON.stringify(env) %>
env: <%= JSON.stringify(env) %><%= isTest ? '// eslint-disable-line' : '' %>
}
// Only set once
if (context.req) app.context.req = context.req
@ -230,7 +230,7 @@ export function promisify(fn, context) {
// Imported from vue-router
export function getLocation(base, mode) {
var path = window.location.pathname
let path = window.location.pathname
if (mode === 'hash') {
return window.location.hash.replace(/^#\//, '')
}
@ -294,17 +294,17 @@ const PATH_REGEXP = new RegExp([
* @return {!Array}
*/
function parse(str, options) {
var tokens = []
var key = 0
var index = 0
var path = ''
var defaultDelimiter = options && options.delimiter || '/'
var res
const tokens = []
let key = 0
let index = 0
let path = ''
const defaultDelimiter = (options && options.delimiter) || '/'
let res
while ((res = PATH_REGEXP.exec(str)) != null) {
var m = res[0]
var escaped = res[1]
var offset = res.index
const m = res[0]
const escaped = res[1]
const offset = res.index
path += str.slice(index, offset)
index = offset + m.length
@ -314,13 +314,13 @@ function parse(str, options) {
continue
}
var next = str[index]
var prefix = res[2]
var name = res[3]
var capture = res[4]
var group = res[5]
var modifier = res[6]
var asterisk = res[7]
const next = str[index]
const prefix = res[2]
const name = res[3]
const capture = res[4]
const group = res[5]
const modifier = res[6]
const asterisk = res[7]
// Push the current path onto the tokens.
if (path) {
@ -328,11 +328,11 @@ function parse(str, options) {
path = ''
}
var partial = prefix != null && next != null && next !== prefix
var repeat = modifier === '+' || modifier === '*'
var optional = modifier === '?' || modifier === '*'
var delimiter = res[2] || defaultDelimiter
var pattern = capture || group
const partial = prefix != null && next != null && next !== prefix
const repeat = modifier === '+' || modifier === '*'
const optional = modifier === '?' || modifier === '*'
const delimiter = res[2] || defaultDelimiter
const pattern = capture || group
tokens.push({
name: name || key++,
@ -366,7 +366,7 @@ function parse(str, options) {
* @return {string}
*/
function encodeURIComponentPretty(str) {
return encodeURI(str).replace(/[\/?#]/g, (c) => {
return encodeURI(str).replace(/[/?#]/g, (c) => {
return '%' + c.charCodeAt(0).toString(16).toUpperCase()
})
}
@ -388,23 +388,23 @@ function encodeAsterisk(str) {
*/
function tokensToFunction(tokens) {
// Compile all the tokens into regexps.
var matches = new Array(tokens.length)
const matches = new Array(tokens.length)
// Compile all the patterns before compilation.
for (var i = 0; i < tokens.length; i++) {
for (let i = 0; i < tokens.length; i++) {
if (typeof tokens[i] === 'object') {
matches[i] = new RegExp('^(?:' + tokens[i].pattern + ')$')
}
}
return function(obj, opts) {
var path = ''
var data = obj || {}
var options = opts || {}
var encode = options.pretty ? encodeURIComponentPretty : encodeURIComponent
return function (obj, opts) {
let path = ''
const data = obj || {}
const options = opts || {}
const encode = options.pretty ? encodeURIComponentPretty : encodeURIComponent
for (var i = 0; i < tokens.length; i++) {
var token = tokens[i]
for (let i = 0; i < tokens.length; i++) {
const token = tokens[i]
if (typeof token === 'string') {
path += token
@ -412,8 +412,8 @@ function tokensToFunction(tokens) {
continue
}
var value = data[token.name]
var segment
const value = data[token.name]
let segment
if (value == null) {
if (token.optional) {
@ -441,7 +441,7 @@ function tokensToFunction(tokens) {
}
}
for (var j = 0; j < value.length; j++) {
for (let j = 0; j < value.length; j++) {
segment = encode(value[j])
if (!matches[i].test(segment)) {
@ -474,7 +474,7 @@ function tokensToFunction(tokens) {
* @return {string}
*/
function escapeString(str) {
return str.replace(/([.+*?=^!:${}()[\]|\/\\])/g, '\\$1')
return str.replace(/([.+*?=^!:${}()[\]|/\\])/g, '\\$1')
}
/**
@ -484,7 +484,7 @@ function escapeString(str) {
* @return {string}
*/
function escapeGroup(group) {
return group.replace(/([=!:$\/()])/g, '\\$1')
return group.replace(/([=!:$/()])/g, '\\$1')
}
/**
@ -494,9 +494,9 @@ function escapeGroup(group) {
* @param {string} query
* @return {string}
*/
function formatUrl (url, query) {
function formatUrl(url, query) {
let protocol
let index = url.indexOf('://')
const index = url.indexOf('://')
if (index !== -1) {
protocol = url.substring(0, index)
url = url.substring(index + 3)
@ -531,9 +531,9 @@ function formatUrl (url, query) {
* @param {object} query
* @return {string}
*/
function formatQuery (query) {
function formatQuery(query) {
return Object.keys(query).sort().map((key) => {
var val = query[key]
const val = query[key]
if (val == null) {
return ''
}

View File

@ -96,9 +96,9 @@
</style>
<script>
window.addEventListener('error', function() {
var e = document.getElementById("nuxt-loading");
if (e) e.className += " error";
window.addEventListener('error', function () {
var e = document.getElementById('nuxt-loading');
if (e) e.className += ' error';
});
</script>

View File

@ -33,7 +33,8 @@ import {
sequence,
relativeTo,
waitFor,
determineGlobals
determineGlobals,
stripWhitespace
} from '@nuxt/common'
import PerfLoader from './webpack/utils/perf-loader'
@ -214,6 +215,7 @@ export default class Builder {
splitChunks: this.options.build.splitChunks,
uniqBy,
isDev: this.options.dev,
isTest: this.options.test,
debug: this.options.debug,
vue: { config: this.options.vue.config },
mode: this.options.mode,
@ -432,7 +434,8 @@ export default class Builder {
},
interpolate: /<%=([\s\S]+?)%>/g
})
content = templateFunction(
content = stripWhitespace(
templateFunction(
Object.assign({}, templateVars, {
options: options || {},
custom,
@ -440,6 +443,7 @@ export default class Builder {
dst
})
)
)
} catch (err) {
/* istanbul ignore next */
throw new Error(`Could not compile template ${src}: ${err.message}`)

View File

@ -10,6 +10,7 @@ const nuxtDir = fs.existsSync(path.resolve(__dirname, '..', '..', 'package.js'))
export default {
// Information about running environment
dev: Boolean(env.dev),
test: Boolean(env.test),
debug: undefined, // = dev
// Mode

View File

@ -389,3 +389,18 @@ const DYNAMIC_ROUTE_REGEX = /^\/(:|\*)/
* @return {array}
*/
export const wrapArray = value => Array.isArray(value) ? value : [value]
const WHITESPACE_REPLACEMENTS = [
[/[ \t\f\r]+\n/g, '\n'], // strip empty indents
[/{\n{2,}/g, '{\n'], // strip start padding from blocks
[/\n{2,}([ \t\f\r]*})/g, '\n$1'], // strip end padding from blocks
[/\n{3,}/g, '\n\n'], // strip multiple blank lines (1 allowed)
[/\n{2,}$/g, '\n'] // strip blank lines EOF (0 allowed)
]
export const stripWhitespace = function stripWhitespace(string) {
WHITESPACE_REPLACEMENTS.forEach(([regex, newSubstr]) => {
string = string.replace(regex, newSubstr)
})
return string
}

View File

@ -1,4 +1,5 @@
export default {
test: true,
hooks(hook) {
hook('build:done', () => {
process.stdout.write('Compiled successfully')

View File

@ -1,7 +1,8 @@
export default {
buildDir: '.nuxt-generate/.build',
test: true,
buildDir: '.nuxt-generate/build',
generate: {
dir: '.nuxt-generate/.generate'
dir: '.nuxt-generate/generate'
},
hooks(hook) {
hook('generate:done', (generator, errors) => {

View File

@ -30,6 +30,7 @@ export const loadFixture = async function (fixture, overrides) {
config.rootDir = rootDir
config.dev = false
config.test = true
return defaultsDeep({}, overrides, config)
}