From af473aaaa3fe3c5ff111574574f22806bccd5525 Mon Sep 17 00:00:00 2001 From: Scott Bedard Date: Mon, 6 Feb 2017 08:13:44 -0700 Subject: [PATCH 01/31] Begin scaffolding v2.1.0 --- .babelrc | 16 +++ .editorconfig | 9 ++ template/.eslintignore => .eslintignore | 0 .eslintrc.js | 21 ++++ template/.gitignore => .gitignore | 6 +- README.md | 73 +++----------- {template/build => build}/build.js | 26 ++--- build/check-versions.js | 48 +++++++++ {template/build => build}/dev-client.js | 0 {template/build => build}/dev-server.js | 51 +++++++--- {template/build => build}/utils.js | 16 ++- build/webpack.base.conf.js | 87 ++++++++++++++++ {template/build => build}/webpack.dev.conf.js | 11 +- .../build => build}/webpack.prod.conf.js | 44 ++++---- build/webpack.test.conf.js | 22 ++++ {template/config => config}/dev.env.js | 0 config/index.js | 24 +++++ {template/config => config}/prod.env.js | 0 {template/config => config}/test.env.js | 0 meta.json | 59 ----------- npm-debug.log | 54 ---------- package.json | 83 +++++++++++++++ src/App.vue | 23 +++++ src/assets/logo.png | Bin 0 -> 6849 bytes src/components/Hello.vue | 53 ++++++++++ {template/src => src}/index.htm | 10 +- src/main.js | 12 +++ src/router/index.js | 16 +++ {template/static => static}/.gitkeep | 0 template/.babelrc | 5 - template/.eslintrc.js | 31 ------ template/README.md | 27 ----- template/build/webpack.base.conf.js | 95 ------------------ template/config/index.js | 32 ------ template/package.json | 87 ---------------- template/src/app/boot.js | 10 -- template/src/app/directives/linkable.js | 26 ----- template/src/app/plugins/resources.js | 22 ---- template/src/app/plugins/router.js | 4 - template/src/app/routes.js | 43 -------- template/src/assets/october.png | Bin 12173 -> 0 bytes template/src/assets/vue.png | Bin 9755 -> 0 bytes template/src/layouts/splash.vue | 20 ---- template/src/layouts/standard.vue | 13 --- template/src/main.js | 28 ------ template/src/pages/404.vue | 10 -- template/src/pages/blog/list.vue | 58 ----------- template/src/pages/blog/show.vue | 36 ------- template/src/pages/welcome.vue | 38 ------- template/src/resources/blog.js | 10 -- template/src/root.vue | 9 -- template/src/scss/classes/transitions.scss | 9 -- template/src/scss/core.scss | 4 - template/src/scss/elements/html_body.scss | 14 --- template/src/scss/global.scss | 15 --- template/test/unit/.eslintrc | 9 -- template/test/unit/index.js | 16 --- template/test/unit/karma.conf.js | 76 -------------- template/test/unit/specs/welcome.spec.js | 17 ---- template/theme.yaml | 3 - test/unit/.eslintrc | 9 ++ test/unit/index.js | 16 +++ test/unit/karma.conf.js | 33 ++++++ test/unit/specs/Hello.spec.js | 13 +++ theme.yaml | 3 + 65 files changed, 603 insertions(+), 1002 deletions(-) create mode 100644 .babelrc create mode 100644 .editorconfig rename template/.eslintignore => .eslintignore (100%) create mode 100644 .eslintrc.js rename template/.gitignore => .gitignore (52%) rename {template/build => build}/build.js (64%) create mode 100644 build/check-versions.js rename {template/build => build}/dev-client.js (100%) rename {template/build => build}/dev-server.js (64%) rename {template/build => build}/utils.js (81%) create mode 100644 build/webpack.base.conf.js rename {template/build => build}/webpack.dev.conf.js (71%) rename {template/build => build}/webpack.prod.conf.js (79%) create mode 100644 build/webpack.test.conf.js rename {template/config => config}/dev.env.js (100%) create mode 100644 config/index.js rename {template/config => config}/prod.env.js (100%) rename {template/config => config}/test.env.js (100%) delete mode 100644 meta.json delete mode 100644 npm-debug.log create mode 100644 package.json create mode 100644 src/App.vue create mode 100644 src/assets/logo.png create mode 100644 src/components/Hello.vue rename {template/src => src}/index.htm (53%) create mode 100644 src/main.js create mode 100644 src/router/index.js rename {template/static => static}/.gitkeep (100%) delete mode 100644 template/.babelrc delete mode 100644 template/.eslintrc.js delete mode 100644 template/README.md delete mode 100644 template/build/webpack.base.conf.js delete mode 100644 template/config/index.js delete mode 100644 template/package.json delete mode 100644 template/src/app/boot.js delete mode 100644 template/src/app/directives/linkable.js delete mode 100644 template/src/app/plugins/resources.js delete mode 100644 template/src/app/plugins/router.js delete mode 100644 template/src/app/routes.js delete mode 100644 template/src/assets/october.png delete mode 100644 template/src/assets/vue.png delete mode 100644 template/src/layouts/splash.vue delete mode 100644 template/src/layouts/standard.vue delete mode 100644 template/src/main.js delete mode 100644 template/src/pages/404.vue delete mode 100644 template/src/pages/blog/list.vue delete mode 100644 template/src/pages/blog/show.vue delete mode 100644 template/src/pages/welcome.vue delete mode 100644 template/src/resources/blog.js delete mode 100644 template/src/root.vue delete mode 100644 template/src/scss/classes/transitions.scss delete mode 100644 template/src/scss/core.scss delete mode 100644 template/src/scss/elements/html_body.scss delete mode 100644 template/src/scss/global.scss delete mode 100644 template/test/unit/.eslintrc delete mode 100644 template/test/unit/index.js delete mode 100644 template/test/unit/karma.conf.js delete mode 100644 template/test/unit/specs/welcome.spec.js delete mode 100644 template/theme.yaml create mode 100644 test/unit/.eslintrc create mode 100644 test/unit/index.js create mode 100644 test/unit/karma.conf.js create mode 100644 test/unit/specs/Hello.spec.js create mode 100644 theme.yaml diff --git a/.babelrc b/.babelrc new file mode 100644 index 0000000..f124173 --- /dev/null +++ b/.babelrc @@ -0,0 +1,16 @@ +{ + "presets": [ + ["es2015", { "modules": false }], + "stage-2", + ], + "plugins": [ + "transform-runtime", + "transform-vue-jsx", + ], + "comments": false, + "env": { + "test": { + "plugins": ["istanbul"], + }, + }, +} diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..e291365 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,9 @@ +root = true + +[*] +charset = utf-8 +indent_style = space +indent_size = 4 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true diff --git a/template/.eslintignore b/.eslintignore similarity index 100% rename from template/.eslintignore rename to .eslintignore diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000..d3f39ba --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,21 @@ +// http://eslint.org/docs/user-guide/configuring +module.exports = { + env: { + browser: true, + }, + parser: 'babel-eslint', + parserOptions: { + sourceType: 'module', + }, + plugins: [ + 'html', // required to lint *.vue files + ], + root: true, + rules: { + 'comma-dangle': ['error', 'always'], + 'indent': ['error', 4], + 'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0, // allow debugger in development + 'quotes': ['error', 'single'], + 'semi': ['error', 'always'], + }, +}; diff --git a/template/.gitignore b/.gitignore similarity index 52% rename from template/.gitignore rename to .gitignore index 8d95da1..6607c6d 100644 --- a/template/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ .DS_Store -node_modules/ -dist/ +/assets +/node_modules +/pages npm-debug.log -selenium-debug.log test/unit/coverage diff --git a/README.md b/README.md index 2059ae7..28d19c5 100644 --- a/README.md +++ b/README.md @@ -1,68 +1,27 @@ -

- October -

- # oc-vuetober-theme -This project is an opinionated approach to single page applications within the wonderful worlds of [Vue.js](https://vuejs.org), [October CMS](https://octobercms.com), and [Laravel](https://laravel.com). To see what's included out of the box, check out the [live demo](http://vuetober.scottbedard.net). +> An opinionated approach to single page applications within the wonderful worlds of Vue.js, October CMS, and Laravel. - -### Getting started +## Build Setup -Before getting started, make sure you have both [NPM](https://www.npmjs.com) and [vue-cli](https://github.com/vuejs/vue-cli) installed. Once that is taken care of, run the following command from your `/themes` directory. +``` bash +# install dependencies +npm install -```bash -$ vue init scottbedard/oc-vuetober-theme myawesometheme -$ cd myawesometheme -$ npm install -``` +# serve with hot reload at localhost:8080 +npm run dev -To build your site for production, run the following command. +# build for production with minification +npm run build -```bash -$ npm run build -``` +# build for production and view the bundle analyzer report +npm run build --report -The development server can be fired up at `localhost:3000` by running the following. +# run unit tests +npm run unit -```bash -$ npm run dev +# run all tests +npm test ``` -For a better development experience, make sure to install the [Vue devtools](https://github.com/vuejs/vue-devtools) Chrome extension. - - -### Routing - -Routes can be registered from the `app/routes.js` file. Simply import your component, and assign it to a route. - -The layout components exist to provide an easy way of creating multiple site structures. To use a given layout for your page, make sure to register its route as a child route of the layout component. - -When displaying dynamic content that may contain local links, it is recommended that you attach the `v-linkable` directive to the container. This will hijack click events and keep your user within the SPA. Without doing this, a full page reload will occur. - -```html -
-``` - - -### Unit testing and continuous integration - -This theme comes ready to go with unit testing and code coverage reporting. To run the test suite, execute the following command. - -```bash -$ npm test -``` - -Most continuous integration services like [Travic CI](https://travis-ci.org) and [Circle CI](https://circleci.com) should be able to infer the test command. Also, this theme works seamlessly with coverage reporting such as [Coveralls](https://coveralls.io). - - -### Resources - -This theme uses quite a few different tools. If you've never used some of these before, it is highly recommended that you familiarize yourself with them by giving their docs the once over. - -- [Karma](https://karma-runner.github.io/1.0/index.html) -- [Vue](http://vuejs.org/guide) -- [Vue Loader](http://vue-loader.vuejs.org) -- [Vue Resource](https://github.com/vuejs/vue-resource) -- [Vue Router](http://router.vuejs.org) -- [Webpack](https://webpack.github.io) +For detailed explanation on how things work, checkout the [guide](http://vuejs-templates.github.io/webpack/) and [docs for vue-loader](http://vuejs.github.io/vue-loader). diff --git a/template/build/build.js b/build/build.js similarity index 64% rename from template/build/build.js rename to build/build.js index c38adab..c2a0067 100644 --- a/template/build/build.js +++ b/build/build.js @@ -1,27 +1,25 @@ // https://github.com/shelljs/shelljs -require('shelljs/global'); +require('./check-versions')(); -env.NODE_ENV = 'production'; +process.env.NODE_ENV = 'production'; -var config = require('../config'); var ora = require('ora'); var path = require('path'); +var chalk = require('chalk'); +var shell = require('shelljs'); var webpack = require('webpack'); +var config = require('../config'); var webpackConfig = require('./webpack.prod.conf'); -console.log( - ' Tip:\n' + - ' Built files are meant to be served over an HTTP server.\n' + - ' Opening index.htm over file:// won\'t work.\n' -); - var spinner = ora('building for production...'); spinner.start(); var assetsPath = path.join(config.build.assetsRoot, config.build.assetsSubDirectory); -rm('-rf', assetsPath); -mkdir('-p', assetsPath); -cp('-R', 'static/', assetsPath); +shell.rm('-rf', assetsPath); +shell.mkdir('-p', assetsPath); +shell.config.silent = true; +shell.cp('-R', 'static/*', assetsPath); +shell.config.silent = false; webpack(webpackConfig, function (err, stats) { spinner.stop(); @@ -36,5 +34,7 @@ webpack(webpackConfig, function (err, stats) { chunks: false, colors: true, modules: false, - }) + '\n'); + }) + '\n\n'); + + console.log(chalk.cyan(' Build complete.\n')); }); diff --git a/build/check-versions.js b/build/check-versions.js new file mode 100644 index 0000000..36ef7d0 --- /dev/null +++ b/build/check-versions.js @@ -0,0 +1,48 @@ +var chalk = require('chalk'); +var semver = require('semver'); +var packageConfig = require('../package.json'); + +function exec (cmd) { + return require('child_process').execSync(cmd).toString().trim(); +}; + +var versionRequirements = [ + { + name: 'node', + currentVersion: semver.clean(process.version), + versionRequirement: packageConfig.engines.node, + }, + { + name: 'npm', + currentVersion: exec('npm --version'), + versionRequirement: packageConfig.engines.npm, + }, +]; + +module.exports = function () { + var warnings = []; + for (var i = 0; i < versionRequirements.length; i++) { + var mod = versionRequirements[i]; + if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) { + warnings.push( + mod.name + ': ' + + chalk.red(mod.currentVersion) + ' should be ' + + chalk.green(mod.versionRequirement) + ); + } + } + + if (warnings.length) { + console.log(''); + console.log(chalk.yellow('To use this template, you must update following to modules:')); + console.log(); + + for (var i = 0; i < warnings.length; i++) { + var warning = warnings[i]; + console.log(' ' + warning); + } + + console.log(); + process.exit(1); + } +}; diff --git a/template/build/dev-client.js b/build/dev-client.js similarity index 100% rename from template/build/dev-client.js rename to build/dev-client.js diff --git a/template/build/dev-server.js b/build/dev-server.js similarity index 64% rename from template/build/dev-server.js rename to build/dev-server.js index 4e8cd51..83f3697 100644 --- a/template/build/dev-server.js +++ b/build/dev-server.js @@ -1,6 +1,13 @@ -var browserSync = require('browser-sync'); +require('./check-versions')(); var config = require('../config'); + +if (!process.env.NODE_ENV) { + process.env.NODE_ENV = JSON.parse(config.dev.env.NODE_ENV); +} + +var browserSync = require('browser-sync'); var express = require('express'); +var opn = require('opn'); var path = require('path'); var proxyMiddleware = require('http-proxy-middleware'); var webpack = require('webpack'); @@ -11,6 +18,9 @@ var webpackConfig = process.env.NODE_ENV === 'testing' // default port where dev server listens for incoming traffic var port = process.env.PORT || config.dev.port; +// automatically open browser, if not set will be false +var autoOpenBrowser = !!config.dev.autoOpenBrowser; + // Define HTTP proxies to your custom API backend // https://github.com/chimurai/http-proxy-middleware var proxyTable = config.dev.proxyTable; @@ -20,13 +30,12 @@ var compiler = webpack(webpackConfig); var devMiddleware = require('webpack-dev-middleware')(compiler, { publicPath: webpackConfig.output.publicPath, - stats: { - chunks: false, - colors: true, - }, + quiet: true, }); -var hotMiddleware = require('webpack-hot-middleware')(compiler); +var hotMiddleware = require('webpack-hot-middleware')(compiler, { + log: () => {}, +}); // force page reload when html-webpack-plugin template changes compiler.plugin('compilation', function (compilation) { @@ -41,22 +50,31 @@ Object.keys(proxyTable).forEach(function (context) { var options = proxyTable[context]; if (typeof options === 'string') { - options = { target: options } + options = { target: options }; } - app.use(proxyMiddleware(context, options)); + app.use(proxyMiddleware(options.filter || context, options)); }); // handle fallback for HTML5 history API app.use(require('connect-history-api-fallback')()); +// serve webpack bundle output +app.use(devMiddleware); + +// enable hot-reload and state-preserving +// compilation error display +app.use(hotMiddleware); + // serve pure static assets var staticPath = path.posix.join(config.dev.assetsPublicPath, config.dev.assetsSubDirectory); app.use(staticPath, express.static('./static')); // browser sync browserSync({ - proxy: "{{ proxy }}", + proxy: { + target: "http://vuetober.october.dev", + }, open: false, middleware: [ devMiddleware, @@ -64,7 +82,7 @@ browserSync({ ], rewriteRules: [ { - match: //ig, + match: //ig, fn: function(match) { return ''; }, @@ -72,17 +90,26 @@ browserSync({ { match: /
<\/div>(.*)<\/body>/ig, fn: function(match) { - return '
'; + return '
'; }, }, ], }); +var uri = 'http://localhost:' + port; + +devMiddleware.waitUntilValid(function () { + console.log('> Listening at ' + uri + '\n'); +}); + module.exports = app.listen(port, function (err) { if (err) { console.log(err); return; } - console.log('Listening at http://localhost:3000' + '\n'); + // when env is testing, don't need open it + if (autoOpenBrowser && process.env.NODE_ENV !== 'testing') { + opn(uri); + } }); diff --git a/template/build/utils.js b/build/utils.js similarity index 81% rename from template/build/utils.js rename to build/utils.js index 186fc68..2f0b186 100644 --- a/template/build/utils.js +++ b/build/utils.js @@ -17,6 +17,7 @@ exports.cssLoaders = function (options) { function generateLoaders (loaders) { var sourceLoader = loaders.map(function (loader) { var extraParamChar; + if (/\?/.test(loader)) { loader = loader.replace(/\?/, '-loader?'); extraParamChar = '&'; @@ -28,14 +29,19 @@ exports.cssLoaders = function (options) { return loader + (options.sourceMap ? extraParamChar + 'sourceMap' : ''); }).join('!'); + // Extract CSS when that option is specified + // (which is the case during production build) if (options.extract) { - return ExtractTextPlugin.extract('vue-style-loader', sourceLoader); + return ExtractTextPlugin.extract({ + use: sourceLoader, + fallback: 'vue-style-loader', + }); } else { return ['vue-style-loader', sourceLoader].join('!'); } - }; + } - // http://vuejs.github.io/vue-loader/configurations/extract-css.html + // http://vuejs.github.io/vue-loader/en/configurations/extract-css.html return { css: generateLoaders(['css']), less: generateLoaders(['css', 'less']), @@ -53,10 +59,10 @@ exports.styleLoaders = function (options) { var loaders = exports.cssLoaders(options); for (var extension in loaders) { - var loader = loaders[extension]; + var loader = loaders[extension] output.push({ test: new RegExp('\\.' + extension + '$'), - loader: loader + loader: loader, }); } diff --git a/build/webpack.base.conf.js b/build/webpack.base.conf.js new file mode 100644 index 0000000..baf2c1a --- /dev/null +++ b/build/webpack.base.conf.js @@ -0,0 +1,87 @@ +var path = require('path'); +var utils = require('./utils'); +var config = require('../config'); +var eslintFriendlyFormatter = require('eslint-friendly-formatter'); +var isProduction = process.env.NODE_ENV === 'production'; + +function resolve (dir) { + return path.join(__dirname, '..', dir); +}; + +module.exports = { + entry: { + app: './src/main.js', + }, + output: { + path: config.build.assetsRoot, + filename: '[name].js', + publicPath: isProduction + ? config.build.assetsPublicPath + : config.dev.assetsPublicPath, + }, + resolve: { + extensions: ['.js', '.vue', '.json'], + modules: [ + resolve('src'), + resolve('node_modules'), + ], + alias: { + 'src': resolve('src'), + 'assets': resolve('src/assets'), + 'components': resolve('src/components'), + }, + }, + module: { + rules: [ + { + test: /\.(js|vue)$/, + loader: 'eslint-loader', + enforce: "pre", + include: [resolve('src'), resolve('test')], + options: { + formatter: eslintFriendlyFormatter, + }, + }, + { + test: /\.vue$/, + loader: 'vue-loader', + options: { + loaders: utils.cssLoaders({ + extract: isProduction, + sourceMap: isProduction + ? config.build.productionSourceMap + : config.dev.cssSourceMap, + }), + postcss: [ + require('autoprefixer')({ browsers: ['last 2 versions'] }), + ], + }, + }, + { + test: /\.js$/, + loader: 'babel-loader', + include: [resolve('src'), resolve('test')], + }, + { + test: /\.json$/, + loader: 'json-loader', + }, + { + test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, + loader: 'url-loader', + query: { + limit: 10000, + name: utils.assetsPath('img/[name].[hash:7].[ext]'), + }, + }, + { + test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, + loader: 'url-loader', + query: { + limit: 10000, + name: utils.assetsPath('fonts/[name].[hash:7].[ext]'), + }, + }, + ], + }, +}; diff --git a/template/build/webpack.dev.conf.js b/build/webpack.dev.conf.js similarity index 71% rename from template/build/webpack.dev.conf.js rename to build/webpack.dev.conf.js index 6aa75b9..e5a3ec4 100644 --- a/template/build/webpack.dev.conf.js +++ b/build/webpack.dev.conf.js @@ -1,5 +1,6 @@ var baseWebpackConfig = require('./webpack.base.conf'); var config = require('../config'); +var FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin'); var HtmlWebpackPlugin = require('html-webpack-plugin'); var merge = require('webpack-merge'); var utils = require('./utils'); @@ -12,20 +13,20 @@ Object.keys(baseWebpackConfig.entry).forEach(function (name) { module.exports = merge(baseWebpackConfig, { module: { - loaders: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap }), + rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap }), }, - devtool: '#eval-source-map', // eval-source-map is faster for development + devtool: '#cheap-module-eval-source-map', // cheap-module-eval-source-map is faster for development plugins: [ new webpack.DefinePlugin({ 'process.env': config.dev.env }), // https://github.com/glenjamin/webpack-hot-middleware#installation--usage - new webpack.optimize.OccurenceOrderPlugin(), new webpack.HotModuleReplacementPlugin(), - new webpack.NoErrorsPlugin(), + new webpack.NoEmitOnErrorsPlugin(), // https://github.com/ampedandwired/html-webpack-plugin new HtmlWebpackPlugin({ - filename: 'src/index.htm', + filename: 'src/index.html', inject: true, template: 'src/index.htm', }), + new FriendlyErrorsPlugin(), ], }); diff --git a/template/build/webpack.prod.conf.js b/build/webpack.prod.conf.js similarity index 79% rename from template/build/webpack.prod.conf.js rename to build/webpack.prod.conf.js index e568211..2785065 100644 --- a/template/build/webpack.prod.conf.js +++ b/build/webpack.prod.conf.js @@ -12,58 +12,51 @@ var env = process.env.NODE_ENV === 'testing' var webpackConfig = merge(baseWebpackConfig, { module: { - loaders: utils.styleLoaders({ sourceMap: config.build.productionSourceMap, extract: true }), + rules: utils.styleLoaders({ + extract: true, + sourceMap: config.build.productionSourceMap, + }), }, devtool: config.build.productionSourceMap ? '#source-map' : false, output: { - path: config.build.assetsRoot, - filename: utils.assetsPath('js/[name].[chunkhash].js'), chunkFilename: utils.assetsPath('js/[id].[chunkhash].js'), - }, - vue: { - loaders: utils.cssLoaders({ - sourceMap: config.build.productionSourceMap, - extract: true, - }), + filename: utils.assetsPath('js/[name].[chunkhash].js'), + path: config.build.assetsRoot, }, plugins: [ - // http://vuejs.github.io/vue-loader/workflow/production.html + // http://vuejs.github.io/vue-loader/en/workflow/production.html new webpack.DefinePlugin({ 'process.env': env }), new webpack.optimize.UglifyJsPlugin({ compress: { warnings: false }}), - new webpack.optimize.OccurenceOrderPlugin(), - // extract css into its own file new ExtractTextPlugin(utils.assetsPath('css/[name].[contenthash].css')), - - // generate dist index.htm with correct asset hash for caching. - // you can customize output by editing /index.htm - // see https://github.com/ampedandwired/html-webpack-plugin new HtmlWebpackPlugin({ - filename: process.env.NODE_ENV === 'testing' ? 'index.htm' : config.build.index, - template: 'src/index.htm', + chunksSortMode: 'dependency', + filename: path.resolve(__dirname, '../pages/index.htm'), inject: true, minify: { + // https://github.com/kangax/html-minifier#options-quick-reference collapseWhitespace: true, removeAttributeQuotes: true, removeComments: true, - // https://github.com/kangax/html-minifier#options-quick-reference }, - chunksSortMode: 'dependency', + template: 'src/index.htm', }), - // split vendor js into its own file new webpack.optimize.CommonsChunkPlugin({ name: 'vendor', minChunks: function (module, count) { + // any required modules inside node_modules are extracted to vendor return module.resource && /\.js$/.test(module.resource) && module.resource.indexOf(path.join(__dirname, '../node_modules')) === 0; }, }), - // extract webpack runtime and module manifest to its own file in order to // prevent vendor hash from being updated whenever app bundle is updated - new webpack.optimize.CommonsChunkPlugin({ chunks: ['vendor'], name: 'manifest' }), + new webpack.optimize.CommonsChunkPlugin({ + name: 'manifest', + chunks: ['vendor'], + }), ], }); @@ -81,4 +74,9 @@ if (config.build.productionGzip) { ); } +if (config.build.bundleAnalyzerReport) { + var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin; + webpackConfig.plugins.push(new BundleAnalyzerPlugin()); +} + module.exports = webpackConfig; diff --git a/build/webpack.test.conf.js b/build/webpack.test.conf.js new file mode 100644 index 0000000..5463855 --- /dev/null +++ b/build/webpack.test.conf.js @@ -0,0 +1,22 @@ +var baseConfig = require('./webpack.base.conf'); +var merge = require('webpack-merge'); +var utils = require('./utils'); +var webpack = require('webpack'); + +var webpackConfig = merge(baseConfig, { + // use inline sourcemap for karma-sourcemap-loader + module: { + rules: utils.styleLoaders(), + }, + devtool: '#inline-source-map', + plugins: [ + new webpack.DefinePlugin({ + 'process.env': require('../config/test.env') + }), + ], +}); + +// no need for app entry during tests +delete webpackConfig.entry; + +module.exports = webpackConfig; diff --git a/template/config/dev.env.js b/config/dev.env.js similarity index 100% rename from template/config/dev.env.js rename to config/dev.env.js diff --git a/config/index.js b/config/index.js new file mode 100644 index 0000000..f5de36e --- /dev/null +++ b/config/index.js @@ -0,0 +1,24 @@ +// see http://vuejs-templates.github.io/webpack for documentation. +var path = require('path'); + +module.exports = { + build: { + assetsPublicPath: '/themes/oc-vuetober-theme/assets/', + assetsRoot: path.resolve(__dirname, '../assets'), + assetsSubDirectory: 'static', + bundleAnalyzerReport: false, + env: require('./prod.env'), + productionGzip: false, + productionGzipExtensions: ['js', 'css'], + productionSourceMap: true, + }, + dev: { + assetsPublicPath: '/', + assetsSubDirectory: 'static', + autoOpenBrowser: true, + cssSourceMap: false, + env: require('./dev.env'), + port: 8080, + proxyTable: {}, + }, +}; diff --git a/template/config/prod.env.js b/config/prod.env.js similarity index 100% rename from template/config/prod.env.js rename to config/prod.env.js diff --git a/template/config/test.env.js b/config/test.env.js similarity index 100% rename from template/config/test.env.js rename to config/test.env.js diff --git a/meta.json b/meta.json deleted file mode 100644 index 285f35f..0000000 --- a/meta.json +++ /dev/null @@ -1,59 +0,0 @@ -{ - "prompts": { - "name": { - "type": "string", - "required": true, - "message": "Project name" - }, - "description": { - "type": "string", - "required": false, - "message": "Project description", - "default": "A Vue.js project" - }, - "author": { - "type": "string", - "message": "Author" - }, - "proxy": { - "type": "string", - "required": true, - "default": "http://vuetober.october.dev" - }, - "lint": { - "type": "confirm", - "message": "Use ESLint to lint your code?" - }, - "lintConfig": { - "when": "lint", - "type": "list", - "message": "Pick an ESLint preset", - "choices": [ - { - "name": "none (configure it yourself)", - "value": "none", - "short": "none" - }, - { - "name": "Standard (https://github.com/feross/standard)", - "value": "standard", - "short": "Standard" - }, - { - "name": "AirBNB (https://github.com/airbnb/javascript)", - "value": "airbnb", - "short": "AirBNB" - } - ] - }, - "unit": { - "type": "confirm", - "message": "Setup unit tests with Karma + Mocha?" - } - }, - "filters": { - ".eslintrc.js": "lint", - "test/unit/**/*": "unit" - }, - "completeMessage": "To get started:\n\n cd {{destDirName}}\n npm install\n npm run dev\n\nDocumentation can be found at https://vuejs-templates.github.io/webpack" -} diff --git a/npm-debug.log b/npm-debug.log deleted file mode 100644 index 940ff6b..0000000 --- a/npm-debug.log +++ /dev/null @@ -1,54 +0,0 @@ -0 info it worked if it ends with ok -1 verbose cli [ 'c:\\Program Files (x86)\\nodejs\\node.exe', -1 verbose cli 'c:\\Program Files (x86)\\nodejs\\node_modules\\npm\\bin\\npm-cli.js', -1 verbose cli 'uninstall', -1 verbose cli '--save-dev', -1 verbose cli 'vuex' ] -2 info using npm@3.6.0 -3 info using node@v5.6.0 -4 silly loadCurrentTree Starting -5 silly install loadCurrentTree -6 silly install readLocalPackageData -7 silly install normalizeTree -8 silly loadCurrentTree Finishing -9 silly loadIdealTree Starting -10 silly install loadIdealTree -11 silly cloneCurrentTree Starting -12 silly install cloneCurrentTreeToIdealTree -13 silly cloneCurrentTree Finishing -14 silly loadShrinkwrap Starting -15 silly install loadShrinkwrap -16 silly loadShrinkwrap Finishing -17 silly loadAllDepsIntoIdealTree Starting -18 silly uninstall loadAllDepsIntoIdealtree -19 verbose stack Error: Missing required argument #3 -19 verbose stack at replaceModule (c:\Program Files (x86)\nodejs\node_modules\npm\lib\install\deps.js:438:3) -19 verbose stack at c:\Program Files (x86)\nodejs\node_modules\npm\lib\install\deps.js:234:7 -19 verbose stack at Array.forEach (native) -19 verbose stack at exports.removeDeps (c:\Program Files (x86)\nodejs\node_modules\npm\lib\install\deps.js:230:8) -19 verbose stack at Array. (c:\Program Files (x86)\nodejs\node_modules\npm\node_modules\slide\lib\bind-actor.js:15:8) -19 verbose stack at LOOP (c:\Program Files (x86)\nodejs\node_modules\npm\node_modules\slide\lib\chain.js:15:14) -19 verbose stack at chain (c:\Program Files (x86)\nodejs\node_modules\npm\node_modules\slide\lib\chain.js:20:5) -19 verbose stack at Uninstaller.loadAllDepsIntoIdealTree (c:\Program Files (x86)\nodejs\node_modules\npm\lib\uninstall.js:72:3) -19 verbose stack at Array. (c:\Program Files (x86)\nodejs\node_modules\npm\node_modules\slide\lib\bind-actor.js:15:8) -19 verbose stack at LOOP (c:\Program Files (x86)\nodejs\node_modules\npm\node_modules\slide\lib\chain.js:15:14) -20 verbose cwd c:\wamp\www\october\oc-vuetober-theme\themes\oc-vuetober-theme -21 error Windows_NT 10.0.10586 -22 error argv "c:\\Program Files (x86)\\nodejs\\node.exe" "c:\\Program Files (x86)\\nodejs\\node_modules\\npm\\bin\\npm-cli.js" "uninstall" "--save-dev" "vuex" -23 error node v5.6.0 -24 error npm v3.6.0 -25 error code EMISSINGARG -26 error typeerror Error: Missing required argument #3 -26 error typeerror at replaceModule (c:\Program Files (x86)\nodejs\node_modules\npm\lib\install\deps.js:438:3) -26 error typeerror at c:\Program Files (x86)\nodejs\node_modules\npm\lib\install\deps.js:234:7 -26 error typeerror at Array.forEach (native) -26 error typeerror at exports.removeDeps (c:\Program Files (x86)\nodejs\node_modules\npm\lib\install\deps.js:230:8) -26 error typeerror at Array. (c:\Program Files (x86)\nodejs\node_modules\npm\node_modules\slide\lib\bind-actor.js:15:8) -26 error typeerror at LOOP (c:\Program Files (x86)\nodejs\node_modules\npm\node_modules\slide\lib\chain.js:15:14) -26 error typeerror at chain (c:\Program Files (x86)\nodejs\node_modules\npm\node_modules\slide\lib\chain.js:20:5) -26 error typeerror at Uninstaller.loadAllDepsIntoIdealTree (c:\Program Files (x86)\nodejs\node_modules\npm\lib\uninstall.js:72:3) -26 error typeerror at Array. (c:\Program Files (x86)\nodejs\node_modules\npm\node_modules\slide\lib\bind-actor.js:15:8) -26 error typeerror at LOOP (c:\Program Files (x86)\nodejs\node_modules\npm\node_modules\slide\lib\chain.js:15:14) -27 error typeerror This is an error with npm itself. Please report this error at: -27 error typeerror -28 verbose exit [ 1, true ] diff --git a/package.json b/package.json new file mode 100644 index 0000000..3162dfe --- /dev/null +++ b/package.json @@ -0,0 +1,83 @@ +{ + "name": "oc-vuetober-theme", + "version": "2.1.0", + "description": "An opinionated approach to single page applications within the wonderful worlds of Vue.js, October CMS, and Laravel.", + "author": "scott@scottbedard.net", + "private": true, + "scripts": { + "dev": "node build/dev-server.js", + "build": "node build/build.js", + "unit": "cross-env BABEL_ENV=test karma start test/unit/karma.conf.js --single-run", + "test": "npm run unit", + "lint": "eslint --ext .js,.vue src test/unit/specs --fix" + }, + "dependencies": { + "vue": "^2.1.10", + "vue-router": "^2.2.0" + }, + "devDependencies": { + "autoprefixer": "^6.7.2", + "babel-core": "^6.22.1", + "babel-eslint": "^7.1.1", + "babel-helper-vue-jsx-merge-props": "^2.0.2", + "babel-loader": "^6.2.10", + "babel-plugin-istanbul": "^3.1.2", + "babel-plugin-syntax-jsx": "^6.18.0", + "babel-plugin-transform-runtime": "^6.22.0", + "babel-plugin-transform-vue-jsx": "^3.3.0", + "babel-preset-es2015": "^6.22.0", + "babel-preset-stage-2": "^6.22.0", + "babel-register": "^6.22.0", + "browser-sync": "^2.18.7", + "chai": "^3.5.0", + "chalk": "^1.1.3", + "compression-webpack-plugin": "^0.3.2", + "connect-history-api-fallback": "^1.3.0", + "cross-env": "^3.1.4", + "css-loader": "^0.26.1", + "eslint": "^3.14.1", + "eslint-friendly-formatter": "^2.0.7", + "eslint-loader": "^1.6.1", + "eslint-plugin-html": "^2.0.0", + "eventsource-polyfill": "^0.9.6", + "express": "^4.14.1", + "extract-text-webpack-plugin": "^2.0.0-rc.2", + "file-loader": "^0.10.0", + "friendly-errors-webpack-plugin": "^1.1.3", + "function-bind": "^1.1.0", + "html-webpack-plugin": "^2.28.0", + "http-proxy-middleware": "^0.17.3", + "inject-loader": "^2.0.1", + "json-loader": "^0.5.4", + "karma": "^1.4.1", + "karma-coverage": "^1.1.1", + "karma-mocha": "^1.3.0", + "karma-phantomjs-launcher": "^1.0.2", + "karma-sinon-chai": "^1.2.4", + "karma-sourcemap-loader": "^0.3.7", + "karma-spec-reporter": "0.0.26", + "karma-webpack": "^2.0.2", + "lolex": "^1.5.2", + "mocha": "^3.2.0", + "opn": "^4.0.2", + "ora": "^1.1.0", + "phantomjs-prebuilt": "^2.1.14", + "semver": "^5.3.0", + "shelljs": "^0.7.6", + "sinon": "^1.17.7", + "sinon-chai": "^2.8.0", + "url-loader": "^0.5.7", + "vue-loader": "^10.3.0", + "vue-style-loader": "^2.0.0", + "vue-template-compiler": "^2.1.10", + "webpack": "^2.2.1", + "webpack-bundle-analyzer": "^2.2.1", + "webpack-dev-middleware": "^1.10.0", + "webpack-hot-middleware": "^2.16.1", + "webpack-merge": "^2.6.1" + }, + "engines": { + "node": ">= 4.0.0", + "npm": ">= 3.0.0" + } +} diff --git a/src/App.vue b/src/App.vue new file mode 100644 index 0000000..15704a4 --- /dev/null +++ b/src/App.vue @@ -0,0 +1,23 @@ + + + + + diff --git a/src/assets/logo.png b/src/assets/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..f3d2503fc2a44b5053b0837ebea6e87a2d339a43 GIT binary patch literal 6849 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 +
+

{{ msg }}

+

Essential Links

+ +

Ecosystem

+ +
+ + + + + + diff --git a/template/src/index.htm b/src/index.htm similarity index 53% rename from template/src/index.htm rename to src/index.htm index 53dbbfa..a34eae8 100644 --- a/template/src/index.htm +++ b/src/index.htm @@ -1,16 +1,18 @@ title = "Index" url = "/:all?*" -description = "Do not modify" is_hidden = 0 == +function onStart() +{ + $this['token'] = \Session::token(); +} +== - Vuetober - - + oc-vuetober-theme
diff --git a/src/main.js b/src/main.js new file mode 100644 index 0000000..994756c --- /dev/null +++ b/src/main.js @@ -0,0 +1,12 @@ +import Vue from 'vue'; +import App from './App'; +import router from './router'; + +console.log ('HELLO'); + +/* eslint-disable no-new */ +new Vue({ + el: '#app', + router, + render: h => h(App), +}); diff --git a/src/router/index.js b/src/router/index.js new file mode 100644 index 0000000..768fa74 --- /dev/null +++ b/src/router/index.js @@ -0,0 +1,16 @@ +import Vue from 'vue'; +import Router from 'vue-router'; + +Vue.use(Router); + +import Hello from 'components/Hello'; + +export default new Router({ + routes: [ + { + path: '/', + name: 'Hello', + component: Hello, + }, + ], +}); diff --git a/template/static/.gitkeep b/static/.gitkeep similarity index 100% rename from template/static/.gitkeep rename to static/.gitkeep diff --git a/template/.babelrc b/template/.babelrc deleted file mode 100644 index 41789ca..0000000 --- a/template/.babelrc +++ /dev/null @@ -1,5 +0,0 @@ -{ - "presets": ["es2015", "stage-2"], - "plugins": ["transform-runtime"], - "comments": false -} diff --git a/template/.eslintrc.js b/template/.eslintrc.js deleted file mode 100644 index 4132af3..0000000 --- a/template/.eslintrc.js +++ /dev/null @@ -1,31 +0,0 @@ -module.exports = { - root: true, - parser: 'babel-eslint', - parserOptions: { - sourceType: 'module', - }, - {{#if_eq lintConfig "standard"}} - // https://github.com/feross/standard/blob/master/RULES.md#javascript-standard-style - extends: 'standard', - {{/if_eq}} - {{#if_eq lintConfig "airbnb"}} - extends: 'airbnb-base', - {{/if_eq}} - plugins: [ - 'html', // required to lint *.vue files - ], - // add your custom rules here - 'rules': { - {{#if_eq lintConfig "standard"}} - // allow paren-less arrow functions - 'arrow-parens': 0, - // allow async-await - 'generator-star-spacing': 0, - {{/if_eq}} - {{#if_eq lintConfig "airbnb"}} - 'import/no-unresolved': 0, - {{/if_eq}} - // allow debugger during development - 'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0, - }, -}; diff --git a/template/README.md b/template/README.md deleted file mode 100644 index 9410e7a..0000000 --- a/template/README.md +++ /dev/null @@ -1,27 +0,0 @@ -# {{ name }} - -> {{ description }} - -## Build Setup - -``` bash -# install dependencies -npm install - -# serve with hot reload at localhost:8080 -npm run dev - -# build for production with minification -npm run build - -# run unit tests -npm run unit - -# run e2e tests -npm run e2e - -# run all tests -npm test -``` - -For detailed explanation on how things work, checkout the [guide](http://vuejs-templates.github.io/webpack/) and [docs for vue-loader](http://vuejs.github.io/vue-loader). diff --git a/template/build/webpack.base.conf.js b/template/build/webpack.base.conf.js deleted file mode 100644 index e7ed26e..0000000 --- a/template/build/webpack.base.conf.js +++ /dev/null @@ -1,95 +0,0 @@ -var config = require('../config'); -var path = require('path'); -var projectRoot = path.resolve(__dirname, '../'); -var utils = require('./utils'); - -module.exports = { - entry: { - app: './src/main.js', - }, - output: { - filename: '[name].js', - path: config.build.assetsRoot, - publicPath: process.env.NODE_ENV === 'production' ? config.build.assetsPublicPath : config.dev.assetsPublicPath, - }, - resolve: { - extensions: ['', '.js', '.vue'], - fallback: [path.join(__dirname, '../node_modules')], - alias: { - 'src': path.resolve(__dirname, '../src'), - 'assets': path.resolve(__dirname, '../src/assets'), - }, - }, - resolveLoader: { - fallback: [path.join(__dirname, '../node_modules')], - }, - sassLoader: { - includePaths: [ - path.resolve(__dirname, '../src/scss'), - path.resolve(__dirname, '../node_modules'), - ], - }, - module: { - {{#lint}} - preLoaders: [ - { - test: /\.vue$/, - loader: 'eslint', - include: projectRoot, - exclude: /node_modules/, - }, - { - test: /\.js$/, - loader: 'eslint', - include: projectRoot, - exclude: /node_modules/, - } - ], - {{/lint}} - loaders: [ - { - test: /\.vue$/, - loader: 'vue', - }, - { - test: /\.js$/, - loader: 'babel', - include: projectRoot, - exclude: /node_modules/, - }, - { - test: /\.json$/, - loader: 'json', - }, - { - test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, - loader: 'url', - query: { - limit: 10000, - name: utils.assetsPath('img/[name].[hash:7].[ext]'), - }, - }, - { - test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, - loader: 'url', - query: { - limit: 10000, - name: utils.assetsPath('fonts/[name].[hash:7].[ext]'), - }, - }, - ], - }, - {{#lint}} - eslint: { - formatter: require('eslint-friendly-formatter'), - }, - {{/lint}} - vue: { - loaders: utils.cssLoaders(), - postcss: [ - require('autoprefixer')({ - browsers: ['last 2 versions'] - }), - ], - }, -}; diff --git a/template/config/index.js b/template/config/index.js deleted file mode 100644 index 3891cd1..0000000 --- a/template/config/index.js +++ /dev/null @@ -1,32 +0,0 @@ -// see http://vuejs-templates.github.io/webpack for documentation. -var path = require('path'); - -module.exports = { - build: { - assetsPublicPath: '/themes/{{ name }}/assets/', - assetsRoot: path.resolve(__dirname, '../assets'), - assetsSubDirectory: 'static', - env: require('./prod.env'), - index: path.resolve(__dirname, '../pages/index.htm'), - // Gzip off by default as many popular static hosts such as - // Surge or Netlify already gzip all static assets for you. - // Before setting to `true`, make sure to: - // npm install --save-dev compression-webpack-plugin - productionGzip: false, - productionGzipExtensions: ['js', 'css'], - productionSourceMap: true, - }, - dev: { - assetsPublicPath: '/', - assetsSubDirectory: 'static', - // CSS Sourcemaps off by default because relative paths are "buggy" - // with this option, according to the CSS-Loader README - // (https://github.com/webpack/css-loader#sourcemaps) - // In our experience, they generally work as expected, - // just be aware of this issue when enabling this option. - cssSourceMap: false, - env: require('./dev.env'), - port: 8080, - proxyTable: {}, - }, -}; diff --git a/template/package.json b/template/package.json deleted file mode 100644 index bc47e4d..0000000 --- a/template/package.json +++ /dev/null @@ -1,87 +0,0 @@ -{ - "name": "{{ name }}", - "version": "1.0.0", - "description": "{{ description }}", - "author": "{{ author }}", - "private": true, - "scripts": { - "dev": "node build/dev-server.js", - {{#unit}}"test": "karma start test/unit/karma.conf.js --single-run", - {{/unit}}{{#lint}}"lint": "eslint --fix --ext .js,.vue src test/unit/specs test/e2e/specs", - {{/lint}}"build": "node build/build.js" - }, - "dependencies": { - "babel-runtime": "^6.0.0", - "vue": "^2.0.0-rc.4", - "vue-resource": "^0.9.3", - "vue-router": "^2.0.0-rc.4" - }, - "devDependencies": { - "autoprefixer": "^6.4.0", - "babel-core": "^6.0.0", - {{#lint}} - "babel-eslint": "^6.1.2", - {{/lint}} - "babel-loader": "^6.0.0", - "babel-plugin-transform-runtime": "^6.0.0", - "babel-preset-es2015": "^6.0.0", - "babel-preset-stage-2": "^6.0.0", - "babel-register": "^6.0.0", - "browser-sync": "^2.14.3", - "connect-history-api-fallback": "^1.1.0", - "css-loader": "^0.23.0", - {{#lint}} - "eslint": "^2.10.2", - "eslint-friendly-formatter": "^2.0.5", - "eslint-loader": "^1.3.0", - "eslint-plugin-html": "^1.3.0", - {{#if_eq lintConfig "standard"}} - "eslint-config-standard": "^5.1.0", - "eslint-plugin-promise": "^1.0.8", - "eslint-plugin-standard": "^1.3.2", - {{/if_eq}} - {{#if_eq lintConfig "airbnb"}} - "eslint-config-airbnb-base": "^3.0.1", - "eslint-plugin-import": "^1.8.1", - {{/if_eq}} - {{/lint}} - "eventsource-polyfill": "^0.9.6", - "express": "^4.13.3", - "extract-text-webpack-plugin": "^1.0.1", - "file-loader": "^0.8.4", - "function-bind": "^1.0.2", - "html-webpack-plugin": "^2.8.1", - "http-proxy-middleware": "^0.12.0", - "json-loader": "^0.5.4", - {{#unit}} - "karma": "^0.13.15", - "karma-coverage": "^0.5.5", - "karma-mocha": "^0.2.2", - "karma-phantomjs-launcher": "^1.0.0", - "karma-sinon-chai": "^1.2.0", - "karma-sourcemap-loader": "^0.3.7", - "karma-spec-reporter": "0.0.24", - "karma-webpack": "^1.7.0", - "lolex": "^1.4.0", - "mocha": "^2.4.5", - "chai": "^3.5.0", - "sinon": "^1.17.3", - "sinon-chai": "^2.8.0", - "inject-loader": "^2.0.1", - "isparta-loader": "^2.0.0", - "phantomjs-prebuilt": "^2.1.3", - {{/unit}} - "node-sass": "^3.8.0", - "normalize.scss": "^0.1.0", - "ora": "^0.2.0", - "sass-loader": "^4.0.1", - "shelljs": "^0.6.0", - "url-loader": "^0.5.7", - "vue-hot-reload-api": "^1.2.0", - "vue-loader": "^9.4.0", - "webpack": "^1.12.2", - "webpack-dev-middleware": "^1.4.0", - "webpack-hot-middleware": "^2.6.0", - "webpack-merge": "^0.8.3" - } -} diff --git a/template/src/app/boot.js b/template/src/app/boot.js deleted file mode 100644 index ed35c4b..0000000 --- a/template/src/app/boot.js +++ /dev/null @@ -1,10 +0,0 @@ -// -// Directives -// -require('./directives/linkable'){{#if_eq lintConfig "airbnb"}};{{/if_eq}} - -// -// Plugins -// -require('./plugins/resources'){{#if_eq lintConfig "airbnb"}};{{/if_eq}} -require('./plugins/router'){{#if_eq lintConfig "airbnb"}};{{/if_eq}} diff --git a/template/src/app/directives/linkable.js b/template/src/app/directives/linkable.js deleted file mode 100644 index feba9a8..0000000 --- a/template/src/app/directives/linkable.js +++ /dev/null @@ -1,26 +0,0 @@ -import Vue from 'vue'{{#if_eq lintConfig "airbnb"}};{{/if_eq}} - -Vue.directive('linkable', { - bind{{#if_eq lintConfig "standard"}} {{/if_eq}}(el, binding, vnode) { - const component = vnode.context{{#if_eq lintConfig "airbnb"}};{{/if_eq}} - -{{#if_eq lintConfig "airbnb"}} /* eslint-disable no-param-reassign */ -{{/if_eq}} - el.linkableClick = (e) => { - for (const clickedElement of e.path) { - if (clickedElement === el || clickedElement.tagName === 'A') { - if (clickedElement.hostname === window.location.hostname) { - e.preventDefault(){{#if_eq lintConfig "airbnb"}};{{/if_eq}} - component.$router.push(clickedElement.pathname){{#if_eq lintConfig "airbnb"}};{{/if_eq}} - } - break{{#if_eq lintConfig "airbnb"}};{{/if_eq}} - } - } - }{{#if_eq lintConfig "airbnb"}};{{/if_eq}} - - el.addEventListener('click', el.linkableClick){{#if_eq lintConfig "airbnb"}};{{/if_eq}} - }, - unbind{{#if_eq lintConfig "standard"}} {{/if_eq}}(el) { - el.removeEventListener('click', el.linkableClick){{#if_eq lintConfig "airbnb"}};{{/if_eq}} - }{{#if_eq lintConfig "airbnb"}},{{/if_eq}} -}){{#if_eq lintConfig "airbnb"}};{{/if_eq}} diff --git a/template/src/app/plugins/resources.js b/template/src/app/plugins/resources.js deleted file mode 100644 index 17ce006..0000000 --- a/template/src/app/plugins/resources.js +++ /dev/null @@ -1,22 +0,0 @@ -import Vue from 'vue'{{#if_eq lintConfig "airbnb"}};{{/if_eq}} -import VueResource from 'vue-resource'{{#if_eq lintConfig "airbnb"}};{{/if_eq}} - -Vue.use(VueResource){{#if_eq lintConfig "airbnb"}};{{/if_eq}} - -Vue.use({ - install{{#if_eq lintConfig "standard"}} {{/if_eq}}() { - Vue.prototype.$resources = this.resources{{#if_eq lintConfig "airbnb"}};{{/if_eq}} - }, - resources{{#if_eq lintConfig "standard"}} {{/if_eq}}(resources) { - const promises = []{{#if_eq lintConfig "airbnb"}};{{/if_eq}} - Object.keys(resources).forEach(key => { - const promise = resources[key]{{#if_eq lintConfig "airbnb"}};{{/if_eq}} - promise.then(({ data, body }) => { - // @todo: figure out why data is a string on the dev server - this[key] = typeof data === 'object' ? data : JSON.parse(body){{#if_eq lintConfig "airbnb"}};{{/if_eq}} - }){{#if_eq lintConfig "airbnb"}};{{/if_eq}} - promises.push(promise){{#if_eq lintConfig "airbnb"}};{{/if_eq}} - }){{#if_eq lintConfig "airbnb"}};{{/if_eq}} - return Promise.all(promises){{#if_eq lintConfig "airbnb"}};{{/if_eq}} - }{{#if_eq lintConfig "airbnb"}},{{/if_eq}} -}){{#if_eq lintConfig "airbnb"}};{{/if_eq}} diff --git a/template/src/app/plugins/router.js b/template/src/app/plugins/router.js deleted file mode 100644 index 1b48416..0000000 --- a/template/src/app/plugins/router.js +++ /dev/null @@ -1,4 +0,0 @@ -import Vue from 'vue'{{#if_eq lintConfig "airbnb"}};{{/if_eq}} -import VueRouter from 'vue-router'{{#if_eq lintConfig "airbnb"}};{{/if_eq}} - -Vue.use(VueRouter){{#if_eq lintConfig "airbnb"}};{{/if_eq}} diff --git a/template/src/app/routes.js b/template/src/app/routes.js deleted file mode 100644 index ed7e52c..0000000 --- a/template/src/app/routes.js +++ /dev/null @@ -1,43 +0,0 @@ -// -// Layouts -// -import SplashLayout from 'src/layouts/splash'{{#if_eq lintConfig "airbnb"}};{{/if_eq}} -import StandardLayout from 'src/layouts/standard'{{#if_eq lintConfig "airbnb"}};{{/if_eq}} - -// -// Pages -// -import BlogListPage from 'src/pages/blog/list'{{#if_eq lintConfig "airbnb"}};{{/if_eq}} -import BlogShowPage from 'src/pages/blog/show'{{#if_eq lintConfig "airbnb"}};{{/if_eq}} -import NotFoundPage from 'src/pages/404'{{#if_eq lintConfig "airbnb"}};{{/if_eq}} -import WelcomePage from 'src/pages/welcome'{{#if_eq lintConfig "airbnb"}};{{/if_eq}} - -// -// Routes -// -export default [ - - { - path: '', - component: SplashLayout, - children: [ - { path: '/welcome', component: WelcomePage }, - { path: '*', component: NotFoundPage }{{#if_eq lintConfig "airbnb"}},{{/if_eq}} - ]{{#if_eq lintConfig "airbnb"}},{{/if_eq}} - }, - - { - path: '', - component: StandardLayout, - children: [ - { path: '/blog', component: BlogListPage }, - { path: '/blog/:slug', name: 'blog/show', component: BlogShowPage }{{#if_eq lintConfig "airbnb"}},{{/if_eq}} - ]{{#if_eq lintConfig "airbnb"}},{{/if_eq}} - }, - - // - // - // Redirects - // - { path: '/', redirect: '/welcome' }{{#if_eq lintConfig "airbnb"}},{{/if_eq}} -]{{#if_eq lintConfig "airbnb"}};{{/if_eq}} diff --git a/template/src/assets/october.png b/template/src/assets/october.png deleted file mode 100644 index 4ce6a5469dd9bed753139cc2a1a0da8c6152b87f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12173 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 O0E%*IvQ^S%!T$kdiN|^X diff --git a/template/src/layouts/splash.vue b/template/src/layouts/splash.vue deleted file mode 100644 index a1d4cfc..0000000 --- a/template/src/layouts/splash.vue +++ /dev/null @@ -1,20 +0,0 @@ - - - diff --git a/template/src/layouts/standard.vue b/template/src/layouts/standard.vue deleted file mode 100644 index 3ca8bfd..0000000 --- a/template/src/layouts/standard.vue +++ /dev/null @@ -1,13 +0,0 @@ - - - diff --git a/template/src/main.js b/template/src/main.js deleted file mode 100644 index 814cbf0..0000000 --- a/template/src/main.js +++ /dev/null @@ -1,28 +0,0 @@ -import Vue from 'vue'{{#if_eq lintConfig "airbnb"}};{{/if_eq}} -import VueRouter from 'vue-router'{{#if_eq lintConfig "airbnb"}};{{/if_eq}} -import RootComponent from './root'{{#if_eq lintConfig "airbnb"}};{{/if_eq}} -import routes from './app/routes'{{#if_eq lintConfig "airbnb"}};{{/if_eq}} - -// -// Configure Vue utilities and plugins -// -require('./app/boot'){{#if_eq lintConfig "airbnb"}};{{/if_eq}} - -// -// Configure the router -// -const router = new VueRouter({ - base: __dirname, - mode: 'history', - routes{{#if_eq lintConfig "airbnb"}},{{/if_eq}} -}){{#if_eq lintConfig "airbnb"}};{{/if_eq}} - -// -// Launch the application -// -/* eslint-disable no-new */ -new Vue({ - router, - el: '#app', - render: h => h(RootComponent){{#if_eq lintConfig "airbnb"}},{{/if_eq}} -}){{#if_eq lintConfig "airbnb"}};{{/if_eq}} diff --git a/template/src/pages/404.vue b/template/src/pages/404.vue deleted file mode 100644 index 5d199fc..0000000 --- a/template/src/pages/404.vue +++ /dev/null @@ -1,10 +0,0 @@ - - - diff --git a/template/src/pages/blog/list.vue b/template/src/pages/blog/list.vue deleted file mode 100644 index ce35eb5..0000000 --- a/template/src/pages/blog/list.vue +++ /dev/null @@ -1,58 +0,0 @@ - - - - - diff --git a/template/src/pages/blog/show.vue b/template/src/pages/blog/show.vue deleted file mode 100644 index 99cbe44..0000000 --- a/template/src/pages/blog/show.vue +++ /dev/null @@ -1,36 +0,0 @@ - - - - - diff --git a/template/src/pages/welcome.vue b/template/src/pages/welcome.vue deleted file mode 100644 index bb70d95..0000000 --- a/template/src/pages/welcome.vue +++ /dev/null @@ -1,38 +0,0 @@ - - - diff --git a/template/src/resources/blog.js b/template/src/resources/blog.js deleted file mode 100644 index 6a1310d..0000000 --- a/template/src/resources/blog.js +++ /dev/null @@ -1,10 +0,0 @@ -import Vue from 'vue'{{#if_eq lintConfig "airbnb"}};{{/if_eq}} - -export default { - getPost{{#if_eq lintConfig "standard"}} {{/if_eq}}({ slug }) { - return Vue.http.get(`/api/rainlab/blog/${slug}`){{#if_eq lintConfig "airbnb"}};{{/if_eq}} - }, - getPosts{{#if_eq lintConfig "standard"}} {{/if_eq}}() { - return Vue.http.get('/api/rainlab/blog'){{#if_eq lintConfig "airbnb"}};{{/if_eq}} - }{{#if_eq lintConfig "airbnb"}},{{/if_eq}} -}{{#if_eq lintConfig "airbnb"}};{{/if_eq}} diff --git a/template/src/root.vue b/template/src/root.vue deleted file mode 100644 index c15c731..0000000 --- a/template/src/root.vue +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/template/src/scss/classes/transitions.scss b/template/src/scss/classes/transitions.scss deleted file mode 100644 index 0364fab..0000000 --- a/template/src/scss/classes/transitions.scss +++ /dev/null @@ -1,9 +0,0 @@ -.fade-enter-active, -.fade-leave-active { - transition: opacity .2s ease; -} - -.fade-enter, -.fade-leave-active { - opacity: 0 -} diff --git a/template/src/scss/core.scss b/template/src/scss/core.scss deleted file mode 100644 index e6eec33..0000000 --- a/template/src/scss/core.scss +++ /dev/null @@ -1,4 +0,0 @@ -// -// Variables -// -$vue-green: #41b883; diff --git a/template/src/scss/elements/html_body.scss b/template/src/scss/elements/html_body.scss deleted file mode 100644 index 7c981d4..0000000 --- a/template/src/scss/elements/html_body.scss +++ /dev/null @@ -1,14 +0,0 @@ -html { - box-sizing: border-box; - height: 100%; - - *, - *:before, - *:after { - box-sizing: inherit; - } -} - -body { - font-family: 'Open Sans', sans-serif; -} diff --git a/template/src/scss/global.scss b/template/src/scss/global.scss deleted file mode 100644 index 05cf773..0000000 --- a/template/src/scss/global.scss +++ /dev/null @@ -1,15 +0,0 @@ -// -// Dependencies -// -@import 'core'; -@import 'normalize.scss/normalize.scss'; - -// -// Classes -// -@import './classes/transitions'; - -// -// Elements -// -@import './elements/html_body'; diff --git a/template/test/unit/.eslintrc b/template/test/unit/.eslintrc deleted file mode 100644 index 08715cf..0000000 --- a/template/test/unit/.eslintrc +++ /dev/null @@ -1,9 +0,0 @@ -{ - "env": { - "mocha": true - }, - "globals": { - "expect": true, - "sinon": true - } -} diff --git a/template/test/unit/index.js b/template/test/unit/index.js deleted file mode 100644 index b9d4cc1..0000000 --- a/template/test/unit/index.js +++ /dev/null @@ -1,16 +0,0 @@ -// Polyfill fn.bind() for PhantomJS -/* eslint-disable no-extend-native */ -Function.prototype.bind = require('function-bind'); - -// use the vue-router plugin -require('src/app/boot'); - -// require all test files (files that ends with .spec.js) -var testsContext = require.context('./specs', true, /\.spec$/); -testsContext.keys().forEach(testsContext); - -// require all src files except main.js for coverage. -// you can also change this to match only the subset of files that -// you want coverage for. -var srcContext = require.context('../../src', true, /^\.\/(?!main(\.js)?$)(.*)(\.vue$|\.js$)/); -srcContext.keys().forEach(srcContext); diff --git a/template/test/unit/karma.conf.js b/template/test/unit/karma.conf.js deleted file mode 100644 index 17f7665..0000000 --- a/template/test/unit/karma.conf.js +++ /dev/null @@ -1,76 +0,0 @@ -// This is a karma config file. For more details see -// http://karma-runner.github.io/0.13/config/configuration-file.html -// we are also using it with karma-webpack -// https://github.com/webpack/karma-webpack - -var path = require('path') -var merge = require('webpack-merge') -var baseConfig = require('../../build/webpack.base.conf') -var utils = require('../../build/utils') -var webpack = require('webpack') -var projectRoot = path.resolve(__dirname, '../../') - -var webpackConfig = merge(baseConfig, { - // use inline sourcemap for karma-sourcemap-loader - module: { - loaders: utils.styleLoaders(), - }, - devtool: '#inline-source-map', - vue: { - loaders: { - js: 'isparta', - }, - }, - plugins: [ - new webpack.DefinePlugin({ - 'process.env': require('../../config/test.env'), - }), - ], -}); - -// no need for app entry during tests -delete webpackConfig.entry; - -// make sure isparta loader is applied before eslint -webpackConfig.module.preLoaders = webpackConfig.module.preLoaders || []; -webpackConfig.module.preLoaders.unshift({ - include: path.resolve(projectRoot, 'src'), - loader: 'isparta', - test: /\.js$/, -}); - -// only apply babel for test files when using isparta -webpackConfig.module.loaders.some(function (loader, i) { - if (loader.loader === 'babel') { - loader.include = path.resolve(projectRoot, 'test/unit'); - - return true; - } -}); - -module.exports = function (config) { - config.set({ - // to run in additional browsers: - // 1. install corresponding karma launcher - // http://karma-runner.github.io/0.13/config/browsers.html - // 2. add it to the `browsers` array below. - browsers: ['PhantomJS'], - frameworks: ['mocha', 'sinon-chai'], - reporters: ['spec', 'coverage'], - files: ['./index.js'], - preprocessors: { - './index.js': ['webpack', 'sourcemap'], - }, - webpack: webpackConfig, - webpackMiddleware: { - noInfo: true, - }, - coverageReporter: { - dir: './coverage', - reporters: [ - { type: 'lcov', subdir: '.' }, - { type: 'text-summary' }, - ], - }, - }); -}; diff --git a/template/test/unit/specs/welcome.spec.js b/template/test/unit/specs/welcome.spec.js deleted file mode 100644 index aae73da..0000000 --- a/template/test/unit/specs/welcome.spec.js +++ /dev/null @@ -1,17 +0,0 @@ -import Vue from 'vue'; -import VueRouter from 'vue'; -import WelcomeComponent from 'src/pages/welcome'; - -Vue.use(VueRouter); - -describe('welcome.vue', () => { - it('should render correct welcome content', () => { - const vm = new Vue({ - render: (h) => h(WelcomeComponent), - el: document.createElement('div'), - router: new VueRouter({ abstract: true }), - }); - - expect(vm.$el.querySelector('h1').textContent).to.equal('Welcome to your new Vuetober theme!'); - }); -}); diff --git a/template/theme.yaml b/template/theme.yaml deleted file mode 100644 index 5903ae9..0000000 --- a/template/theme.yaml +++ /dev/null @@ -1,3 +0,0 @@ -name: '{{ name }}' -description: '{{ description }}' -author: '{{ author }}' diff --git a/test/unit/.eslintrc b/test/unit/.eslintrc new file mode 100644 index 0000000..959a4f4 --- /dev/null +++ b/test/unit/.eslintrc @@ -0,0 +1,9 @@ +{ + "env": { + "mocha": true + }, + "globals": { + "expect": true, + "sinon": true + } +} diff --git a/test/unit/index.js b/test/unit/index.js new file mode 100644 index 0000000..e522b35 --- /dev/null +++ b/test/unit/index.js @@ -0,0 +1,16 @@ +// Polyfill fn.bind() for PhantomJS +/* eslint-disable no-extend-native */ +Function.prototype.bind = require('function-bind'); + +// require all test files (files that ends with .spec.js) +const testsContext = require.context('./specs', true, /\.spec$/); +testsContext.keys().forEach(testsContext); + +// require all files that should be included in code coverage +let coverageBlacklist = [ + './index.htm', + './main.js', +]; + +var srcContext = require.context('../../src', true, /^\.\/(.*)(\.vue$|\.js$)/); +srcContext.keys().filter(file => coverageBlacklist.indexOf(file) === -1).forEach(srcContext); diff --git a/test/unit/karma.conf.js b/test/unit/karma.conf.js new file mode 100644 index 0000000..3211fb6 --- /dev/null +++ b/test/unit/karma.conf.js @@ -0,0 +1,33 @@ +// This is a karma config file. For more details see +// http://karma-runner.github.io/0.13/config/configuration-file.html +// we are also using it with karma-webpack +// https://github.com/webpack/karma-webpack + +var webpackConfig = require('../../build/webpack.test.conf') + +module.exports = function (config) { + config.set({ + // to run in additional browsers: + // 1. install corresponding karma launcher + // http://karma-runner.github.io/0.13/config/browsers.html + // 2. add it to the `browsers` array below. + browsers: ['PhantomJS'], + frameworks: ['mocha', 'sinon-chai'], + reporters: ['spec', 'coverage'], + files: ['./index.js'], + preprocessors: { + './index.js': ['webpack', 'sourcemap'] + }, + webpack: webpackConfig, + webpackMiddleware: { + noInfo: true + }, + coverageReporter: { + dir: './coverage', + reporters: [ + { type: 'lcov', subdir: '.' }, + { type: 'text-summary' } + ] + } + }) +} diff --git a/test/unit/specs/Hello.spec.js b/test/unit/specs/Hello.spec.js new file mode 100644 index 0000000..b089a85 --- /dev/null +++ b/test/unit/specs/Hello.spec.js @@ -0,0 +1,13 @@ +import Vue from 'vue'; +import Hello from 'src/components/Hello'; + +describe('Hello.vue', () => { + it('should render correct contents', () => { + const vm = new Vue({ + el: document.createElement('div'), + render: (h) => h(Hello), + }); + expect(vm.$el.querySelector('.hello h1').textContent) + .to.equal('Welcome to Your Vue.js App'); + }); +}); diff --git a/theme.yaml b/theme.yaml new file mode 100644 index 0000000..4bce874 --- /dev/null +++ b/theme.yaml @@ -0,0 +1,3 @@ +name: 'Vuetober' +description: 'An opinionated approach to single page applications within the wonderful worlds of Vue.js, October CMS, and Laravel.' +author: 'scott@scottbedard.net' From 3142ca7165ae7dd60027852e422f0388e0e98950 Mon Sep 17 00:00:00 2001 From: Scott Bedard Date: Mon, 6 Feb 2017 09:19:27 -0700 Subject: [PATCH 02/31] Setup new project wizard --- build/dev-server.js | 4 +--- build/setup.js | 47 +++++++++++++++++++++++++++++++++++++++++++++ package.json | 8 +++++--- 3 files changed, 53 insertions(+), 6 deletions(-) create mode 100644 build/setup.js diff --git a/build/dev-server.js b/build/dev-server.js index 83f3697..cfb8bc6 100644 --- a/build/dev-server.js +++ b/build/dev-server.js @@ -72,9 +72,7 @@ app.use(staticPath, express.static('./static')); // browser sync browserSync({ - proxy: { - target: "http://vuetober.october.dev", - }, + proxy: 'http://vuetober.october.dev', open: false, middleware: [ devMiddleware, diff --git a/build/setup.js b/build/setup.js new file mode 100644 index 0000000..1d915c6 --- /dev/null +++ b/build/setup.js @@ -0,0 +1,47 @@ +var fs = require('fs'); +var path = require('path'); +var prompt = require('prompt'); + +prompt.message = false; + +var themeDirectory = path.basename(path.resolve(__dirname, '..')); + +var schema = { + properties: { + name: { + description: 'Theme name', + default: themeDirectory, + required: true, + }, + description: { + description: 'Theme description', + required: false, + }, + author: { + description: 'Theme author', + required: false, + }, + url: { + description: 'Development url', + required: true, + }, + }, +}; + +prompt.start(); + +prompt.get(schema, function (err, result) { + // create our theme.yaml file + var theme = 'name: \'' + result.name + '\'\n' + + 'description: \'' + result.description + '\'\n' + + 'author: \'' + result.author + '\''; + + fs.writeFileSync(path.resolve(__dirname, '../theme.yaml'), theme); + + // update our dev-server to use the correct url and directory + var devServer = fs.readFileSync(path.resolve(__dirname, './dev-server.js'), 'utf8') + .replace(/oc-vuetober-theme/g, themeDirectory) + .replace(/http:\/\/vuetober\.october\.dev/g, result.url); + + fs.writeFileSync(path.resolve(__dirname, './dev-server.js'), devServer); +}); diff --git a/package.json b/package.json index 3162dfe..c9db94f 100644 --- a/package.json +++ b/package.json @@ -5,11 +5,12 @@ "author": "scott@scottbedard.net", "private": true, "scripts": { - "dev": "node build/dev-server.js", "build": "node build/build.js", - "unit": "cross-env BABEL_ENV=test karma start test/unit/karma.conf.js --single-run", + "dev": "node build/dev-server.js", + "lint": "eslint --ext .js,.vue src test/unit/specs --fix", + "setup": "node build/setup.js", "test": "npm run unit", - "lint": "eslint --ext .js,.vue src test/unit/specs --fix" + "unit": "cross-env BABEL_ENV=test karma start test/unit/karma.conf.js --single-run" }, "dependencies": { "vue": "^2.1.10", @@ -62,6 +63,7 @@ "opn": "^4.0.2", "ora": "^1.1.0", "phantomjs-prebuilt": "^2.1.14", + "prompt": "^1.0.0", "semver": "^5.3.0", "shelljs": "^0.7.6", "sinon": "^1.17.7", From 0b103d6323aecdfa86097c0c034dc17200cd1abd Mon Sep 17 00:00:00 2001 From: scottbedard Date: Mon, 6 Feb 2017 17:46:59 -0700 Subject: [PATCH 03/31] Update dev port --- build/dev-server.js | 4 ++-- config/index.js | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/build/dev-server.js b/build/dev-server.js index cfb8bc6..89636a7 100644 --- a/build/dev-server.js +++ b/build/dev-server.js @@ -16,7 +16,7 @@ var webpackConfig = process.env.NODE_ENV === 'testing' : require('./webpack.dev.conf'); // default port where dev server listens for incoming traffic -var port = process.env.PORT || config.dev.port; +var port = process.env.PORT; // automatically open browser, if not set will be false var autoOpenBrowser = !!config.dev.autoOpenBrowser; @@ -94,7 +94,7 @@ browserSync({ ], }); -var uri = 'http://localhost:' + port; +var uri = 'http://localhost:3000'; devMiddleware.waitUntilValid(function () { console.log('> Listening at ' + uri + '\n'); diff --git a/config/index.js b/config/index.js index f5de36e..65d80f9 100644 --- a/config/index.js +++ b/config/index.js @@ -18,7 +18,6 @@ module.exports = { autoOpenBrowser: true, cssSourceMap: false, env: require('./dev.env'), - port: 8080, proxyTable: {}, }, }; From faedc95a8314596ee1ba246ad7fe5181be3c6eb8 Mon Sep 17 00:00:00 2001 From: Scott Bedard Date: Tue, 7 Feb 2017 07:42:19 -0700 Subject: [PATCH 04/31] Begin setting up scss --- build/webpack.base.conf.js | 8 ++++-- package.json | 3 ++ scss/core.scss | 3 ++ scss/elements/html_body.scss | 15 ++++++++++ scss/global.scss | 14 ++++++++++ src/App.vue | 23 ---------------- src/components/Hello.vue | 53 ------------------------------------ src/index.htm | 7 +++++ src/main.js | 8 ++---- src/root.vue | 9 ++++++ src/router/index.js | 16 ----------- 11 files changed, 58 insertions(+), 101 deletions(-) create mode 100644 scss/core.scss create mode 100644 scss/elements/html_body.scss create mode 100644 scss/global.scss delete mode 100644 src/App.vue delete mode 100644 src/components/Hello.vue create mode 100644 src/root.vue delete mode 100644 src/router/index.js diff --git a/build/webpack.base.conf.js b/build/webpack.base.conf.js index baf2c1a..b71ef8f 100644 --- a/build/webpack.base.conf.js +++ b/build/webpack.base.conf.js @@ -1,8 +1,9 @@ -var path = require('path'); -var utils = require('./utils'); var config = require('../config'); var eslintFriendlyFormatter = require('eslint-friendly-formatter'); var isProduction = process.env.NODE_ENV === 'production'; +var path = require('path'); +var utils = require('./utils'); +var webpack = require('webpack'); function resolve (dir) { return path.join(__dirname, '..', dir); @@ -20,9 +21,10 @@ module.exports = { : config.dev.assetsPublicPath, }, resolve: { - extensions: ['.js', '.vue', '.json'], + extensions: ['.js', '.vue', '.json', '.scss'], modules: [ resolve('src'), + resolve('scss'), resolve('node_modules'), ], alias: { diff --git a/package.json b/package.json index c9db94f..779cb3b 100644 --- a/package.json +++ b/package.json @@ -60,10 +60,13 @@ "karma-webpack": "^2.0.2", "lolex": "^1.5.2", "mocha": "^3.2.0", + "node-sass": "^4.5.0", + "normalize.scss": "^0.1.0", "opn": "^4.0.2", "ora": "^1.1.0", "phantomjs-prebuilt": "^2.1.14", "prompt": "^1.0.0", + "sass-loader": "^5.0.0", "semver": "^5.3.0", "shelljs": "^0.7.6", "sinon": "^1.17.7", diff --git a/scss/core.scss b/scss/core.scss new file mode 100644 index 0000000..4ffff5d --- /dev/null +++ b/scss/core.scss @@ -0,0 +1,3 @@ +// This file is used as a single include point for all of +// your scss that does not output any css. These might +// include variables, mixins, and functions, etc... diff --git a/scss/elements/html_body.scss b/scss/elements/html_body.scss new file mode 100644 index 0000000..2ef44ff --- /dev/null +++ b/scss/elements/html_body.scss @@ -0,0 +1,15 @@ +html { + box-sizing: border-box; + height: 100%; + + *, + *:before, + *:after { + box-sizing: inherit; + } +} + +body { + font-family: 'Open Sans', sans-serif; + min-height: 100%; +} diff --git a/scss/global.scss b/scss/global.scss new file mode 100644 index 0000000..5fe65a4 --- /dev/null +++ b/scss/global.scss @@ -0,0 +1,14 @@ +// This file should reference all of our global styles +// that output css. It should be included only from +// root component from a non-scoped style block. + +// +// Dependencies +// +@import './core'; +@import '~normalize.scss/normalize.scss'; // @todo: remove tilde when node_modules is included in paths + +// +// Elements +// +@import './elements/html_body'; diff --git a/src/App.vue b/src/App.vue deleted file mode 100644 index 15704a4..0000000 --- a/src/App.vue +++ /dev/null @@ -1,23 +0,0 @@ - - - - - diff --git a/src/components/Hello.vue b/src/components/Hello.vue deleted file mode 100644 index bbdda76..0000000 --- a/src/components/Hello.vue +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - diff --git a/src/index.htm b/src/index.htm index a34eae8..d2db850 100644 --- a/src/index.htm +++ b/src/index.htm @@ -11,7 +11,14 @@ + + + + + + + oc-vuetober-theme diff --git a/src/main.js b/src/main.js index 994756c..4e35397 100644 --- a/src/main.js +++ b/src/main.js @@ -1,12 +1,8 @@ import Vue from 'vue'; -import App from './App'; -import router from './router'; - -console.log ('HELLO'); +import RootComponent from './root'; /* eslint-disable no-new */ new Vue({ + render: h => h(RootComponent), el: '#app', - router, - render: h => h(App), }); diff --git a/src/root.vue b/src/root.vue new file mode 100644 index 0000000..d53c693 --- /dev/null +++ b/src/root.vue @@ -0,0 +1,9 @@ + + + diff --git a/src/router/index.js b/src/router/index.js deleted file mode 100644 index 768fa74..0000000 --- a/src/router/index.js +++ /dev/null @@ -1,16 +0,0 @@ -import Vue from 'vue'; -import Router from 'vue-router'; - -Vue.use(Router); - -import Hello from 'components/Hello'; - -export default new Router({ - routes: [ - { - path: '/', - name: 'Hello', - component: Hello, - }, - ], -}); From eb3f15f550e12d4d73841aa6017ff8d1e07c40f4 Mon Sep 17 00:00:00 2001 From: Scott Bedard Date: Tue, 7 Feb 2017 07:44:02 -0700 Subject: [PATCH 05/31] Autofix js coding style --- build/webpack.base.conf.js | 1 + 1 file changed, 1 insertion(+) diff --git a/build/webpack.base.conf.js b/build/webpack.base.conf.js index b71ef8f..ef502ff 100644 --- a/build/webpack.base.conf.js +++ b/build/webpack.base.conf.js @@ -41,6 +41,7 @@ module.exports = { enforce: "pre", include: [resolve('src'), resolve('test')], options: { + fix: true, formatter: eslintFriendlyFormatter, }, }, From 51bef32ccc34b062a5fff8b993736c0d4ec4f995 Mon Sep 17 00:00:00 2001 From: Scott Bedard Date: Tue, 7 Feb 2017 08:02:36 -0700 Subject: [PATCH 06/31] Downgrade sass-loader to 4.x and set default paths --- build/webpack.base.conf.js | 12 ++++++++++++ package.json | 2 +- scss/global.scss | 4 ++-- src/root.vue | 5 ++--- 4 files changed, 17 insertions(+), 6 deletions(-) diff --git a/build/webpack.base.conf.js b/build/webpack.base.conf.js index ef502ff..b6edcc3 100644 --- a/build/webpack.base.conf.js +++ b/build/webpack.base.conf.js @@ -87,4 +87,16 @@ module.exports = { }, ], }, + plugins: [ + new webpack.LoaderOptionsPlugin({ + options: { + sassLoader: { + includePaths: [ + path.resolve(__dirname, '../scss'), + path.resolve(__dirname, '../node_modules'), + ], + }, + }, + }), + ], }; diff --git a/package.json b/package.json index 779cb3b..3d65590 100644 --- a/package.json +++ b/package.json @@ -66,7 +66,7 @@ "ora": "^1.1.0", "phantomjs-prebuilt": "^2.1.14", "prompt": "^1.0.0", - "sass-loader": "^5.0.0", + "sass-loader": "^4.1.1", "semver": "^5.3.0", "shelljs": "^0.7.6", "sinon": "^1.17.7", diff --git a/scss/global.scss b/scss/global.scss index 5fe65a4..a91f047 100644 --- a/scss/global.scss +++ b/scss/global.scss @@ -5,8 +5,8 @@ // // Dependencies // -@import './core'; -@import '~normalize.scss/normalize.scss'; // @todo: remove tilde when node_modules is included in paths +@import 'core'; +@import 'normalize.scss/normalize.scss'; // // Elements diff --git a/src/root.vue b/src/root.vue index d53c693..9bc4ad5 100644 --- a/src/root.vue +++ b/src/root.vue @@ -1,6 +1,5 @@ - + +