├── app ├── fonts │ └── .gitkeep ├── styles │ └── popup.scss ├── images │ ├── icon-128.png │ ├── icon-16.png │ ├── icon-19.png │ └── icon-38.png ├── scripts │ ├── popup.js │ └── background.js ├── pages │ └── popup.html ├── component │ ├── hello.vue │ └── app.vue ├── _locales │ └── en │ │ └── messages.json └── manifest.json ├── .gitattributes ├── .babelrc ├── tasks ├── default.js ├── clean.js ├── vue.js ├── build.js ├── pages.js ├── locales.js ├── fonts.js ├── images.js ├── manifest.js ├── pack.js ├── lib │ ├── args.js │ └── applyBrowserPrefixesFor.js ├── version.js ├── chromereload.js ├── styles.js └── scripts.js ├── .gitignore ├── promo ├── Screenshot_640x400.png ├── Screenshot_1280x800.png ├── Promo-Image-Large_920x680.png ├── Promo-Image-Small_440x280.png ├── Chrome-Webstore-Icon_128x128.png └── Promo-Image-Marquee_1400x560.png ├── gulpfile.babel.js ├── .eslintrc ├── .editorconfig ├── LICENSE ├── package.json └── README.md /app/fonts/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015"] 3 | } 4 | -------------------------------------------------------------------------------- /app/styles/popup.scss: -------------------------------------------------------------------------------- 1 | @import "../../node_modules/bulma/bulma.sass"; 2 | -------------------------------------------------------------------------------- /tasks/default.js: -------------------------------------------------------------------------------- 1 | import gulp from 'gulp'; 2 | 3 | gulp.task('default', ['build']); 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | .DS_Store 3 | 4 | node_modules 5 | npm-debug.log 6 | 7 | dist/ 8 | packages/ 9 | -------------------------------------------------------------------------------- /app/images/icon-128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beupgo/vue-chrome-extension-example/HEAD/app/images/icon-128.png -------------------------------------------------------------------------------- /app/images/icon-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beupgo/vue-chrome-extension-example/HEAD/app/images/icon-16.png -------------------------------------------------------------------------------- /app/images/icon-19.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beupgo/vue-chrome-extension-example/HEAD/app/images/icon-19.png -------------------------------------------------------------------------------- /app/images/icon-38.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beupgo/vue-chrome-extension-example/HEAD/app/images/icon-38.png -------------------------------------------------------------------------------- /promo/Screenshot_640x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beupgo/vue-chrome-extension-example/HEAD/promo/Screenshot_640x400.png -------------------------------------------------------------------------------- /promo/Screenshot_1280x800.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beupgo/vue-chrome-extension-example/HEAD/promo/Screenshot_1280x800.png -------------------------------------------------------------------------------- /promo/Promo-Image-Large_920x680.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beupgo/vue-chrome-extension-example/HEAD/promo/Promo-Image-Large_920x680.png -------------------------------------------------------------------------------- /promo/Promo-Image-Small_440x280.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beupgo/vue-chrome-extension-example/HEAD/promo/Promo-Image-Small_440x280.png -------------------------------------------------------------------------------- /promo/Chrome-Webstore-Icon_128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beupgo/vue-chrome-extension-example/HEAD/promo/Chrome-Webstore-Icon_128x128.png -------------------------------------------------------------------------------- /promo/Promo-Image-Marquee_1400x560.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beupgo/vue-chrome-extension-example/HEAD/promo/Promo-Image-Marquee_1400x560.png -------------------------------------------------------------------------------- /gulpfile.babel.js: -------------------------------------------------------------------------------- 1 | import requireDir from 'require-dir'; 2 | 3 | // Check out the tasks directory 4 | // if you want to modify tasks! 5 | requireDir('./tasks'); 6 | -------------------------------------------------------------------------------- /tasks/clean.js: -------------------------------------------------------------------------------- 1 | import gulp from 'gulp'; 2 | import del from 'del'; 3 | import args from './lib/args'; 4 | 5 | gulp.task('clean', () => { 6 | return del(`dist/${args.vendor}/**/*`); 7 | }); 8 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true 4 | }, 5 | "globals": { 6 | "chrome": true, 7 | "crypto": true 8 | }, 9 | "parser": "babel-eslint", 10 | "rules": { 11 | "strict": 0 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /app/scripts/popup.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import App from '../component/app.vue'; 3 | 4 | var app=new Vue({ 5 | el:'#app', 6 | data:{ 7 | name:'vue-chrome-extension' 8 | }, 9 | render: h =>h(App) 10 | }) 11 | -------------------------------------------------------------------------------- /tasks/vue.js: -------------------------------------------------------------------------------- 1 | import gulp from 'gulp'; 2 | import vueify from 'gulp-vueify'; 3 | 4 | 5 | gulp.task('vue', function () { 6 | return gulp.src('app/component/**/*.vue') 7 | .pipe(vueify()) 8 | .pipe(gulp.dest('app/component/')); 9 | }); 10 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false 13 | -------------------------------------------------------------------------------- /app/scripts/background.js: -------------------------------------------------------------------------------- 1 | // Enable chromereload by uncommenting this line: 2 | // import 'chromereload/devonly'; 3 | 4 | chrome.runtime.onInstalled.addListener(function (details) { 5 | console.log('previousVersion', details.previousVersion); 6 | }); 7 | 8 | chrome.browserAction.setBadgeText({text: ''}); 9 | -------------------------------------------------------------------------------- /tasks/build.js: -------------------------------------------------------------------------------- 1 | import gulp from 'gulp'; 2 | import gulpSequence from 'gulp-sequence'; 3 | 4 | gulp.task('build', gulpSequence( 5 | 'clean', [ 6 | 'manifest', 7 | 'scripts', 8 | 'styles', 9 | 'pages', 10 | 'locales', 11 | 'images', 12 | 'fonts', 13 | 'chromereload' 14 | ] 15 | )); 16 | -------------------------------------------------------------------------------- /app/pages/popup.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Popup 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /tasks/pages.js: -------------------------------------------------------------------------------- 1 | import gulp from 'gulp'; 2 | import gulpif from 'gulp-if'; 3 | import livereload from 'gulp-livereload'; 4 | import args from './lib/args'; 5 | 6 | gulp.task('pages', () => { 7 | return gulp.src('app/pages/**/*.html') 8 | .pipe(gulp.dest(`dist/${args.vendor}/pages`)) 9 | .pipe(gulpif(args.watch, livereload())); 10 | }); 11 | -------------------------------------------------------------------------------- /tasks/locales.js: -------------------------------------------------------------------------------- 1 | import gulp from 'gulp'; 2 | import gulpif from 'gulp-if'; 3 | import livereload from 'gulp-livereload'; 4 | import args from './lib/args'; 5 | 6 | gulp.task('locales', () => { 7 | return gulp.src('app/_locales/**/*.json') 8 | .pipe(gulp.dest(`dist/${args.vendor}/_locales`)) 9 | .pipe(gulpif(args.watch, livereload())); 10 | }); 11 | -------------------------------------------------------------------------------- /tasks/fonts.js: -------------------------------------------------------------------------------- 1 | import gulp from 'gulp'; 2 | import gulpif from 'gulp-if'; 3 | import livereload from 'gulp-livereload'; 4 | import args from './lib/args'; 5 | 6 | gulp.task('fonts', () => { 7 | return gulp.src('app/fonts/**/*.{woff,woff2,ttf,eot,svg}') 8 | .pipe(gulp.dest(`dist/${args.vendor}/fonts`)) 9 | .pipe(gulpif(args.watch, livereload())); 10 | }); 11 | -------------------------------------------------------------------------------- /app/component/hello.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 14 | 15 | 22 | -------------------------------------------------------------------------------- /tasks/images.js: -------------------------------------------------------------------------------- 1 | import gulp from 'gulp'; 2 | import gulpif from 'gulp-if'; 3 | import imagemin from 'gulp-imagemin'; 4 | import livereload from 'gulp-livereload'; 5 | import args from './lib/args'; 6 | 7 | gulp.task('images', () => { 8 | return gulp.src('app/images/**/*') 9 | .pipe(gulpif(args.production, imagemin())) 10 | .pipe(gulp.dest(`dist/${args.vendor}/images`)) 11 | .pipe(gulpif(args.watch, livereload())); 12 | }); 13 | -------------------------------------------------------------------------------- /app/_locales/en/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "appName": { 3 | "message": "vue chrome extension example", 4 | "description": "The name of the application" 5 | }, 6 | "appShortName": { 7 | "message": "vue_chrome_extension", 8 | "description": "The short_name (maximum of 12 characters recommended) is a short version of the app's name." 9 | }, 10 | "appDescription": { 11 | "message": "n", 12 | "description": "The description of the application" 13 | }, 14 | "browserActionTitle": { 15 | "message": "vue chrome extension example", 16 | "description": "The title of the browser action button" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /tasks/manifest.js: -------------------------------------------------------------------------------- 1 | import gulp from 'gulp'; 2 | import gulpif from 'gulp-if'; 3 | import livereload from 'gulp-livereload'; 4 | import jsonTransform from 'gulp-json-transform'; 5 | import plumber from 'gulp-plumber'; 6 | import applyBrowserPrefixesFor from './lib/applyBrowserPrefixesFor'; 7 | import args from './lib/args'; 8 | 9 | gulp.task('manifest', () => { 10 | return gulp.src('app/manifest.json') 11 | .pipe(plumber()) 12 | .pipe( 13 | jsonTransform( 14 | applyBrowserPrefixesFor(args.vendor) 15 | , 2 /* whitespace */ 16 | ) 17 | ) 18 | .pipe(gulp.dest(`dist/${args.vendor}`)) 19 | .pipe(gulpif(args.watch, livereload())); 20 | }); 21 | -------------------------------------------------------------------------------- /tasks/pack.js: -------------------------------------------------------------------------------- 1 | import gulp from 'gulp'; 2 | import { colors, log } from 'gulp-util'; 3 | import zip from 'gulp-zip'; 4 | import packageDetails from '../package.json'; 5 | import args from './lib/args'; 6 | 7 | function getPackFileType(){ 8 | switch(args.vendor){ 9 | case 'firefox': 10 | return '.xpi'; 11 | default: 12 | return '.zip'; 13 | } 14 | } 15 | 16 | gulp.task('pack', () => { 17 | let name = packageDetails.name; 18 | let version = packageDetails.version; 19 | let filetype = getPackFileType(); 20 | let filename = `${name}-${version}-${args.vendor}${filetype}`; 21 | return gulp.src(`dist/${args.vendor}/**/*`) 22 | .pipe(zip(filename)) 23 | .pipe(gulp.dest('./packages')) 24 | .on('end', () => { 25 | let distStyled = colors.magenta(`dist/${args.vendor}`); 26 | let filenameStyled = colors.magenta(`./packages/${filename}`); 27 | log(`Packed ${distStyled} to ${filenameStyled}`); 28 | }); 29 | }); 30 | -------------------------------------------------------------------------------- /tasks/lib/args.js: -------------------------------------------------------------------------------- 1 | import yargs from 'yargs'; 2 | 3 | const args = yargs 4 | 5 | .option('production', { 6 | boolean: true, 7 | default: false, 8 | describe: 'Minify all scripts and assets' 9 | }) 10 | 11 | .option('watch', { 12 | boolean: true, 13 | default: false, 14 | describe: 'Watch all files and start a livereload server' 15 | }) 16 | 17 | .option('verbose', { 18 | boolean: true, 19 | default: false, 20 | describe: 'Log additional data' 21 | }) 22 | 23 | .option('vendor', { 24 | string: true, 25 | default: 'chrome', 26 | describe: 'Compile the extension for different vendors', 27 | choices: ['chrome', 'firefox', 'opera'] 28 | }) 29 | 30 | .option('sourcemaps', { 31 | describe: 'Force the creation of sourcemaps' 32 | }) 33 | 34 | .argv 35 | 36 | // Use production flag for sourcemaps 37 | // as a fallback 38 | if(typeof args.sourcemaps === 'undefined'){ 39 | args.sourcemaps = !args.production; 40 | } 41 | 42 | export default args; 43 | 44 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 快乐动起来 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /app/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "__MSG_appName__", 3 | "short_name": "__MSG_appShortName__", 4 | "description": "__MSG_appDescription__", 5 | "version": "0.0.0", 6 | "manifest_version": 2, 7 | "default_locale": "en", 8 | "icons": { 9 | "16": "images/icon-16.png", 10 | "128": "images/icon-128.png" 11 | }, 12 | "background": { 13 | "scripts": [ 14 | "scripts/background.js" 15 | ] 16 | }, 17 | "browser_action": { 18 | "default_icon": { 19 | "19": "images/icon-19.png", 20 | "38": "images/icon-38.png" 21 | }, 22 | "default_title": "__MSG_browserActionTitle__", 23 | "default_popup": "pages/popup.html" 24 | }, 25 | "permissions": [ 26 | "bookmarks", 27 | "clipboardRead", 28 | "clipboardWrite", 29 | "commands", 30 | "contentSettings", 31 | "contextMenus", 32 | "cookies", 33 | "debugger", 34 | "declarativeContent", 35 | "history", 36 | "management", 37 | "notifications", 38 | "pageCapture", 39 | "proxy", 40 | "tabCapture", 41 | "tabs", 42 | "topSites", 43 | "webNavigation", 44 | "webRequest", 45 | "webRequestBlocking", 46 | "" 47 | ] 48 | } 49 | -------------------------------------------------------------------------------- /app/component/app.vue: -------------------------------------------------------------------------------- 1 | 28 | 29 | 42 | 43 | 45 | -------------------------------------------------------------------------------- /tasks/lib/applyBrowserPrefixesFor.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Converts and removes keys with a 3 | * browser prefix to the key without prefix 4 | * 5 | * Example: 6 | * 7 | * __chrome__keyName 8 | * __firefox__keyName 9 | * __opera__keyName 10 | * 11 | * to `keyName`. 12 | * This way we can write one manifest thats valid 13 | * for all browsers 14 | * 15 | * @param {Object} manifest 16 | * @return {Object} 17 | */ 18 | export default function applyBrowserPrefixesFor(_vendor){ 19 | vendor = _vendor; 20 | return iterator; 21 | }; 22 | 23 | 24 | /** 25 | * Vendor key 26 | * @type {String} 27 | */ 28 | var vendor = ''; 29 | 30 | 31 | /** 32 | * Recursive iterator over all object keys 33 | * @param {Object} obj Object to iterate over 34 | * @return {Object} Processed object 35 | */ 36 | function iterator(obj){ 37 | Object.keys(obj).forEach((key)=>{ 38 | let match = key.match(/^__(chrome|firefox|opera)__(.*)/); 39 | if(match){ 40 | 41 | // Swap key with non prefixed name 42 | if(match[1] === vendor){ 43 | obj[match[2]] = obj[key]; 44 | } 45 | 46 | // Remove the prefixed key 47 | // so it won't cause warings 48 | delete obj[key]; 49 | } 50 | else { // no match? try deeper 51 | // Recurse over object's inner keys 52 | if (typeof(obj[key]) === "object") iterator(obj[key]); 53 | } 54 | 55 | }); 56 | return obj; 57 | } 58 | -------------------------------------------------------------------------------- /tasks/version.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Bumping version number and tagging the repository with it. 3 | * Please read http://semver.org/ 4 | * 5 | * You can use the commands 6 | * 7 | * gulp patch # makes v0.1.0 → v0.1.1 8 | * gulp feature # makes v0.1.1 → v0.2.0 9 | * gulp release # makes v0.2.1 → v1.0.0 10 | * 11 | * To bump the version numbers accordingly after you did a patch, 12 | * introduced a feature or made a backwards-incompatible release. 13 | */ 14 | 15 | import gulp from 'gulp'; 16 | import git from 'gulp-git'; 17 | import bump from 'gulp-bump'; 18 | import filter from 'gulp-filter'; 19 | import tagVersion from 'gulp-tag-version'; 20 | 21 | function inc(importance) { 22 | // get all the files to bump version in 23 | return gulp.src([ 24 | 'package.json', 25 | 'app/manifest.json' 26 | ], { 27 | base: "./" 28 | }) 29 | // bump the version number in those files 30 | .pipe(bump({ 31 | type: importance 32 | })) 33 | // save it back to filesystem 34 | .pipe(gulp.dest('./')) 35 | // commit the changed version number 36 | .pipe(git.commit('bump package version')) 37 | // read only one file to get the version number 38 | .pipe(filter('package.json')) 39 | // **tag it in the repository** 40 | .pipe(tagVersion()); 41 | } 42 | 43 | gulp.task('patch', () => { 44 | return inc('patch'); 45 | }); 46 | 47 | gulp.task('feature', () => { 48 | return inc('minor'); 49 | }); 50 | 51 | gulp.task('release', () => { 52 | return inc('major'); 53 | }); 54 | -------------------------------------------------------------------------------- /tasks/chromereload.js: -------------------------------------------------------------------------------- 1 | import gulp from 'gulp'; 2 | import gutil from 'gulp-util'; 3 | import gulpSequence from 'gulp-sequence'; 4 | import livereload from 'gulp-livereload'; 5 | import args from './lib/args'; 6 | 7 | // In order to make chromereload work you'll need to include 8 | // the following line in your `scipts/background.js` file. 9 | // 10 | // import 'chromereload/devonly'; 11 | // 12 | // This will reload your extension everytime a file changes. 13 | // If you just want to reload a specific context of your extension 14 | // (e.g. `pages/options.html`) include the script in that context 15 | // (e.g. `scripts/options.js`). 16 | // 17 | // Please note that you'll have to restart the gulp task if you 18 | // create new file. We'll fix that when gulp 4 comes out. 19 | 20 | gulp.task('chromereload', (cb) => { 21 | 22 | // This task runs only if the 23 | // watch argument is present! 24 | if (!args.watch) return cb(); 25 | 26 | // Start livereload server 27 | livereload.listen({ 28 | reloadPage: 'Extension', 29 | quiet: !args.verbose 30 | }); 31 | 32 | gutil.log('Starting', gutil.colors.cyan('\'livereload-server\'')); 33 | 34 | // The watching for javascript files is done by webpack 35 | // Check out ./tasks/scripts.js for further info. 36 | gulp.watch('app/manifest.json', ['manifest']); 37 | gulp.watch('app/component/**/*.vue',['pages','scripts']); 38 | gulp.watch('app/styles/**/*.css', ['styles:css']); 39 | gulp.watch('app/styles/**/*.less', ['styles:less']); 40 | gulp.watch('app/styles/**/*.scss', ['styles:sass']); 41 | gulp.watch('app/pages/**/*.html', ['pages']); 42 | gulp.watch('app/_locales/**/*', ['locales']); 43 | gulp.watch('app/images/**/*', ['images']); 44 | gulp.watch('app/fonts/**/*.{woff,ttf,eot,svg}', ['fonts']); 45 | 46 | }); 47 | -------------------------------------------------------------------------------- /tasks/styles.js: -------------------------------------------------------------------------------- 1 | import gulp from 'gulp'; 2 | import gulpif from 'gulp-if'; 3 | import gutil from 'gulp-util'; 4 | import sourcemaps from 'gulp-sourcemaps'; 5 | import less from 'gulp-less'; 6 | import sass from 'gulp-sass'; 7 | import cleanCSS from 'gulp-clean-css'; 8 | import livereload from 'gulp-livereload'; 9 | import args from './lib/args'; 10 | 11 | gulp.task('styles:css', function() { 12 | return gulp.src('app/styles/*.css') 13 | .pipe(gulpif(args.sourcemaps, sourcemaps.init())) 14 | .pipe(gulpif(args.production, cleanCSS())) 15 | .pipe(gulpif(args.sourcemaps, sourcemaps.write())) 16 | .pipe(gulp.dest(`dist/${args.vendor}/styles`)) 17 | .pipe(gulpif(args.watch, livereload())); 18 | }); 19 | 20 | gulp.task('styles:less', function() { 21 | return gulp.src('app/styles/*.less') 22 | .pipe(gulpif(args.sourcemaps, sourcemaps.init())) 23 | .pipe(less({ paths: ['./app']}).on('error', function(error) { 24 | gutil.log(gutil.colors.red('Error (' + error.plugin + '): ' + error.message)); 25 | this.emit('end'); 26 | })) 27 | .pipe(gulpif(args.production, cleanCSS())) 28 | .pipe(gulpif(args.sourcemaps, sourcemaps.write())) 29 | .pipe(gulp.dest(`dist/${args.vendor}/styles`)) 30 | .pipe(gulpif(args.watch, livereload())); 31 | }); 32 | 33 | gulp.task('styles:sass', function() { 34 | return gulp.src('app/styles/*.scss') 35 | .pipe(gulpif(args.sourcemaps, sourcemaps.init())) 36 | .pipe(sass({ includePaths: ['./app']}).on('error', function(error) { 37 | gutil.log(gutil.colors.red('Error (' + error.plugin + '): ' + error.message)); 38 | this.emit('end'); 39 | })) 40 | .pipe(gulpif(args.production, cleanCSS())) 41 | .pipe(gulpif(args.sourcemaps, sourcemaps.write())) 42 | .pipe(gulp.dest(`dist/${args.vendor}/styles`)) 43 | .pipe(gulpif(args.watch, livereload())); 44 | }); 45 | 46 | gulp.task('styles', [ 47 | 'styles:css', 48 | 'styles:less', 49 | 'styles:sass' 50 | ]); 51 | 52 | -------------------------------------------------------------------------------- /tasks/scripts.js: -------------------------------------------------------------------------------- 1 | import gulp from 'gulp'; 2 | import gulpif from 'gulp-if'; 3 | import { log, colors} from 'gulp-util'; 4 | import named from 'vinyl-named'; 5 | import webpack from 'webpack'; 6 | import gulpWebpack from 'webpack-stream'; 7 | import plumber from 'gulp-plumber'; 8 | import livereload from 'gulp-livereload'; 9 | import args from './lib/args'; 10 | 11 | const ENV = args.production ? 'production' : 'development'; 12 | 13 | gulp.task('scripts', (cb) => { 14 | return gulp.src(['app/scripts/*.js']) 15 | .pipe(plumber({ 16 | errorHandler: function() { 17 | // Webpack will log the errors 18 | } 19 | })) 20 | .pipe(named()) 21 | .pipe(gulpWebpack({ 22 | devtool: args.sourcemaps ? 'inline-source-map': null, 23 | watch: args.watch, 24 | plugins: [ 25 | new webpack.DefinePlugin({ 26 | 'process.env': { 27 | 'NODE_ENV': JSON.stringify(ENV) 28 | }, 29 | '__ENV__': JSON.stringify(ENV), 30 | '__VENDOR__': JSON.stringify(args.vendor) 31 | }), 32 | ].concat(args.production ? [ 33 | new webpack.optimize.UglifyJsPlugin() 34 | ] : []), 35 | module: { 36 | preLoaders: [{ 37 | test: /\.js$/, 38 | loader: 'eslint-loader', 39 | exclude: /node_modules/ 40 | }], 41 | loaders: [{ 42 | test: /\.js$/, 43 | loader: 'babel' 44 | },{ 45 | test: /\.vue$/, 46 | loader: 'vue-loader' 47 | }] 48 | }, 49 | resolve: { 50 | alias: { 51 | 'vue$': 'vue/dist/vue.esm.js' // 'vue/dist/vue.common.js' for webpack 1 52 | } 53 | }, 54 | eslint: { 55 | configFile: '.eslintrc' 56 | } 57 | }, null, (err, stats) => { 58 | log(`Finished '${colors.cyan('scripts')}'`, stats.toString({ 59 | chunks: false, 60 | colors: true, 61 | cached: false, 62 | children: false 63 | })); 64 | })) 65 | .pipe(gulp.dest(`dist/${args.vendor}/scripts`)) 66 | .pipe(gulpif(args.watch, livereload())); 67 | }); 68 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-chrome-extension-example", 3 | "private": true, 4 | "version": "0.0.0", 5 | "description": "chrome extesion with vue", 6 | "scripts": { 7 | "start": "npm run dev:chrome", 8 | "build": "npm run build:chrome", 9 | "build:chrome": "gulp --production --vendor=chrome && gulp pack --vendor=chrome", 10 | "build:firefox": "gulp --production --vendor=firefox && gulp pack --vendor=firefox", 11 | "build:opera": "gulp --production --vendor=opera && gulp pack --vendor=opera", 12 | "dev": "npm run dev:chrome", 13 | "dev:chrome": "gulp --watch --vendor=chrome", 14 | "dev:firefox": "gulp --watch --vendor=firefox", 15 | "dev:opera": "gulp --watch --vendor=opera" 16 | }, 17 | "devDependencies": { 18 | "babel-cli": "6.x.x", 19 | "babel-core": "^6.22.1", 20 | "babel-eslint": "6.x.x", 21 | "babel-loader": "6.x.x", 22 | "babel-plugin-transform-runtime": "^6.22.0", 23 | "babel-preset-es2015": "^6.22.0", 24 | "babel-preset-stage-0": "6.x.x", 25 | "bulma": "^0.3.1", 26 | "chai": "3.x.x", 27 | "chromereload": "0.x.x", 28 | "css-loader": "^0.26.2", 29 | "debounce": "1.x.x", 30 | "del": "2.x.x", 31 | "eslint": "3.x.x", 32 | "eslint-loader": "1.x.x", 33 | "gulp": "3.x.x", 34 | "gulp-bump": "2.x.x", 35 | "gulp-cache": "0.x.x", 36 | "gulp-clean-css": "2.x.x", 37 | "gulp-filter": "4.x.x", 38 | "gulp-git": "1.x.x", 39 | "gulp-if": "2.x.x", 40 | "gulp-imagemin": "3.x.x", 41 | "gulp-json-transform": "0.x.x", 42 | "gulp-less": "3.x.x", 43 | "gulp-livereload": "3.x.x", 44 | "gulp-plumber": "1.x.x", 45 | "gulp-sass": "2.x.x", 46 | "gulp-sequence": "0.x.x", 47 | "gulp-sourcemaps": "1.x.x", 48 | "gulp-tag-version": "1.x.x", 49 | "gulp-util": "3.x.x", 50 | "gulp-vueify": "0.0.3", 51 | "gulp-zip": "3.x.x", 52 | "require-dir": "0.x.x", 53 | "vinyl-named": "1.x.x", 54 | "vue": "^2.2.1", 55 | "vue-loader": "^11.1.4", 56 | "vue-template-compiler": "^2.2.1", 57 | "vueify-insert-css": "^1.0.0", 58 | "webpack": "^2.2.1", 59 | "webpack-stream": "3.x.x", 60 | "yargs": "5.x.x" 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vue chrome extension example 2 | 3 | develop chrome extension with vue 4 | 5 | ## Installation 6 | 7 | $ npm install 8 | 9 | ## Usage 10 | 11 | Run `$ gulp --watch` and load the `dist`-directory into chrome. 12 | 13 | ## Entryfiles (bundles) 14 | 15 | There are two kinds of entryfiles that create bundles. 16 | 17 | 1. All js-files in the root of the `./app/scripts` directory 18 | 2. All css-,scss- and less-files in the root of the `./app/styles` directory 19 | 20 | ## Tasks 21 | 22 | ### Build 23 | 24 | $ gulp 25 | 26 | 27 | | Option | Description | 28 | |----------------|-------------------------------------------------------------------------------------------------------------------------------------------------------| 29 | | `--watch` | Starts a livereload server and watches all assets.
To reload the extension on change include `livereload.js` in your bundle. | 30 | | `--production` | Minifies all assets | 31 | | `--verbose` | Log additional data to the console. | 32 | | `--vendor` | Compile the extension for different vendors (chrome, firefox, opera) Default: chrome | 33 | | `--sourcemaps` | Force the creation of sourcemaps. Default: !production | 34 | 35 | 36 | ### pack 37 | 38 | Zips your `dist` directory and saves it in the `packages` directory. 39 | 40 | $ gulp pack --vendor=firefox 41 | 42 | ### Version 43 | 44 | Increments version number of `manifest.json` and `package.json`, 45 | commits the change to git and adds a git tag. 46 | 47 | 48 | $ gulp patch // => 0.0.X 49 | 50 | or 51 | 52 | $ gulp feature // => 0.X.0 53 | 54 | or 55 | 56 | $ gulp release // => X.0.0 57 | 58 | 59 | ## Globals 60 | 61 | The build tool also defines a variable named `ENV` in your scripts. It will be set to `development` unless you use the `--production` option. 62 | 63 | 64 | **Example:** `./app/background.js` 65 | 66 | if(ENV === 'development'){ 67 | console.log('We are in development mode!'); 68 | } 69 | --------------------------------------------------------------------------------