Signed-off-by: John Molakvoæ (skjnldsv) <skjnldsv@protonmail.com>
This commit is contained in:
John Molakvoæ (skjnldsv) 2018-08-17 16:57:42 +02:00
Родитель 4dde928741
Коммит f27d675871
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 60C25B8C072916CF
24 изменённых файлов: 14127 добавлений и 74 удалений

12
.babelrc Normal file
Просмотреть файл

@ -0,0 +1,12 @@
{
"presets": [
[
"env",
{
"targets": {
"browsers": ["> 1%", "last 2 versions", "not ie <= 11"]
}
}
]
]
}

9
.editorconfig Normal file
Просмотреть файл

@ -0,0 +1,9 @@
root = true
[*]
charset = utf-8
indent_style = tab
indent_size = 4
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true

59
.eslintrc.js Normal file
Просмотреть файл

@ -0,0 +1,59 @@
module.exports = {
root: true,
env: {
browser: true,
es6: true,
node: true,
jest: true
},
globals: {
t: false,
n: false,
OC: false,
OCA: false
},
parserOptions: {
parser: 'babel-eslint'
},
extends: [
'eslint:recommended',
'plugin:node/recommended',
'plugin:vue/recommended',
'standard'
],
plugins: ['vue', 'node'],
rules: {
// space before function ()
'space-before-function-paren': ['error', 'never'],
// curly braces always space
'object-curly-spacing': ['error', 'always'],
// stay consistent with array brackets
'array-bracket-newline': ['error', 'consistent'],
// 1tbs brace style
'brace-style': 'error',
// tabs only
indent: ['error', 'tab'],
'no-tabs': 0,
'vue/html-indent': ['error', 'tab'],
// only debug console
'no-console': ['error', { 'allow': ['error', 'warn', 'debug'] }],
// classes blocks
'padded-blocks': ['error', { 'classes': 'always' }],
// es6 import/export and require
'node/no-unpublished-require': ['off'],
'node/no-unsupported-features': ['off'],
// space before self-closing elements
'vue/html-closing-bracket-spacing': 'error',
// code spacing with attributes
'vue/max-attributes-per-line': [
'error',
{
singleline: 3,
multiline: {
max: 3,
allowFirstLine: true
}
}
]
}
};

71
.gitignore поставляемый
Просмотреть файл

@ -1,66 +1,15 @@
# Created by https://www.gitignore.io/api/node
### Node ###
# Logs
logs
*.log
.DS_Store
node_modules/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# Typescript v1 declaration files
typings/
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
# End of https://www.gitignore.io/api/node
.marginalia

1
.npmignore Normal file
Просмотреть файл

@ -0,0 +1 @@
node_modules

1
.prettierrc.js Normal file
Просмотреть файл

@ -0,0 +1 @@
module.exports = {};

22
.stylelintrc Normal file
Просмотреть файл

@ -0,0 +1,22 @@
{
"extends": "stylelint-config-recommended-scss",
"rules": {
"indentation": "tab",
"selector-type-no-unknown": null,
"number-leading-zero": null,
"rule-empty-line-before": ["always", {
"ignore": ["after-comment", "inside-block"]
}],
"declaration-empty-line-before": ["never", {
"ignore": ["after-declaration"]
}],
"comment-empty-line-before": null,
"selector-type-case": null,
"selector-list-comma-newline-after": null,
"no-descending-specificity": null,
"string-quotes": "single"
},
"plugins": [
"stylelint-scss"
]
}

46
Makefile Normal file
Просмотреть файл

@ -0,0 +1,46 @@
all: dev-setup lint build-js-production test
# Dev env management
dev-setup: clean clean-dev npm-init
npm-init:
npm install
npm-update:
npm update
# Building
build-js:
npm run dev
build-js-production:
npm run build
watch-js:
npm run watch
# Testing
test:
npm run test
test-watch:
npm run test:watch
test-coverage:
npm run test:coverage
# Linting
lint:
npm run lint
lint-fix:
npm run lint:fix
# Cleaning
clean:
rm -f dist/ncvuecomponents.js
rm -f dist/ncvuecomponents.js.map
clean-dev:
rm -rf node_modules

50
dist/ncvuecomponents.js поставляемый Normal file

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

1
dist/ncvuecomponents.js.map поставляемый Normal file

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -1,8 +0,0 @@
{
"lerna": "2.10.1",
"packages": [
"packages/*"
],
"version": "independent",
"useWorkspaces": true
}

13273
package-lock.json сгенерированный Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,15 +1,87 @@
{
"devDependencies": {
"lerna": "^2.10.1"
},
"name": "vue-components",
"version": "1.0.0",
"description": "Nextcloud vue components",
"keywords": ["vuejs", "nextcloud", "components"],
"keywords": [
"vuejs",
"nextcloud",
"components"
],
"repository": "https://github.com/nextcloud/vue-components",
"homepage": "https://github.com/nextcloud/vue-components",
"bugs": "https://github.com/nextcloud/vue-components/issues",
"author": "John Molakvoæ (skjnldsv) <skjnldsv@protonmail.com>",
"license": "AGPL-3.0",
"workspaces-experimental": true
"scripts": {
"dev": "webpack --config webpack.dev.js",
"watch": "webpack --progress --watch --config webpack.dev.js",
"build": "webpack --progress --hide-modules --config webpack.prod.js",
"lint": "eslint --ext .js,.vue src tests",
"lint:fix": "eslint --ext .js,.vue src tests --fix",
"test": "jest",
"test:coverage": "jest --coverage"
},
"dependencies": {
"babel-polyfill": "^6.26.0",
"v-tooltip": "^2.0.0-rc.33",
"vue": "^2.5.16",
"vue-click-outside": "^1.0.7"
},
"browserslist": [
"last 2 versions",
"not ie <= 11"
],
"engines": {
"node": ">=10.0.0"
},
"devDependencies": {
"@vue/test-utils": "^1.0.0-beta.20",
"babel-core": "^6.26.3",
"babel-eslint": "^8.2.5",
"babel-jest": "^23.4.0",
"babel-loader": "^7.1.4",
"babel-preset-env": "^1.7.0",
"css-loader": "^0.28.11",
"eslint": "^4.19.1",
"eslint-config-standard": "^11.0.0",
"eslint-friendly-formatter": "^4.0.1",
"eslint-loader": "^2.0.0",
"eslint-plugin-import": "^2.13.0",
"eslint-plugin-node": "^6.0.1",
"eslint-plugin-promise": "^3.8.0",
"eslint-plugin-standard": "^3.1.0",
"eslint-plugin-vue": "^4.5.0",
"jest": "^23.4.0",
"jest-serializer-vue": "^2.0.2",
"node-sass": "^4.9.0",
"prettier-eslint": "^8.8.2",
"raw-loader": "^0.5.1",
"sass-loader": "^7.0.3",
"stylelint": "^8.4.0",
"stylelint-config-recommended-scss": "^3.2.0",
"stylelint-scss": "^3.1.3",
"stylelint-webpack-plugin": "^0.10.5",
"vue-jest": "^2.6.0",
"vue-loader": "^15.2.4",
"vue-template-compiler": "^2.5.16",
"webpack": "^4.16.2",
"webpack-cli": "^3.0.4",
"webpack-merge": "^4.1.2"
},
"jest": {
"moduleFileExtensions": [
"js",
"vue"
],
"moduleNameMapper": {
"^@/(.*)$": "<rootDir>/src/$1"
},
"transform": {
"^.+\\.js$": "<rootDir>/node_modules/babel-jest",
".*\\.(vue)$": "<rootDir>/node_modules/vue-jest"
},
"snapshotSerializers": [
"<rootDir>/node_modules/jest-serializer-vue"
]
}
}

Просмотреть файл

@ -0,0 +1,96 @@
<!--
- @copyright Copyright (c) 2018 John Molakvoæ <skjnldsv@protonmail.com>
-
- @author John Molakvoæ <skjnldsv@protonmail.com>
-
- @license GNU AGPL version 3 or any later version
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as
- published by the Free Software Foundation, either version 3 of the
- License, or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-->
<template>
<div id="app-navigation" :class="{'icon-loading': menu.loading}">
<div v-if="menu.new" class="app-navigation-new">
<button :id="menu.new.id" :class="menu.new.icon" type="button"
@click="menu.new.action">{{ menu.new.text }}</button>
</div>
<ul :id="menu.id">
<app-navigation-item v-for="item in menu.items" :item="item" :key="item.key" />
</ul>
<div v-click-outside="closeMenu" v-if="!!$slots['settings-content']" id="app-settings"
:class="{open: opened}">
<div id="app-settings-header">
<button class="settings-button"
data-apps-slide-toggle="#app-settings-content"
@click="toggleMenu"
>{{ t('contacts', 'Settings') }}</button>
</div>
<div id="app-settings-content">
<slot name="settings-content" />
</div>
</div>
</div>
</template>
<script>
import AppNavigationItem from './AppNavigationItem'
import ClickOutside from 'vue-click-outside'
export default {
name: 'AppNavigation',
components: {
AppNavigationItem,
ClickOutside
},
directives: {
ClickOutside
},
props: {
menu: {
type: Object,
required: true,
default: () => {
return {
new: {
id: 'new-item',
action: () => alert('Success!'),
icon: 'icon-add',
text: 'New item'
},
menu: {
id: 'navigation',
items: [
]
}
}
}
}
},
data() {
return {
opened: false
}
},
methods: {
toggleMenu() {
this.opened = !this.opened
},
closeMenu() {
this.opened = false
}
}
}
</script>

Просмотреть файл

@ -0,0 +1,162 @@
<!--
- @copyright Copyright (c) 2018 John Molakvoæ <skjnldsv@protonmail.com>
-
- @author John Molakvoæ <skjnldsv@protonmail.com>
-
- @license GNU AGPL version 3 or any later version
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as
- published by the Free Software Foundation, either version 3 of the
- License, or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-->
<template>
<!-- Is this a caption ? -->
<li v-if="item.caption" class="app-navigation-caption">{{ item.text }}</li>
<!-- Navigation item -->
<nav-element v-else :id="item.id" v-bind="navElement(item)"
:class="[{'icon-loading-small': item.loading, 'open': item.opened, 'collapsible': item.collapsible&&item.children&&item.children.length>0 }, item.classes]">
<!-- Bullet -->
<div v-if="item.bullet" :style="{ backgroundColor: item.bullet }" class="app-navigation-entry-bullet" />
<!-- Main link -->
<a :href="(item.href) ? item.href : '#' " :class="item.icon" @click="toggleCollapse">
<img v-if="item.iconUrl" :alt="item.text" :src="item.iconUrl">
{{ item.text }}
</a>
<!-- Popover, counter and button(s) -->
<div v-if="item.utils" class="app-navigation-entry-utils">
<ul>
<!-- counter -->
<li v-if="Number.isInteger(item.utils.counter)"
class="app-navigation-entry-utils-counter">{{ item.utils.counter }}</li>
<!-- first action if only one action and counter -->
<li v-if="item.utils.actions && item.utils.actions.length === 1 && Number.isInteger(item.utils.counter)"
class="app-navigation-entry-utils-menu-button">
<button :class="item.utils.actions[0].icon" :title="item.utils.actions[0].text" @click="item.utils.actions[0].action" />
</li>
<!-- second action only two actions and no counter -->
<li v-for="action in item.utils.actions"
v-else-if="item.utils.actions && item.utils.actions.length === 2 && !Number.isInteger(item.utils.counter)" :key="action.action"
class="app-navigation-entry-utils-menu-button">
<button :class="action.icon" :title="action.text" @click="action.action" />
</li>
<!-- menu if only at least one action and counter OR two actions and no counter-->
<li v-else-if="item.utils.actions && item.utils.actions.length > 1 && (Number.isInteger(item.utils.counter) || item.utils.actions.length > 2)"
class="app-navigation-entry-utils-menu-button">
<button v-click-outside="hideMenu" @click="showMenu" />
</li>
</ul>
</div>
<!-- if more than 2 actions or more than 1 actions with counter -->
<div v-if="item.utils && item.utils.actions && item.utils.actions.length > 1 && (Number.isInteger(item.utils.counter) || item.utils.actions.length > 2)"
:class="{ 'open': openedMenu }" class="app-navigation-entry-menu">
<popover-menu :menu="item.utils.actions" />
</div>
<!-- undo entry -->
<div v-if="item.undo" class="app-navigation-entry-deleted">
<div class="app-navigation-entry-deleted-description">{{ item.undo.text }}</div>
<button :title="t('settings', 'Undo')" class="app-navigation-entry-deleted-button icon-history" />
</div>
<!-- edit entry -->
<div v-if="item.edit" class="app-navigation-entry-edit">
<form>
<input v-model="item.text" type="text">
<input type="submit" value="" class="icon-confirm">
<input type="submit" value="" class="icon-close"
@click.stop.prevent="cancelEdit">
</form>
</div>
<!-- if the item has children, inject the component with proper data -->
<ul v-if="item.children">
<navigation-item v-for="(item, key) in item.children" :item="item" :key="key" />
</ul>
</nav-element>
</template>
<script>
import PopoverMenu from 'components/PopoverMenu/PopoverMenu'
import ClickOutside from 'vue-click-outside'
import Vue from 'vue'
export default {
name: 'AppNavigationItem',
components: {
PopoverMenu
},
directives: {
ClickOutside
},
props: {
item: {
type: Object,
required: true
}
},
data() {
return {
openedMenu: false
}
},
mounted() {
// prevent click outside event with popupItem.
this.popupItem = this.$el
},
methods: {
showMenu() {
this.openedMenu = true
},
hideMenu() {
this.openedMenu = false
},
toggleCollapse() {
// if item.opened isn't set, Vue won't trigger view updates https://vuejs.org/v2/api/#Vue-set
// ternary is here to detect the undefined state of item.opened
Vue.set(this.item, 'opened', this.item.opened ? !this.item.opened : true)
},
cancelEdit() {
// remove the editing class
if (Array.isArray(this.item.classes)) {
this.item.classes = this.item.classes.filter(
item => item !== 'editing'
)
}
},
// This is used to decide which outter element type to use
// li or router-link
navElement(item) {
if (item.href) {
return {
is: 'li'
}
}
return {
is: 'router-link',
tag: 'li',
to: item.router,
exact: true
}
}
}
}
</script>

Просмотреть файл

@ -0,0 +1,26 @@
/**
* @copyright Copyright (c) 2018 John Molakvoæ <skjnldsv@protonmail.com>
*
* @author John Molakvoæ <skjnldsv@protonmail.com>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
import AppNavigation from './AppNavigation'
export default Vue => {
Vue.component(AppNavigation.name, AppNavigation)
}

Просмотреть файл

@ -0,0 +1,51 @@
<!--
- @copyright Copyright (c) 2018 John Molakvoæ <skjnldsv@protonmail.com>
-
- @author John Molakvoæ <skjnldsv@protonmail.com>
-
- @license GNU AGPL version 3 or any later version
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as
- published by the Free Software Foundation, either version 3 of the
- License, or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-->
<template>
<ul>
<popover-menu-item v-for="(item, key) in menu" :item="item" :key="key" />
</ul>
</template>
<script>
import popoverMenuItem from './PopoverMenuItem'
export default {
name: 'PopoverMenu',
components: {
popoverMenuItem
},
props: {
menu: {
type: Array,
default: () => {
return [{
href: 'https://nextcloud.com',
icon: 'icon-links',
text: 'Nextcloud'
}]
},
required: true
}
}
}
</script>

Просмотреть файл

@ -0,0 +1,71 @@
<!--
- @copyright Copyright (c) 2018 John Molakvoæ <skjnldsv@protonmail.com>
-
- @author John Molakvoæ <skjnldsv@protonmail.com>
-
- @license GNU AGPL version 3 or any later version
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as
- published by the Free Software Foundation, either version 3 of the
- License, or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-->
<template>
<li>
<!-- If item.href is set, a link will be directly used -->
<a v-if="item.href" :href="(item.href) ? item.href : '#' " :target="(item.target) ? item.target : '' "
rel="noreferrer noopener" @click="item.action">
<span :class="item.icon" />
<span v-if="item.text">{{ item.text }}</span>
<p v-else-if="item.longtext">{{ item.longtext }}</p>
</a>
<!-- If item.input is set instead, an put will be used -->
<span v-else-if="item.input" class="menuitem">
<input :id="item.key" :type="item.input" :class="item.input"
v-model="item.model">
<label :for="item.key">{{ item.text }}</label>
</span>
<!-- If item.action is set instead, a button will be used -->
<button v-else-if="item.action" @click="item.action">
<span :class="item.icon" />
<span v-if="item.text">{{ item.text }}</span>
<p v-else-if="item.longtext">{{ item.longtext }}</p>
</button>
<!-- If item.longtext is set AND the item does not have an action -->
<span v-else class="menuitem">
<span :class="item.icon" />
<span v-if="item.text">{{ item.text }}</span>
<p v-else-if="item.longtext">{{ item.longtext }}</p>
</span>
</li>
</template>
<script>
export default {
name: 'PopoverMenuItem',
props: {
item: {
type: Object,
default: () => {
return {
key: '1',
href: 'https://nextcloud.com',
icon: 'icon-links',
text: 'Nextcloud'
}
},
required: true
}
}
}
</script>

Просмотреть файл

@ -0,0 +1,26 @@
/**
* @copyright Copyright (c) 2018 John Molakvoæ <skjnldsv@protonmail.com>
*
* @author John Molakvoæ <skjnldsv@protonmail.com>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
import PopoverMenu from './PopoverMenu'
export default Vue => {
Vue.component(PopoverMenu.name, PopoverMenu)
}

29
src/components/index.js Normal file
Просмотреть файл

@ -0,0 +1,29 @@
/**
* @copyright Copyright (c) 2018 John Molakvoæ <skjnldsv@protonmail.com>
*
* @author John Molakvoæ <skjnldsv@protonmail.com>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
import AppNavigation from './AppNavigation'
import PopoverMenu from './PopoverMenu'
export {
AppNavigation,
PopoverMenu
}

33
src/index.js Normal file
Просмотреть файл

@ -0,0 +1,33 @@
/**
* @copyright Copyright (c) 2018 John Molakvoæ <skjnldsv@protonmail.com>
*
* @author John Molakvoæ <skjnldsv@protonmail.com>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
import * as NcComponents from './components'
let NcVueComponents = Vue => {
Object.values(NcComponents).forEach((NcComponent) => {
Vue.use(NcComponent)
})
}
NcVueComponents.version = '__VERSION__'
export default NcVueComponents

53
webpack.common.js Normal file
Просмотреть файл

@ -0,0 +1,53 @@
const path = require('path')
const { VueLoaderPlugin } = require('vue-loader')
const StyleLintPlugin = require('stylelint-webpack-plugin')
module.exports = {
entry: ['babel-polyfill', path.join(__dirname, 'src', 'index.js')],
output: {
path: path.resolve(__dirname, './dist'),
publicPath: '/dist/',
filename: 'ncvuecomponents.js'
},
module: {
rules: [
{
test: /\.css$/,
use: ['vue-style-loader', 'css-loader']
},
{
test: /\.scss$/,
use: ['vue-style-loader', 'css-loader', 'sass-loader']
},
{
test: /\.(js|vue)$/,
use: 'eslint-loader',
enforce: 'pre'
},
{
test: /\.vue$/,
loader: 'vue-loader'
},
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/
},
{
test: /\.(png|jpg|gif|svg)$/,
loader: 'file-loader',
options: {
name: '[name].[ext]?[hash]'
}
}
]
},
plugins: [new VueLoaderPlugin(), new StyleLintPlugin()],
resolve: {
alias: {
components: path.join(__dirname, 'src', 'components'),
vue$: 'vue/dist/vue.esm.js'
},
extensions: ['*', '.js', '.vue', '.json']
}
}

12
webpack.dev.js Normal file
Просмотреть файл

@ -0,0 +1,12 @@
const merge = require('webpack-merge');
const common = require('./webpack.common.js');
module.exports = merge(common, {
mode: 'development',
devServer: {
historyApiFallback: true,
noInfo: true,
overlay: true
},
devtool: '#eval-source-map',
})

7
webpack.prod.js Normal file
Просмотреть файл

@ -0,0 +1,7 @@
const merge = require('webpack-merge')
const common = require('./webpack.common.js')
module.exports = merge(common, {
mode: 'production',
devtool: '#source-map'
})