Commit 99246a895497d26e552bf5633ae6c07c07335726
Committed by
GitHub
Merge pull request #340 from huixisheng/2.0
Support Breadcrumb and add test unit and optimize webpack config
Showing
56 changed files
with
362 additions
and
143 deletions
Show diff stats
.gitignore
README.md
| @@ -53,7 +53,7 @@ | @@ -53,7 +53,7 @@ | ||
| 53 | - [x] Tabs | 53 | - [x] Tabs |
| 54 | - [x] Dropdown | 54 | - [x] Dropdown |
| 55 | - [ ] Page | 55 | - [ ] Page |
| 56 | -- [ ] Breadcrumb | 56 | +- [x] Breadcrumb |
| 57 | - [x] Steps | 57 | - [x] Steps |
| 58 | - [ ] LoadingBar | 58 | - [ ] LoadingBar |
| 59 | - [x] Circle | 59 | - [x] Circle |
| @@ -76,7 +76,7 @@ | @@ -76,7 +76,7 @@ | ||
| 76 | 76 | ||
| 77 | ## Install | 77 | ## Install |
| 78 | 78 | ||
| 79 | -### Install vue-webpack project in the first place | 79 | +### Install vue-webpack project in the first place |
| 80 | 80 | ||
| 81 | Use [iview-project](https://github.com/iview/iview-project)(Recommended) Or [vue-cli](https://github.com/vuejs/vue-cli) | 81 | Use [iview-project](https://github.com/iview/iview-project)(Recommended) Or [vue-cli](https://github.com/vuejs/vue-cli) |
| 82 | 82 |
| 1 | +/** | ||
| 2 | + * 公共配置 | ||
| 3 | + */ | ||
| 4 | +var webpack = require('webpack'); | ||
| 5 | +var path = require('path'); | ||
| 6 | +function resolve (dir) { | ||
| 7 | + return path.join(__dirname, '..', dir) | ||
| 8 | +} | ||
| 9 | + | ||
| 10 | +module.exports = { | ||
| 11 | + // 加载器 | ||
| 12 | + module: { | ||
| 13 | + // https://doc.webpack-china.org/guides/migrating/#module-loaders-module-rules | ||
| 14 | + rules: [ | ||
| 15 | + { | ||
| 16 | + // https://vue-loader.vuejs.org/en/configurations/extract-css.html | ||
| 17 | + test: /\.vue$/, | ||
| 18 | + loader: 'vue-loader', | ||
| 19 | + options: { | ||
| 20 | + loaders: { | ||
| 21 | + css: 'vue-style-loader!css-loader', | ||
| 22 | + less: 'vue-style-loader!css-loader!less-loader' | ||
| 23 | + }, | ||
| 24 | + postLoaders: { | ||
| 25 | + html: 'babel-loader' | ||
| 26 | + } | ||
| 27 | + } | ||
| 28 | + }, | ||
| 29 | + { | ||
| 30 | + test: /\.js$/, | ||
| 31 | + loader: 'babel-loader', exclude: /node_modules/ | ||
| 32 | + }, | ||
| 33 | + { | ||
| 34 | + test: /\.css$/, | ||
| 35 | + use: [ | ||
| 36 | + 'style-loader', | ||
| 37 | + 'css-loader', | ||
| 38 | + 'autoprefixer-loader' | ||
| 39 | + ] | ||
| 40 | + }, | ||
| 41 | + { | ||
| 42 | + test: /\.less$/, | ||
| 43 | + use: [ | ||
| 44 | + 'style-loader', | ||
| 45 | + 'css-loader', | ||
| 46 | + 'less-loader' | ||
| 47 | + ] | ||
| 48 | + }, | ||
| 49 | + { | ||
| 50 | + test: /\.scss$/, | ||
| 51 | + use: [ | ||
| 52 | + 'style-loader', | ||
| 53 | + 'css-loader', | ||
| 54 | + 'sass-loader?sourceMap' | ||
| 55 | + ] | ||
| 56 | + }, | ||
| 57 | + { test: /\.(gif|jpg|png|woff|svg|eot|ttf)\??.*$/, loader: 'url-loader?limit=8192'}, | ||
| 58 | + { test: /\.(html|tpl)$/, loader: 'html-loader' } | ||
| 59 | + ] | ||
| 60 | + }, | ||
| 61 | + resolve: { | ||
| 62 | + extensions: ['.js', '.vue'], | ||
| 63 | + alias: { | ||
| 64 | + 'vue': 'vue/dist/vue.esm.js', | ||
| 65 | + '@': resolve('src'), | ||
| 66 | + } | ||
| 67 | + } | ||
| 68 | +}; |
build/webpack.dev.config.js
| @@ -6,109 +6,37 @@ var path = require('path'); | @@ -6,109 +6,37 @@ var path = require('path'); | ||
| 6 | var webpack = require('webpack'); | 6 | var webpack = require('webpack'); |
| 7 | // var ExtractTextPlugin = require('extract-text-webpack-plugin'); | 7 | // var ExtractTextPlugin = require('extract-text-webpack-plugin'); |
| 8 | var HtmlWebpackPlugin = require('html-webpack-plugin'); | 8 | var HtmlWebpackPlugin = require('html-webpack-plugin'); |
| 9 | +var merge = require('webpack-merge') | ||
| 10 | +var webpackBaseConfig = require('./webpack.base.config.js'); | ||
| 11 | +var FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin') | ||
| 9 | 12 | ||
| 10 | -module.exports = { | 13 | + |
| 14 | +module.exports = merge(webpackBaseConfig, { | ||
| 11 | // 入口 | 15 | // 入口 |
| 12 | entry: { | 16 | entry: { |
| 13 | - main: './test/main', | 17 | + main: './examples/main', |
| 14 | vendors: ['vue', 'vue-router'] | 18 | vendors: ['vue', 'vue-router'] |
| 15 | }, | 19 | }, |
| 16 | // 输出 | 20 | // 输出 |
| 17 | output: { | 21 | output: { |
| 18 | - path: path.join(__dirname, '../test/dist'), | 22 | + path: path.join(__dirname, '../examples/dist'), |
| 19 | publicPath: '', | 23 | publicPath: '', |
| 20 | filename: '[name].js', | 24 | filename: '[name].js', |
| 21 | chunkFilename: '[name].chunk.js' | 25 | chunkFilename: '[name].chunk.js' |
| 22 | }, | 26 | }, |
| 23 | - // 加载器 | ||
| 24 | - module: { | ||
| 25 | - // https://doc.webpack-china.org/guides/migrating/#module-loaders-module-rules | ||
| 26 | - rules: [ | ||
| 27 | - { | ||
| 28 | - // https://vue-loader.vuejs.org/en/configurations/extract-css.html | ||
| 29 | - test: /\.vue$/, | ||
| 30 | - loader: 'vue-loader', | ||
| 31 | - options: { | ||
| 32 | - loaders: { | ||
| 33 | - css: 'vue-style-loader!css-loader', | ||
| 34 | - less: 'vue-style-loader!css-loader!less-loader' | ||
| 35 | - }, | ||
| 36 | - postLoaders: { | ||
| 37 | - html: 'babel-loader' | ||
| 38 | - } | ||
| 39 | - } | ||
| 40 | - }, | ||
| 41 | - // { test: /\.vue$/, loader: 'vue' }, | ||
| 42 | - // Module build failed: Error: The node API for `babel` has been moved to `babel-core`. | ||
| 43 | - // https://github.com/babel/babel-loader/blob/master/README.md#the-node-api-for-babel-has-been-moved-to-babel-core | ||
| 44 | - { | ||
| 45 | - test: /\.js$/, | ||
| 46 | - loader: 'babel-loader', exclude: /node_modules/ | ||
| 47 | - }, | ||
| 48 | - { | ||
| 49 | - test: /\.css$/, | ||
| 50 | - use: [ | ||
| 51 | - 'style-loader', | ||
| 52 | - 'css-loader', | ||
| 53 | - 'autoprefixer-loader' | ||
| 54 | - ] | ||
| 55 | - }, | ||
| 56 | - { | ||
| 57 | - test: /\.less$/, | ||
| 58 | - use: [ | ||
| 59 | - 'style-loader', | ||
| 60 | - 'css-loader', | ||
| 61 | - 'less-loader' | ||
| 62 | - ] | ||
| 63 | - // loader: 'style!css!less' | ||
| 64 | - }, | ||
| 65 | - { | ||
| 66 | - test: /\.scss$/, | ||
| 67 | - use: [ | ||
| 68 | - 'style-loader', | ||
| 69 | - 'css-loader', | ||
| 70 | - 'sass-loader?sourceMap' | ||
| 71 | - ] | ||
| 72 | - // loader: 'style!css!sass?sourceMap' | ||
| 73 | - }, | ||
| 74 | - { test: /\.(gif|jpg|png|woff|svg|eot|ttf)\??.*$/, loader: 'url-loader?limit=8192'}, | ||
| 75 | - { test: /\.(html|tpl)$/, loader: 'html-loader' } | ||
| 76 | - ] | ||
| 77 | - }, | ||
| 78 | - // vue: { | ||
| 79 | - // loaders: { | ||
| 80 | - // css: ExtractTextPlugin.extract( | ||
| 81 | - // "style-loader", | ||
| 82 | - // "css-loader?sourceMap", | ||
| 83 | - // { | ||
| 84 | - // publicPath: "/test/dist/" | ||
| 85 | - // } | ||
| 86 | - // ), | ||
| 87 | - // less: ExtractTextPlugin.extract( | ||
| 88 | - // 'vue-style-loader', | ||
| 89 | - // 'css-loader!less-loader' | ||
| 90 | - // ), | ||
| 91 | - // js: 'babel' | ||
| 92 | - // } | ||
| 93 | - // }, | ||
| 94 | resolve: { | 27 | resolve: { |
| 95 | - // require时省略的扩展名,如:require('module') 不需要module.js | ||
| 96 | - extensions: ['.js', '.vue'], | ||
| 97 | alias: { | 28 | alias: { |
| 98 | iview: '../../src/index', | 29 | iview: '../../src/index', |
| 99 | vue: 'vue/dist/vue.js' | 30 | vue: 'vue/dist/vue.js' |
| 100 | } | 31 | } |
| 101 | }, | 32 | }, |
| 102 | plugins: [ | 33 | plugins: [ |
| 103 | - // new ExtractTextPlugin({ filename: '[name].css', disable: false, allChunks: true }), | ||
| 104 | - // new ExtractTextPlugin("[name].css",{ allChunks : true,resolve : ['modules'] }), // 提取CSS | ||
| 105 | - // https://doc.webpack-china.org/plugins/commons-chunk-plugin/ | ||
| 106 | new webpack.optimize.CommonsChunkPlugin({ name: 'vendors', filename: 'vendor.bundle.js' }), | 34 | new webpack.optimize.CommonsChunkPlugin({ name: 'vendors', filename: 'vendor.bundle.js' }), |
| 107 | new HtmlWebpackPlugin({ | 35 | new HtmlWebpackPlugin({ |
| 108 | inject: true, | 36 | inject: true, |
| 109 | - filename: path.join(__dirname, '../test/dist/index.html'), | ||
| 110 | - template: path.join(__dirname, '../test/index.html') // 模版文件 | ||
| 111 | - }) | ||
| 112 | - // new webpack.optimize.CommonsChunkPlugin('vendors', 'vendors.js'), // 提取第三方库 | 37 | + filename: path.join(__dirname, '../examples/dist/index.html'), |
| 38 | + template: path.join(__dirname, '../examples/index.html') | ||
| 39 | + }), | ||
| 40 | + new FriendlyErrorsPlugin() | ||
| 113 | ] | 41 | ] |
| 114 | -}; | 42 | +}); |
build/webpack.dist.dev.config.js
| 1 | var path = require('path'); | 1 | var path = require('path'); |
| 2 | var webpack = require('webpack'); | 2 | var webpack = require('webpack'); |
| 3 | +var merge = require('webpack-merge') | ||
| 4 | +var webpackBaseConfig = require('./webpack.base.config.js'); | ||
| 3 | 5 | ||
| 4 | -module.exports = { | 6 | +module.exports = merge(webpackBaseConfig, { |
| 5 | entry: { | 7 | entry: { |
| 6 | main: './src/index.js' | 8 | main: './src/index.js' |
| 7 | }, | 9 | }, |
| @@ -21,26 +23,6 @@ module.exports = { | @@ -21,26 +23,6 @@ module.exports = { | ||
| 21 | amd: 'vue' | 23 | amd: 'vue' |
| 22 | } | 24 | } |
| 23 | }, | 25 | }, |
| 24 | - resolve: { | ||
| 25 | - extensions: ['.js', '.vue'] | ||
| 26 | - }, | ||
| 27 | - module: { | ||
| 28 | - rules: [ | ||
| 29 | - { | ||
| 30 | - test: /\.vue$/, | ||
| 31 | - loader: 'vue-loader', | ||
| 32 | - options: { | ||
| 33 | - postLoaders: { | ||
| 34 | - html: 'babel-loader' | ||
| 35 | - } | ||
| 36 | - } | ||
| 37 | - }, | ||
| 38 | - { | ||
| 39 | - test: /\.js$/, | ||
| 40 | - loader: 'babel-loader', exclude: /node_modules/ | ||
| 41 | - } | ||
| 42 | - ] | ||
| 43 | - }, | ||
| 44 | plugins: [ | 26 | plugins: [ |
| 45 | new webpack.DefinePlugin({ | 27 | new webpack.DefinePlugin({ |
| 46 | 'process.env': { | 28 | 'process.env': { |
| @@ -48,4 +30,4 @@ module.exports = { | @@ -48,4 +30,4 @@ module.exports = { | ||
| 48 | } | 30 | } |
| 49 | }) | 31 | }) |
| 50 | ] | 32 | ] |
| 51 | -} | 33 | +}); |
build/webpack.dist.prod.config.js
| 1 | var path = require('path'); | 1 | var path = require('path'); |
| 2 | var webpack = require('webpack'); | 2 | var webpack = require('webpack'); |
| 3 | +var merge = require('webpack-merge') | ||
| 4 | +var webpackBaseConfig = require('./webpack.base.config.js'); | ||
| 3 | 5 | ||
| 4 | -module.exports = { | 6 | + |
| 7 | + | ||
| 8 | +module.exports = merge(webpackBaseConfig, { | ||
| 5 | entry: { | 9 | entry: { |
| 6 | main: './src/index.js' | 10 | main: './src/index.js' |
| 7 | }, | 11 | }, |
| @@ -21,26 +25,6 @@ module.exports = { | @@ -21,26 +25,6 @@ module.exports = { | ||
| 21 | amd: 'vue' | 25 | amd: 'vue' |
| 22 | } | 26 | } |
| 23 | }, | 27 | }, |
| 24 | - resolve: { | ||
| 25 | - extensions: ['.js', '.vue'] | ||
| 26 | - }, | ||
| 27 | - module: { | ||
| 28 | - rules: [ | ||
| 29 | - { | ||
| 30 | - test: /\.vue$/, | ||
| 31 | - loader: 'vue-loader', | ||
| 32 | - options: { | ||
| 33 | - postLoaders: { | ||
| 34 | - html: 'babel-loader' | ||
| 35 | - } | ||
| 36 | - } | ||
| 37 | - }, | ||
| 38 | - { | ||
| 39 | - test: /\.js$/, | ||
| 40 | - loader: 'babel-loader', exclude: /node_modules/ | ||
| 41 | - } | ||
| 42 | - ] | ||
| 43 | - }, | ||
| 44 | plugins: [ | 28 | plugins: [ |
| 45 | new webpack.DefinePlugin({ | 29 | new webpack.DefinePlugin({ |
| 46 | 'process.env': { | 30 | 'process.env': { |
| @@ -53,4 +37,4 @@ module.exports = { | @@ -53,4 +37,4 @@ module.exports = { | ||
| 53 | } | 37 | } |
| 54 | }) | 38 | }) |
| 55 | ] | 39 | ] |
| 56 | -} | 40 | +}); |
| 1 | +/** | ||
| 2 | + * 用于单元测试 | ||
| 3 | + */ | ||
| 4 | + | ||
| 5 | +var webpack = require('webpack') | ||
| 6 | +var merge = require('webpack-merge') | ||
| 7 | +var webpackBaseConfig = require('./webpack.base.config.js'); | ||
| 8 | + | ||
| 9 | + | ||
| 10 | +var webpackConfig = merge(webpackBaseConfig, { | ||
| 11 | + // use inline sourcemap for karma-sourcemap-loader | ||
| 12 | + devtool: '#inline-source-map', | ||
| 13 | + plugins: [ | ||
| 14 | + new webpack.DefinePlugin({ | ||
| 15 | + 'process.env': { | ||
| 16 | + NODE_ENV: '"testing"' | ||
| 17 | + } | ||
| 18 | + }) | ||
| 19 | + ] | ||
| 20 | +}) | ||
| 21 | + | ||
| 22 | +// no need for app entry during tests | ||
| 23 | +delete webpackConfig.entry | ||
| 24 | + | ||
| 25 | +module.exports = webpackConfig |
test/app.vue renamed to examples/app.vue
| @@ -39,6 +39,7 @@ li + li { border-left: solid 1px #bbb; padding-left: 10px; margin-left: 10px; } | @@ -39,6 +39,7 @@ li + li { border-left: solid 1px #bbb; padding-left: 10px; margin-left: 10px; } | ||
| 39 | <li><router-link to="/poptip">Poptip</router-link></li> | 39 | <li><router-link to="/poptip">Poptip</router-link></li> |
| 40 | <li><router-link to="/slider">Slider</router-link></li> | 40 | <li><router-link to="/slider">Slider</router-link></li> |
| 41 | <li><router-link to="/dropdown">Dropdown</router-link></li> | 41 | <li><router-link to="/dropdown">Dropdown</router-link></li> |
| 42 | + <li><router-link to="/breadcrumb">Breadcrumb</router-link></li> | ||
| 42 | </ul> | 43 | </ul> |
| 43 | </nav> | 44 | </nav> |
| 44 | <router-view></router-view> | 45 | <router-view></router-view> |
test/index.html renamed to examples/index.html
test/main.js renamed to examples/main.js
| @@ -120,6 +120,10 @@ const router = new VueRouter({ | @@ -120,6 +120,10 @@ const router = new VueRouter({ | ||
| 120 | { | 120 | { |
| 121 | path: '/dropdown', | 121 | path: '/dropdown', |
| 122 | component: require('./routers/dropdown.vue') | 122 | component: require('./routers/dropdown.vue') |
| 123 | + }, | ||
| 124 | + { | ||
| 125 | + path: '/breadcrumb', | ||
| 126 | + component: require('./routers/breadcrumb.vue') | ||
| 123 | } | 127 | } |
| 124 | ] | 128 | ] |
| 125 | }); | 129 | }); |
test/routers/affix.vue renamed to examples/routers/affix.vue
test/routers/alert.vue renamed to examples/routers/alert.vue
test/routers/badge.vue renamed to examples/routers/badge.vue
| 1 | +<style> | ||
| 2 | + .demo-breadcrumb-separator{ | ||
| 3 | + color: #ff5500; | ||
| 4 | + padding: 0 5px; | ||
| 5 | + } | ||
| 6 | +</style> | ||
| 7 | +<template> | ||
| 8 | +<div> | ||
| 9 | + <Breadcrumb separator="<b class='demo-breadcrumb-separator'>=></b>"> | ||
| 10 | + <Breadcrumb-item href="/">Home4</Breadcrumb-item> | ||
| 11 | + <Breadcrumb-item href="/components/breadcrumb">Components</Breadcrumb-item> | ||
| 12 | + <Breadcrumb-item>Breadcrumb</Breadcrumb-item> | ||
| 13 | + </Breadcrumb> | ||
| 14 | + <Breadcrumb separator=""> | ||
| 15 | + <Breadcrumb-item href="/"> | ||
| 16 | + <template>Home</template> | ||
| 17 | + <template slot="separator"> | ||
| 18 | + <b style="color: #ff5500;">-></b> | ||
| 19 | + </template> | ||
| 20 | + </Breadcrumb-item> | ||
| 21 | + <Breadcrumb-item href="/components/breadcrumb"> | ||
| 22 | + <template>Breadcrumb</template> | ||
| 23 | + <template slot="separator"> | ||
| 24 | + <b style="color: #ff5500;">-></b> | ||
| 25 | + </template> | ||
| 26 | + </Breadcrumb-item> | ||
| 27 | + <Breadcrumb-item>Breadcrumb</Breadcrumb-item> | ||
| 28 | + </Breadcrumb> | ||
| 29 | +</div> | ||
| 30 | +</template> | ||
| 31 | +<script> | ||
| 32 | + export default { | ||
| 33 | + | ||
| 34 | + } | ||
| 35 | +</script> | ||
| 0 | \ No newline at end of file | 36 | \ No newline at end of file |
test/routers/button.vue renamed to examples/routers/button.vue
test/routers/card.vue renamed to examples/routers/card.vue
test/routers/carousel.vue renamed to examples/routers/carousel.vue
test/routers/cascader.vue renamed to examples/routers/cascader.vue
test/routers/checkbox.vue renamed to examples/routers/checkbox.vue
test/routers/circle.vue renamed to examples/routers/circle.vue
test/routers/collapse.vue renamed to examples/routers/collapse.vue
test/routers/date.vue renamed to examples/routers/date.vue
test/routers/dropdown.vue renamed to examples/routers/dropdown.vue
test/routers/form.vue renamed to examples/routers/form.vue
test/routers/grid.vue renamed to examples/routers/grid.vue
test/routers/input-number.vue renamed to examples/routers/input-number.vue
test/routers/input.vue renamed to examples/routers/input.vue
test/routers/menu.vue renamed to examples/routers/menu.vue
test/routers/message.vue renamed to examples/routers/message.vue
test/routers/more.vue renamed to examples/routers/more.vue
test/routers/notice.vue renamed to examples/routers/notice.vue
test/routers/page.vue renamed to examples/routers/page.vue
test/routers/poptip.vue renamed to examples/routers/poptip.vue
test/routers/progress.vue renamed to examples/routers/progress.vue
test/routers/radio.vue renamed to examples/routers/radio.vue
test/routers/rate.vue renamed to examples/routers/rate.vue
test/routers/select.vue renamed to examples/routers/select.vue
test/routers/slider.vue renamed to examples/routers/slider.vue
test/routers/steps.vue renamed to examples/routers/steps.vue
test/routers/switch.vue renamed to examples/routers/switch.vue
test/routers/table.vue renamed to examples/routers/table.vue
test/routers/tabs.vue renamed to examples/routers/tabs.vue
test/routers/tag.vue renamed to examples/routers/tag.vue
test/routers/timeline.vue renamed to examples/routers/timeline.vue
test/routers/tooltip.vue renamed to examples/routers/tooltip.vue
test/routers/transfer.vue renamed to examples/routers/transfer.vue
test/routers/tree.vue renamed to examples/routers/tree.vue
test/routers/upload.vue renamed to examples/routers/upload.vue
package.json
| @@ -25,7 +25,8 @@ | @@ -25,7 +25,8 @@ | ||
| 25 | "dist:prod": "webpack --config build/webpack.dist.prod.config.js", | 25 | "dist:prod": "webpack --config build/webpack.dist.prod.config.js", |
| 26 | "dist": "npm run dist:style && npm run dist:dev && npm run dist:prod", | 26 | "dist": "npm run dist:style && npm run dist:dev && npm run dist:prod", |
| 27 | "lint": "eslint --fix --ext .js,.vue src", | 27 | "lint": "eslint --fix --ext .js,.vue src", |
| 28 | - "test": "npm run dist && npm run lint", | 28 | + "unit": "cross-env BABEL_ENV=test karma start test/unit/karma.conf.js --single-run", |
| 29 | + "test": "npm run lint && npm run unit", | ||
| 29 | "prepublish": "npm run dist" | 30 | "prepublish": "npm run dist" |
| 30 | }, | 31 | }, |
| 31 | "repository": { | 32 | "repository": { |
| @@ -54,11 +55,15 @@ | @@ -54,11 +55,15 @@ | ||
| 54 | "babel-plugin-transform-runtime": "^6.12.0", | 55 | "babel-plugin-transform-runtime": "^6.12.0", |
| 55 | "babel-preset-es2015": "^6.9.0", | 56 | "babel-preset-es2015": "^6.9.0", |
| 56 | "babel-runtime": "^6.11.6", | 57 | "babel-runtime": "^6.11.6", |
| 58 | + "chai": "^3.5.0", | ||
| 59 | + "cross-env": "^3.1.4", | ||
| 57 | "css-loader": "^0.23.1", | 60 | "css-loader": "^0.23.1", |
| 58 | "eslint": "^3.12.2", | 61 | "eslint": "^3.12.2", |
| 59 | "eslint-plugin-html": "^1.7.0", | 62 | "eslint-plugin-html": "^1.7.0", |
| 60 | "extract-text-webpack-plugin": "^2.0.0", | 63 | "extract-text-webpack-plugin": "^2.0.0", |
| 61 | "file-loader": "^0.8.5", | 64 | "file-loader": "^0.8.5", |
| 65 | + "friendly-errors-webpack-plugin": "^1.6.1", | ||
| 66 | + "function-bind": "^1.1.0", | ||
| 62 | "gulp": "^3.9.1", | 67 | "gulp": "^3.9.1", |
| 63 | "gulp-autoprefixer": "^3.1.1", | 68 | "gulp-autoprefixer": "^3.1.1", |
| 64 | "gulp-clean-css": "^2.0.13", | 69 | "gulp-clean-css": "^2.0.13", |
| @@ -66,8 +71,21 @@ | @@ -66,8 +71,21 @@ | ||
| 66 | "gulp-rename": "^1.2.2", | 71 | "gulp-rename": "^1.2.2", |
| 67 | "html-loader": "^0.3.0", | 72 | "html-loader": "^0.3.0", |
| 68 | "html-webpack-plugin": "^2.28.0", | 73 | "html-webpack-plugin": "^2.28.0", |
| 74 | + "karma": "^1.4.1", | ||
| 75 | + "karma-coverage": "^1.1.1", | ||
| 76 | + "karma-mocha": "^1.3.0", | ||
| 77 | + "karma-phantomjs-launcher": "^1.0.2", | ||
| 78 | + "karma-sinon-chai": "^1.2.4", | ||
| 79 | + "karma-sourcemap-loader": "^0.3.7", | ||
| 80 | + "karma-spec-reporter": "0.0.26", | ||
| 81 | + "karma-webpack": "^2.0.2", | ||
| 69 | "less": "^2.7.1", | 82 | "less": "^2.7.1", |
| 70 | "less-loader": "^2.2.3", | 83 | "less-loader": "^2.2.3", |
| 84 | + "lolex": "^1.5.2", | ||
| 85 | + "mocha": "^3.2.0", | ||
| 86 | + "phantomjs-prebuilt": "^2.1.13", | ||
| 87 | + "sinon": "^1.17.7", | ||
| 88 | + "sinon-chai": "^2.8.0", | ||
| 71 | "style-loader": "^0.13.1", | 89 | "style-loader": "^0.13.1", |
| 72 | "url-loader": "^0.5.7", | 90 | "url-loader": "^0.5.7", |
| 73 | "vue": "^2.2.1", | 91 | "vue": "^2.2.1", |
| @@ -78,6 +96,11 @@ | @@ -78,6 +96,11 @@ | ||
| 78 | "vue-style-loader": "^1.0.0", | 96 | "vue-style-loader": "^1.0.0", |
| 79 | "vue-template-compiler": "^2.2.1", | 97 | "vue-template-compiler": "^2.2.1", |
| 80 | "webpack": "^2.2.1", | 98 | "webpack": "^2.2.1", |
| 81 | - "webpack-dev-server": "^2.4.1" | 99 | + "webpack-dev-server": "^2.4.1", |
| 100 | + "webpack-merge": "^3.0.0" | ||
| 101 | + }, | ||
| 102 | + "engines": { | ||
| 103 | + "node": ">= 4.0.0", | ||
| 104 | + "npm": ">= 3.0.0" | ||
| 82 | } | 105 | } |
| 83 | } | 106 | } |
src/components/breadcrumb/breadcrumb-item.vue
| @@ -6,8 +6,10 @@ | @@ -6,8 +6,10 @@ | ||
| 6 | <span v-else :class="linkClasses"> | 6 | <span v-else :class="linkClasses"> |
| 7 | <slot></slot> | 7 | <slot></slot> |
| 8 | </span> | 8 | </span> |
| 9 | - <span :class="separatorClasses"> | ||
| 10 | - <slot name="separator">{{{ separator }}}</slot> | 9 | + <span :class="separatorClasses" v-html="separator" v-if="!showSeparator"> |
| 10 | + </span> | ||
| 11 | + <span :class="separatorClasses" v-else> | ||
| 12 | + <slot name="separator"></slot> | ||
| 11 | </span> | 13 | </span> |
| 12 | </span> | 14 | </span> |
| 13 | </template> | 15 | </template> |
| @@ -18,12 +20,17 @@ | @@ -18,12 +20,17 @@ | ||
| 18 | props: { | 20 | props: { |
| 19 | href: { | 21 | href: { |
| 20 | type: String | 22 | type: String |
| 21 | - }, | ||
| 22 | - separator: { | ||
| 23 | - type: String, | ||
| 24 | - default: '/' | ||
| 25 | } | 23 | } |
| 26 | }, | 24 | }, |
| 25 | + data () { | ||
| 26 | + return { | ||
| 27 | + separator: '', | ||
| 28 | + showSeparator: false | ||
| 29 | + }; | ||
| 30 | + }, | ||
| 31 | + mounted () { | ||
| 32 | + this.showSeparator = this.$slots.separator !== undefined; | ||
| 33 | + }, | ||
| 27 | computed: { | 34 | computed: { |
| 28 | linkClasses () { | 35 | linkClasses () { |
| 29 | return `${prefixCls}-link`; | 36 | return `${prefixCls}-link`; |
src/components/breadcrumb/breadcrumb.vue
src/index.js
| @@ -5,7 +5,7 @@ import Affix from './components/affix'; | @@ -5,7 +5,7 @@ import Affix from './components/affix'; | ||
| 5 | import Alert from './components/alert'; | 5 | import Alert from './components/alert'; |
| 6 | // import BackTop from './components/back-top'; | 6 | // import BackTop from './components/back-top'; |
| 7 | import Badge from './components/badge'; | 7 | import Badge from './components/badge'; |
| 8 | -// import Breadcrumb from './components/breadcrumb'; | 8 | +import Breadcrumb from './components/breadcrumb'; |
| 9 | import Button from './components/button'; | 9 | import Button from './components/button'; |
| 10 | import Card from './components/card'; | 10 | import Card from './components/card'; |
| 11 | import Carousel from './components/carousel'; | 11 | import Carousel from './components/carousel'; |
| @@ -51,8 +51,8 @@ const iview = { | @@ -51,8 +51,8 @@ const iview = { | ||
| 51 | Alert, | 51 | Alert, |
| 52 | // BackTop, | 52 | // BackTop, |
| 53 | Badge, | 53 | Badge, |
| 54 | - // Breadcrumb, | ||
| 55 | - // BreadcrumbItem: Breadcrumb.Item, | 54 | + Breadcrumb, |
| 55 | + BreadcrumbItem: Breadcrumb.Item, | ||
| 56 | // iButton: Button, | 56 | // iButton: Button, |
| 57 | Button, | 57 | Button, |
| 58 | ButtonGroup: Button.Group, | 58 | ButtonGroup: Button.Group, |
| 1 | +import Vue from 'vue'; | ||
| 2 | +Vue.config.productionTip = false; | ||
| 3 | + | ||
| 4 | +// Polyfill fn.bind() for PhantomJS | ||
| 5 | +/* eslint-disable no-extend-native */ | ||
| 6 | +Function.prototype.bind = require('function-bind'); | ||
| 7 | + | ||
| 8 | +// require all test files (files that ends with .spec.js) | ||
| 9 | +const testsContext = require.context('./specs', true, /\.spec$/); | ||
| 10 | +testsContext.keys().forEach(testsContext); | ||
| 11 | + | ||
| 12 | +// require all src files except main.js for coverage. | ||
| 13 | +// you can also change this to match only the subset of files that | ||
| 14 | +// you want coverage for. | ||
| 15 | +// const srcContext = require.context('../../src', true, /^\.\/(?!main(\.js)?$)/); | ||
| 16 | +// @todo | ||
| 17 | +const srcContext = require.context('../../src/components/breadcrumb', true, /^\.\/(?!styles.*?(\.less)?$)/); | ||
| 18 | +srcContext.keys().forEach(srcContext); |
| 1 | +// This is a karma config file. For more details see | ||
| 2 | +// http://karma-runner.github.io/0.13/config/configuration-file.html | ||
| 3 | +// we are also using it with karma-webpack | ||
| 4 | +// https://github.com/webpack/karma-webpack | ||
| 5 | + | ||
| 6 | +var webpackConfig = require('../../build/webpack.test.config.js'); | ||
| 7 | + | ||
| 8 | +module.exports = function (config) { | ||
| 9 | + config.set({ | ||
| 10 | + // to run in additional browsers: | ||
| 11 | + // 1. install corresponding karma launcher | ||
| 12 | + // http://karma-runner.github.io/0.13/config/browsers.html | ||
| 13 | + // 2. add it to the `browsers` array below. | ||
| 14 | + browsers: ['PhantomJS'], | ||
| 15 | + frameworks: ['mocha', 'sinon-chai'], | ||
| 16 | + reporters: ['spec', 'coverage'], | ||
| 17 | + files: ['./index.js'], | ||
| 18 | + preprocessors: { | ||
| 19 | + './index.js': ['webpack', 'sourcemap'] | ||
| 20 | + }, | ||
| 21 | + webpack: webpackConfig, | ||
| 22 | + webpackMiddleware: { | ||
| 23 | + noInfo: true, | ||
| 24 | + }, | ||
| 25 | + coverageReporter: { | ||
| 26 | + dir: './coverage', | ||
| 27 | + reporters: [ | ||
| 28 | + { type: 'lcov', subdir: '.' }, | ||
| 29 | + { type: 'text-summary' }, | ||
| 30 | + ] | ||
| 31 | + }, | ||
| 32 | + }); | ||
| 33 | +}; |
| 1 | +import { createVue, destroyVM } from '../util'; | ||
| 2 | + | ||
| 3 | +describe('Breadcrumb.vue', () => { | ||
| 4 | + let vm; | ||
| 5 | + afterEach(() => { | ||
| 6 | + destroyVM(vm); | ||
| 7 | + }); | ||
| 8 | + it('create', done => { | ||
| 9 | + vm = createVue(` | ||
| 10 | + <Breadcrumb separator="<b class='demo-breadcrumb-separator'>=></b>"> | ||
| 11 | + <Breadcrumb-item href="/">Home4</Breadcrumb-item> | ||
| 12 | + <Breadcrumb-item href="/components/breadcrumb">Components</Breadcrumb-item> | ||
| 13 | + <Breadcrumb-item>Breadcrumb</Breadcrumb-item> | ||
| 14 | + </Breadcrumb> | ||
| 15 | + `); | ||
| 16 | + expect(vm.$el.querySelectorAll('.ivu-breadcrumb-item-link').length).to.equal(3); | ||
| 17 | + | ||
| 18 | + vm.$nextTick(_ => { | ||
| 19 | + // console.log(vm.$el.querySelector('.ivu-breadcrumb-item-separator').innerHTML); | ||
| 20 | + expect(vm.$el.querySelector('.ivu-breadcrumb-item-separator').innerHTML).to.equal('<b class="demo-breadcrumb-separator">=></b>'); | ||
| 21 | + done(); | ||
| 22 | + }); | ||
| 23 | + }); | ||
| 24 | +}); | ||
| 0 | \ No newline at end of file | 25 | \ No newline at end of file |
| 1 | +import Vue from 'vue'; | ||
| 2 | +import iView from '../../src/index'; | ||
| 3 | + | ||
| 4 | +Vue.use(iView); | ||
| 5 | + | ||
| 6 | +let id = 0; | ||
| 7 | + | ||
| 8 | +const createElm = function() { | ||
| 9 | + const elm = document.createElement('div'); | ||
| 10 | + | ||
| 11 | + elm.id = 'app' + ++id; | ||
| 12 | + document.body.appendChild(elm); | ||
| 13 | + | ||
| 14 | + return elm; | ||
| 15 | +}; | ||
| 16 | + | ||
| 17 | +/** | ||
| 18 | + * 回收 vm | ||
| 19 | + * @param {Object} vm | ||
| 20 | + */ | ||
| 21 | +exports.destroyVM = function(vm) { | ||
| 22 | + vm.$el && | ||
| 23 | + vm.$el.parentNode && | ||
| 24 | + vm.$el.parentNode.removeChild(vm.$el); | ||
| 25 | +}; | ||
| 26 | + | ||
| 27 | +/** | ||
| 28 | + * 创建一个 Vue 的实例对象 | ||
| 29 | + * @param {Object|String} Compo 组件配置,可直接传 template | ||
| 30 | + * @param {Boolean=false} mounted 是否添加到 DOM 上 | ||
| 31 | + * @return {Object} vm | ||
| 32 | + */ | ||
| 33 | +exports.createVue = function(Compo, mounted = false) { | ||
| 34 | + const elm = createElm(); | ||
| 35 | + | ||
| 36 | + if (Object.prototype.toString.call(Compo) === '[object String]') { | ||
| 37 | + Compo = { template: Compo }; | ||
| 38 | + } | ||
| 39 | + return new Vue(Compo).$mount(mounted === false ? null : elm); | ||
| 40 | +}; | ||
| 41 | + | ||
| 42 | +/** | ||
| 43 | + * 创建一个测试组件实例 | ||
| 44 | + * @link http://vuejs.org/guide/unit-testing.html#Writing-Testable-Components | ||
| 45 | + * @param {Object} Compo - 组件对象 | ||
| 46 | + * @param {Object} propsData - props 数据 | ||
| 47 | + * @param {Boolean=false} mounted - 是否添加到 DOM 上 | ||
| 48 | + * @return {Object} vm | ||
| 49 | + */ | ||
| 50 | +exports.createTest = function(Compo, propsData = {}, mounted = false) { | ||
| 51 | + if (propsData === true || propsData === false) { | ||
| 52 | + mounted = propsData; | ||
| 53 | + propsData = {}; | ||
| 54 | + } | ||
| 55 | + const elm = createElm(); | ||
| 56 | + const Ctor = Vue.extend(Compo); | ||
| 57 | + return new Ctor({ propsData }).$mount(mounted === false ? null : elm); | ||
| 58 | +}; | ||
| 59 | + | ||
| 60 | +/** | ||
| 61 | + * 触发一个事件 | ||
| 62 | + * mouseenter, mouseleave, mouseover, keyup, change, click 等 | ||
| 63 | + * @param {Element} elm | ||
| 64 | + * @param {String} name | ||
| 65 | + * @param {*} opts | ||
| 66 | + */ | ||
| 67 | +exports.triggerEvent = function(elm, name, ...opts) { | ||
| 68 | + let eventName; | ||
| 69 | + | ||
| 70 | + if (/^mouse|click/.test(name)) { | ||
| 71 | + eventName = 'MouseEvents'; | ||
| 72 | + } else if (/^key/.test(name)) { | ||
| 73 | + eventName = 'KeyboardEvent'; | ||
| 74 | + } else { | ||
| 75 | + eventName = 'HTMLEvents'; | ||
| 76 | + } | ||
| 77 | + const evt = document.createEvent(eventName); | ||
| 78 | + | ||
| 79 | + evt.initEvent(name, ...opts); | ||
| 80 | + elm.dispatchEvent | ||
| 81 | + ? elm.dispatchEvent(evt) | ||
| 82 | + : elm.fireEvent('on' + name, evt); | ||
| 83 | + | ||
| 84 | + return elm; | ||
| 85 | +}; |