diff --git a/浏览器插件/bookmark-chrome/.babelrc b/浏览器插件/bookmark-chrome/.babelrc new file mode 100644 index 0000000..e93edff --- /dev/null +++ b/浏览器插件/bookmark-chrome/.babelrc @@ -0,0 +1,15 @@ +{ + "plugins": [ + "@babel/plugin-proposal-optional-chaining" + ], + "presets": [ + ["@babel/preset-env", { + "useBuiltIns": "usage", + "corejs": 3, + "targets": { + // https://jamie.build/last-2-versions + "browsers": ["> 0.25%", "not ie 11", "not op_mini all"] + } + }] + ] +} diff --git a/浏览器插件/bookmark-chrome/.eslintrc.js b/浏览器插件/bookmark-chrome/.eslintrc.js new file mode 100644 index 0000000..e1ed748 --- /dev/null +++ b/浏览器插件/bookmark-chrome/.eslintrc.js @@ -0,0 +1,33 @@ +// https://eslint.org/docs/user-guide/configuring +// File taken from https://github.com/vuejs-templates/webpack/blob/1.3.1/template/.eslintrc.js, thanks. + +module.exports = { + root: true, + parserOptions: { + parser: 'babel-eslint' + }, + env: { + browser: true, + webextensions: true, + }, + extends: [ + // https://github.com/vuejs/eslint-plugin-vue#priority-a-essential-error-prevention + // consider switching to `plugin:vue/strongly-recommended` or `plugin:vue/recommended` for stricter rules. + 'plugin:vue/essential', + // https://github.com/standard/standard/blob/master/docs/RULES-en.md + 'standard', + // https://prettier.io/docs/en/index.html + 'plugin:prettier/recommended' + ], + // required to lint *.vue files + plugins: [ + 'vue' + ], + // add your custom rules here + rules: { + // allow async-await + 'generator-star-spacing': 'off', + // allow debugger during development + 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off' + } +} diff --git a/浏览器插件/bookmark-chrome/.gitignore b/浏览器插件/bookmark-chrome/.gitignore new file mode 100644 index 0000000..8e33e27 --- /dev/null +++ b/浏览器插件/bookmark-chrome/.gitignore @@ -0,0 +1,4 @@ +/node_modules +/*.log +/dist +/dist-zip diff --git a/浏览器插件/bookmark-chrome/.prettierrc b/浏览器插件/bookmark-chrome/.prettierrc new file mode 100644 index 0000000..cc78523 --- /dev/null +++ b/浏览器插件/bookmark-chrome/.prettierrc @@ -0,0 +1,5 @@ +{ + "singleQuote": true, + "printWidth": 180, + "trailingComma": "es5" +} diff --git a/浏览器插件/bookmark-chrome/package.json b/浏览器插件/bookmark-chrome/package.json new file mode 100644 index 0000000..bc5c41f --- /dev/null +++ b/浏览器插件/bookmark-chrome/package.json @@ -0,0 +1,67 @@ +{ + "name": "bookmark-chrome", + "version": "1.0.0", + "description": "A Vue.js web extension", + "author": "fanxb ", + "license": "MIT", + "scripts": { + "lint": "eslint --ext .js,.vue src", + "prettier": "prettier \"src/**/*.{js,vue}\"", + "prettier:write": "npm run prettier -- --write", + "build": "cross-env NODE_ENV=production webpack --hide-modules", + "build:dev": "cross-env NODE_ENV=development webpack --hide-modules", + "build-zip": "node scripts/build-zip.js", + "watch": "npm run build -- --watch", + "watch:dev": "cross-env HMR=true npm run build:dev -- --watch" + }, + "husky": { + "hooks": { + "pre-commit": "pretty-quick --staged" + } + }, + "dependencies": { + "axios": "^0.19.0", + "vue": "^2.6.10", + "vue-router": "^3.0.1", + "vuex": "^3.0.1", + "webextension-polyfill": "^0.3.1" + }, + "devDependencies": { + "@babel/core": "^7.1.2", + "@babel/plugin-proposal-optional-chaining": "^7.0.0", + "@babel/preset-env": "^7.1.0", + "@babel/runtime-corejs3": "^7.4.0", + "archiver": "^3.0.0", + "babel-eslint": "^10.0.1", + "babel-loader": "^8.0.2", + "copy-webpack-plugin": "^4.5.3", + "core-js": "^3.0.1", + "cross-env": "^5.2.0", + "css-loader": "^2.1.1", + "ejs": "^2.6.1", + "eslint": "^5.16.0", + "eslint-config-prettier": "^4.3.0", + "eslint-config-standard": "^12.0.0", + "eslint-friendly-formatter": "^4.0.1", + "eslint-loader": "^2.1.2", + "eslint-plugin-import": "^2.16.0", + "eslint-plugin-node": "^7.0.1", + "eslint-plugin-prettier": "^3.1.0", + "eslint-plugin-promise": "^4.1.1", + "eslint-plugin-standard": "^4.0.0", + "eslint-plugin-vue": "^5.2.2", + "file-loader": "^1.1.11", + "husky": "^2.4.0", + "mini-css-extract-plugin": "^0.4.4", + "node-sass": "^4.9.3", + "prettier": "^1.17.1", + "pretty-quick": "^1.8.0", + "sass-loader": "^7.1.0", + "vue-loader": "^15.4.2", + "vue-template-compiler": "^2.6.10", + "web-ext-types": "^2.1.0", + "webpack": "^4.20.2", + "webpack-cli": "^3.1.2", + "webpack-extension-reloader": "^1.1.0" + } +} diff --git a/浏览器插件/bookmark-chrome/scripts/build-zip.js b/浏览器插件/bookmark-chrome/scripts/build-zip.js new file mode 100644 index 0000000..9a84c2a --- /dev/null +++ b/浏览器插件/bookmark-chrome/scripts/build-zip.js @@ -0,0 +1,53 @@ +#!/usr/bin/env node + +const fs = require('fs'); +const path = require('path'); +const archiver = require('archiver'); + +const DEST_DIR = path.join(__dirname, '../dist'); +const DEST_ZIP_DIR = path.join(__dirname, '../dist-zip'); + +const extractExtensionData = () => { + const extPackageJson = require('../package.json'); + + return { + name: extPackageJson.name, + version: extPackageJson.version + } +}; + +const makeDestZipDirIfNotExists = () => { + if(!fs.existsSync(DEST_ZIP_DIR)) { + fs.mkdirSync(DEST_ZIP_DIR); + } +} + +const buildZip = (src, dist, zipFilename) => { + console.info(`Building ${zipFilename}...`); + + const archive = archiver('zip', { zlib: { level: 9 }}); + const stream = fs.createWriteStream(path.join(dist, zipFilename)); + + return new Promise((resolve, reject) => { + archive + .directory(src, false) + .on('error', err => reject(err)) + .pipe(stream); + + stream.on('close', () => resolve()); + archive.finalize(); + }); +}; + +const main = () => { + const {name, version} = extractExtensionData(); + const zipFilename = `${name}-v${version}.zip`; + + makeDestZipDirIfNotExists(); + + buildZip(DEST_DIR, DEST_ZIP_DIR, zipFilename) + .then(() => console.info('OK')) + .catch(console.err); +}; + +main(); diff --git a/浏览器插件/bookmark-chrome/src/background.js b/浏览器插件/bookmark-chrome/src/background.js new file mode 100644 index 0000000..8610f97 --- /dev/null +++ b/浏览器插件/bookmark-chrome/src/background.js @@ -0,0 +1,4 @@ +import store from './store'; +global.browser = require('webextension-polyfill'); + +alert(`Hello ${store.getters.foo}!`); diff --git a/浏览器插件/bookmark-chrome/src/icons/icon.xcf b/浏览器插件/bookmark-chrome/src/icons/icon.xcf new file mode 100644 index 0000000..e1cde95 Binary files /dev/null and b/浏览器插件/bookmark-chrome/src/icons/icon.xcf differ diff --git a/浏览器插件/bookmark-chrome/src/icons/icon_128.png b/浏览器插件/bookmark-chrome/src/icons/icon_128.png new file mode 100644 index 0000000..c4ed868 Binary files /dev/null and b/浏览器插件/bookmark-chrome/src/icons/icon_128.png differ diff --git a/浏览器插件/bookmark-chrome/src/icons/icon_48.png b/浏览器插件/bookmark-chrome/src/icons/icon_48.png new file mode 100644 index 0000000..e2d41f1 Binary files /dev/null and b/浏览器插件/bookmark-chrome/src/icons/icon_48.png differ diff --git a/浏览器插件/bookmark-chrome/src/manifest.json b/浏览器插件/bookmark-chrome/src/manifest.json new file mode 100644 index 0000000..07fd085 --- /dev/null +++ b/浏览器插件/bookmark-chrome/src/manifest.json @@ -0,0 +1,23 @@ +{ + "name": "bookmark-chrome", + "description": "A Vue.js web extension", + "version": null, + "manifest_version": 2, + "icons": { + "48": "icons/icon_48.png", + "128": "icons/icon_128.png" + }, + "browser_action": { + "default_title": "bookmark-chrome", + "default_popup": "popup/popup.html" + }, + "background": { + "scripts": [ + "background.js" + ] + }, + "options_ui": { + "page": "options/options.html", + "chrome_style": true + } +} diff --git a/浏览器插件/bookmark-chrome/src/options/App.vue b/浏览器插件/bookmark-chrome/src/options/App.vue new file mode 100644 index 0000000..3216d20 --- /dev/null +++ b/浏览器插件/bookmark-chrome/src/options/App.vue @@ -0,0 +1,17 @@ + + + + + diff --git a/浏览器插件/bookmark-chrome/src/options/options.html b/浏览器插件/bookmark-chrome/src/options/options.html new file mode 100644 index 0000000..9c976ae --- /dev/null +++ b/浏览器插件/bookmark-chrome/src/options/options.html @@ -0,0 +1,15 @@ + + + + + bookmark-chrome - Options + + <% if (NODE_ENV === 'development') { %> + + <% } %> + + +
+ + + diff --git a/浏览器插件/bookmark-chrome/src/options/options.js b/浏览器插件/bookmark-chrome/src/options/options.js new file mode 100644 index 0000000..fa15a1e --- /dev/null +++ b/浏览器插件/bookmark-chrome/src/options/options.js @@ -0,0 +1,10 @@ +import Vue from 'vue'; +import App from './App'; + +global.browser = require('webextension-polyfill'); + +/* eslint-disable no-new */ +new Vue({ + el: '#app', + render: h => h(App), +}); diff --git a/浏览器插件/bookmark-chrome/src/popup/App.vue b/浏览器插件/bookmark-chrome/src/popup/App.vue new file mode 100644 index 0000000..689e916 --- /dev/null +++ b/浏览器插件/bookmark-chrome/src/popup/App.vue @@ -0,0 +1,15 @@ + + + + + diff --git a/浏览器插件/bookmark-chrome/src/popup/popup.html b/浏览器插件/bookmark-chrome/src/popup/popup.html new file mode 100644 index 0000000..0f6fd6b --- /dev/null +++ b/浏览器插件/bookmark-chrome/src/popup/popup.html @@ -0,0 +1,17 @@ + + + + + Title + + <% if (NODE_ENV === 'development') { %> + + <% } %> + + +
+ +
+ + + diff --git a/浏览器插件/bookmark-chrome/src/popup/popup.js b/浏览器插件/bookmark-chrome/src/popup/popup.js new file mode 100644 index 0000000..53ab1dd --- /dev/null +++ b/浏览器插件/bookmark-chrome/src/popup/popup.js @@ -0,0 +1,15 @@ +import Vue from 'vue' +import App from './App' +import store from '../store' +import router from './router' + +global.browser = require('webextension-polyfill') +Vue.prototype.$browser = global.browser + +/* eslint-disable no-new */ +new Vue({ + el: '#app', + store, + router, + render: h => h(App) +}) diff --git a/浏览器插件/bookmark-chrome/src/popup/router/index.js b/浏览器插件/bookmark-chrome/src/popup/router/index.js new file mode 100644 index 0000000..c3fe07e --- /dev/null +++ b/浏览器插件/bookmark-chrome/src/popup/router/index.js @@ -0,0 +1,9 @@ +import Vue from 'vue' +import VueRouter from 'vue-router' +import routes from './routes' + +Vue.use(VueRouter) + +export default new VueRouter({ + routes +}) diff --git a/浏览器插件/bookmark-chrome/src/popup/router/pages/Index.vue b/浏览器插件/bookmark-chrome/src/popup/router/pages/Index.vue new file mode 100644 index 0000000..325c4fd --- /dev/null +++ b/浏览器插件/bookmark-chrome/src/popup/router/pages/Index.vue @@ -0,0 +1,17 @@ + + + + + diff --git a/浏览器插件/bookmark-chrome/src/popup/router/routes.js b/浏览器插件/bookmark-chrome/src/popup/router/routes.js new file mode 100644 index 0000000..a1111b4 --- /dev/null +++ b/浏览器插件/bookmark-chrome/src/popup/router/routes.js @@ -0,0 +1,8 @@ +import PageIndex from './pages/Index' + +export default [ + { + path: '/', + component: PageIndex + } +] diff --git a/浏览器插件/bookmark-chrome/src/store/actions.js b/浏览器插件/bookmark-chrome/src/store/actions.js new file mode 100644 index 0000000..3dadd8c --- /dev/null +++ b/浏览器插件/bookmark-chrome/src/store/actions.js @@ -0,0 +1,5 @@ +import * as types from './mutation-types' + +export const setFoo = ({commit}, payload) => { + commit(types.UPDATE_FOO, payload) +} diff --git a/浏览器插件/bookmark-chrome/src/store/getters.js b/浏览器插件/bookmark-chrome/src/store/getters.js new file mode 100644 index 0000000..075cef6 --- /dev/null +++ b/浏览器插件/bookmark-chrome/src/store/getters.js @@ -0,0 +1 @@ +export const foo = (state) => state.foo diff --git a/浏览器插件/bookmark-chrome/src/store/index.js b/浏览器插件/bookmark-chrome/src/store/index.js new file mode 100644 index 0000000..45fac81 --- /dev/null +++ b/浏览器插件/bookmark-chrome/src/store/index.js @@ -0,0 +1,17 @@ +import Vue from 'vue' +import Vuex from 'vuex' + +import * as getters from './getters' +import mutations from './mutations' +import * as actions from './actions' + +Vue.use(Vuex) + +export default new Vuex.Store({ + state: { + foo: 'bar' + }, + getters, + mutations, + actions +}) diff --git a/浏览器插件/bookmark-chrome/src/store/mutation-types.js b/浏览器插件/bookmark-chrome/src/store/mutation-types.js new file mode 100644 index 0000000..c986c3c --- /dev/null +++ b/浏览器插件/bookmark-chrome/src/store/mutation-types.js @@ -0,0 +1 @@ +export const UPDATE_FOO = 'UPDATE_FOO' diff --git a/浏览器插件/bookmark-chrome/src/store/mutations.js b/浏览器插件/bookmark-chrome/src/store/mutations.js new file mode 100644 index 0000000..dd926bc --- /dev/null +++ b/浏览器插件/bookmark-chrome/src/store/mutations.js @@ -0,0 +1,7 @@ +import * as types from './mutation-types' + +export default { + [types.UPDATE_FOO] (state, payload) { + state.foo = payload + } +} diff --git a/浏览器插件/bookmark-chrome/webpack.config.js b/浏览器插件/bookmark-chrome/webpack.config.js new file mode 100644 index 0000000..c3d49b2 --- /dev/null +++ b/浏览器插件/bookmark-chrome/webpack.config.js @@ -0,0 +1,121 @@ +const webpack = require('webpack'); +const ejs = require('ejs'); +const MiniCssExtractPlugin = require('mini-css-extract-plugin'); +const CopyWebpackPlugin = require('copy-webpack-plugin'); +const ExtensionReloader = require('webpack-extension-reloader'); +const { VueLoaderPlugin } = require('vue-loader'); +const { version } = require('./package.json'); + +const config = { + mode: process.env.NODE_ENV, + context: __dirname + '/src', + entry: { + 'background': './background.js', + 'popup/popup': './popup/popup.js', + 'options/options': './options/options.js', + }, + output: { + path: __dirname + '/dist', + filename: '[name].js', + }, + resolve: { + extensions: ['.js', '.vue'], + }, + module: { + rules: [ + { + test: /\.vue$/, + loaders: 'vue-loader', + }, + { + test: /\.js$/, + loader: 'babel-loader', + exclude: /node_modules/, + }, + { + test: /\.css$/, + use: [MiniCssExtractPlugin.loader, 'css-loader'], + }, + { + test: /\.scss$/, + use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader'], + }, + { + test: /\.sass$/, + use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader?indentedSyntax'], + }, + { + test: /\.(png|jpg|jpeg|gif|svg|ico)$/, + loader: 'file-loader', + options: { + name: '[name].[ext]', + outputPath: '/images/', + emitFile: false, + }, + }, + { + test: /\.(woff(2)?|ttf|eot|svg)(\?v=\d+\.\d+\.\d+)?$/, + loader: 'file-loader', + options: { + name: '[name].[ext]', + outputPath: '/fonts/', + emitFile: false, + }, + }, + ], + }, + plugins: [ + new webpack.DefinePlugin({ + global: 'window', + }), + new VueLoaderPlugin(), + new MiniCssExtractPlugin({ + filename: '[name].css', + }), + new CopyWebpackPlugin([ + { from: 'icons', to: 'icons', ignore: ['icon.xcf'] }, + { from: 'popup/popup.html', to: 'popup/popup.html', transform: transformHtml }, + { from: 'options/options.html', to: 'options/options.html', transform: transformHtml }, + { + from: 'manifest.json', + to: 'manifest.json', + transform: (content) => { + const jsonContent = JSON.parse(content); + jsonContent.version = version; + + if (config.mode === 'development') { + jsonContent['content_security_policy'] = "script-src 'self' 'unsafe-eval'; object-src 'self'"; + } + + return JSON.stringify(jsonContent, null, 2); + }, + }, + ]), + ], +}; + +if (config.mode === 'production') { + config.plugins = (config.plugins || []).concat([ + new webpack.DefinePlugin({ + 'process.env': { + NODE_ENV: '"production"', + }, + }), + ]); +} + +if (process.env.HMR === 'true') { + config.plugins = (config.plugins || []).concat([ + new ExtensionReloader({ + manifest: __dirname + '/src/manifest.json', + }), + ]); +} + +function transformHtml(content) { + return ejs.render(content.toString(), { + ...process.env, + }); +} + +module.exports = config; diff --git a/浏览器插件/chrome/background.js b/浏览器插件/chrome/background.js deleted file mode 100644 index 3b75cd3..0000000 --- a/浏览器插件/chrome/background.js +++ /dev/null @@ -1,3 +0,0 @@ -chrome.runtime.onInstalled.addListener(() => { - alert('Hello, World!'); -}); \ No newline at end of file diff --git a/浏览器插件/chrome/manifest.json b/浏览器插件/chrome/manifest.json deleted file mode 100644 index dc75215..0000000 --- a/浏览器插件/chrome/manifest.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "name": "Hello World Extension", - "version": "0.0.1", - "manifest_version": 2, - "background": { - "scripts": ["background.js"], - "persistent": false - } -} \ No newline at end of file