├── .gitignore ├── README.md ├── package.json ├── slushfile.js └── template ├── Makefile ├── README.md ├── _babelrc ├── _eslintrc ├── _gitignore ├── app.json ├── build.js ├── cooking.conf.js ├── index.tpl ├── karma.conf.js ├── package.json ├── src └── pages │ ├── admin │ ├── app.vue │ └── index.js │ └── home │ ├── app.vue │ └── index.js └── test ├── _eslintrc ├── index.js └── specs └── hello.spec.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | npm-debug.log 3 | dist 4 | .DS_Store 5 | etc 6 | .idea 7 | .cooking 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # slush-cooking-pages-vue 2 | 3 | > A multiple pages project for vue. 4 | 5 | ## Dependency 6 | - [cooking-vue](https://github.com/cookingjs/cooking-vue/) 7 | - [cooking-lint](https://github.com/cookingjs/cooking-lint/) 8 | - [cooking-buble](https://github.com/cookingjs/cooking-buble/) 9 | 10 | ## Quick Start 11 | ```shell 12 | npm i cooking -g 13 | 14 | mkdir test-vue && cd test-vue 15 | cooking init pages-vue 16 | ``` -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "slush-cooking-pages-vue", 3 | "version": "0.1.2", 4 | "description": "A multiple pages project for vue", 5 | "keywords": [ 6 | "slush-cooking-pages-vue", 7 | "cooking", 8 | "slushgenerator" 9 | ], 10 | "scripts": { 11 | "dev": "cooking watch", 12 | "dist": "cooking build" 13 | }, 14 | "repository": { 15 | "type": "git", 16 | "url": "git+https://github.com/cookingjs/slush-cooking-pages-vue.git" 17 | }, 18 | "homepage": "https://github.com/cookingjs/slush-cooking-pages-vue#readme", 19 | "bugs": { 20 | "url": "https://github.com/cookingjs/slush-cooking-pages-vue/issues" 21 | }, 22 | "author": "qingwei-li", 23 | "license": "MIT" 24 | } 25 | -------------------------------------------------------------------------------- /slushfile.js: -------------------------------------------------------------------------------- 1 | var gulp = require('gulp') 2 | var install = require('gulp-install') 3 | var conflict = require('gulp-conflict') 4 | var rename = require('gulp-rename') 5 | var template = require('gulp-template') 6 | var inquirer = require('inquirer') 7 | var cookingConfig = require('cooking-config') 8 | 9 | gulp.task('default', function (done) { 10 | inquirer.prompt([ 11 | { 12 | type: 'input', 13 | name: 'name', 14 | message: 'Give your app a name', 15 | default: getNameProposal() 16 | }, 17 | { 18 | type: 'input', 19 | name: 'description', 20 | message: 'Give your app a description', 21 | default: 'A vue project.' 22 | }, 23 | { 24 | type: 'confirm', 25 | name: 'private', 26 | message: 'Private?', 27 | default: true 28 | }, 29 | { 30 | type: 'list', 31 | name: 'vueVersion', 32 | message: 'Which Vue version do you want?', 33 | default: 2, 34 | choices: [ 35 | {name: 'Vue 2', value: 2}, 36 | {name: 'Vue 1', value: ''} 37 | ] 38 | }, 39 | { 40 | type: 'list', 41 | name: 'js', 42 | message: 'Which ES2015+ compiler do you want to use?', 43 | default: '', 44 | choices: [ 45 | {name: 'bable (preset-es2015, preset-stage-0, perset-stage-2, plugin-transform-runtime)', value: ''}, 46 | {name: 'bublé (only use wepback 2)', value: 'buble'} 47 | ] 48 | }, 49 | { 50 | type: 'list', 51 | name: 'cooking', 52 | message: 'How do you want to use cooking?', 53 | default: '', 54 | choices: [ 55 | {name: 'Global cooking (webpack 2)', value: ''}, 56 | {name: 'Local cooking (and use webpack 1)', value: '1'}, 57 | {name: 'Local cooking (and use webpack 2)', value: 'beta'} 58 | ] 59 | }, 60 | { 61 | type: 'confirm', 62 | name: 'devServer', 63 | message: 'Need dev server?', 64 | default: true 65 | }, 66 | { 67 | type: 'list', 68 | name: 'csstype', 69 | message: 'Which CSS preprocessor do you want to use?', 70 | default: '', 71 | choices: [ 72 | {name: 'Only CSS', value: ''}, 73 | {name: 'Salad', value: 'saladcss'}, 74 | {name: 'Sass', value: 'sass'}, 75 | {name: 'Less', value: 'less'} 76 | ] 77 | }, 78 | { 79 | type: 'confirm', 80 | name: 'unit', 81 | message: 'Setup unit tests with Karma + Mocha?', 82 | default: true 83 | }, 84 | { 85 | type: 'input', 86 | name: 'github', 87 | message: 'git repository', 88 | default: cookingConfig.github 89 | }, 90 | { 91 | type: 'input', 92 | name: 'author', 93 | message: 'author', 94 | default: cookingConfig.author 95 | }, 96 | { 97 | type: 'input', 98 | name: 'license', 99 | message: 'license', 100 | default: 'ISC' 101 | }, 102 | { 103 | type: 'confirm', 104 | name: 'moveon', 105 | message: 'Continue?' 106 | } 107 | ], 108 | function (answers) { 109 | if (answers.github) { 110 | answers.github = answers.github.replace(/\/$/, '') + '/' + answers.name 111 | } 112 | 113 | if (!answers.moveon) { 114 | return done() 115 | } 116 | 117 | var filesPath = [__dirname + '/template/**'] 118 | if (!answers.unit) { 119 | filesPath = filesPath.concat([ 120 | '!' + __dirname + '/template/karma.conf.js', 121 | '!' + __dirname + '/template/test', 122 | '!' + __dirname + '/template/test/**' 123 | ]) 124 | } 125 | 126 | if (answers.js) { 127 | filesPath = filesPath.concat([ 128 | '!' + __dirname + '/template/_babelrc' 129 | ]) 130 | } 131 | 132 | gulp.src(filesPath, { dot: true }) 133 | .pipe(template(answers)) 134 | .pipe(rename(function (file) { 135 | if (file.basename[0] === '_') { 136 | file.basename = '.' + file.basename.slice(1) 137 | } 138 | })) 139 | .pipe(conflict('./')) 140 | .pipe(gulp.dest('./')) 141 | .pipe(install()) 142 | .on('end', function () { 143 | done() 144 | }) 145 | .resume() 146 | }) 147 | }) 148 | 149 | function getNameProposal () { 150 | var path = require('path') 151 | try { 152 | return require(path.join(process.cwd(), 'package.json')).name 153 | } catch (e) { 154 | return path.basename(process.cwd()) 155 | } 156 | } 157 | -------------------------------------------------------------------------------- /template/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: dist 2 | 3 | dev: 4 | @npm run dev 5 | 6 | dist: 7 | @npm run dist 8 | -------------------------------------------------------------------------------- /template/README.md: -------------------------------------------------------------------------------- 1 | # <%= name %> 2 | > <%= description %> 3 | 4 | # Development 5 | 6 | ```shell 7 | npm run dev 8 | ``` 9 | 10 | # Production 11 | ``` 12 | npm run dist 13 | ``` 14 | 15 | # License 16 | <%= license %> 17 | -------------------------------------------------------------------------------- /template/_babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015", "stage-0", "stage-2"], 3 | "comments": false, 4 | "env": { 5 | "production": { 6 | "plugins": [ 7 | ["transform-runtime", { "polyfill": false, "regenerator": false }] 8 | ] 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /template/_eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": ["vue"], 3 | "extends": ["elemefe"] 4 | } -------------------------------------------------------------------------------- /template/_gitignore: -------------------------------------------------------------------------------- 1 | *.log 2 | .cache 3 | .DS_Store 4 | .idea 5 | build 6 | dist 7 | node_modules 8 | .gitkeep 9 | converage 10 | -------------------------------------------------------------------------------- /template/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "pages": [ 3 | { 4 | "entry": "home", 5 | "title": "Home Page", 6 | "cdn": {} 7 | }, 8 | { 9 | "entry": "admin", 10 | "title": "Admin Page", 11 | "cdn": {} 12 | } 13 | ], 14 | "basePath": "./src/pages/", 15 | "cdn": { 16 | "js": [ 17 | "//unpkg.com/babel-polyfill@6.13.0/dist/polyfill.min.js", 18 | "//cdn.jsdelivr.net/vue/2.0.2/vue.min.js", 19 | "//cdn.jsdelivr.net/vuex/2.0.0/vuex.min.js" 20 | ], 21 | "css": [] 22 | }, 23 | "externals": { 24 | "vue": "Vue", 25 | "vuex": "Vuex" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /template/build.js: -------------------------------------------------------------------------------- 1 | var App = require('./app.json'); 2 | var path = require('path'); 3 | 4 | var merge = function(a, b) { 5 | return { 6 | css: (a.css || []).concat(b.css || []), 7 | js: (a.js || []).concat(b.js || []) 8 | }; 9 | }; 10 | 11 | exports.entries = function() { 12 | var result = {}; 13 | App.pages.forEach(p => { 14 | result[p.entry] = path.resolve(App.basePath, p.entry); 15 | }); 16 | return result; 17 | }; 18 | 19 | exports.templates = function() { 20 | return App.pages.map(p => { 21 | return { 22 | title: p.title, 23 | filename: p.entry + '.html', 24 | template: path.resolve(__dirname, 'index.tpl'), 25 | cdn: merge(App.cdn, p.cdn), 26 | chunks: ['vendor', 'manifest', p.entry] 27 | }; 28 | }); 29 | }; 30 | 31 | exports.externals = function() { 32 | return App.externals; 33 | }; 34 | -------------------------------------------------------------------------------- /template/cooking.conf.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var cooking = require('cooking'); 3 | var build = require('./build'); 4 | var isProd = process.env.NODE_ENV === 'production'; 5 | 6 | cooking.set({ 7 | entry: build.entries(), 8 | dist: './dist', 9 | template: build.templates(), 10 | devServer: {<% if (devServer) { %> 11 | port: 8080, 12 | publicPath: '/'<% } else { %> 13 | enable: false, 14 | extractCSS: true<% } %> 15 | }, 16 | clean: true, 17 | hash: true, 18 | sourceMap: true, 19 | chunk: true, 20 | postcss: [], 21 | publicPath: '/dist/', 22 | extractCSS: isProd ? 'static/[name].[contenthash:7].css' : true, 23 | alias: { 24 | 'src': path.join(__dirname, 'src') 25 | }, 26 | extends: ['vue<%= vueVersion %>'<% if (js) { %>, '<%= js %>'<% } %>, 'lint'<% if (csstype) { %>, '<%= csstype %>'<% } %><% if (csstype != 'saladcss') { %>, 'autoprefixer'<% } %>], 27 | externals: build.externals() 28 | }); 29 | 30 | isProd && cooking.add('output.filename', 'static/[name].[hash:7].js'); 31 | 32 | module.exports = cooking.resolve(); 33 | -------------------------------------------------------------------------------- /template/index.tpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | <%= "\<%= htmlWebpackPlugin.options.title %\>" %> 7 | <%= "\<% for (var i in htmlWebpackPlugin.options.cdn.css) { %\>\">\<% } %\>"%> 8 | 9 | 10 |
<% if (!vueVersion) { %> 11 | 12 | <% } %>
13 | <%= "\<% for (var i in htmlWebpackPlugin.options.cdn.js) { %\>\<% } %\>"%> 14 | 15 | 16 | -------------------------------------------------------------------------------- /template/karma.conf.js: -------------------------------------------------------------------------------- 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('./cooking.conf.js'); 7 | var webpack = require('webpack'); 8 | var merge = require('webpack-merge'); 9 | var path = require('path'); 10 | var projectRoot = path.resolve(__dirname, '../'); 11 | 12 | // no need for app entry and plugin during tests 13 | delete webpackConfig.entry; 14 | delete webpackConfig.plugins; 15 | 16 | webpackConfig = merge(webpackConfig, { 17 | devtool: '#inline-source-map', 18 | vue: { 19 | loaders: { 20 | js: 'isparta' 21 | } 22 | }, 23 | plugins: [ 24 | new webpack.DefinePlugin({ 25 | 'process.env': JSON.stringify('testing') 26 | }) 27 | ] 28 | }); 29 | 30 | // make sure isparta loader is applied before eslint 31 | webpackConfig.module.preLoaders = webpackConfig.module.preLoaders || []; 32 | webpackConfig.module.preLoaders.unshift({ 33 | test: /\.js$/, 34 | loader: 'isparta', 35 | include: path.resolve(projectRoot, 'src') 36 | }); 37 | 38 | webpackConfig.module.loaders.some(function (loader, i) { 39 | if (loader.loader === 'babel') { 40 | loader.include = path.resolve(projectRoot, 'test'); 41 | return true; 42 | } 43 | }); 44 | 45 | module.exports = function (config) { 46 | config.set({ 47 | // to run in additional browsers: 48 | // 1. install corresponding karma launcher 49 | // http://karma-runner.github.io/0.13/config/browsers.html 50 | // 2. add it to the `browsers` array below. 51 | browsers: ['Chrome'/* ,'PhantomJS'*/], 52 | frameworks: ['mocha', 'sinon-chai'], 53 | reporters: ['spec', 'coverage'], 54 | files: ['./test/index.js'], 55 | preprocessors: { 56 | './test/index.js': ['webpack', 'sourcemap'] 57 | }, 58 | webpack: webpackConfig, 59 | webpackMiddleware: { 60 | noInfo: true 61 | }, 62 | coverageReporter: { 63 | dir: './coverage', 64 | reporters: [ 65 | { type: 'lcov', subdir: '.' }, 66 | { type: 'text-summary' } 67 | ] 68 | } 69 | }); 70 | }; 71 | 72 | -------------------------------------------------------------------------------- /template/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "<%= name %>", 3 | "version": "0.0.0", 4 | "description": "<%= description %>", 5 | "private": <%= private %>, 6 | "keywords": [ 7 | ], 8 | "scripts": { 9 | "dev": "cooking watch -p", 10 | "dist": "cooking build -p", 11 | "deploy": "cooking build --no-color"<% if (unit) { %>, 12 | "test": "cooking test karma start --single-run"<% } %> 13 | },<% if (github) { %> 14 | "repository": { 15 | "type": "git", 16 | "url": "git+<%= github %>.git" 17 | }, 18 | "homepage": "<%= github %>#readme", 19 | "bugs": { 20 | "url": "<%= github %>/issues" 21 | },<% } %><% if (author) { %> 22 | "author": "<%= author %>",<% } %> 23 | "license": "<%= license %>", 24 | "dependencies": { 25 | "vue": <% if (!vueVersion) { %>"^1.0.0"<% } else {%>"^2.0.2"<% } %>, 26 | "babel-polyfill": "*" 27 | }, 28 | "devDependencies": { 29 | "cooking-vue<%= vueVersion %>": "*"<% if (js) { %>, 30 | "cooking-<%= js %>": "*"<% } %><% if (cooking) { %>, 31 | "cooking": "^1.0.0", 32 | "cooking-vue<%= vueVersion %>": "*", 33 | "cooking-lint": "*",<% if (csstype) { %> 34 | "cooking-<%= csstype %>": "*",<% } %> 35 | "cooking-autoprefixer": "*", 36 | "babel-core": "^6.0.0", 37 | "babel-loader": "^6.0.0", 38 | "babel-plugin-transform-runtime": "^6.0.0", 39 | "babel-preset-es2015": "^6.0.0", 40 | "babel-preset-stage-0": "^6.0.0", 41 | "babel-preset-stage-2": "^6.0.0", 42 | "css-loader": "^0.24.0", 43 | "extract-text-webpack-plugin": <% if (cooking == 1) { %>"^1.0.0"<% } else {%>"^2.0.0-beta"<% } %>, 44 | "file-loader": "^0.9.0", 45 | "html-loader": "^0.4.3", 46 | "html-webpack-plugin": "^2.9.0", 47 | "json-loader": "^0.5.4", 48 | "style-loader": "^0.13.1", 49 | "url-loader": "^0.5.7", 50 | "webpack": <% if (cooking == 1) { %>"^1.12.0"<% } else {%>"^2.1.0-beta"<% } %>, 51 | "webpack-dev-server": <% if (cooking == 1) { %>"^1.14.0"<% } else {%>"^2.1.0-beta"<% } %>, 52 | "postcss": "^5.1.0", 53 | "postcss-loader": "^0.11.1"<% } %> 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /template/src/pages/admin/app.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 13 | -------------------------------------------------------------------------------- /template/src/pages/admin/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import App from './app'; 3 | 4 | new Vue({ // eslint-disable-line 5 | el: '#app', 6 | <% if (!vueVersion) { %>components: { App }<% } else { %>render: h => h(App)<% } %> 7 | }); 8 | -------------------------------------------------------------------------------- /template/src/pages/home/app.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 13 | -------------------------------------------------------------------------------- /template/src/pages/home/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import App from './app'; 3 | 4 | new Vue({ // eslint-disable-line 5 | el: '#app', 6 | <% if (!vueVersion) { %>components: { App }<% } else { %>render: h => h(App)<% } %> 7 | }); 8 | -------------------------------------------------------------------------------- /template/test/_eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "mocha": true 4 | }, 5 | "globals": { 6 | "expect": true, 7 | "sinon": true 8 | } 9 | } -------------------------------------------------------------------------------- /template/test/index.js: -------------------------------------------------------------------------------- 1 | // Polyfill fn.bind() for PhantomJS 2 | /* eslint-disable no-extend-native */ 3 | Function.prototype.bind = require('function-bind'); 4 | 5 | // require all test files (files that ends with .spec.js) 6 | var testsContext = require.context('./specs', true, /\.spec$/); 7 | testsContext.keys().forEach(testsContext); 8 | 9 | // require all src files except main.js and index.tpl for coverage. 10 | // you can also change this to match only the subset of files that 11 | // you want coverage for. 12 | var srcContext = require.context('../src', true, /^\.\/(?!index\.tpl|main\.js$)/); 13 | srcContext.keys().forEach(srcContext); 14 | -------------------------------------------------------------------------------- /template/test/specs/hello.spec.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import App from 'src/app'; 3 | 4 | describe('App.vue', () => { 5 | it('should render correct contents', () => { 6 | const vm = new Vue({ 7 | template: '
', 8 | components: { App } 9 | }).$mount(); 10 | expect(vm.$el.querySelector('h1').textContent).to.contain('<%= name %>'); 11 | expect(vm.$el.querySelector('p').textContent).to.contain('<%= description %>'); 12 | }); 13 | }); 14 | --------------------------------------------------------------------------------