chore: lint vue-app templates (#4689)

This commit is contained in:
Pim 2019-01-06 08:56:59 +01:00 committed by Pooya Parsa
parent d063cb09e8
commit 605b76073b
14 changed files with 96 additions and 63 deletions

View File

@ -109,6 +109,16 @@ jobs:
paths: paths:
- test/fixtures - test/fixtures
lint-app:
<<: *defaults
steps:
- checkout
- attach_workspace:
at: ~/project
- run:
name: Lint vue-app templates
command: yarn lint:app
# -------------------------------------------------------------------------- # --------------------------------------------------------------------------
# Phase 3: Unit and E2E tests # Phase 3: Unit and E2E tests
# -------------------------------------------------------------------------- # --------------------------------------------------------------------------
@ -148,17 +158,18 @@ workflows:
version: 2 version: 2
# Build and test after each commit # Build and test after each commit
# Manually release on releas branches # Manually release on release branches
commit: commit:
jobs: jobs:
- setup - setup
- lint: { requires: [setup] } - lint: { requires: [setup] }
- audit: { requires: [setup] } - audit: { requires: [setup] }
- build: { requires: [setup] } - build: { requires: [setup] }
- lint-app: { requires: [build] }
- test-unit: { requires: [build] } - test-unit: { requires: [build] }
- test-e2e: { requires: [build] } - test-e2e: { requires: [build] }
- release-commit: - release-commit:
requires: [build, lint, audit, test-unit, test-e2e] requires: [build, lint, lint-app, audit, test-unit, test-e2e]
filters: filters:
<<: *release_branches <<: *release_branches
@ -169,10 +180,11 @@ workflows:
- lint: { requires: [setup] } - lint: { requires: [setup] }
- audit: { requires: [setup] } - audit: { requires: [setup] }
- build: { requires: [setup] } - build: { requires: [setup] }
- lint-app: { requires: [build] }
- test-unit: { requires: [build] } - test-unit: { requires: [build] }
- test-e2e: { requires: [build] } - test-e2e: { requires: [build] }
- release-nightly: - release-nightly:
requires: [build, lint, audit, test-unit, test-e2e] requires: [build, lint, lint-app, audit, test-unit, test-e2e]
triggers: triggers:
- schedule: - schedule:
cron: "0 0 * * *" cron: "0 0 * * *"

View File

@ -13,9 +13,9 @@ module.exports = {
overrides: [{ overrides: [{
files: [ 'test/fixtures/*/.nuxt*/**' ], files: [ 'test/fixtures/*/.nuxt*/**' ],
rules: { rules: {
'vue/name-property-casing': ['error', 'kebab-case'] 'vue/name-property-casing': 'error'
} }
},{ }, {
files: [ files: [
'examples/storybook/**', 'examples/storybook/**',
'examples/with-element-ui/**', 'examples/with-element-ui/**',
@ -29,9 +29,9 @@ module.exports = {
'vue/component-name-in-template-casing': ['warn', 'kebab-case'] 'vue/component-name-in-template-casing': ['warn', 'kebab-case']
} }
}, { }, {
files: [ 'test/fixtures/*/.nuxt*/**/+(App|index).js' ], files: [ 'test/fixtures/*/.nuxt*/**/+(App|index|server|client).js' ],
rules: { rules: {
'import/order': 'ignore' 'import/order': 'off'
} }
}, { }, {
files: [ 'test/fixtures/*/.nuxt*/**/client.js' ], files: [ 'test/fixtures/*/.nuxt*/**/client.js' ],
@ -47,7 +47,18 @@ module.exports = {
files: [ 'test/fixtures/*/.nuxt*/**/*.html' ], files: [ 'test/fixtures/*/.nuxt*/**/*.html' ],
rules: { rules: {
'semi': ['error', 'always', { 'omitLastInOneLineBlock': true }], 'semi': ['error', 'always', { 'omitLastInOneLineBlock': true }],
'no-var': 'warn' 'no-var': 'off'
}
}, {
files: [ 'test/fixtures/*/.nuxt*/**/nuxt-error.vue' ],
rules: {
'vue/singleline-html-element-content-newline': 'off'
}
}, {
// might be removed in the future, see https://github.com/standard/eslint-plugin-standard/issues/27
files: [ 'test/fixtures/*/.nuxt*/**/nuxt-link.client.js' ],
rules: {
'standard/no-callback-literal': 'off'
} }
}] }]
} }

View File

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

View File

@ -5,17 +5,17 @@ export function serializeFunction(func) {
let open = false let open = false
return serialize(func) return serialize(func)
.replace(serializeFunction.assignmentRE, (_, spaces) => { .replace(serializeFunction.assignmentRE, (_, spaces) => {
return `${spaces}:function(` return `${spaces}: function (`
}) })
.replace(serializeFunction.internalFunctionRE, (_, spaces, name, args) => { .replace(serializeFunction.internalFunctionRE, (_, spaces, name, args) => {
if (open) { if (open) {
return `${spaces}${name}:function(${args}) {` return `${spaces}${name}: function (${args}) {`
} else { } else {
open = true open = true
return _ return _
} }
}) })
.replace(`${func.name}(`, 'function(') .replace(`${func.name}(`, 'function (')
} }
serializeFunction.internalFunctionRE = /^(\s*)(?!(?:if)|(?:for)|(?:while)|(?:switch))(\w+)\s*\((.*?)\)\s*\{/gm serializeFunction.internalFunctionRE = /^(\s*)(?!(?:if)|(?:for)|(?:while)|(?:switch))(\w+)\s*\((.*?)\)\s*\{/gm

View File

@ -17,9 +17,9 @@ const layouts = { <%= Object.keys(layouts).map(key => `"_${key}": _${hash(key)}`
<% if (splitChunks.layouts) { %>let resolvedLayouts = {}<% } %> <% if (splitChunks.layouts) { %>let resolvedLayouts = {}<% } %>
export default { export default {
<%= isTest ? '/* eslint-disable quotes, semi, indent, comma-spacing, key-spacing, object-curly-spacing, object-property-newline, arrow-parens */' : '' %> <%= isTest ? '/* eslint-disable quotes, semi, indent, comma-spacing, key-spacing, object-curly-spacing, space-before-function-paren */' : '' %>
head: <%= serializeFunction(head) %>, head: <%= serializeFunction(head) %>,
<%= isTest ? '/* eslint-enable quotes, semi, indent, comma-spacing, key-spacing, object-curly-spacing, object-property-newline, arrow-parens */' : '' %> <%= isTest ? '/* eslint-enable quotes, semi, indent, comma-spacing, key-spacing, object-curly-spacing, space-before-function-paren */' : '' %>
render(h, props) { render(h, props) {
<% if (loading) { %>const loadingEl = h('NuxtLoading', { ref: 'loading' })<% } %> <% if (loading) { %>const loadingEl = h('NuxtLoading', { ref: 'loading' })<% } %>
const layoutEl = h(this.layout || 'nuxt') const layoutEl = h(this.layout || 'nuxt')

View File

@ -22,14 +22,11 @@ import NuxtLink from './components/nuxt-link.<%= router.prefetchLinks ? "client"
Vue.component(NuxtLink.name, NuxtLink) Vue.component(NuxtLink.name, NuxtLink)
Vue.component('NLink', NuxtLink) Vue.component('NLink', NuxtLink)
const noopData = () => { return {} }
const noopFetch = () => {}
// Global shared references // Global shared references
let _lastPaths = [] let _lastPaths = []
let app let app
let router let router
<% if (store) { %>let store<% } %> <% if (store) { %>let store<%= isTest ? '// eslint-disable-line no-unused-vars' : '' %><% } %>
// Try to rehydrate SSR data from window // Try to rehydrate SSR data from window
const NUXT = window.<%= globals.context %> || {} const NUXT = window.<%= globals.context %> || {}
@ -150,8 +147,8 @@ async function loadAsyncComponents(to, from, next) {
<% } %> <% } %>
// Call next() // Call next()
next() next()
} catch (err) { } catch (error) {
err = err || {} const err = error || {}
const statusCode = err.statusCode || err.status || (err.response && err.response.status) || 500 const statusCode = err.statusCode || err.status || (err.response && err.response.status) || 500
const message = err.message || '' const message = err.message || ''
@ -524,6 +521,9 @@ function nuxtReady(_app) {
} }
<% if (isDev) { %> <% if (isDev) { %>
const noopData = () => { return {} }
const noopFetch = () => {}
// Special hot reload with asyncData(context) // Special hot reload with asyncData(context)
function getNuxtChildComponents($parent, $components = []) { function getNuxtChildComponents($parent, $components = []) {
$parent.$children.forEach(($child) => { $parent.$children.forEach(($child) => {

View File

@ -8,7 +8,10 @@ export default {
default: '' default: ''
}, },
keepAlive: Boolean, keepAlive: Boolean,
keepAliveProps: Object keepAliveProps: {
type: Object,
default: undefined
}
}, },
render(h, { parent, data, props }) { render(h, { parent, data, props }) {
data.nuxtChild = true data.nuxtChild = true

View File

@ -1,7 +1,9 @@
<template> <template>
<div class="__nuxt-error-page"> <div class="__nuxt-error-page">
<div class="error"> <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> <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> <div class="title">{{ message }}</div>
<p v-if="statusCode === 404" class="description"> <p v-if="statusCode === 404" class="description">

View File

@ -1,4 +1,3 @@
<%= isTest ? '// @vue/component' : '' %>
import Vue from 'vue' import Vue from 'vue'
const requestIdleCallback = window.requestIdleCallback || const requestIdleCallback = window.requestIdleCallback ||
@ -9,11 +8,11 @@ const requestIdleCallback = window.requestIdleCallback ||
didTimeout: false, didTimeout: false,
timeRemaining: function () { timeRemaining: function () {
return Math.max(0, 50 - (Date.now() - start)) return Math.max(0, 50 - (Date.now() - start))
}, }
}) })
}, 1) }, 1)
} }
const observer = window.IntersectionObserver && new window.IntersectionObserver(entries => { const observer = window.IntersectionObserver && new window.IntersectionObserver((entries) => {
entries.forEach(({ intersectionRatio, target: link }) => { entries.forEach(({ intersectionRatio, target: link }) => {
if (intersectionRatio <= 0) { if (intersectionRatio <= 0) {
return return
@ -22,9 +21,10 @@ const observer = window.IntersectionObserver && new window.IntersectionObserver(
}) })
}) })
<%= isTest ? '// @vue/component' : '' %>
export default { export default {
extends: Vue.component('RouterLink'),
name: 'NuxtLink', name: 'NuxtLink',
extends: Vue.component('RouterLink'),
props: { props: {
noPrefetch: { noPrefetch: {
type: Boolean, type: Boolean,
@ -72,9 +72,9 @@ export default {
}, },
getPrefetchComponents() { getPrefetchComponents() {
const ref = this.$router.resolve(this.to, this.$route, this.append) const ref = this.$router.resolve(this.to, this.$route, this.append)
const Components = ref.resolved.matched.map((r) => r.components.default) const Components = ref.resolved.matched.map(r => r.components.default)
return Components.filter((Component) => typeof Component === 'function' && !Component.options && !Component.__prefetched) return Components.filter(Component => typeof Component === 'function' && !Component.options && !Component.__prefetched)
}, },
prefetch() { prefetch() {
if (!this.canPrefetch()) { if (!this.canPrefetch()) {

View File

@ -1,9 +1,9 @@
<%= isTest ? '// @vue/component' : '' %>
import Vue from 'vue' import Vue from 'vue'
<%= isTest ? '// @vue/component' : '' %>
export default { export default {
extends: Vue.component('RouterLink'),
name: 'NuxtLink', name: 'NuxtLink',
extends: Vue.component('RouterLink'),
props: { props: {
noPrefetch: { noPrefetch: {
type: Boolean, type: Boolean,

View File

@ -1,4 +1,3 @@
<%= isTest ? '// @vue/component' : '' %>
import Vue from 'vue' import Vue from 'vue'
import { compile } from '../utils' import { compile } from '../utils'
@ -13,17 +12,44 @@ import NuxtError from './nuxt-error.vue'
<% } %> <% } %>
import NuxtChild from './nuxt-child' import NuxtChild from './nuxt-child'
<%= isTest ? '// @vue/component' : '' %>
export default { export default {
name: 'Nuxt', name: 'Nuxt',
components: {
NuxtChild,
NuxtError
},
props: { props: {
nuxtChildKey: String, nuxtChildKey: {
type: String,
default: undefined
},
keepAlive: Boolean, keepAlive: Boolean,
keepAliveProps: Object, keepAliveProps: {
type: Object,
default: undefined
},
name: { name: {
type: String, type: String,
default: 'default' default: 'default'
} }
}, },
computed: {
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)
}
const Component = this.$route.matched[0] && this.$route.matched[0].components.default
if (Component && Component.options && Component.options.key) {
return (typeof Component.options.key === 'function' ? Component.options.key(this.$route) : Component.options.key)
}
return this.$route.path
}
},
beforeCreate() {
Vue.util.defineReactive(this, 'nuxt', this.$root.$options.nuxt)
},
render(h) { render(h) {
// If there is some error // If there is some error
if (this.nuxt.err) { if (this.nuxt.err) {
@ -38,25 +64,5 @@ export default {
key: this.routerViewKey, key: this.routerViewKey,
props: this.$props props: this.$props
}) })
},
beforeCreate() {
Vue.util.defineReactive(this, 'nuxt', this.$root.$options.nuxt)
},
computed: {
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)
}
const Component = this.$route.matched[0] && this.$route.matched[0].components.default
if (Component && Component.options && Component.options.key) {
return (typeof Component.options.key === 'function' ? Component.options.key(this.$route) : Component.options.key)
}
return this.$route.path
}
},
components: {
NuxtChild,
NuxtError
} }
} }

View File

@ -1,6 +1,6 @@
import Vue from 'vue' import Vue from 'vue'
import Router from 'vue-router' import Router from 'vue-router'
import { interopDefault } from './utils' import { interopDefault } from './utils'<%= isTest ? '// eslint-disable-line no-unused-vars' : '' %>
<% function recursiveRoutes(routes, tab, components, indentCount) { <% function recursiveRoutes(routes, tab, components, indentCount) {
let res = '', resMap = '' let res = '', resMap = ''
@ -143,9 +143,9 @@ export function createRouter() {
linkActiveClass: '<%= router.linkActiveClass %>', linkActiveClass: '<%= router.linkActiveClass %>',
linkExactActiveClass: '<%= router.linkExactActiveClass %>', linkExactActiveClass: '<%= router.linkExactActiveClass %>',
scrollBehavior, scrollBehavior,
<%= isTest ? '/* eslint-disable quotes */' : '' %> <%= isTest ? '/* eslint-disable quotes, object-curly-spacing, key-spacing */' : '' %>
routes: [<%= _routes %>], routes: [<%= _routes %>],
<%= isTest ? '/* eslint-enable quotes */' : '' %> <%= isTest ? '/* eslint-enable quotes, object-curly-spacing, key-spacing */' : '' %>
<% if (router.parseQuery) { %>parseQuery: <%= serializeFunction(router.parseQuery) %>,<% } %> <% if (router.parseQuery) { %>parseQuery: <%= serializeFunction(router.parseQuery) %>,<% } %>
<% if (router.stringifyQuery) { %>stringifyQuery: <%= serializeFunction(router.stringifyQuery) %>,<% } %> <% if (router.stringifyQuery) { %>stringifyQuery: <%= serializeFunction(router.stringifyQuery) %>,<% } %>
fallback: <%= router.fallback %> fallback: <%= router.fallback %>

View File

@ -3,7 +3,7 @@ import Vue from 'vue'
import middleware from './middleware.js' import middleware from './middleware.js'
import { applyAsyncData, getMatchedComponents, middlewareSeries, promisify, urlJoin } from './utils.js' import { applyAsyncData, getMatchedComponents, middlewareSeries, promisify, urlJoin } from './utils.js'
import { createApp, NuxtError } from './index.js' import { createApp, NuxtError } from './index.js'
import NuxtLink from './components/nuxt-link.server.js' import NuxtLink from './components/nuxt-link.server.js' // should be included after ./index.js
// Component: <NuxtLink> // Component: <NuxtLink>
Vue.component(NuxtLink.name, NuxtLink) Vue.component(NuxtLink.name, NuxtLink)
@ -12,7 +12,7 @@ Vue.component('NLink', NuxtLink)
const debug = require('debug')('nuxt:render') const debug = require('debug')('nuxt:render')
debug.color = 4 // force blue color debug.color = 4 // force blue color
const isDev = <%= isDev %> const isDev = <%= isDev %><%= isTest ? '// eslint-disable-line no-unused-vars' : '' %>
const noopApp = () => new Vue({ render: h => h('div') }) const noopApp = () => new Vue({ render: h => h('div') })

View File

@ -5,9 +5,9 @@ Vue.use(Vuex)
let storeData = {} let storeData = {}
let files; let files
void function updateModules() { void (function updateModules() {
files = require.context('@/<%= dir.store %>', true, /^\.\/(?!<%= ignorePrefix %>)[^.]+\.(<%= extensions %>)$/) files = require.context('@/<%= dir.store %>', true, /^\.\/(?!<%= ignorePrefix %>)[^.]+\.(<%= extensions %>)$/)
const filenames = files.keys() const filenames = files.keys()
@ -82,12 +82,11 @@ void function updateModules() {
window.<%= globals.nuxt %>.$store.hotUpdate(storeData) window.<%= globals.nuxt %>.$store.hotUpdate(storeData)
}) })
}<% } %> }<% } %>
} } else {
else {
const log = (process.server ? require('consola') : console) const log = (process.server ? require('consola') : console)
log.warn('Classic mode for store/ is deprecated and will be removed in Nuxt 3.') log.warn('Classic mode for store/ is deprecated and will be removed in Nuxt 3.')
} }
}() })()
// createStore // createStore
export const createStore = storeData instanceof Function ? storeData : () => { export const createStore = storeData instanceof Function ? storeData : () => {