├── .gitignore ├── LICENSE.md ├── README.md ├── example ├── MoveSearch │ ├── .gitignore │ ├── README.md │ ├── dist │ │ ├── app.bundle.js │ │ ├── app.bundle.js.LICENSE.txt │ │ ├── app.bundle.js.map │ │ ├── index.html │ │ ├── vendor.bundle.js │ │ ├── vendor.bundle.js.LICENSE.txt │ │ └── vendor.bundle.js.map │ ├── package-lock.json │ ├── package.json │ ├── public │ │ ├── favicon.ico │ │ ├── icon.jpg │ │ └── index.html │ ├── src │ │ ├── app.js │ │ ├── app.less │ │ └── index.js │ ├── tampermonkey.js │ ├── webpack.config.base.js │ └── webpack.config.js ├── jsDelivr │ ├── .gitignore │ ├── README.md │ ├── package-lock.json │ ├── package.json │ ├── public │ │ ├── favicon.ico │ │ ├── icon.jpg │ │ └── index.html │ ├── src │ │ ├── app.css │ │ ├── app.js │ │ └── index.js │ ├── tampermonkey.txt │ ├── webpack.config.base.js │ └── webpack.config.js ├── wokoo-demo │ ├── .gitignore │ ├── README.md │ ├── dist │ │ └── app.bundle.js │ ├── package-lock.json │ ├── package.json │ ├── public │ │ ├── favicon.ico │ │ ├── icon.jpg │ │ └── index.html │ ├── src │ │ ├── app.less │ │ ├── app.vue │ │ └── index.js │ ├── tampermonkey.txt │ ├── webpack.config.base.js │ └── webpack.config.js └── zhihu-helper │ ├── .gitignore │ ├── README.md │ ├── dist │ ├── app.bundle.js │ ├── app.bundle.js.LICENSE.txt │ ├── app.bundle.js.map │ ├── index.html │ ├── vendor.bundle.js │ ├── vendor.bundle.js.LICENSE.txt │ └── vendor.bundle.js.map │ ├── package-lock.json │ ├── package.json │ ├── public │ ├── favicon.ico │ ├── icon.jpg │ └── index.html │ ├── src │ ├── app.js │ ├── app.less │ ├── index.js │ ├── step1.js │ └── step2.js │ ├── tampermonkey.js │ ├── webpack.config.base.js │ └── webpack.config.js ├── lerna-debug.log ├── lerna.json ├── package-lock.json ├── package.json ├── packages ├── wokoo-scripts │ ├── README.md │ ├── bin │ │ └── www │ ├── index.js │ ├── modifyTemplate.js │ ├── package-lock.json │ └── package.json └── wokoo-template │ ├── .gitignore │ ├── README.md │ ├── package-lock.json │ ├── package.json │ ├── public │ ├── favicon.ico │ ├── icon.jpg │ └── index.html │ ├── react-template │ ├── README.md │ ├── src │ │ ├── app.js │ │ ├── app.less │ │ └── index.js │ ├── tampermonkey.js │ ├── template.json │ └── webpack.config.base.js │ ├── vue-template │ ├── README.md │ ├── src │ │ ├── app.less │ │ ├── app.vue │ │ └── index.js │ ├── tampermonkey.js │ ├── template.json │ └── webpack.config.base.js │ └── webpack.config.js └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kinyaying/wokoo/2961afcb53c0e85dae8ec0f93b6f73fb0c9eb134/LICENSE.md -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Wokoo 脚手架 2 | 3 | - 一键式创建基于油猴插件的基础工程 4 | - 自带的油猴配置文件 👉 tampermonkey.js 5 | - 提供实时开发,实时查看插件效果的解决方案 6 | - 提供绕过 csp 安全策略解决方案 7 | 8 | 不太了解油猴插件是什么?先阅读这篇文章补充基础知识吧 [Chrome 插件大杀器:「油猴」Tampermonkey 使用详解](https://zhuanlan.zhihu.com/p/99390731) 9 | 10 | 如何使用? 👉 [5 分钟上手开发浏览器插件——油猴脚手架 wokoo(使用篇)](https://juejin.cn/post/6922815205575491597) 11 | 12 | 还提供了两款有意思的油猴插件开发案例 👉 [快速上手油猴插件开发(实战篇)](https://juejin.cn/post/6925605904561750030/) 13 | 14 | 想知道 Wokoo 脚手架怎么搭建的吗? 👉 [wokoo 脚手架(搭建篇)](https://juejin.cn/post/6925613440752943112#) 15 | 16 | # 使用 17 | 18 | 1. 创建基础项目 19 | 20 | ```shell 21 | npx wokoo my-app 22 | ``` 23 | 24 | 2. 起服务 25 | 26 | ``` 27 | npm start 28 | ``` 29 | 30 | 3. 复制 tampermonkey.js 内容到 [油猴插件编辑器](chrome-extension://dhdgffkkebhmkfjojejmpbldmpobfkfo/options.html#url=&nav=new-user-script) ,注意:要复制全部内容,包括注释部分。(此步骤默认你已经安装了油猴插件,没安装的话就安装下 👉[油猴插件安装地址](https://chrome.google.com/webstore/detail/tampermonkey/dhdgffkkebhmkfjojejmpbldmpobfkfo?hl=zh-CN),没有梯子的同学可以从 chrome 商店镜像下载,比如[收藏猫插件](https://chrome.pictureknow.com/extension?id=4d999497b75d4eb6acf4d0db3053f1af)) 31 | ![](https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/811cad2db5cb4332bfec83ea697aa2a2~tplv-k3u1fbpfcp-watermark.image) 32 | 33 | 4. 打开某网页,你能看到一只的猴子 🐒,代表流程已跑通,你只需开发自己的业务代码即可 🎉。 34 | ![](https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/6f8e6a5a044f4f2980febedf066bbcd1~tplv-k3u1fbpfcp-watermark.gif) 35 | -------------------------------------------------------------------------------- /example/MoveSearch/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /example/MoveSearch/README.md: -------------------------------------------------------------------------------- 1 | ## MoveSearch 2 | 3 | 划词搜索插件 4 | 5 | ## 功能 6 | 7 | 基于油猴插件,在任何网页选中文字,弹出弹窗。弹窗内容是百度开发者搜索的内容。 8 | **优势:** 快速检索文章中的知识点 9 | 10 | ## 使用 11 | 12 | 1. 安装[油猴插件](https://chrome.google.com/webstore/detail/tampermonkey/dhdgffkkebhmkfjojejmpbldmpobfkfo?hl=zh-CN),没有梯子的同学可以从 chrome 商店镜像下载,比如[收藏猫插件](https://chrome.pictureknow.com/extension?id=4d999497b75d4eb6acf4d0db3053f1af) 13 | 2. 安装[MoveSearch](https://greasyfork.org/zh-CN/scripts/421189-movesearch) 14 | 15 | ## 开发 16 | 17 | 基于 wokoo 脚手架搭建的初始化工程 18 | 19 | 具体开发过程请阅读:xxx 20 | 21 | **业务难点** 22 | 23 | 1. 弹窗的位置计算 24 | 2. 鼠标点击位置的边界检测 25 | 3. baidu 接口跨域问题 26 | 27 | ## 了解更多 28 | 29 | 如果想了解更多内容,请访问下面的网址: 30 | [油猴脚手架 wokoo 使用说明](https://juejin.cn/post/6922815205575491597) 31 | [油猴脚手架 wokoo git 仓库](https://github.com/kinyaying/wokoo) 32 | -------------------------------------------------------------------------------- /example/MoveSearch/dist/app.bundle.js.LICENSE.txt: -------------------------------------------------------------------------------- 1 | /* 2 | object-assign 3 | (c) Sindre Sorhus 4 | @license MIT 5 | */ 6 | 7 | /** @license React v0.20.1 8 | * scheduler.production.min.js 9 | * 10 | * Copyright (c) Facebook, Inc. and its affiliates. 11 | * 12 | * This source code is licensed under the MIT license found in the 13 | * LICENSE file in the root directory of this source tree. 14 | */ 15 | 16 | /** @license React v16.14.0 17 | * react.production.min.js 18 | * 19 | * Copyright (c) Facebook, Inc. and its affiliates. 20 | * 21 | * This source code is licensed under the MIT license found in the 22 | * LICENSE file in the root directory of this source tree. 23 | */ 24 | 25 | /** @license React v17.0.1 26 | * react-dom.production.min.js 27 | * 28 | * Copyright (c) Facebook, Inc. and its affiliates. 29 | * 30 | * This source code is licensed under the MIT license found in the 31 | * LICENSE file in the root directory of this source tree. 32 | */ 33 | -------------------------------------------------------------------------------- /example/MoveSearch/dist/index.html: -------------------------------------------------------------------------------- 1 | Document -------------------------------------------------------------------------------- /example/MoveSearch/dist/vendor.bundle.js.LICENSE.txt: -------------------------------------------------------------------------------- 1 | /* 2 | object-assign 3 | (c) Sindre Sorhus 4 | @license MIT 5 | */ 6 | 7 | /** @license React v0.20.1 8 | * scheduler.production.min.js 9 | * 10 | * Copyright (c) Facebook, Inc. and its affiliates. 11 | * 12 | * This source code is licensed under the MIT license found in the 13 | * LICENSE file in the root directory of this source tree. 14 | */ 15 | 16 | /** @license React v16.14.0 17 | * react.production.min.js 18 | * 19 | * Copyright (c) Facebook, Inc. and its affiliates. 20 | * 21 | * This source code is licensed under the MIT license found in the 22 | * LICENSE file in the root directory of this source tree. 23 | */ 24 | 25 | /** @license React v17.0.1 26 | * react-dom.production.min.js 27 | * 28 | * Copyright (c) Facebook, Inc. and its affiliates. 29 | * 30 | * This source code is licensed under the MIT license found in the 31 | * LICENSE file in the root directory of this source tree. 32 | */ 33 | -------------------------------------------------------------------------------- /example/MoveSearch/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "MoveSearch", 3 | "version": "0.0.1", 4 | "private": true, 5 | "scripts": { 6 | "start": "cross-env NODE_ENV=development webpack-dev-server", 7 | "build": "webpack" 8 | }, 9 | "dependencies": { 10 | "@babel/core": "7.12.10", 11 | "@babel/preset-react": "7.12.10", 12 | "axios": "^0.21.1", 13 | "babel-loader": "8.2.2", 14 | "react": "16.14.0", 15 | "react-dom": "17.0.1", 16 | "react-loader": "2.4.7" 17 | }, 18 | "devDependencies": { 19 | "@babel/plugin-proposal-class-properties": "7.12.1", 20 | "@babel/plugin-proposal-decorators": "7.12.12", 21 | "@babel/preset-env": "7.12.11", 22 | "cross-env": "7.0.3", 23 | "css-loader": "5.0.1", 24 | "file-loader": "6.2.0", 25 | "html-webpack-plugin": "4.5.1", 26 | "less": "4.1.1", 27 | "less-loader": "7.3.0", 28 | "style-loader": "2.0.0", 29 | "url-loader": "4.1.1", 30 | "webpack": "5.19.0", 31 | "webpack-cli": "3.3.12", 32 | "webpack-dev-server": "3.11.2", 33 | "webpack-merge": "5.7.3" 34 | } 35 | } -------------------------------------------------------------------------------- /example/MoveSearch/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kinyaying/wokoo/2961afcb53c0e85dae8ec0f93b6f73fb0c9eb134/example/MoveSearch/public/favicon.ico -------------------------------------------------------------------------------- /example/MoveSearch/public/icon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kinyaying/wokoo/2961afcb53c0e85dae8ec0f93b6f73fb0c9eb134/example/MoveSearch/public/icon.jpg -------------------------------------------------------------------------------- /example/MoveSearch/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /example/MoveSearch/src/app.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import axios from 'axios' 3 | import './app.less' 4 | 5 | // 弹窗宽度 6 | const MODAL_WIDTH = 350 7 | /** 8 | * 边界检测,鼠标点击modal之外,modal隐藏 9 | * @param {*} x 鼠标的x轴位置 10 | * @param {*} y 鼠标的y轴位置 11 | * @param {*} modalPosition 弹窗的left和top 12 | */ 13 | function boundaryDetection(x, y, modalPosition = { left: 0, top: 0 }) { 14 | let { left, top } = modalPosition 15 | if ( 16 | x > left && 17 | x < left + MODAL_WIDTH && 18 | y > top && 19 | y < top + MoveSearchApp.offsetHeight 20 | ) { 21 | return true 22 | } 23 | return false 24 | } 25 | 26 | export default class extends React.Component { 27 | constructor(props) { 28 | super(props) 29 | this.state = { 30 | show: false, 31 | selectedText: '', 32 | modalPosition: {}, 33 | data: null, 34 | } 35 | } 36 | componentDidMount() { 37 | document.addEventListener('mouseup', (e) => { 38 | var selectionObj = window.getSelection() 39 | var selectedText = selectionObj.toString() 40 | // 选中文字为空,说明当前操作为点击 41 | if (selectedText.length === 0) { 42 | if (this.state.show) { 43 | // 重新计算是否关闭弹窗 44 | // 检测鼠标位置是否在弹窗内,不是则关闭弹窗 45 | var inModal = boundaryDetection( 46 | e.clientX, 47 | e.clientY, 48 | this.state.modalPosition 49 | ) 50 | if (!inModal) { 51 | this.setState({ 52 | show: false, 53 | data: [], 54 | }) 55 | } 56 | } 57 | } else { 58 | // 选中文字不为空,1. 请求百度接口,2. 根据返回数据确定是否显示弹窗 59 | var selectionObjRect = selectionObj 60 | .getRangeAt(0) 61 | .getBoundingClientRect() 62 | let { x, y, height, width } = selectionObjRect // 获取选中文字的位置,x y是横纵坐标,height width是选中文字的高度和宽度 63 | // 计算弹窗位置,算出left和top 64 | var left = x - MODAL_WIDTH / 2 + width / 2 65 | left = left > 10 ? left : 10 66 | left = 67 | left < window.innerWidth - MODAL_WIDTH - 10 68 | ? left 69 | : window.innerWidth - MODAL_WIDTH - 10 70 | var top = y + height 71 | var scrollLeft = 72 | document.documentElement.scrollLeft || document.body.scrollLeft 73 | var scrollTop = 74 | document.documentElement.scrollTop || document.body.scrollTop 75 | axios 76 | .get( 77 | `https://service-47o6x44o-1256165881.gz.apigw.tencentcs.com/release/api/baidu?query=${selectedText}&pageNum=1&pageSize=10` 78 | ) 79 | .then((res) => { 80 | let { data } = res.data.data.documents 81 | if (data.length) { 82 | this.setState({ 83 | data, 84 | show: true, 85 | selectedText: selectedText, 86 | modalPosition: { 87 | left: left + scrollLeft, 88 | top: top + scrollTop, 89 | }, 90 | }) 91 | } 92 | }) 93 | } 94 | }) 95 | } 96 | 97 | render() { 98 | let { show, selectedText, modalPosition, data } = this.state 99 | return ( 100 | <> 101 | {show && data && data.length ? ( 102 |
109 |
110 | 120 |
121 |
122 | 130 |
131 | ) : null} 132 | 133 | ) 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /example/MoveSearch/src/app.less: -------------------------------------------------------------------------------- 1 | @font-color: #2440b3; 2 | @background-color: #fff; 3 | @background-color-dk: #22313f; 4 | @border-color-dk: #282a33; 5 | #wokooApp-MoveSearch { 6 | .move-search { 7 | position: absolute; 8 | text-align: center; 9 | width: 350px; 10 | max-height: 300px; 11 | top: 0; 12 | right: 0; 13 | border-radius: 5px; 14 | z-index: 2147483647; 15 | box-shadow: rgba(0, 0, 0, 0.2) 0px 16px 100px 0px; 16 | transition: all 0.1s ease-out 0s; 17 | border: 1px solide #282a33; 18 | background: @background-color; 19 | font-size: 12px; 20 | } 21 | .move-search-content { 22 | position: relative; 23 | max-height: 276px; 24 | overflow-y: auto; 25 | } 26 | .move-search-li { 27 | list-style: none; 28 | text-align: left; 29 | margin: 16px; 30 | line-height: 16px; 31 | word-wrap: break-word; 32 | white-space: normal; 33 | word-break: break-all; 34 | } 35 | .move-search-li a { 36 | display: flex; 37 | font-size: 14px; 38 | margin-bottom: 8px; 39 | color: @font-color; 40 | text-decoration: none; 41 | } 42 | .move-search-bottom-fade { 43 | position: absolute; 44 | bottom: 0px; 45 | left: 0px; 46 | right: 0px; 47 | border-bottom-left-radius: 5px; 48 | border-bottom-right-radius: 5px; 49 | margin: 0px; 50 | padding: 36px; 51 | background: linear-gradient( 52 | rgba(255, 255, 255, 0) 0%, 53 | rgb(255, 255, 255) 50%, 54 | rgb(255, 255, 255) 100% 55 | ); 56 | background: linear-gradient( 57 | rgba(255, 255, 255, 0) 0%, 58 | rgb(255, 255, 255) 50%, 59 | rgb(255, 255, 255) 100% 60 | ); 61 | } 62 | .move-search-footer { 63 | position: absolute; 64 | display: flex; 65 | bottom: 0; 66 | height: 24px; 67 | line-height: 24px; 68 | justify-content: space-between; 69 | width: 100%; 70 | padding: 0 16px; 71 | } 72 | .move-search-footer a { 73 | color: @font-color; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /example/MoveSearch/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import ReactDOM from 'react-dom' 3 | import App from './app' 4 | 5 | const wokooApp = document.createElement('div') 6 | wokooApp.id = 'wokooApp-MoveSearch' 7 | document.body.appendChild(wokooApp) 8 | 9 | ReactDOM.render(, wokooApp) 10 | -------------------------------------------------------------------------------- /example/MoveSearch/tampermonkey.js: -------------------------------------------------------------------------------- 1 | // ==UserScript== 2 | // @name MoveSearch 3 | // @namespace http://tampermonkey.net/ 4 | // @version 0.0.1 5 | // @description 划词翻译,在网页中选中文字,会出现弹窗,弹窗内容是百度搜索的内容 6 | // @author kinyaying 7 | // @match https://*/* 8 | // @match http://*/* 9 | 10 | // ==/UserScript== 11 | 12 | ;(function () { 13 | 'use strict' 14 | if (location.href === 'http://localhost:8080/') return 15 | var script = document.createElement('script') 16 | script.src = 'http://localhost:8080/app.bundle.js' 17 | document.body.appendChild(script) 18 | })() 19 | -------------------------------------------------------------------------------- /example/MoveSearch/webpack.config.base.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | entry: { 3 | app: '/src/index.js', 4 | vendor: [ 5 | // 将react和react-dom这些单独打包出来,减小打包文件体积 6 | 'react', 7 | 'react-dom', 8 | ], 9 | }, 10 | module: { 11 | rules: [ 12 | { 13 | test: /\.(js|jsx)$/, //匹配js文件 14 | use: { 15 | loader: 'babel-loader', 16 | options: { 17 | presets: ['@babel/preset-react', '@babel/preset-env'], 18 | plugins: [ 19 | ['@babel/plugin-proposal-decorators', { legacy: true }], 20 | ['@babel/plugin-proposal-class-properties', { loose: true }], 21 | ], 22 | }, 23 | }, 24 | }, 25 | ], 26 | }, 27 | } 28 | -------------------------------------------------------------------------------- /example/MoveSearch/webpack.config.js: -------------------------------------------------------------------------------- 1 | const HtmlWebpackPlugin = require('html-webpack-plugin') 2 | const { merge } = require('webpack-merge') 3 | const base = require('./webpack.config.base') 4 | 5 | module.exports = merge(base, { 6 | mode: process.env.NODE_ENV || 'production', 7 | devtool: 'source-map', 8 | output: { 9 | filename: '[name].bundle.js', 10 | path: __dirname + '/dist', 11 | }, 12 | module: { 13 | rules: [ 14 | { 15 | test: /\.(less|css)$/, 16 | use: ['style-loader', 'css-loader', 'less-loader'], 17 | }, 18 | { 19 | test: /\.(woff|woff2|eot|ttf|otf|png|svg|jpg|gif)$/, 20 | use: { 21 | loader: 'url-loader', 22 | options: { 23 | limit: 20480, 24 | }, 25 | }, 26 | }, 27 | ], 28 | }, 29 | plugins: [ 30 | new HtmlWebpackPlugin({ 31 | template: './public/index.html', 32 | }), 33 | ], 34 | }) 35 | -------------------------------------------------------------------------------- /example/jsDelivr/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /example/jsDelivr/README.md: -------------------------------------------------------------------------------- 1 | ## jsdelivr 2 | 3 | 基于 wokoo 搭建的初始化工程,用于油猴插件开发。 4 | 5 | **基础配置:** 6 | 7 | - react 8 | - less 9 | - webpack 10 | 11 | ## 目录结构 12 | 13 | ## 开发 14 | 15 | **启动** 16 | 17 | **构建** 18 | 19 | ## 实例 demo 20 | 21 | ## 了解更多 22 | 23 | 如果想了解更多内容,请访问下面的网址: 24 | [油猴脚手架 wokoo 使用说明](https://juejin.cn/post/6922815205575491597) 25 | [油猴脚手架 wokoo git 仓库](https://github.com/kinyaying/wokoo) 26 | -------------------------------------------------------------------------------- /example/jsDelivr/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jsdelivr", 3 | "version": "0.0.1", 4 | "private": true, 5 | "scripts": { 6 | "start": "cross-env NODE_ENV=development webpack-dev-server", 7 | "build": "webpack" 8 | }, 9 | "dependencies": { 10 | "@babel/core": "7.12.10", 11 | "@babel/preset-react": "7.12.10", 12 | "babel-loader": "8.2.2", 13 | "react": "17.0.1", 14 | "react-dom": "17.0.1", 15 | "react-loader": "2.4.7" 16 | }, 17 | "devDependencies": { 18 | "cross-env": "7.0.3", 19 | "css-loader": "5.0.1", 20 | "file-loader": "6.2.0", 21 | "html-webpack-plugin": "4.5.1", 22 | "less": "4.1.0", 23 | "less-loader": "7.3.0", 24 | "style-loader": "2.0.0", 25 | "url-loader": "4.1.1", 26 | "webpack": "5.18.0", 27 | "webpack-cli": "3.3.12", 28 | "webpack-dev-server": "3.11.2", 29 | "webpack-merge": "5.7.3" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /example/jsDelivr/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kinyaying/wokoo/2961afcb53c0e85dae8ec0f93b6f73fb0c9eb134/example/jsDelivr/public/favicon.ico -------------------------------------------------------------------------------- /example/jsDelivr/public/icon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kinyaying/wokoo/2961afcb53c0e85dae8ec0f93b6f73fb0c9eb134/example/jsDelivr/public/icon.jpg -------------------------------------------------------------------------------- /example/jsDelivr/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /example/jsDelivr/src/app.css: -------------------------------------------------------------------------------- 1 | .App { 2 | position: absolute; 3 | text-align: center; 4 | width: 400px; 5 | height: 400px; 6 | top: 0; 7 | right: 0; 8 | z-index: 999; 9 | } 10 | .App-logo { 11 | height: 30vmin; 12 | border-radius: 50%; 13 | pointer-events: none; 14 | } 15 | @media (prefers-reduced-motion: no-preference) { 16 | .App-logo { 17 | animation: App-logo-spin infinite 20s linear; 18 | } 19 | } 20 | 21 | .App-header { 22 | background-color: #6c4d25; 23 | display: flex; 24 | flex-direction: column; 25 | align-items: center; 26 | justify-content: center; 27 | font-size: calc(10px + 2vmin); 28 | color: white; 29 | height: 100%; 30 | } 31 | 32 | .App-link { 33 | color: #efb61c; 34 | } 35 | .App-close-icon { 36 | position: absolute; 37 | top: 10px; 38 | right: 10px; 39 | cursor: pointer; 40 | } 41 | .App-hide { 42 | position: absolute; 43 | text-align: center; 44 | width: 100px; 45 | height: 40px; 46 | background-color: #6c4d25; 47 | top: 0; 48 | right: 0; 49 | z-index: 999; 50 | display: flex; 51 | align-items: center; 52 | justify-content: center; 53 | color: #fff; 54 | cursor: pointer; 55 | } 56 | .App-hide-logo { 57 | width: 30px; 58 | height: 30px; 59 | border-radius: 50%; 60 | margin-right: 10px; 61 | } 62 | 63 | @keyframes App-logo-spin { 64 | from { 65 | transform: rotate(0deg); 66 | } 67 | to { 68 | transform: rotate(360deg); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /example/jsDelivr/src/app.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import './app.css' 3 | import logo from '../public/icon.jpg' 4 | export default class extends React.Component { 5 | constructor(props) { 6 | super(props) 7 | this.state = { show: true } 8 | } 9 | handleClose() { 10 | this.setState({ 11 | show: !this.state.show, 12 | }) 13 | } 14 | render() { 15 | let { show } = this.state 16 | return ( 17 | <> 18 | {show ? ( 19 |
20 |
21 | logo 22 | 26 | X 27 | 28 |

29 | Edit App.js and save to reload. 30 |

31 | 37 | Learn Wokoo 38 | 39 |
40 |
41 | ) : ( 42 |
43 | logo 44 | open 45 |
46 | )} 47 | 48 | ) 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /example/jsDelivr/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import ReactDOM from 'react-dom' 3 | import App from './app' 4 | 5 | const wokooApp = document.createElement('div') 6 | wokooApp.id = 'wokooApp' 7 | document.body.appendChild(wokooApp) 8 | ReactDOM.render(, wokooApp) 9 | -------------------------------------------------------------------------------- /example/jsDelivr/tampermonkey.txt: -------------------------------------------------------------------------------- 1 | // ==UserScript== 2 | // @name jsdelivr 3 | // @namespace http://tampermonkey.net/ 4 | // @version 0.0.1 5 | // @description try to take over the world! 6 | // @author kinyaying 7 | // @match https://*/* 8 | // @match http://*/* 9 | 10 | 11 | // ==/UserScript== 12 | 13 | (function() { 14 | 'use strict'; 15 | if(location.href === "http://localhost:8080/") return 16 | var script = document.createElement('script') 17 | script.src='http://localhost:8080/app.bundle.js' 18 | document.body.appendChild(script) 19 | })(); -------------------------------------------------------------------------------- /example/jsDelivr/webpack.config.base.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | entry: { 3 | app: '/src/index.js', 4 | }, 5 | module: { 6 | rules: [ 7 | { 8 | test: /\.(js|jsx)$/, 9 | use: [ 10 | { 11 | loader: 'babel-loader', 12 | options: { 13 | presets: ['@babel/preset-react'], 14 | }, 15 | }, 16 | ], 17 | }, 18 | ], 19 | }, 20 | } 21 | -------------------------------------------------------------------------------- /example/jsDelivr/webpack.config.js: -------------------------------------------------------------------------------- 1 | const HtmlWebpackPlugin = require('html-webpack-plugin') 2 | const { merge } = require('webpack-merge') 3 | const base = require('./webpack.config.base') 4 | 5 | module.exports = merge(base, { 6 | mode: process.env.NODE_ENV || 'production', 7 | devtool: 'source-map', 8 | output: { 9 | filename: '[name].bundle.js', 10 | path: __dirname + '/dist', 11 | }, 12 | module: { 13 | rules: [ 14 | { 15 | test: /\.(less|css)$/, 16 | use: ['style-loader', 'css-loader', 'less-loader'], 17 | }, 18 | { 19 | test: /\.(woff|woff2|eot|ttf|otf|png|svg|jpg|gif)$/, 20 | use: { 21 | loader: 'url-loader', 22 | options: { 23 | limit: 20480, 24 | }, 25 | }, 26 | }, 27 | ], 28 | }, 29 | plugins: [ 30 | new HtmlWebpackPlugin({ 31 | template: './public/index.html', 32 | }), 33 | ], 34 | }) 35 | -------------------------------------------------------------------------------- /example/wokoo-demo/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /example/wokoo-demo/README.md: -------------------------------------------------------------------------------- 1 | ## wokoo-demo 2 | 3 | 基于 wokoo 搭建的初始化工程,用于油猴插件开发。 4 | 5 | **基础配置:** 6 | 7 | - vue 8 | - less 9 | - webpack 10 | 11 | ## 使用 12 | 13 | 1. 谷歌商店搜索并安装 👉[油猴插件](https://chrome.google.com/webstore/detail/tampermonkey-beta/gcalenpjmijncebpfijmoaglllgpjagf),点击「添加扩展程序」 14 | 2. 油猴市场上搜索 [wokoo-demo](https://greasyfork.org/en/scripts?filter_locale=0&q=wokoo-demo) 15 | 3. 点击进入详情,[wokoo-demo](https://greasyfork.org/en/scripts/420327-wokoo-demo) 点击「install this script」 16 | 4. 随便打开一个网页,比如 [baidu](https://www.baidu.com),网页右上角会出现初始化界面 17 | ![wokoo-demo](https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/0e978d446a66435b9cf1f9b30eee979d~tplv-k3u1fbpfcp-watermark.image) 18 | > 这个简单的 demo 只是一个示例,实际上可以发挥你的想象实现任何你想做的插件。🎉 19 | 20 | ## 了解更多 21 | 22 | 如果想了解更多内容,请访问下面的网址: 23 | [油猴脚手架 wokoo 使用说明](https://juejin.cn/post/6922815205575491597) 24 | [油猴脚手架 wokoo git 仓库](https://github.com/kinyaying/wokoo) 25 | -------------------------------------------------------------------------------- /example/wokoo-demo/dist/app.bundle.js: -------------------------------------------------------------------------------- 1 | /*! For license information please see app.bundle.js.LICENSE.txt */ 2 | (()=>{"use strict";var t={31:(t,e,n)=>{n.d(e,{Z:()=>s});var r=n(15),o=n.n(r),i=n(645),a=n.n(i)()(o());a.push([t.id,".App {\n position: absolute;\n text-align: center;\n width: 400px;\n height: 400px;\n top: 0;\n right: 0;\n z-index: 999;\n}\n.App-logo {\n height: 30vmin;\n border-radius: 50%;\n pointer-events: none;\n}\n@media (prefers-reduced-motion: no-preference) {\n .App-logo {\n animation: App-logo-spin infinite 20s linear;\n }\n}\n.App-header {\n background-color: #6c4d25;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n font-size: calc(10px + 2vmin);\n color: white;\n height: 100%;\n}\n.App-link {\n color: #efb61c;\n}\n.App-close-icon {\n position: absolute;\n top: 0;\n right: 10px;\n font-size: 30px;\n cursor: pointer;\n}\n.App-hide {\n position: absolute;\n text-align: center;\n width: 100px;\n height: 40px;\n background-color: #6c4d25;\n top: 0;\n right: 0;\n z-index: 999;\n display: flex;\n align-items: center;\n justify-content: center;\n color: #fff;\n cursor: pointer;\n}\n.App-hide-logo {\n width: 30px;\n height: 30px;\n border-radius: 50%;\n margin-right: 10px;\n}\n@keyframes App-logo-spin {\n from {\n transform: rotate(0deg);\n }\n to {\n transform: rotate(360deg);\n }\n}\n","",{version:3,sources:["webpack://./src/app.less"],names:[],mappings:"AAAA;EACE,kBAAA;EACA,kBAAA;EACA,YAAA;EACA,aAAA;EACA,MAAA;EACA,QAAA;EACA,YAAA;AACF;AACA;EACE,cAAA;EACA,kBAAA;EACA,oBAAA;AACF;AACA;EACE;IACE,4CAAA;EACF;AACF;AAEA;EACE,yBAAA;EACA,aAAA;EACA,sBAAA;EACA,mBAAA;EACA,uBAAA;EACA,6BAAA;EACA,YAAA;EACA,YAAA;AAAF;AAGA;EACE,cAAA;AADF;AAGA;EACE,kBAAA;EACA,MAAA;EACA,WAAA;EACA,eAAA;EACA,eAAA;AADF;AAGA;EACE,kBAAA;EACA,kBAAA;EACA,YAAA;EACA,YAAA;EACA,yBAAA;EACA,MAAA;EACA,QAAA;EACA,YAAA;EACA,aAAA;EACA,mBAAA;EACA,uBAAA;EACA,WAAA;EACA,eAAA;AADF;AAGA;EACE,WAAA;EACA,YAAA;EACA,kBAAA;EACA,kBAAA;AADF;AAIA;EACE;IACE,uBAAA;EAFF;EAIA;IACE,yBAAA;EAFF;AACF",sourcesContent:[".App {\n position: absolute;\n text-align: center;\n width: 400px;\n height: 400px;\n top: 0;\n right: 0;\n z-index: 999;\n}\n.App-logo {\n height: 30vmin;\n border-radius: 50%;\n pointer-events: none;\n}\n@media (prefers-reduced-motion: no-preference) {\n .App-logo {\n animation: App-logo-spin infinite 20s linear;\n }\n}\n\n.App-header {\n background-color: #6c4d25;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n font-size: calc(10px + 2vmin);\n color: white;\n height: 100%;\n}\n\n.App-link {\n color: #efb61c;\n}\n.App-close-icon {\n position: absolute;\n top: 0;\n right: 10px;\n font-size: 30px;\n cursor: pointer;\n}\n.App-hide {\n position: absolute;\n text-align: center;\n width: 100px;\n height: 40px;\n background-color: #6c4d25;\n top: 0;\n right: 0;\n z-index: 999;\n display: flex;\n align-items: center;\n justify-content: center;\n color: #fff;\n cursor: pointer;\n}\n.App-hide-logo {\n width: 30px;\n height: 30px;\n border-radius: 50%;\n margin-right: 10px;\n}\n\n@keyframes App-logo-spin {\n from {\n transform: rotate(0deg);\n }\n to {\n transform: rotate(360deg);\n }\n}\n"],sourceRoot:""}]);const s=a},645:t=>{t.exports=function(t){var e=[];return e.toString=function(){return this.map((function(e){var n=t(e);return e[2]?"@media ".concat(e[2]," {").concat(n,"}"):n})).join("")},e.i=function(t,n,r){"string"==typeof t&&(t=[[null,t,""]]);var o={};if(r)for(var i=0;i{function e(t,e){(null==e||e>t.length)&&(e=t.length);for(var n=0,r=new Array(e);n{var r,o=function(){var t={};return function(e){if(void 0===t[e]){var n=document.querySelector(e);if(window.HTMLIFrameElement&&n instanceof window.HTMLIFrameElement)try{n=n.contentDocument.head}catch(t){n=null}t[e]=n}return t[e]}}(),i=[];function a(t){for(var e=-1,n=0;n{var e=t&&t.__esModule?()=>t.default:()=>t;return n.d(e,{a:e}),e},n.d=(t,e)=>{for(var r in e)n.o(e,r)&&!n.o(t,r)&&Object.defineProperty(t,r,{enumerable:!0,get:e[r]})},n.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(t){if("object"==typeof window)return window}}(),n.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e),(()=>{var t=Object.freeze({});function e(t){return null==t}function r(t){return null!=t}function o(t){return!0===t}function i(t){return"string"==typeof t||"number"==typeof t||"symbol"==typeof t||"boolean"==typeof t}function a(t){return null!==t&&"object"==typeof t}var s=Object.prototype.toString;function c(t){return"[object Object]"===s.call(t)}function u(t){var e=parseFloat(String(t));return e>=0&&Math.floor(e)===e&&isFinite(t)}function l(t){return r(t)&&"function"==typeof t.then&&"function"==typeof t.catch}function f(t){return null==t?"":Array.isArray(t)||c(t)&&t.toString===s?JSON.stringify(t,null,2):String(t)}function d(t){var e=parseFloat(t);return isNaN(e)?t:e}function p(t,e){for(var n=Object.create(null),r=t.split(","),o=0;o-1)return t.splice(n,1)}}var h=Object.prototype.hasOwnProperty;function y(t,e){return h.call(t,e)}function m(t){var e=Object.create(null);return function(n){return e[n]||(e[n]=t(n))}}var g=/-(\w)/g,b=m((function(t){return t.replace(g,(function(t,e){return e?e.toUpperCase():""}))})),C=m((function(t){return t.charAt(0).toUpperCase()+t.slice(1)})),_=/\B([A-Z])/g,w=m((function(t){return t.replace(_,"-$1").toLowerCase()})),E=Function.prototype.bind?function(t,e){return t.bind(e)}:function(t,e){function n(n){var r=arguments.length;return r?r>1?t.apply(e,arguments):t.call(e,n):t.call(e)}return n._length=t.length,n};function x(t,e){e=e||0;for(var n=t.length-e,r=new Array(n);n--;)r[n]=t[n+e];return r}function k(t,e){for(var n in e)t[n]=e[n];return t}function O(t){for(var e={},n=0;n0,Y=X&&X.indexOf("edge/")>0,W=(X&&X.indexOf("android"),X&&/iphone|ipad|ipod|ios/.test(X)||"ios"===U),q=(X&&/chrome\/\d+/.test(X),X&&/phantomjs/.test(X),X&&X.match(/firefox\/(\d+)/)),J={}.watch,$=!1;if(z)try{var K={};Object.defineProperty(K,"passive",{get:function(){$=!0}}),window.addEventListener("test-passive",null,K)}catch(t){}var tt=function(){return void 0===R&&(R=!z&&!V&&void 0!==n.g&&n.g.process&&"server"===n.g.process.env.VUE_ENV),R},et=z&&window.__VUE_DEVTOOLS_GLOBAL_HOOK__;function nt(t){return"function"==typeof t&&/native code/.test(t.toString())}var rt,ot="undefined"!=typeof Symbol&&nt(Symbol)&&"undefined"!=typeof Reflect&&nt(Reflect.ownKeys);rt="undefined"!=typeof Set&&nt(Set)?Set:function(){function t(){this.set=Object.create(null)}return t.prototype.has=function(t){return!0===this.set[t]},t.prototype.add=function(t){this.set[t]=!0},t.prototype.clear=function(){this.set=Object.create(null)},t}();var it=j,at=0,st=function(){this.id=at++,this.subs=[]};st.prototype.addSub=function(t){this.subs.push(t)},st.prototype.removeSub=function(t){A(this.subs,t)},st.prototype.depend=function(){st.target&&st.target.addDep(this)},st.prototype.notify=function(){for(var t=this.subs.slice(),e=0,n=t.length;e-1)if(i&&!y(o,"default"))a=!1;else if(""===a||a===w(t)){var c=Ft(String,o.type);(c<0||s0&&(ce((s=ue(s,(n||"")+"_"+a))[0])&&ce(u)&&(l[c]=vt(u.text+s[0].text),s.shift()),l.push.apply(l,s)):i(s)?ce(u)?l[c]=vt(u.text+s):""!==s&&l.push(vt(s)):ce(s)&&ce(u)?l[c]=vt(u.text+s.text):(o(t._isVList)&&r(s.tag)&&e(s.key)&&r(n)&&(s.key="__vlist"+n+"_"+a+"__"),l.push(s)));return l}function le(t,e){if(t){for(var n=Object.create(null),r=ot?Reflect.ownKeys(t):Object.keys(t),o=0;o0,a=e?!!e.$stable:!i,s=e&&e.$key;if(e){if(e._normalized)return e._normalized;if(a&&r&&r!==t&&s===r.$key&&!i&&!r.$hasNormal)return r;for(var c in o={},e)e[c]&&"$"!==c[0]&&(o[c]=ve(n,c,e[c]))}else o={};for(var u in n)u in o||(o[u]=Ae(n,u));return e&&Object.isExtensible(e)&&(e._normalized=o),F(o,"$stable",a),F(o,"$key",s),F(o,"$hasNormal",i),o}function ve(t,e,n){var r=function(){var t=arguments.length?n.apply(null,arguments):n({});return(t=t&&"object"==typeof t&&!Array.isArray(t)?[t]:se(t))&&(0===t.length||1===t.length&&t[0].isComment)?void 0:t};return n.proxy&&Object.defineProperty(t,e,{get:r,enumerable:!0,configurable:!0}),r}function Ae(t,e){return function(){return t[e]}}function he(t,e){var n,o,i,s,c;if(Array.isArray(t)||"string"==typeof t)for(n=new Array(t.length),o=0,i=t.length;odocument.createEvent("Event").timeStamp&&(un=function(){return ln.now()})}function fn(){var t,e;for(cn=un(),an=!0,en.sort((function(t,e){return t.id-e.id})),sn=0;snsn&&en[n].id>t.id;)n--;en.splice(n+1,0,t)}else en.push(t);on||(on=!0,$t(fn))}}(this)},pn.prototype.run=function(){if(this.active){var t=this.get();if(t!==this.value||a(t)||this.deep){var e=this.value;if(this.value=t,this.user)try{this.cb.call(this.vm,t,e)}catch(t){Rt(t,this.vm,'callback for watcher "'+this.expression+'"')}else this.cb.call(this.vm,t,e)}}},pn.prototype.evaluate=function(){this.value=this.get(),this.dirty=!1},pn.prototype.depend=function(){for(var t=this.deps.length;t--;)this.deps[t].depend()},pn.prototype.teardown=function(){if(this.active){this.vm._isBeingDestroyed||A(this.vm._watchers,this);for(var t=this.deps.length;t--;)this.deps[t].removeSub(this);this.active=!1}};var vn={enumerable:!0,configurable:!0,get:j,set:j};function An(t,e,n){vn.get=function(){return this[e][n]},vn.set=function(t){this[e][n]=t},Object.defineProperty(t,n,vn)}var hn={lazy:!0};function yn(t,e,n){var r=!tt();"function"==typeof n?(vn.get=r?mn(e):gn(n),vn.set=j):(vn.get=n.get?r&&!1!==n.cache?mn(e):gn(n.get):j,vn.set=n.set||j),Object.defineProperty(t,e,vn)}function mn(t){return function(){var e=this._computedWatchers&&this._computedWatchers[t];if(e)return e.dirty&&e.evaluate(),st.target&&e.depend(),e.value}}function gn(t){return function(){return t.call(this,this)}}function bn(t,e,n,r){return c(n)&&(r=n,n=n.handler),"string"==typeof n&&(n=t[n]),t.$watch(e,n,r)}var Cn=0;function _n(t){var e=t.options;if(t.super){var n=_n(t.super);if(n!==t.superOptions){t.superOptions=n;var r=function(t){var e,n=t.options,r=t.sealedOptions;for(var o in n)n[o]!==r[o]&&(e||(e={}),e[o]=n[o]);return e}(t);r&&k(t.extendOptions,r),(e=t.options=Nt(n,t.extendOptions)).name&&(e.components[e.name]=t)}}return e}function wn(t){this._init(t)}function En(t){return t&&(t.Ctor.options.name||t.tag)}function xn(t,e){return Array.isArray(t)?t.indexOf(e)>-1:"string"==typeof t?t.split(",").indexOf(e)>-1:(n=t,!("[object RegExp]"!==s.call(n))&&t.test(e));var n}function kn(t,e){var n=t.cache,r=t.keys,o=t._vnode;for(var i in n){var a=n[i];if(a){var s=En(a.componentOptions);s&&!e(s)&&On(n,i,r,o)}}}function On(t,e,n,r){var o=t[e];!o||r&&o.tag===r.tag||o.componentInstance.$destroy(),t[e]=null,A(n,e)}!function(e){e.prototype._init=function(e){var n=this;n._uid=Cn++,n._isVue=!0,e&&e._isComponent?function(t,e){var n=t.$options=Object.create(t.constructor.options),r=e._parentVnode;n.parent=e.parent,n._parentVnode=r;var o=r.componentOptions;n.propsData=o.propsData,n._parentListeners=o.listeners,n._renderChildren=o.children,n._componentTag=o.tag,e.render&&(n.render=e.render,n.staticRenderFns=e.staticRenderFns)}(n,e):n.$options=Nt(_n(n.constructor),e||{},n),n._renderProxy=n,n._self=n,function(t){var e=t.$options,n=e.parent;if(n&&!e.abstract){for(;n.$options.abstract&&n.$parent;)n=n.$parent;n.$children.push(t)}t.$parent=n,t.$root=n?n.$root:t,t.$children=[],t.$refs={},t._watcher=null,t._inactive=null,t._directInactive=!1,t._isMounted=!1,t._isDestroyed=!1,t._isBeingDestroyed=!1}(n),function(t){t._events=Object.create(null),t._hasHookEvent=!1;var e=t.$options._parentListeners;e&&Ye(t,e)}(n),function(e){e._vnode=null,e._staticTrees=null;var n=e.$options,r=e.$vnode=n._parentVnode,o=r&&r.context;e.$slots=fe(n._renderChildren,o),e.$scopedSlots=t,e._c=function(t,n,r,o){return Fe(e,t,n,r,o,!1)},e.$createElement=function(t,n,r,o){return Fe(e,t,n,r,o,!0)};var i=r&&r.data;wt(e,"$attrs",i&&i.attrs||t,null,!0),wt(e,"$listeners",n._parentListeners||t,null,!0)}(n),tn(n,"beforeCreate"),function(t){var e=le(t.$options.inject,t);e&&(bt(!1),Object.keys(e).forEach((function(n){wt(t,n,e[n])})),bt(!0))}(n),function(t){t._watchers=[];var e=t.$options;e.props&&function(t,e){var n=t.$options.propsData||{},r=t._props={},o=t.$options._propKeys=[];t.$parent&&bt(!1);var i=function(i){o.push(i);var a=Pt(i,e,n,t);wt(r,i,a),i in t||An(t,"_props",i)};for(var a in e)i(a);bt(!0)}(t,e.props),e.methods&&function(t,e){for(var n in t.$options.props,e)t[n]="function"!=typeof e[n]?j:E(e[n],t)}(t,e.methods),e.data?function(t){var e=t.$options.data;c(e=t._data="function"==typeof e?function(t,e){ut();try{return t.call(e,e)}catch(t){return Rt(t,e,"data()"),{}}finally{lt()}}(e,t):e||{})||(e={});for(var n,r=Object.keys(e),o=t.$options.props,i=(t.$options.methods,r.length);i--;){var a=r[i];o&&y(o,a)||(n=void 0,36===(n=(a+"").charCodeAt(0))||95===n)||An(t,"_data",a)}_t(e,!0)}(t):_t(t._data={},!0),e.computed&&function(t,e){var n=t._computedWatchers=Object.create(null),r=tt();for(var o in e){var i=e[o],a="function"==typeof i?i:i.get;r||(n[o]=new pn(t,a||j,j,hn)),o in t||yn(t,o,i)}}(t,e.computed),e.watch&&e.watch!==J&&function(t,e){for(var n in e){var r=e[n];if(Array.isArray(r))for(var o=0;o1?x(n):n;for(var r=x(arguments,1),o='event handler for "'+t+'"',i=0,a=n.length;iparseInt(this.max)&&On(a,s[0],s,this._vnode)),e.data.keepAlive=!0}return e||t&&t[0]}}};!function(t){var e={get:function(){return D}};Object.defineProperty(t,"config",e),t.util={warn:it,extend:k,mergeOptions:Nt,defineReactive:wt},t.set=Et,t.delete=xt,t.nextTick=$t,t.observable=function(t){return _t(t),t},t.options=Object.create(null),P.forEach((function(e){t.options[e+"s"]=Object.create(null)})),t.options._base=t,k(t.options.components,Sn),function(t){t.use=function(t){var e=this._installedPlugins||(this._installedPlugins=[]);if(e.indexOf(t)>-1)return this;var n=x(arguments,1);return n.unshift(this),"function"==typeof t.install?t.install.apply(t,n):"function"==typeof t&&t.apply(null,n),e.push(t),this}}(t),function(t){t.mixin=function(t){return this.options=Nt(this.options,t),this}}(t),function(t){t.cid=0;var e=1;t.extend=function(t){t=t||{};var n=this,r=n.cid,o=t._Ctor||(t._Ctor={});if(o[r])return o[r];var i=t.name||n.options.name,a=function(t){this._init(t)};return(a.prototype=Object.create(n.prototype)).constructor=a,a.cid=e++,a.options=Nt(n.options,t),a.super=n,a.options.props&&function(t){var e=t.options.props;for(var n in e)An(t.prototype,"_props",n)}(a),a.options.computed&&function(t){var e=t.options.computed;for(var n in e)yn(t.prototype,n,e[n])}(a),a.extend=n.extend,a.mixin=n.mixin,a.use=n.use,P.forEach((function(t){a[t]=n[t]})),i&&(a.options.components[i]=a),a.superOptions=n.options,a.extendOptions=t,a.sealedOptions=k({},a.options),o[r]=a,a}}(t),function(t){P.forEach((function(e){t[e]=function(t,n){return n?("component"===e&&c(n)&&(n.name=n.name||t,n=this.options._base.extend(n)),"directive"===e&&"function"==typeof n&&(n={bind:n,update:n}),this.options[e+"s"][t]=n,n):this.options[e+"s"][t]}}))}(t)}(wn),Object.defineProperty(wn.prototype,"$isServer",{get:tt}),Object.defineProperty(wn.prototype,"$ssrContext",{get:function(){return this.$vnode&&this.$vnode.ssrContext}}),Object.defineProperty(wn,"FunctionalRenderContext",{value:Be}),wn.version="2.6.12";var In=p("style,class"),Bn=p("input,textarea,option,select,progress"),Ln=p("contenteditable,draggable,spellcheck"),Nn=p("events,caret,typing,plaintext-only"),Tn=p("allowfullscreen,async,autofocus,autoplay,checked,compact,controls,declare,default,defaultchecked,defaultmuted,defaultselected,defer,disabled,enabled,formnovalidate,hidden,indeterminate,inert,ismap,itemscope,loop,multiple,muted,nohref,noresize,noshade,novalidate,nowrap,open,pauseonexit,readonly,required,reversed,scoped,seamless,selected,sortable,translate,truespeed,typemustmatch,visible"),Pn="http://www.w3.org/1999/xlink",Qn=function(t){return":"===t.charAt(5)&&"xlink"===t.slice(0,5)},Dn=function(t){return Qn(t)?t.slice(6,t.length):""},Fn=function(t){return null==t||!1===t};function Rn(t,e){return{staticClass:Mn(t.staticClass,e.staticClass),class:r(t.class)?[t.class,e.class]:e.class}}function Mn(t,e){return t?e?t+" "+e:t:e||""}function Hn(t){return Array.isArray(t)?function(t){for(var e,n="",o=0,i=t.length;o-1?lr(t,e,n):Tn(e)?Fn(n)?t.removeAttribute(e):(n="allowfullscreen"===e&&"EMBED"===t.tagName?"true":e,t.setAttribute(e,n)):Ln(e)?t.setAttribute(e,function(t,e){return Fn(e)||"false"===e?"false":"contenteditable"===t&&Nn(e)?e:"true"}(e,n)):Qn(e)?Fn(n)?t.removeAttributeNS(Pn,Dn(e)):t.setAttributeNS(Pn,e,n):lr(t,e,n)}function lr(t,e,n){if(Fn(n))t.removeAttribute(e);else{if(Z&&!G&&"TEXTAREA"===t.tagName&&"placeholder"===e&&""!==n&&!t.__ieph){var r=function(e){e.stopImmediatePropagation(),t.removeEventListener("input",r)};t.addEventListener("input",r),t.__ieph=!0}t.setAttribute(e,n)}}var fr={create:cr,update:cr};function dr(t,n){var o=n.elm,i=n.data,a=t.data;if(!(e(i.staticClass)&&e(i.class)&&(e(a)||e(a.staticClass)&&e(a.class)))){var s=function(t){for(var e=t.data,n=t,o=t;r(o.componentInstance);)(o=o.componentInstance._vnode)&&o.data&&(e=Rn(o.data,e));for(;r(n=n.parent);)n&&n.data&&(e=Rn(e,n.data));return i=e.staticClass,a=e.class,r(i)||r(a)?Mn(i,Hn(a)):"";var i,a}(n),c=o._transitionClasses;r(c)&&(s=Mn(s,Hn(c))),s!==o._prevClass&&(o.setAttribute("class",s),o._prevClass=s)}}var pr,vr={create:dr,update:dr};function Ar(t,e,n){var r=pr;return function o(){var i=e.apply(null,arguments);null!==i&&mr(t,o,n,r)}}var hr=Ut&&!(q&&Number(q[1])<=53);function yr(t,e,n,r){if(hr){var o=cn,i=e;e=i._wrapper=function(t){if(t.target===t.currentTarget||t.timeStamp>=o||t.timeStamp<=0||t.target.ownerDocument!==document)return i.apply(this,arguments)}}pr.addEventListener(t,e,$?{capture:n,passive:r}:n)}function mr(t,e,n,r){(r||pr).removeEventListener(t,e._wrapper||e,n)}function gr(t,n){if(!e(t.data.on)||!e(n.data.on)){var o=n.data.on||{},i=t.data.on||{};pr=n.elm,function(t){if(r(t.__r)){var e=Z?"change":"input";t[e]=[].concat(t.__r,t[e]||[]),delete t.__r}r(t.__c)&&(t.change=[].concat(t.__c,t.change||[]),delete t.__c)}(o),oe(o,i,yr,mr,Ar,n.context),pr=void 0}}var br,Cr={create:gr,update:gr};function _r(t,n){if(!e(t.data.domProps)||!e(n.data.domProps)){var o,i,a=n.elm,s=t.data.domProps||{},c=n.data.domProps||{};for(o in r(c.__ob__)&&(c=n.data.domProps=k({},c)),s)o in c||(a[o]="");for(o in c){if(i=c[o],"textContent"===o||"innerHTML"===o){if(n.children&&(n.children.length=0),i===s[o])continue;1===a.childNodes.length&&a.removeChild(a.childNodes[0])}if("value"===o&&"PROGRESS"!==a.tagName){a._value=i;var u=e(i)?"":String(i);wr(a,u)&&(a.value=u)}else if("innerHTML"===o&&Un(a.tagName)&&e(a.innerHTML)){(br=br||document.createElement("div")).innerHTML=""+i+"";for(var l=br.firstChild;a.firstChild;)a.removeChild(a.firstChild);for(;l.firstChild;)a.appendChild(l.firstChild)}else if(i!==s[o])try{a[o]=i}catch(t){}}}}function wr(t,e){return!t.composing&&("OPTION"===t.tagName||function(t,e){var n=!0;try{n=document.activeElement!==t}catch(t){}return n&&t.value!==e}(t,e)||function(t,e){var n=t.value,o=t._vModifiers;if(r(o)){if(o.number)return d(n)!==d(e);if(o.trim)return n.trim()!==e.trim()}return n!==e}(t,e))}var Er={create:_r,update:_r},xr=m((function(t){var e={},n=/:(.+)/;return t.split(/;(?![^(]*\))/g).forEach((function(t){if(t){var r=t.split(n);r.length>1&&(e[r[0].trim()]=r[1].trim())}})),e}));function kr(t){var e=Or(t.style);return t.staticStyle?k(t.staticStyle,e):e}function Or(t){return Array.isArray(t)?O(t):"string"==typeof t?xr(t):t}var jr,Sr=/^--/,Ir=/\s*!important$/,Br=function(t,e,n){if(Sr.test(e))t.style.setProperty(e,n);else if(Ir.test(n))t.style.setProperty(w(e),n.replace(Ir,""),"important");else{var r=Nr(e);if(Array.isArray(n))for(var o=0,i=n.length;o-1?e.split(Qr).forEach((function(e){return t.classList.add(e)})):t.classList.add(e);else{var n=" "+(t.getAttribute("class")||"")+" ";n.indexOf(" "+e+" ")<0&&t.setAttribute("class",(n+e).trim())}}function Fr(t,e){if(e&&(e=e.trim()))if(t.classList)e.indexOf(" ")>-1?e.split(Qr).forEach((function(e){return t.classList.remove(e)})):t.classList.remove(e),t.classList.length||t.removeAttribute("class");else{for(var n=" "+(t.getAttribute("class")||"")+" ",r=" "+e+" ";n.indexOf(r)>=0;)n=n.replace(r," ");(n=n.trim())?t.setAttribute("class",n):t.removeAttribute("class")}}function Rr(t){if(t){if("object"==typeof t){var e={};return!1!==t.css&&k(e,Mr(t.name||"v")),k(e,t),e}return"string"==typeof t?Mr(t):void 0}}var Mr=m((function(t){return{enterClass:t+"-enter",enterToClass:t+"-enter-to",enterActiveClass:t+"-enter-active",leaveClass:t+"-leave",leaveToClass:t+"-leave-to",leaveActiveClass:t+"-leave-active"}})),Hr=z&&!G,zr="transition",Vr="animation",Ur="transition",Xr="transitionend",Zr="animation",Gr="animationend";Hr&&(void 0===window.ontransitionend&&void 0!==window.onwebkittransitionend&&(Ur="WebkitTransition",Xr="webkitTransitionEnd"),void 0===window.onanimationend&&void 0!==window.onwebkitanimationend&&(Zr="WebkitAnimation",Gr="webkitAnimationEnd"));var Yr=z?window.requestAnimationFrame?window.requestAnimationFrame.bind(window):setTimeout:function(t){return t()};function Wr(t){Yr((function(){Yr(t)}))}function qr(t,e){var n=t._transitionClasses||(t._transitionClasses=[]);n.indexOf(e)<0&&(n.push(e),Dr(t,e))}function Jr(t,e){t._transitionClasses&&A(t._transitionClasses,e),Fr(t,e)}function $r(t,e,n){var r=to(t,e),o=r.type,i=r.timeout,a=r.propCount;if(!o)return n();var s=o===zr?Xr:Gr,c=0,u=function(){t.removeEventListener(s,l),n()},l=function(e){e.target===t&&++c>=a&&u()};setTimeout((function(){c0&&(n=zr,l=a,f=i.length):e===Vr?u>0&&(n=Vr,l=u,f=c.length):f=(n=(l=Math.max(a,u))>0?a>u?zr:Vr:null)?n===zr?i.length:c.length:0,{type:n,timeout:l,propCount:f,hasTransform:n===zr&&Kr.test(r[Ur+"Property"])}}function eo(t,e){for(;t.length1}function so(t,e){!0!==e.data.show&&ro(e)}var co=function(t){var n,a,s={},c=t.modules,u=t.nodeOps;for(n=0;n<$n.length;++n)for(s[$n[n]]=[],a=0;av?g(t,e(o[y+1])?null:o[y+1].elm,o,p,y,i):p>y&&C(n,d,v)}(d,A,y,i,l):r(y)?(r(t.text)&&u.setTextContent(d,""),g(d,null,y,0,y.length-1,i)):r(A)?C(A,0,A.length-1):r(t.text)&&u.setTextContent(d,""):t.text!==n.text&&u.setTextContent(d,n.text),r(v)&&r(p=v.hook)&&r(p=p.postpatch)&&p(t,n)}}}function x(t,e,n){if(o(n)&&r(t.parent))t.parent.data.pendingInsert=e;else for(var i=0;i-1,a.selected!==i&&(a.selected=i);else if(B(vo(a),r))return void(t.selectedIndex!==s&&(t.selectedIndex=s));o||(t.selectedIndex=-1)}}function po(t,e){return e.every((function(e){return!B(e,t)}))}function vo(t){return"_value"in t?t._value:t.value}function Ao(t){t.target.composing=!0}function ho(t){t.target.composing&&(t.target.composing=!1,yo(t.target,"input"))}function yo(t,e){var n=document.createEvent("HTMLEvents");n.initEvent(e,!0,!0),t.dispatchEvent(n)}function mo(t){return!t.componentInstance||t.data&&t.data.transition?t:mo(t.componentInstance._vnode)}var go={model:uo,show:{bind:function(t,e,n){var r=e.value,o=(n=mo(n)).data&&n.data.transition,i=t.__vOriginalDisplay="none"===t.style.display?"":t.style.display;r&&o?(n.data.show=!0,ro(n,(function(){t.style.display=i}))):t.style.display=r?i:"none"},update:function(t,e,n){var r=e.value;!r!=!e.oldValue&&((n=mo(n)).data&&n.data.transition?(n.data.show=!0,r?ro(n,(function(){t.style.display=t.__vOriginalDisplay})):oo(n,(function(){t.style.display="none"}))):t.style.display=r?t.__vOriginalDisplay:"none")},unbind:function(t,e,n,r,o){o||(t.style.display=t.__vOriginalDisplay)}}},bo={name:String,appear:Boolean,css:Boolean,mode:String,type:String,enterClass:String,leaveClass:String,enterToClass:String,leaveToClass:String,enterActiveClass:String,leaveActiveClass:String,appearClass:String,appearActiveClass:String,appearToClass:String,duration:[Number,String,Object]};function Co(t){var e=t&&t.componentOptions;return e&&e.Ctor.options.abstract?Co(Ue(e.children)):t}function _o(t){var e={},n=t.$options;for(var r in n.propsData)e[r]=t[r];var o=n._parentListeners;for(var i in o)e[b(i)]=o[i];return e}function wo(t,e){if(/\d-keep-alive$/.test(e.tag))return t("keep-alive",{props:e.componentOptions.propsData})}var Eo=function(t){return t.tag||Ve(t)},xo=function(t){return"show"===t.name},ko={name:"transition",props:bo,abstract:!0,render:function(t){var e=this,n=this.$slots.default;if(n&&(n=n.filter(Eo)).length){var r=this.mode,o=n[0];if(function(t){for(;t=t.parent;)if(t.data.transition)return!0}(this.$vnode))return o;var a=Co(o);if(!a)return o;if(this._leaving)return wo(t,o);var s="__transition-"+this._uid+"-";a.key=null==a.key?a.isComment?s+"comment":s+a.tag:i(a.key)?0===String(a.key).indexOf(s)?a.key:s+a.key:a.key;var c=(a.data||(a.data={})).transition=_o(this),u=this._vnode,l=Co(u);if(a.data.directives&&a.data.directives.some(xo)&&(a.data.show=!0),l&&l.data&&!function(t,e){return e.key===t.key&&e.tag===t.tag}(a,l)&&!Ve(l)&&(!l.componentInstance||!l.componentInstance._vnode.isComment)){var f=l.data.transition=k({},c);if("out-in"===r)return this._leaving=!0,ie(f,"afterLeave",(function(){e._leaving=!1,e.$forceUpdate()})),wo(t,o);if("in-out"===r){if(Ve(a))return u;var d,p=function(){d()};ie(c,"afterEnter",p),ie(c,"enterCancelled",p),ie(f,"delayLeave",(function(t){d=t}))}}return o}}},Oo=k({tag:String,moveClass:String},bo);function jo(t){t.elm._moveCb&&t.elm._moveCb(),t.elm._enterCb&&t.elm._enterCb()}function So(t){t.data.newPos=t.elm.getBoundingClientRect()}function Io(t){var e=t.data.pos,n=t.data.newPos,r=e.left-n.left,o=e.top-n.top;if(r||o){t.data.moved=!0;var i=t.elm.style;i.transform=i.WebkitTransform="translate("+r+"px,"+o+"px)",i.transitionDuration="0s"}}delete Oo.mode;var Bo={Transition:ko,TransitionGroup:{props:Oo,beforeMount:function(){var t=this,e=this._update;this._update=function(n,r){var o=qe(t);t.__patch__(t._vnode,t.kept,!1,!0),t._vnode=t.kept,o(),e.call(t,n,r)}},render:function(t){for(var e=this.tag||this.$vnode.data.tag||"span",n=Object.create(null),r=this.prevChildren=this.children,o=this.$slots.default||[],i=this.children=[],a=_o(this),s=0;s-1?Zn[t]=e.constructor===window.HTMLUnknownElement||e.constructor===window.HTMLElement:Zn[t]=/HTMLUnknownElement/.test(e.toString())},k(wn.options.directives,go),k(wn.options.components,Bo),wn.prototype.__patch__=z?co:j,wn.prototype.$mount=function(t,e){return function(t,e,n){var r;return t.$el=e,t.$options.render||(t.$options.render=pt),tn(t,"beforeMount"),r=function(){t._update(t._render(),n)},new pn(t,r,j,{before:function(){t._isMounted&&!t._isDestroyed&&tn(t,"beforeUpdate")}},!0),n=!1,null==t.$vnode&&(t._isMounted=!0,tn(t,"mounted")),t}(this,t=t&&z?function(t){return"string"==typeof t?document.querySelector(t)||document.createElement("div"):t}(t):void 0,e)},z&&setTimeout((function(){D.devtools&&et&&et.emit("init",wn)}),0);const Lo=wn;var No=function(){var t=this,e=t.$createElement,n=t._self._c||e;return t.show?n("div",{staticClass:"App"},[n("header",{staticClass:"App-header"},[n("img",{staticClass:"App-logo",attrs:{src:t.logo,alt:"logo"}}),t._v(" "),n("span",{staticClass:"App-close-icon",on:{click:t.handleClose}},[t._v("\n ×\n ")]),t._v(" "),t._m(0),t._v(" "),n("a",{staticClass:"App-link",attrs:{href:"https://reactjs.org",target:"_blank",rel:"noopener noreferrer"}},[t._v("\n Learn Wokoo\n ")])])]):n("div",{staticClass:"App-hide",on:{click:t.handleClose}},[n("img",{staticClass:"App-hide-logo",attrs:{src:t.logo,alt:"logo"}}),t._v("\n open\n")])};No._withStripped=!0;var To=n(379),Po=n.n(To),Qo=n(31);Po()(Qo.Z,{insert:"head",singleton:!1}),Qo.Z.locals;var Do=function(t,e,n,r,o,i,a,s){var c,u="function"==typeof t?t.options:t;if(e&&(u.render=e,u.staticRenderFns=[function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("p",[t._v("\n Edit "),n("code",[t._v("App.vue")]),t._v(" and save to reload.\n ")])}],u._compiled=!0),u._scopeId="data-v-5ef48958",c)if(u.functional){u._injectStyles=c;var l=u.render;u.render=function(t,e){return c.call(e),l(t,e)}}else{var f=u.beforeCreate;u.beforeCreate=f?[].concat(f,c):[c]}return{exports:t,options:u}}({data:function(){return{logo:"data:image/jpeg;base64,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",show:!0}},methods:{handleClose(){this.show=!this.show}}},No);Do.options.__file="src/app.vue";const Fo=Do.exports,Ro=document.createElement("div");Ro.id="wokoonApp",document.body.appendChild(Ro),new Lo({el:"#wokoonApp",render:t=>t(Fo)})})()})(); 3 | //# sourceMappingURL=app.bundle.js.map -------------------------------------------------------------------------------- /example/wokoo-demo/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "d", 3 | "version": "0.0.1", 4 | "private": true, 5 | "scripts": { 6 | "start": "cross-env NODE_ENV=development webpack-dev-server", 7 | "build": "webpack" 8 | }, 9 | "dependencies": { 10 | "vue": "2.6.12", 11 | "vue-template-compiler": "2.6.12" 12 | }, 13 | "devDependencies": { 14 | "cross-env": "7.0.3", 15 | "css-loader": "5.0.1", 16 | "file-loader": "6.2.0", 17 | "html-webpack-plugin": "4.5.1", 18 | "less": "4.1.0", 19 | "less-loader": "7.2.1", 20 | "style-loader": "2.0.0", 21 | "url-loader": "4.1.1", 22 | "vue-loader": "15.9.6", 23 | "webpack": "5.15.0", 24 | "webpack-cli": "3.3.12", 25 | "webpack-dev-server": "3.11.2", 26 | "webpack-merge": "5.7.3" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /example/wokoo-demo/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kinyaying/wokoo/2961afcb53c0e85dae8ec0f93b6f73fb0c9eb134/example/wokoo-demo/public/favicon.ico -------------------------------------------------------------------------------- /example/wokoo-demo/public/icon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kinyaying/wokoo/2961afcb53c0e85dae8ec0f93b6f73fb0c9eb134/example/wokoo-demo/public/icon.jpg -------------------------------------------------------------------------------- /example/wokoo-demo/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /example/wokoo-demo/src/app.less: -------------------------------------------------------------------------------- 1 | .App { 2 | position: absolute; 3 | text-align: center; 4 | width: 400px; 5 | height: 400px; 6 | top: 0; 7 | right: 0; 8 | z-index: 999; 9 | } 10 | .App-logo { 11 | height: 30vmin; 12 | border-radius: 50%; 13 | pointer-events: none; 14 | } 15 | @media (prefers-reduced-motion: no-preference) { 16 | .App-logo { 17 | animation: App-logo-spin infinite 20s linear; 18 | } 19 | } 20 | 21 | .App-header { 22 | background-color: #6c4d25; 23 | display: flex; 24 | flex-direction: column; 25 | align-items: center; 26 | justify-content: center; 27 | font-size: calc(10px + 2vmin); 28 | color: white; 29 | height: 100%; 30 | } 31 | 32 | .App-link { 33 | color: #efb61c; 34 | } 35 | .App-close-icon { 36 | position: absolute; 37 | top: 0; 38 | right: 10px; 39 | font-size: 30px; 40 | cursor: pointer; 41 | } 42 | .App-hide { 43 | position: absolute; 44 | text-align: center; 45 | width: 100px; 46 | height: 40px; 47 | background-color: #6c4d25; 48 | top: 0; 49 | right: 0; 50 | z-index: 999; 51 | display: flex; 52 | align-items: center; 53 | justify-content: center; 54 | color: #fff; 55 | cursor: pointer; 56 | } 57 | .App-hide-logo { 58 | width: 30px; 59 | height: 30px; 60 | border-radius: 50%; 61 | margin-right: 10px; 62 | } 63 | 64 | @keyframes App-logo-spin { 65 | from { 66 | transform: rotate(0deg); 67 | } 68 | to { 69 | transform: rotate(360deg); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /example/wokoo-demo/src/app.vue: -------------------------------------------------------------------------------- 1 | 29 | 46 | 48 | -------------------------------------------------------------------------------- /example/wokoo-demo/src/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import App from './app.vue' 3 | 4 | const root = document.createElement('div') 5 | root.id = 'wokooApp' 6 | document.body.appendChild(root) 7 | const vm = new Vue({ 8 | el: '#wokooApp', 9 | render: (h) => h(App), 10 | }) 11 | -------------------------------------------------------------------------------- /example/wokoo-demo/tampermonkey.txt: -------------------------------------------------------------------------------- 1 | // ==UserScript== 2 | // @name wokoo-demo 3 | // @namespace http://tampermonkey.net/ 4 | // @version 0.0.1 5 | // @description try to take over the world! 6 | // @author kinyaying 7 | // @match https://*/* 8 | // @match http://*/* 9 | 10 | 11 | // ==/UserScript== 12 | 13 | (function() { 14 | 'use strict'; 15 | if(location.href === "http://localhost:8080/") return 16 | let script = document.createElement('script') 17 | script.src='http://localhost:8080/app.bundle.js' 18 | document.body.appendChild(script) 19 | 20 | })(); -------------------------------------------------------------------------------- /example/wokoo-demo/webpack.config.base.js: -------------------------------------------------------------------------------- 1 | const VueLoaderPlugin = require('vue-loader/lib/plugin') 2 | 3 | module.exports = { 4 | entry: { 5 | app: '/src/index.js', 6 | }, 7 | module: { 8 | rules: [ 9 | { 10 | test: /\.vue$/, 11 | loader: 'vue-loader', 12 | }, 13 | ], 14 | }, 15 | plugins: [new VueLoaderPlugin()], 16 | } 17 | -------------------------------------------------------------------------------- /example/wokoo-demo/webpack.config.js: -------------------------------------------------------------------------------- 1 | const HtmlWebpackPlugin = require('html-webpack-plugin') 2 | const { merge } = require('webpack-merge') 3 | const base = require('./webpack.config.base') 4 | 5 | module.exports = merge(base, { 6 | mode: process.env.NODE_ENV || 'production', 7 | devtool: 'source-map', 8 | output: { 9 | filename: '[name].bundle.js', 10 | path: __dirname + '/dist', 11 | }, 12 | module: { 13 | rules: [ 14 | { 15 | test: /\.(less|css)$/, 16 | use: ['style-loader', 'css-loader', 'less-loader'], 17 | }, 18 | { 19 | test: /\.(woff|woff2|eot|ttf|otf|png|svg|jpg|gif)$/, 20 | use: { 21 | loader: 'url-loader', 22 | options: { 23 | limit: 20480, 24 | }, 25 | }, 26 | }, 27 | ], 28 | }, 29 | plugins: [ 30 | new HtmlWebpackPlugin({ 31 | template: './public/index.html', 32 | }), 33 | ], 34 | }) 35 | -------------------------------------------------------------------------------- /example/zhihu-helper/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /example/zhihu-helper/README.md: -------------------------------------------------------------------------------- 1 | ## zhihu-helper 2 | 3 | 基于 wokoo 搭建的初始化工程,用于油猴插件开发。 4 | 5 | **基础配置:** 6 | 7 | - react 8 | - less 9 | - webpack 10 | 11 | ## 目录结构 12 | 13 | ``` 14 | . 15 | ├── README.md 说明 16 | ├── package-lock.json 17 | ├── package.json 18 | ├── public 静态文件 19 | │   ├── favicon.ico 20 | │   ├── icon.jpg 21 | │   └── index.html html 文件 22 | ├── src 23 | │   ├── app.less 24 | │   ├── app.js 25 | │   └── index.js 项目入口 26 | ├── tampermonkey.txt 油猴脚本入口文件 27 | ├── webpack.config.base.js 28 | └── webpack.config.js webpack 配置 29 | ``` 30 | 31 | ## 开发 32 | 33 | **启动** 34 | 进入项目目录后,在命令行中输入: 35 | 36 | ```shell 37 | npm start 38 | ``` 39 | 40 | **调试** 41 | 42 | 1. 打开浏览器,输入`localhost:8080`,查看页面展示是否正常。 43 | 2. 安装油猴插件 44 | 3. 打开油猴插件编辑界面,将 tampermonkey.txt 里的内容复制到编辑框中,保存。 45 | 4. 打开任意一个网页,比如`www.baidu.com`, 46 | 47 | - 查看油猴 icon 是否有一个 1 的数字标志,如果有说明油猴脚本已经成功激活 48 | - 网页的右上角会出现初始页面 49 | 50 | **构建** 51 | 52 | ```shell 53 | npm run build 54 | ``` 55 | 56 | **发布插件到油猴市场** 57 | 58 | 油猴市场的优点是不用审核,即发即用,非常方便。 59 | 60 | 1. 将/dist/app.bundle.js 文件部署到 cdn 上,获取到对应 url。(可以放到 github 上,如果托管到 git 上最好做 cdn 加速) 61 | 2. 登录[油猴市场](https://greasyfork.org/),谷歌账号或 github 账号都可使用。 62 | 3. 点击账号名称,再点击**发布你编写的脚本** 63 | 4. 进入编辑页,将 tampermonkey.txt 里的内容复制到编辑框中,记得将里面的`localhost:8080`网址替换成静态资源 url 64 | 5. 点击 「发布脚本」即可 65 | 66 | ## 例子 demo 67 | 68 | 我已经使用 wokoo 脚手架开发了多个 demo,并发布到[油猴市场](https://greasyfork.org/),欢迎安装试用。 69 | [wokoo-demo](https://greasyfork.org/zh-CN/scripts/420327-wokoo-demo): 简单的示例插件 70 | 71 | ## 了解更多 72 | 73 | 如果想了解更多内容,请访问下面的网址: 74 | [油猴脚手架 wokoo 使用说明](https://juejin.cn/post/6922815205575491597) 75 | [油猴脚手架 wokoo git 仓库](https://github.com/kinyaying/wokoo) 76 | -------------------------------------------------------------------------------- /example/zhihu-helper/dist/app.bundle.js.LICENSE.txt: -------------------------------------------------------------------------------- 1 | /* 2 | object-assign 3 | (c) Sindre Sorhus 4 | @license MIT 5 | */ 6 | 7 | /** @license React v0.20.1 8 | * scheduler.production.min.js 9 | * 10 | * Copyright (c) Facebook, Inc. and its affiliates. 11 | * 12 | * This source code is licensed under the MIT license found in the 13 | * LICENSE file in the root directory of this source tree. 14 | */ 15 | 16 | /** @license React v16.14.0 17 | * react.production.min.js 18 | * 19 | * Copyright (c) Facebook, Inc. and its affiliates. 20 | * 21 | * This source code is licensed under the MIT license found in the 22 | * LICENSE file in the root directory of this source tree. 23 | */ 24 | 25 | /** @license React v17.0.1 26 | * react-dom.production.min.js 27 | * 28 | * Copyright (c) Facebook, Inc. and its affiliates. 29 | * 30 | * This source code is licensed under the MIT license found in the 31 | * LICENSE file in the root directory of this source tree. 32 | */ 33 | -------------------------------------------------------------------------------- /example/zhihu-helper/dist/index.html: -------------------------------------------------------------------------------- 1 | Document -------------------------------------------------------------------------------- /example/zhihu-helper/dist/vendor.bundle.js.LICENSE.txt: -------------------------------------------------------------------------------- 1 | /* 2 | object-assign 3 | (c) Sindre Sorhus 4 | @license MIT 5 | */ 6 | 7 | /** @license React v0.20.1 8 | * scheduler.production.min.js 9 | * 10 | * Copyright (c) Facebook, Inc. and its affiliates. 11 | * 12 | * This source code is licensed under the MIT license found in the 13 | * LICENSE file in the root directory of this source tree. 14 | */ 15 | 16 | /** @license React v16.14.0 17 | * react.production.min.js 18 | * 19 | * Copyright (c) Facebook, Inc. and its affiliates. 20 | * 21 | * This source code is licensed under the MIT license found in the 22 | * LICENSE file in the root directory of this source tree. 23 | */ 24 | 25 | /** @license React v17.0.1 26 | * react-dom.production.min.js 27 | * 28 | * Copyright (c) Facebook, Inc. and its affiliates. 29 | * 30 | * This source code is licensed under the MIT license found in the 31 | * LICENSE file in the root directory of this source tree. 32 | */ 33 | -------------------------------------------------------------------------------- /example/zhihu-helper/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "zhihu-helper", 3 | "version": "0.0.1", 4 | "private": true, 5 | "scripts": { 6 | "start": "cross-env NODE_ENV=development webpack-dev-server", 7 | "build": "webpack" 8 | }, 9 | "dependencies": { 10 | "@babel/core": "7.12.10", 11 | "@babel/plugin-transform-runtime": "^7.12.13", 12 | "@babel/preset-react": "7.12.10", 13 | "axios": "^0.21.1", 14 | "babel-loader": "8.2.2", 15 | "react": "16.14.0", 16 | "react-dom": "17.0.1", 17 | "react-infinite-scroll-component": "^5.1.0" 18 | }, 19 | "devDependencies": { 20 | "@babel/plugin-proposal-class-properties": "^7.12.1", 21 | "@babel/plugin-proposal-decorators": "^7.12.12", 22 | "@babel/preset-env": "^7.12.11", 23 | "babel-plugin-transform-runtime": "^6.23.0", 24 | "cross-env": "7.0.3", 25 | "css-loader": "5.0.1", 26 | "file-loader": "6.2.0", 27 | "html-webpack-plugin": "4.5.1", 28 | "less": "4.1.0", 29 | "less-loader": "7.3.0", 30 | "style-loader": "2.0.0", 31 | "url-loader": "4.1.1", 32 | "webpack": "5.19.0", 33 | "webpack-cli": "3.3.12", 34 | "webpack-dev-server": "3.11.2", 35 | "webpack-merge": "5.7.3" 36 | } 37 | } -------------------------------------------------------------------------------- /example/zhihu-helper/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kinyaying/wokoo/2961afcb53c0e85dae8ec0f93b6f73fb0c9eb134/example/zhihu-helper/public/favicon.ico -------------------------------------------------------------------------------- /example/zhihu-helper/public/icon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kinyaying/wokoo/2961afcb53c0e85dae8ec0f93b6f73fb0c9eb134/example/zhihu-helper/public/icon.jpg -------------------------------------------------------------------------------- /example/zhihu-helper/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /example/zhihu-helper/src/app.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import axios from 'axios' 3 | import InfiniteScroll from 'react-infinite-scroll-component' 4 | import './app.less' 5 | 6 | const limit = 20 7 | export default class extends React.Component { 8 | constructor(props) { 9 | super(props) 10 | this.state = { 11 | show: false, 12 | list: [], 13 | offset: 0, 14 | hasMore: true, 15 | } 16 | this.queryName = null 17 | } 18 | handleShow = () => { 19 | this.setState({ 20 | show: !this.state.show, 21 | }) 22 | } 23 | handleMouseOver = async () => { 24 | this.setState({ 25 | show: true, 26 | }) 27 | wokooAppZhihu.className = 'wokoo-app-unfold' 28 | this.getQueryName() 29 | this.getList() 30 | } 31 | handleMouseLeave = () => { 32 | this.setState({ 33 | show: false, 34 | }) 35 | wokooAppZhihu.className = 'wokoo-app-fold' 36 | } 37 | handleInfiniteOnLoad = () => { 38 | this.getList() 39 | } 40 | 41 | getQueryName = () => { 42 | let pathname = location.pathname 43 | let detailRegExp = /^\/p\/\d+/ 44 | let queryName = '' 45 | // 专栏详情页 46 | if (detailRegExp.test(pathname)) { 47 | let aTage = document.getElementsByClassName( 48 | 'ColumnPageHeader-TitleColumn' 49 | ) 50 | let url = aTage[0].href 51 | queryName = url.slice(url.lastIndexOf('/')) 52 | } else { 53 | // 专栏列表页 54 | // http://zhuanlan.zhihu和http://zhihu/column两种情况都是专栏 55 | if (pathname.indexOf('/column') === 0) { 56 | pathname = pathname.slice('/column'.length) 57 | } 58 | queryName = pathname 59 | } 60 | this.queryName = queryName 61 | } 62 | 63 | getList = async () => { 64 | if (!this.state.hasMore) return 65 | if (this.queryName === '/') return 66 | let { offset } = this.state 67 | let { data } = await axios.get( 68 | `https://www.zhihu.com/api/v4/columns${this.queryName}/items?limit=20&offset=${offset}` 69 | ) 70 | let list = data.data.map((i) => ({ 71 | title: i.title, 72 | url: i.url, 73 | id: i.id, 74 | commentCount: i.comment_count, 75 | voteupCount: i.voteup_count, 76 | })) 77 | if (data.paging.is_end) { 78 | this.setState({ hasMore: false }) 79 | } 80 | offset += limit 81 | 82 | this.setState({ 83 | list: [...this.state.list, ...list], 84 | offset, 85 | }) 86 | } 87 | 88 | render() { 89 | let { show, list, hasMore } = this.state 90 | return ( 91 | <> 92 | {show ? ( 93 |
    94 | Loading...} 99 | height={document.documentElement.clientHeight - 53} 100 | endMessage={ 101 |

    102 | 到底了,没内容啦~ 103 |

    104 | } 105 | > 106 | {list.map((i) => ( 107 |
  • 108 | 109 | {i.title} 110 | 111 | 112 | 113 | 119 | 123 | 124 | 125 | {i.voteupCount} 赞同 126 | 127 | 128 | 129 | 135 | 139 | 140 | 141 | {i.commentCount} 条评论 142 | 143 |
  • 144 | ))} 145 |
    146 |
147 | ) : ( 148 |
154 | 专栏目录 155 | 156 | » 157 | 158 |
159 | )} 160 | 161 | ) 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /example/zhihu-helper/src/app.less: -------------------------------------------------------------------------------- 1 | .wokoo-app-fold { 2 | position: fixed; 3 | top: 50%; 4 | margin-top: -47px; 5 | } 6 | 7 | .wokoo-app-unfold { 8 | position: fixed; 9 | top: 52px; 10 | height: calc(100% - 52px); 11 | width: 250px; 12 | z-index: 99; 13 | background: #fff; 14 | font-size: 14px; 15 | overflow: auto; 16 | overscroll-behavior: contain; 17 | -ms-scroll-chaining: contain; 18 | box-shadow: 1px 0px 3px rgb(18 18 18 / 10%); 19 | } 20 | ::-webkit-scrollbar { 21 | display: none; /* Chrome Safari */ 22 | } 23 | .list-ul { 24 | padding: 10px; 25 | } 26 | .list-li { 27 | padding: 10px 0; 28 | border-bottom: 1px solid #f6f6f6; 29 | } 30 | .list-a { 31 | display: block; 32 | margin-bottom: 5px; 33 | } 34 | .list-span { 35 | width: 50%; 36 | display: inline-block; 37 | text-align: right; 38 | color: #8590a6; 39 | } 40 | .list-li:hover { 41 | color: #0066ff; 42 | } 43 | .octotree-toggle { 44 | display: flex; 45 | align-items: center; 46 | justify-content: center; 47 | font-size: 14px; 48 | left: 0; 49 | box-sizing: border-box; 50 | --color-text-primary: #24292e; 51 | --color-bg-canvas: #ffffff; 52 | --color-border-primary: #e1e4e8; 53 | color: var(--color-text-primary); 54 | background-color: var(--color-bg-canvas); 55 | box-shadow: 0 2px 8px var(--color-border-primary); 56 | opacity: 1; 57 | height: 94px; 58 | line-height: 1; 59 | position: absolute; 60 | right: -30px; 61 | text-align: center; 62 | top: 33%; 63 | width: 36px; 64 | z-index: 1000000001; 65 | cursor: pointer; 66 | border-radius: 0px 4px 4px 0px; 67 | border-left: none; 68 | padding: 6px; 69 | transition: right 0.25s ease-in 0.2s, opacity 0.35s ease-in 0.2s; 70 | } 71 | .octotree-toggle-icon { 72 | margin-left: 4px; 73 | } 74 | .svg-icon { 75 | display: inline-flex; 76 | align-self: center; 77 | position: relative; 78 | height: 1em; 79 | width: 1em; 80 | color: #0066ff; 81 | opacity: 0.3; 82 | margin-right: 5px; 83 | } 84 | 85 | .svg-icon svg { 86 | height: 1em; 87 | width: 1em; 88 | bottom: -0.125em; 89 | position: absolute; 90 | } 91 | -------------------------------------------------------------------------------- /example/zhihu-helper/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import ReactDOM from 'react-dom' 3 | import App from './app' 4 | 5 | const wokooApp = document.createElement('div') 6 | wokooApp.id = 'wokooAppZhihu' 7 | wokooApp.className = 'wokoo-app-fold' 8 | 9 | document.body.appendChild(wokooApp) 10 | ReactDOM.render( 11 |
12 | 13 |
, 14 | wokooApp 15 | ) 16 | -------------------------------------------------------------------------------- /example/zhihu-helper/src/step1.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import './app.less' 3 | 4 | export default class extends React.Component { 5 | constructor(props) { 6 | super(props) 7 | this.state = { 8 | show: false, 9 | } 10 | } 11 | handleShow = () => { 12 | this.setState({ 13 | show: !this.state.show, 14 | }) 15 | } 16 | handleMouseOver = async () => { 17 | this.setState({ 18 | show: true, 19 | }) 20 | wokooAppZhihu.className = 'wokoo-app-unfold' 21 | } 22 | handleMouseLeave = () => { 23 | this.setState({ 24 | show: false, 25 | }) 26 | wokooAppZhihu.className = 'wokoo-app-fold' 27 | } 28 | 29 | render() { 30 | let { show } = this.state 31 | return ( 32 | <> 33 | {show ? ( 34 |
    39 | list 40 |
41 | ) : ( 42 |
47 | 专栏目录 48 | 49 | » 50 | 51 |
52 | )} 53 | 54 | ) 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /example/zhihu-helper/src/step2.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import axios from 'axios' 3 | import './app.less' 4 | 5 | const limit = 20 6 | export default class extends React.Component { 7 | constructor(props) { 8 | super(props) 9 | this.state = { 10 | show: false, 11 | list: [], 12 | offset: 0, 13 | hasMore: true, 14 | } 15 | this.queryName = null 16 | } 17 | handleShow = () => { 18 | this.setState({ 19 | show: !this.state.show, 20 | }) 21 | } 22 | handleMouseOver = async () => { 23 | this.setState({ 24 | show: true, 25 | }) 26 | wokooAppZhihu.className = 'wokoo-app-unfold' 27 | this.getQueryName() 28 | this.getList() 29 | } 30 | handleMouseLeave = () => { 31 | this.setState({ 32 | show: false, 33 | }) 34 | wokooAppZhihu.className = 'wokoo-app' 35 | } 36 | 37 | getQueryName = () => { 38 | let pathname = location.pathname 39 | let detailRegExp = /^\/p\/\d+/ 40 | let queryName = '' 41 | // 专栏详情页 42 | if (detailRegExp.test(pathname)) { 43 | let aTage = document.getElementsByClassName( 44 | 'ColumnPageHeader-TitleColumn' 45 | ) 46 | let url = aTage[0].href 47 | queryName = url.slice(url.lastIndexOf('/')) 48 | } else { 49 | // 专栏列表页 50 | // http://zhuanlan.zhihu和http://zhihu/column两种情况都是专栏 51 | if (pathname.indexOf('/column') === 0) { 52 | pathname = pathname.slice('/column'.length) 53 | } 54 | queryName = pathname 55 | } 56 | this.queryName = queryName 57 | } 58 | 59 | getList = async () => { 60 | if (!this.state.hasMore) return 61 | let { offset } = this.state 62 | let { data } = await axios.get( 63 | `https://www.zhihu.com/api/v4/columns${this.queryName}/items?limit=20&offset=${offset}` 64 | ) 65 | let list = data.data.map((i) => ({ 66 | title: i.title, 67 | url: i.url, 68 | id: i.id, 69 | commentCount: i.comment_count, 70 | voteupCount: i.voteup_count, 71 | })) 72 | if (data.paging.is_end) { 73 | this.setState({ hasMore: false }) 74 | } 75 | offset += limit 76 | 77 | this.setState({ 78 | list: [...this.state.list, ...list], 79 | offset, 80 | }) 81 | } 82 | 83 | render() { 84 | let { show, list, hasMore } = this.state 85 | return ( 86 | <> 87 | {show ? ( 88 |
    89 | {list.map((i) => ( 90 |
  • 91 | 92 | {i.title} 93 | 94 | {i.voteupCount} 赞同 95 | {i.commentCount} 条评论 96 |
  • 97 | ))} 98 |
99 | ) : ( 100 |
106 | 专栏目录 107 | 108 | » 109 | 110 |
111 | )} 112 | 113 | ) 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /example/zhihu-helper/tampermonkey.js: -------------------------------------------------------------------------------- 1 | // ==UserScript== 2 | // @name zhihu-helper 3 | // @namespace http://tampermonkey.net/ 4 | // @version 0.0.1 5 | // @description 知乎目录 6 | // @author kinyaying 7 | // @match https://zhuanlan.zhihu.com/* 8 | // @match https://www.zhihu.com/column/* 9 | // @require https://unpkg.com/react@17/umd/react.production.min.js 10 | // @require https://unpkg.com/react-dom@17/umd/react-dom.production.min.js 11 | 12 | // ==/UserScript== 13 | 14 | ;(function () { 15 | 'use strict' 16 | if (location.href === 'http://localhost:8080/') return 17 | var script = document.createElement('script') 18 | script.src = 'http://localhost:8080/app.bundle.js' 19 | document.body.appendChild(script) 20 | })() 21 | -------------------------------------------------------------------------------- /example/zhihu-helper/webpack.config.base.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | entry: { 3 | app: '/src/index.js', 4 | vendor: [ 5 | // 将react和react-dom这些单独打包出来,减小打包文件体积 6 | 'react', 7 | 'react-dom', 8 | ], 9 | }, 10 | module: { 11 | rules: [ 12 | { 13 | test: /\.(js|jsx)$/, //匹配js文件 14 | use: { 15 | loader: 'babel-loader', 16 | options: { 17 | presets: ['@babel/preset-react', '@babel/preset-env'], 18 | plugins: [ 19 | ['@babel/plugin-proposal-decorators', { legacy: true }], 20 | ['@babel/plugin-proposal-class-properties', { loose: true }], 21 | ], 22 | }, 23 | }, 24 | }, 25 | ], 26 | }, 27 | } 28 | -------------------------------------------------------------------------------- /example/zhihu-helper/webpack.config.js: -------------------------------------------------------------------------------- 1 | const HtmlWebpackPlugin = require('html-webpack-plugin') 2 | const { merge } = require('webpack-merge') 3 | const base = require('./webpack.config.base') 4 | 5 | module.exports = merge(base, { 6 | mode: process.env.NODE_ENV || 'production', 7 | devtool: 'source-map', 8 | output: { 9 | filename: '[name].bundle.js', 10 | path: __dirname + '/dist', 11 | }, 12 | module: { 13 | rules: [ 14 | { 15 | test: /\.(less|css)$/, 16 | use: ['style-loader', 'css-loader', 'less-loader'], 17 | }, 18 | { 19 | test: /\.(woff|woff2|eot|ttf|otf|png|svg|jpg|gif)$/, 20 | use: { 21 | loader: 'url-loader', 22 | options: { 23 | limit: 20480, 24 | }, 25 | }, 26 | }, 27 | ], 28 | }, 29 | plugins: [ 30 | new HtmlWebpackPlugin({ 31 | template: './public/index.html', 32 | }), 33 | ], 34 | }) 35 | -------------------------------------------------------------------------------- /lerna-debug.log: -------------------------------------------------------------------------------- 1 | 48 error Error: Command failed: git tag v0.1.7 -m v0.1.7 2 | 48 error fatal: tag 'v0.1.7' already exists 3 | 48 error 4 | 48 error at makeError (/Users/kin/MyCode/wokoo/node_modules/execa/index.js:174:9) 5 | 48 error at /Users/kin/MyCode/wokoo/node_modules/execa/index.js:278:16 6 | 48 error at processTicksAndRejections (internal/process/task_queues.js:97:5) 7 | -------------------------------------------------------------------------------- /lerna.json: -------------------------------------------------------------------------------- 1 | { 2 | "packages": [ 3 | "packages/*" 4 | ], 5 | "version": "0.3.3" 6 | } 7 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wokoo-cli", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "private": true, 7 | "workspaces": [ 8 | "packages/*" 9 | ], 10 | "scripts": { 11 | "start": "node packages/wokoo-scripts/index.js", 12 | "test": "node test.js" 13 | }, 14 | "keywords": [], 15 | "author": "kinyaying", 16 | "license": "MIT", 17 | "devDependencies": { 18 | "lerna": "^3.22.1" 19 | }, 20 | "dependencies": { 21 | "chalk": "^4.1.0", 22 | "cross-spawn": "^7.0.3", 23 | "fs-extra": "^9.0.1" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /packages/wokoo-scripts/README.md: -------------------------------------------------------------------------------- 1 | # wokoo-scripts 2 | 3 | 使用 nodejs 编写的脚本工具,用于初始化一个基于 [wokoo-template](https://www.npmjs.com/package/wokoo-template) 模板的,有基础配置的油猴项目 4 | 5 | ## 功能 6 | 7 | - 分析用户在控制台输入的命令 8 | - 和用户交互,拉取 wokoo-template,生成对应的初始项目 9 | 10 | ## 使用 11 | 12 | 1. 安装 13 | 14 | ``` 15 | npm i wokoo -g 16 | ``` 17 | 18 | 2. 创建项目 19 | 20 | ``` 21 | wokoo my-plugin 22 | ``` 23 | 24 | 3. 命令行中会弹出询问: 25 | ? which template do you prefer? 26 | [ ] react 27 | [ ] vue 28 | 4. 选择对应模板,生成初始化项目 29 | 30 | ## 使用到的库 31 | 32 | - [chalk](https://www.npmjs.com/package/chalk) 丰富控制台显示的字颜色 33 | - [cross-spawn](https://www.npmjs.com/package/cross-spawn) 开启子线程 34 | - [commander](https://www.npmjs.com/package/commander) 提供命令行交互 35 | - [fs-extra](https://www.npmjs.com/package/fs-extra) 操作文件 36 | - [inquirer](https://www.npmjs.com/package/inquirer) 命令行弹出选项 37 | - [metalsmith](https://www.npmjs.com/package/metalsmith) 遍历文件夹 38 | - [consolidate](https://www.npmjs.com/package/consolidate) 渲染 ejs 模板 39 | 40 | ## 目录结构 41 | 42 | ``` 43 | . 44 | ├── README.md 45 | ├── bin 46 | │   └── www 入口文件 47 | ├── index.js 主程序 48 | ├── modifyTemplate.js 将temp目录下的ejs语法,替换成js变量 49 | ├── package-lock.json 50 | └── package.json 51 | ``` 52 | 53 | ## 了解更多 54 | 55 | 如果想了解更多内容,请访问下面的网址: 56 | [油猴脚手架 wokoo 使用说明](https://juejin.cn/post/6922815205575491597) 57 | [油猴脚手架 wokoo git 仓库](https://github.com/kinyaying/wokoo) 58 | -------------------------------------------------------------------------------- /packages/wokoo-scripts/bin/www: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env node 2 | 3 | require('../index.js'); -------------------------------------------------------------------------------- /packages/wokoo-scripts/index.js: -------------------------------------------------------------------------------- 1 | const chalk = require('chalk') 2 | const spawn = require('cross-spawn') 3 | const { Command } = require('commander') 4 | const fs = require('fs-extra') 5 | const path = require('path') 6 | const inquirer = require('inquirer') 7 | const packageJson = require('./package.json') 8 | const modifyTemplate = require('./modifyTemplate') // 修改替换ejs模板内字段 9 | let program = new Command() 10 | init() 11 | // 程序入口,读取命令行脚本,获得项目名称 12 | async function init() { 13 | let projectName, target 14 | program 15 | .version(packageJson.version) 16 | .arguments('') // 项目目录名 参数格式:<必选> [可选] 17 | .usage(`${chalk.green(``)}`) 18 | .option('-t, --target [value]', 'chose template') 19 | .action((...argvs) => { 20 | const [name] = argvs 21 | projectName = name 22 | target = argvs[1].target 23 | }) 24 | .parse(process.argv) // [node路径,脚本路径,参数] 25 | await createApp(projectName, target) 26 | } 27 | /** 28 | * 根据appName生成项目目录 29 | * @param {*} appName 30 | */ 31 | async function createApp(appName, target) { 32 | let root = path.resolve(appName) // 要生成的项目的绝对路径 33 | fs.ensureDirSync(appName) // 没有则创建文件夹 34 | console.log(`create a new app in ${chalk.green(root)}`) 35 | // 初始化package.json 36 | const packageJson = { 37 | name: appName, 38 | version: '0.0.1', 39 | private: true, 40 | scripts: { 41 | start: 'cross-env NODE_ENV=development webpack serve', 42 | build: 'webpack', 43 | }, 44 | } 45 | // 写入package.json 46 | fs.writeFileSync( 47 | path.join(root, 'package.json'), 48 | JSON.stringify(packageJson, null, 2) 49 | ) 50 | // 改变工作目录,进入项目目录 51 | process.chdir(root) 52 | // 复制项目模板,安装项目依赖等 53 | await run(root, appName, target) 54 | } 55 | /** 56 | 1、安装wokoo-template 57 | 2、复制模板文件到临时文件夹temp, 58 | 3、调用modifyTemplate替换其中的ejs模板 59 | 4、删除临时文件夹temp 60 | 5、卸载wokoo-template 61 | * @param {*} root 项目路径 62 | * @param {*} appName 项目名 63 | */ 64 | async function run(root, appName, target) { 65 | const templateName = 'wokoo-template' // 对应的wokoo模板 66 | const allDependencies = [templateName] 67 | // 安装wokoo-template包 68 | console.log('Installing packages. This might take a couple of minutes') 69 | console.log(`Installing ${chalk.cyan(templateName)} ...`) 70 | try { 71 | await doAction(root, allDependencies) 72 | } catch (e) { 73 | console.log(`Installing ${chalk.red(templateName)} failed ...`, e) 74 | } 75 | console.log(`Installing ${chalk.cyan(templateName)} succeed!`) 76 | 77 | // 选择模板 78 | const repos = ['vue', 'react'] 79 | let targetTemplate 80 | if(target) { 81 | targetTemplate = target 82 | console.log('This is a test project:' + target) 83 | } else { 84 | const data = await inquirer.prompt({ 85 | name: 'targetTemplate', 86 | type: 'list', 87 | message: 'which template do you prefer?', 88 | choices: repos, // 选择模式 89 | }) 90 | targetTemplate = data.targetTemplate 91 | } 92 | 93 | const templatePath = path.dirname( 94 | require.resolve(`${templateName}/package.json`, { paths: [root] }) 95 | ) 96 | 97 | // 复制文件到项目目录 98 | const scriptsConfigDir = path.join(templatePath, 'webpack.config.js') 99 | const gitIgnoreDir = path.join(templatePath, '.npmignore') 100 | const publicDir = path.join(templatePath, 'public') 101 | const tempDir = path.join(root, 'temp') // 临时模板路径 102 | const templateDir = path.join(templatePath, `${targetTemplate}-template`) 103 | // 从wokoo-template中拷贝模板到项目目录 104 | if (fs.existsSync(templatePath)) { 105 | // 将templateDir内模板拷贝到temp文件,并修改模板文件中的ejs配置项 106 | await modifyTemplate(templateDir, 'temp', { 107 | projectName: appName, 108 | basicProject: targetTemplate, 109 | }) 110 | 111 | fs.copySync(tempDir, root) // 源 目标 112 | fs.copySync(publicDir, root + '/public') 113 | fs.copyFileSync(scriptsConfigDir, root + '/webpack.config.js') 114 | fs.copyFileSync(gitIgnoreDir, root + '/.gitignore') 115 | deleteFolder(tempDir) 116 | } else { 117 | console.error( 118 | `Could not locate supplied template: ${chalk.green(templatePath)}` 119 | ) 120 | return 121 | } 122 | // 合并template.json和package.json 123 | let tempPkg = fs.readFileSync(root + '/template.json').toString() 124 | let pkg = fs.readFileSync(root + '/package.json').toString() 125 | const tempPkgJson = JSON.parse(tempPkg) 126 | const pkgJson = JSON.parse(pkg) 127 | 128 | pkgJson.dependencies = { 129 | ...pkgJson.dependencies, 130 | ...tempPkgJson.package.dependencies, 131 | } 132 | pkgJson.devDependencies = { 133 | ...tempPkgJson.package.devDependencies, 134 | } 135 | // 编写package.json 136 | fs.writeFileSync( 137 | path.join(root, 'package.json'), 138 | JSON.stringify(pkgJson, null, 2) 139 | ) 140 | fs.unlinkSync(path.join(root, 'template.json')) // 删除template.json文件 141 | 142 | // 再次根据dependenciesToInstall执行npm install 143 | const dependenciesToInstall = Object.entries({ 144 | ...pkgJson.dependencies, 145 | ...pkgJson.devDependencies, 146 | }) 147 | let newDependencies = [] 148 | if (dependenciesToInstall.length) { 149 | newDependencies = newDependencies.concat( 150 | dependenciesToInstall.map(([dependency, version]) => { 151 | return `${dependency}@${version}` 152 | }) 153 | ) 154 | } 155 | await doAction(root, newDependencies) 156 | console.log(`${chalk.cyan('Installing succeed!')}`) 157 | 158 | // 卸载wokoo-template 159 | await doAction(root, 'wokoo-template', 'uninstall') 160 | 161 | console.log(`🎉 Successfully created project ${appName}.`) 162 | console.log('👉 Get started with the following commands:') 163 | console.log(`${chalk.cyan(`cd ${appName}`)}`) 164 | console.log(`${chalk.cyan('$ npm start')}`) 165 | 166 | process.exit(0) 167 | } 168 | 169 | /** 170 | * 使用npm安装或卸载项目依赖 171 | * @param {*} root 项目路径 172 | * @param {*} allDependencies 项目依赖 173 | * @param {*} action npm install 或 npm uninstall 174 | */ 175 | async function doAction(root, allDependencies, action = 'install') { 176 | typeof allDependencies === 'string' 177 | ? (allDependencies = [allDependencies]) 178 | : null 179 | return new Promise((resolve) => { 180 | const command = 'npm' 181 | const args = [ 182 | action, 183 | '--save', 184 | '--save-exact', 185 | '--loglevel', 186 | 'error', 187 | ...allDependencies, 188 | '--prefix', 189 | root, 190 | ] 191 | const child = spawn(command, args, { stdio: 'inherit' }) 192 | child.on('close', resolve) // 安装成功后触发resolve 193 | }) 194 | } 195 | 196 | /** 197 | * 删除文件、文件夹 198 | * @param {*} path 要删除资源的路径 199 | */ 200 | function deleteFolder(path) { 201 | let files = [] 202 | if (fs.existsSync(path)) { 203 | if (!fs.statSync(path).isDirectory()) { 204 | // path是文件,直接删除 205 | fs.unlinkSync(path) 206 | } else { 207 | // 删除文件夹 208 | files = fs.readdirSync(path) 209 | files.forEach(function (file) { 210 | let curPath = path + '/' + file 211 | deleteFolder(curPath) 212 | }) 213 | fs.rmdirSync(path) 214 | } 215 | } 216 | } 217 | -------------------------------------------------------------------------------- /packages/wokoo-scripts/modifyTemplate.js: -------------------------------------------------------------------------------- 1 | const MetalSmith = require('metalsmith') // 遍历文件夹 2 | let { render } = require('consolidate').ejs 3 | const { promisify } = require('util') 4 | const path = require('path') 5 | render = promisify(render) // 包装渲染方法 6 | 7 | /** 8 | * 遍历template文件夹,将内部的.js .json .txt .md文件中ejs模板替换成注入的变量 9 | * 例如 wokoo-template/vue-template/tampermokey.js 文件中的 <%=projectName%> 会被替换成config中的projectName 10 | * @param {*} fromPath 源路径 11 | * @param {*} toPath 目标路径 12 | * @param {object} config 配置,eg. 13 | * { 14 | projectName: appName, 15 | basicProject: targetTemplate, 16 | } 17 | */ 18 | async function handleTemplate(fromPath, toPath, config) { 19 | await new Promise((resovle, reject) => { 20 | MetalSmith(__dirname) 21 | .source(fromPath) // 遍历下载的目录 22 | .destination(path.join(path.resolve(), toPath)) // 输出渲染后的结果 23 | .use(async (files, metal, done) => { 24 | // result 替换模板内数据 25 | let result = { 26 | license: 'MIT', 27 | version: '0.0.1', 28 | ...config, 29 | randomNumber: new Date().getTime().toString().slice(8), 30 | } 31 | const data = metal.metadata() 32 | Object.assign(data, result) // 将询问的结果放到metadata中保证在下一个中间件中可以获取到 33 | done() 34 | }) 35 | .use((files, metal, done) => { 36 | Reflect.ownKeys(files).forEach(async (file) => { 37 | let content = files[file].contents.toString() // 获取文件中的内容 38 | if ( 39 | file.includes('.js') || 40 | file.includes('.json') || 41 | file.includes('.txt') || 42 | file.includes('.md') 43 | ) { 44 | // 如果是md或者txt才有可能是模板 45 | if (content.includes('<%')) { 46 | // 文件中用<% 我才需要编译 47 | content = await render(content, metal.metadata()) // 用数据渲染模板 48 | files[file].contents = Buffer.from(content) // 渲染好的结果替换即可 49 | } 50 | } 51 | }) 52 | done() 53 | }) 54 | .build((err) => { 55 | // 执行中间件 56 | if (!err) { 57 | resovle() 58 | } else { 59 | reject(err) 60 | } 61 | }) 62 | }) 63 | } 64 | 65 | module.exports = handleTemplate 66 | -------------------------------------------------------------------------------- /packages/wokoo-scripts/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wokoo", 3 | "version": "0.3.3", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "absolute": { 8 | "version": "0.0.1", 9 | "resolved": "https://registry.npmjs.org/absolute/-/absolute-0.0.1.tgz", 10 | "integrity": "sha1-wigi+H4ck59XmIdQTZwQnEFzgp0=" 11 | }, 12 | "ansi-escapes": { 13 | "version": "4.3.1", 14 | "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.1.tgz", 15 | "integrity": "sha512-JWF7ocqNrp8u9oqpgV+wH5ftbt+cfvv+PTjOvKLT3AdYly/LmORARfEVT1iyjwN+4MqE5UmVKoAdIBqeoCHgLA==", 16 | "requires": { 17 | "type-fest": "^0.11.0" 18 | } 19 | }, 20 | "ansi-red": { 21 | "version": "0.1.1", 22 | "resolved": "https://registry.npmjs.org/ansi-red/-/ansi-red-0.1.1.tgz", 23 | "integrity": "sha1-jGOPnRCAgAo1PJwoyKgcpHBdlGw=", 24 | "requires": { 25 | "ansi-wrap": "0.1.0" 26 | } 27 | }, 28 | "ansi-regex": { 29 | "version": "5.0.0", 30 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", 31 | "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==" 32 | }, 33 | "ansi-styles": { 34 | "version": "4.3.0", 35 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 36 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 37 | "requires": { 38 | "color-convert": "^2.0.1" 39 | } 40 | }, 41 | "ansi-wrap": { 42 | "version": "0.1.0", 43 | "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", 44 | "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=" 45 | }, 46 | "argparse": { 47 | "version": "1.0.10", 48 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", 49 | "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", 50 | "requires": { 51 | "sprintf-js": "~1.0.2" 52 | } 53 | }, 54 | "async": { 55 | "version": "0.9.2", 56 | "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", 57 | "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=" 58 | }, 59 | "at-least-node": { 60 | "version": "1.0.0", 61 | "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", 62 | "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==" 63 | }, 64 | "balanced-match": { 65 | "version": "1.0.0", 66 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", 67 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" 68 | }, 69 | "bluebird": { 70 | "version": "3.7.2", 71 | "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", 72 | "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" 73 | }, 74 | "brace-expansion": { 75 | "version": "1.1.11", 76 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 77 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 78 | "requires": { 79 | "balanced-match": "^1.0.0", 80 | "concat-map": "0.0.1" 81 | } 82 | }, 83 | "chalk": { 84 | "version": "4.1.0", 85 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", 86 | "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", 87 | "requires": { 88 | "ansi-styles": "^4.1.0", 89 | "supports-color": "^7.1.0" 90 | } 91 | }, 92 | "chardet": { 93 | "version": "0.7.0", 94 | "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", 95 | "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==" 96 | }, 97 | "cli-cursor": { 98 | "version": "3.1.0", 99 | "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", 100 | "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", 101 | "requires": { 102 | "restore-cursor": "^3.1.0" 103 | } 104 | }, 105 | "cli-width": { 106 | "version": "3.0.0", 107 | "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", 108 | "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==" 109 | }, 110 | "clone": { 111 | "version": "1.0.4", 112 | "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", 113 | "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=" 114 | }, 115 | "co": { 116 | "version": "3.1.0", 117 | "resolved": "https://registry.npmjs.org/co/-/co-3.1.0.tgz", 118 | "integrity": "sha1-TqVOpaCJOBUxheFSEMaNkJK8G3g=" 119 | }, 120 | "co-from-stream": { 121 | "version": "0.0.0", 122 | "resolved": "https://registry.npmjs.org/co-from-stream/-/co-from-stream-0.0.0.tgz", 123 | "integrity": "sha1-GlzYztdyY5RglPo58kmaYyl7yvk=", 124 | "requires": { 125 | "co-read": "0.0.1" 126 | } 127 | }, 128 | "co-fs-extra": { 129 | "version": "1.2.1", 130 | "resolved": "https://registry.npmjs.org/co-fs-extra/-/co-fs-extra-1.2.1.tgz", 131 | "integrity": "sha1-O2rXfPJhRTD2d7HPYmZPW6dWtyI=", 132 | "requires": { 133 | "co-from-stream": "~0.0.0", 134 | "fs-extra": "~0.26.5", 135 | "thunkify-wrap": "~1.0.4" 136 | }, 137 | "dependencies": { 138 | "fs-extra": { 139 | "version": "0.26.7", 140 | "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.26.7.tgz", 141 | "integrity": "sha1-muH92UiXeY7at20JGM9C0MMYT6k=", 142 | "requires": { 143 | "graceful-fs": "^4.1.2", 144 | "jsonfile": "^2.1.0", 145 | "klaw": "^1.0.0", 146 | "path-is-absolute": "^1.0.0", 147 | "rimraf": "^2.2.8" 148 | } 149 | }, 150 | "jsonfile": { 151 | "version": "2.4.0", 152 | "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", 153 | "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", 154 | "requires": { 155 | "graceful-fs": "^4.1.6" 156 | } 157 | } 158 | } 159 | }, 160 | "co-read": { 161 | "version": "0.0.1", 162 | "resolved": "https://registry.npmjs.org/co-read/-/co-read-0.0.1.tgz", 163 | "integrity": "sha1-+Bs+uKhmdf7FHj2IOn9WToc8k4k=" 164 | }, 165 | "coffee-script": { 166 | "version": "1.12.7", 167 | "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.12.7.tgz", 168 | "integrity": "sha512-fLeEhqwymYat/MpTPUjSKHVYYl0ec2mOyALEMLmzr5i1isuG+6jfI2j2d5oBO3VIzgUXgBVIcOT9uH1TFxBckw==" 169 | }, 170 | "color-convert": { 171 | "version": "2.0.1", 172 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 173 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 174 | "requires": { 175 | "color-name": "~1.1.4" 176 | } 177 | }, 178 | "color-name": { 179 | "version": "1.1.4", 180 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 181 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" 182 | }, 183 | "commander": { 184 | "version": "7.0.0", 185 | "resolved": "https://registry.npmjs.org/commander/-/commander-7.0.0.tgz", 186 | "integrity": "sha512-ovx/7NkTrnPuIV8sqk/GjUIIM1+iUQeqA3ye2VNpq9sVoiZsooObWlQy+OPWGI17GDaEoybuAGJm6U8yC077BA==" 187 | }, 188 | "concat-map": { 189 | "version": "0.0.1", 190 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 191 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" 192 | }, 193 | "consolidate": { 194 | "version": "0.16.0", 195 | "resolved": "https://registry.npmjs.org/consolidate/-/consolidate-0.16.0.tgz", 196 | "integrity": "sha512-Nhl1wzCslqXYTJVDyJCu3ODohy9OfBMB5uD2BiBTzd7w+QY0lBzafkR8y8755yMYHAaMD4NuzbAw03/xzfw+eQ==", 197 | "requires": { 198 | "bluebird": "^3.7.2" 199 | } 200 | }, 201 | "cross-spawn": { 202 | "version": "7.0.3", 203 | "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", 204 | "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", 205 | "requires": { 206 | "path-key": "^3.1.0", 207 | "shebang-command": "^2.0.0", 208 | "which": "^2.0.1" 209 | } 210 | }, 211 | "ejs": { 212 | "version": "3.1.5", 213 | "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.5.tgz", 214 | "integrity": "sha512-dldq3ZfFtgVTJMLjOe+/3sROTzALlL9E34V4/sDtUd/KlBSS0s6U1/+WPE1B4sj9CXHJpL1M6rhNJnc9Wbal9w==", 215 | "requires": { 216 | "jake": "^10.6.1" 217 | } 218 | }, 219 | "emoji-regex": { 220 | "version": "8.0.0", 221 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 222 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" 223 | }, 224 | "enable": { 225 | "version": "1.3.2", 226 | "resolved": "https://registry.npmjs.org/enable/-/enable-1.3.2.tgz", 227 | "integrity": "sha1-nrpoN9FtCYK1n4fYib91REPVKTE=" 228 | }, 229 | "escape-string-regexp": { 230 | "version": "1.0.5", 231 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 232 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" 233 | }, 234 | "esprima": { 235 | "version": "4.0.1", 236 | "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", 237 | "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" 238 | }, 239 | "extend-shallow": { 240 | "version": "2.0.1", 241 | "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", 242 | "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", 243 | "requires": { 244 | "is-extendable": "^0.1.0" 245 | } 246 | }, 247 | "external-editor": { 248 | "version": "3.1.0", 249 | "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", 250 | "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", 251 | "requires": { 252 | "chardet": "^0.7.0", 253 | "iconv-lite": "^0.4.24", 254 | "tmp": "^0.0.33" 255 | } 256 | }, 257 | "figures": { 258 | "version": "3.2.0", 259 | "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", 260 | "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", 261 | "requires": { 262 | "escape-string-regexp": "^1.0.5" 263 | } 264 | }, 265 | "filelist": { 266 | "version": "1.0.1", 267 | "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.1.tgz", 268 | "integrity": "sha512-8zSK6Nu0DQIC08mUC46sWGXi+q3GGpKydAG36k+JDba6VRpkevvOWUW5a/PhShij4+vHT9M+ghgG7eM+a9JDUQ==", 269 | "requires": { 270 | "minimatch": "^3.0.4" 271 | } 272 | }, 273 | "fs-extra": { 274 | "version": "9.1.0", 275 | "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", 276 | "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", 277 | "requires": { 278 | "at-least-node": "^1.0.0", 279 | "graceful-fs": "^4.2.0", 280 | "jsonfile": "^6.0.1", 281 | "universalify": "^2.0.0" 282 | } 283 | }, 284 | "fs.realpath": { 285 | "version": "1.0.0", 286 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 287 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" 288 | }, 289 | "glob": { 290 | "version": "7.1.6", 291 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", 292 | "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", 293 | "requires": { 294 | "fs.realpath": "^1.0.0", 295 | "inflight": "^1.0.4", 296 | "inherits": "2", 297 | "minimatch": "^3.0.4", 298 | "once": "^1.3.0", 299 | "path-is-absolute": "^1.0.0" 300 | } 301 | }, 302 | "graceful-fs": { 303 | "version": "4.2.4", 304 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", 305 | "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==" 306 | }, 307 | "gray-matter": { 308 | "version": "2.1.1", 309 | "resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-2.1.1.tgz", 310 | "integrity": "sha1-MELZrewqHe1qdwep7SOA+KF6Qw4=", 311 | "requires": { 312 | "ansi-red": "^0.1.1", 313 | "coffee-script": "^1.12.4", 314 | "extend-shallow": "^2.0.1", 315 | "js-yaml": "^3.8.1", 316 | "toml": "^2.3.2" 317 | } 318 | }, 319 | "has-ansi": { 320 | "version": "2.0.0", 321 | "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", 322 | "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", 323 | "requires": { 324 | "ansi-regex": "^2.0.0" 325 | }, 326 | "dependencies": { 327 | "ansi-regex": { 328 | "version": "2.1.1", 329 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", 330 | "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" 331 | } 332 | } 333 | }, 334 | "has-flag": { 335 | "version": "4.0.0", 336 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", 337 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" 338 | }, 339 | "has-generators": { 340 | "version": "1.0.1", 341 | "resolved": "https://registry.npmjs.org/has-generators/-/has-generators-1.0.1.tgz", 342 | "integrity": "sha1-pqLlVIYBGUBILhPiyTeRxEms9Ek=" 343 | }, 344 | "iconv-lite": { 345 | "version": "0.4.24", 346 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 347 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 348 | "requires": { 349 | "safer-buffer": ">= 2.1.2 < 3" 350 | } 351 | }, 352 | "inflight": { 353 | "version": "1.0.6", 354 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 355 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 356 | "requires": { 357 | "once": "^1.3.0", 358 | "wrappy": "1" 359 | } 360 | }, 361 | "inherits": { 362 | "version": "2.0.4", 363 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 364 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 365 | }, 366 | "inquirer": { 367 | "version": "7.3.3", 368 | "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.3.3.tgz", 369 | "integrity": "sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA==", 370 | "requires": { 371 | "ansi-escapes": "^4.2.1", 372 | "chalk": "^4.1.0", 373 | "cli-cursor": "^3.1.0", 374 | "cli-width": "^3.0.0", 375 | "external-editor": "^3.0.3", 376 | "figures": "^3.0.0", 377 | "lodash": "^4.17.19", 378 | "mute-stream": "0.0.8", 379 | "run-async": "^2.4.0", 380 | "rxjs": "^6.6.0", 381 | "string-width": "^4.1.0", 382 | "strip-ansi": "^6.0.0", 383 | "through": "^2.3.6" 384 | } 385 | }, 386 | "is": { 387 | "version": "3.3.0", 388 | "resolved": "https://registry.npmjs.org/is/-/is-3.3.0.tgz", 389 | "integrity": "sha512-nW24QBoPcFGGHJGUwnfpI7Yc5CdqWNdsyHQszVE/z2pKHXzh7FZ5GWhJqSyaQ9wMkQnsTx+kAI8bHlCX4tKdbg==" 390 | }, 391 | "is-extendable": { 392 | "version": "0.1.1", 393 | "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", 394 | "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" 395 | }, 396 | "is-fullwidth-code-point": { 397 | "version": "3.0.0", 398 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 399 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" 400 | }, 401 | "is-utf8": { 402 | "version": "0.2.1", 403 | "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", 404 | "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=" 405 | }, 406 | "isexe": { 407 | "version": "2.0.0", 408 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 409 | "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" 410 | }, 411 | "jake": { 412 | "version": "10.8.2", 413 | "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.2.tgz", 414 | "integrity": "sha512-eLpKyrfG3mzvGE2Du8VoPbeSkRry093+tyNjdYaBbJS9v17knImYGNXQCUV0gLxQtF82m3E8iRb/wdSQZLoq7A==", 415 | "requires": { 416 | "async": "0.9.x", 417 | "chalk": "^2.4.2", 418 | "filelist": "^1.0.1", 419 | "minimatch": "^3.0.4" 420 | }, 421 | "dependencies": { 422 | "ansi-styles": { 423 | "version": "3.2.1", 424 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", 425 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", 426 | "requires": { 427 | "color-convert": "^1.9.0" 428 | } 429 | }, 430 | "chalk": { 431 | "version": "2.4.2", 432 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", 433 | "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", 434 | "requires": { 435 | "ansi-styles": "^3.2.1", 436 | "escape-string-regexp": "^1.0.5", 437 | "supports-color": "^5.3.0" 438 | } 439 | }, 440 | "color-convert": { 441 | "version": "1.9.3", 442 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", 443 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", 444 | "requires": { 445 | "color-name": "1.1.3" 446 | } 447 | }, 448 | "color-name": { 449 | "version": "1.1.3", 450 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", 451 | "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" 452 | }, 453 | "has-flag": { 454 | "version": "3.0.0", 455 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 456 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" 457 | }, 458 | "supports-color": { 459 | "version": "5.5.0", 460 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 461 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 462 | "requires": { 463 | "has-flag": "^3.0.0" 464 | } 465 | } 466 | } 467 | }, 468 | "js-yaml": { 469 | "version": "3.14.1", 470 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", 471 | "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", 472 | "requires": { 473 | "argparse": "^1.0.7", 474 | "esprima": "^4.0.0" 475 | } 476 | }, 477 | "jsonfile": { 478 | "version": "6.1.0", 479 | "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", 480 | "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", 481 | "requires": { 482 | "graceful-fs": "^4.1.6", 483 | "universalify": "^2.0.0" 484 | } 485 | }, 486 | "klaw": { 487 | "version": "1.3.1", 488 | "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", 489 | "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", 490 | "requires": { 491 | "graceful-fs": "^4.1.9" 492 | } 493 | }, 494 | "lodash": { 495 | "version": "4.17.20", 496 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", 497 | "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" 498 | }, 499 | "metalsmith": { 500 | "version": "2.3.0", 501 | "resolved": "https://registry.npmjs.org/metalsmith/-/metalsmith-2.3.0.tgz", 502 | "integrity": "sha1-gzr7taKmOF4tmuPZNeOeM+rqUjE=", 503 | "requires": { 504 | "absolute": "0.0.1", 505 | "chalk": "^1.1.3", 506 | "clone": "^1.0.2", 507 | "co-fs-extra": "^1.2.1", 508 | "commander": "^2.6.0", 509 | "gray-matter": "^2.0.0", 510 | "has-generators": "^1.0.1", 511 | "is": "^3.1.0", 512 | "is-utf8": "~0.2.0", 513 | "recursive-readdir": "^2.1.0", 514 | "rimraf": "^2.2.8", 515 | "stat-mode": "^0.2.0", 516 | "thunkify": "^2.1.2", 517 | "unyield": "0.0.1", 518 | "ware": "^1.2.0", 519 | "win-fork": "^1.1.1" 520 | }, 521 | "dependencies": { 522 | "ansi-regex": { 523 | "version": "2.1.1", 524 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", 525 | "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" 526 | }, 527 | "ansi-styles": { 528 | "version": "2.2.1", 529 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", 530 | "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" 531 | }, 532 | "chalk": { 533 | "version": "1.1.3", 534 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", 535 | "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", 536 | "requires": { 537 | "ansi-styles": "^2.2.1", 538 | "escape-string-regexp": "^1.0.2", 539 | "has-ansi": "^2.0.0", 540 | "strip-ansi": "^3.0.0", 541 | "supports-color": "^2.0.0" 542 | } 543 | }, 544 | "commander": { 545 | "version": "2.20.3", 546 | "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", 547 | "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" 548 | }, 549 | "strip-ansi": { 550 | "version": "3.0.1", 551 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", 552 | "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", 553 | "requires": { 554 | "ansi-regex": "^2.0.0" 555 | } 556 | }, 557 | "supports-color": { 558 | "version": "2.0.0", 559 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", 560 | "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" 561 | } 562 | } 563 | }, 564 | "mimic-fn": { 565 | "version": "2.1.0", 566 | "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", 567 | "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" 568 | }, 569 | "minimatch": { 570 | "version": "3.0.4", 571 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 572 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 573 | "requires": { 574 | "brace-expansion": "^1.1.7" 575 | } 576 | }, 577 | "mute-stream": { 578 | "version": "0.0.8", 579 | "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", 580 | "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" 581 | }, 582 | "once": { 583 | "version": "1.4.0", 584 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 585 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 586 | "requires": { 587 | "wrappy": "1" 588 | } 589 | }, 590 | "onetime": { 591 | "version": "5.1.2", 592 | "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", 593 | "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", 594 | "requires": { 595 | "mimic-fn": "^2.1.0" 596 | } 597 | }, 598 | "os-tmpdir": { 599 | "version": "1.0.2", 600 | "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", 601 | "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" 602 | }, 603 | "path-is-absolute": { 604 | "version": "1.0.1", 605 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 606 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" 607 | }, 608 | "path-key": { 609 | "version": "3.1.1", 610 | "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", 611 | "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" 612 | }, 613 | "recursive-readdir": { 614 | "version": "2.2.2", 615 | "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.2.tgz", 616 | "integrity": "sha512-nRCcW9Sj7NuZwa2XvH9co8NPeXUBhZP7CRKJtU+cS6PW9FpCIFoI5ib0NT1ZrbNuPoRy0ylyCaUL8Gih4LSyFg==", 617 | "requires": { 618 | "minimatch": "3.0.4" 619 | } 620 | }, 621 | "restore-cursor": { 622 | "version": "3.1.0", 623 | "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", 624 | "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", 625 | "requires": { 626 | "onetime": "^5.1.0", 627 | "signal-exit": "^3.0.2" 628 | } 629 | }, 630 | "rimraf": { 631 | "version": "2.7.1", 632 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", 633 | "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", 634 | "requires": { 635 | "glob": "^7.1.3" 636 | } 637 | }, 638 | "run-async": { 639 | "version": "2.4.1", 640 | "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", 641 | "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==" 642 | }, 643 | "rxjs": { 644 | "version": "6.6.3", 645 | "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.3.tgz", 646 | "integrity": "sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ==", 647 | "requires": { 648 | "tslib": "^1.9.0" 649 | } 650 | }, 651 | "safer-buffer": { 652 | "version": "2.1.2", 653 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 654 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 655 | }, 656 | "shebang-command": { 657 | "version": "2.0.0", 658 | "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", 659 | "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", 660 | "requires": { 661 | "shebang-regex": "^3.0.0" 662 | } 663 | }, 664 | "shebang-regex": { 665 | "version": "3.0.0", 666 | "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", 667 | "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" 668 | }, 669 | "signal-exit": { 670 | "version": "3.0.3", 671 | "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", 672 | "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==" 673 | }, 674 | "sprintf-js": { 675 | "version": "1.0.3", 676 | "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", 677 | "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" 678 | }, 679 | "stat-mode": { 680 | "version": "0.2.2", 681 | "resolved": "https://registry.npmjs.org/stat-mode/-/stat-mode-0.2.2.tgz", 682 | "integrity": "sha1-5sgLYjEj19gM8TLOU480YokHJQI=" 683 | }, 684 | "string-width": { 685 | "version": "4.2.0", 686 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", 687 | "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", 688 | "requires": { 689 | "emoji-regex": "^8.0.0", 690 | "is-fullwidth-code-point": "^3.0.0", 691 | "strip-ansi": "^6.0.0" 692 | } 693 | }, 694 | "strip-ansi": { 695 | "version": "6.0.0", 696 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", 697 | "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", 698 | "requires": { 699 | "ansi-regex": "^5.0.0" 700 | } 701 | }, 702 | "supports-color": { 703 | "version": "7.2.0", 704 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", 705 | "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", 706 | "requires": { 707 | "has-flag": "^4.0.0" 708 | } 709 | }, 710 | "through": { 711 | "version": "2.3.8", 712 | "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", 713 | "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" 714 | }, 715 | "thunkify": { 716 | "version": "2.1.2", 717 | "resolved": "https://registry.npmjs.org/thunkify/-/thunkify-2.1.2.tgz", 718 | "integrity": "sha1-+qDp0jDFGsyVyhOjYawFyn4EVT0=" 719 | }, 720 | "thunkify-wrap": { 721 | "version": "1.0.4", 722 | "resolved": "https://registry.npmjs.org/thunkify-wrap/-/thunkify-wrap-1.0.4.tgz", 723 | "integrity": "sha1-tSvlSN3+/aIOALWMYJZ2K0PdaIA=", 724 | "requires": { 725 | "enable": "1" 726 | } 727 | }, 728 | "tmp": { 729 | "version": "0.0.33", 730 | "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", 731 | "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", 732 | "requires": { 733 | "os-tmpdir": "~1.0.2" 734 | } 735 | }, 736 | "toml": { 737 | "version": "2.3.6", 738 | "resolved": "https://registry.npmjs.org/toml/-/toml-2.3.6.tgz", 739 | "integrity": "sha512-gVweAectJU3ebq//Ferr2JUY4WKSDe5N+z0FvjDncLGyHmIDoxgY/2Ie4qfEIDm4IS7OA6Rmdm7pdEEdMcV/xQ==" 740 | }, 741 | "tslib": { 742 | "version": "1.14.1", 743 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", 744 | "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" 745 | }, 746 | "type-fest": { 747 | "version": "0.11.0", 748 | "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.11.0.tgz", 749 | "integrity": "sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ==" 750 | }, 751 | "universalify": { 752 | "version": "2.0.0", 753 | "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", 754 | "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" 755 | }, 756 | "unyield": { 757 | "version": "0.0.1", 758 | "resolved": "https://registry.npmjs.org/unyield/-/unyield-0.0.1.tgz", 759 | "integrity": "sha1-FQ5l2kK/d0JEW5WKZOubhdHSsYA=", 760 | "requires": { 761 | "co": "~3.1.0" 762 | } 763 | }, 764 | "ware": { 765 | "version": "1.3.0", 766 | "resolved": "https://registry.npmjs.org/ware/-/ware-1.3.0.tgz", 767 | "integrity": "sha1-0bFPOdLiy0q4xAmPdW/ksWTkc9Q=", 768 | "requires": { 769 | "wrap-fn": "^0.1.0" 770 | } 771 | }, 772 | "which": { 773 | "version": "2.0.2", 774 | "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", 775 | "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", 776 | "requires": { 777 | "isexe": "^2.0.0" 778 | } 779 | }, 780 | "win-fork": { 781 | "version": "1.1.1", 782 | "resolved": "https://registry.npmjs.org/win-fork/-/win-fork-1.1.1.tgz", 783 | "integrity": "sha1-j1jgZW/KAK3IyGoriePNLWotXl4=" 784 | }, 785 | "wrap-fn": { 786 | "version": "0.1.5", 787 | "resolved": "https://registry.npmjs.org/wrap-fn/-/wrap-fn-0.1.5.tgz", 788 | "integrity": "sha1-8htuQQFv9KfjFyDbxjoJAWvfmEU=", 789 | "requires": { 790 | "co": "3.1.0" 791 | } 792 | }, 793 | "wrappy": { 794 | "version": "1.0.2", 795 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 796 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" 797 | } 798 | } 799 | } 800 | -------------------------------------------------------------------------------- /packages/wokoo-scripts/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wokoo", 3 | "version": "0.3.3", 4 | "description": "create the basic project of tampermonkey", 5 | "author": "kinyaying ", 6 | "homepage": "", 7 | "license": "MIT", 8 | "main": "index.js", 9 | "directories": { 10 | "lib": "lib", 11 | "test": "__tests__" 12 | }, 13 | "bin": { 14 | "wokoo": "./bin/www" 15 | }, 16 | "files": [ 17 | "lib", 18 | "modifyTemplate.js" 19 | ], 20 | "scripts": { 21 | "test": "echo \"Error: run tests from root\" && exit 1" 22 | }, 23 | "gitHead": "074c60fcb699bbdba2f179efb50a60eb86e09f96", 24 | "dependencies": { 25 | "chalk": "^4.1.0", 26 | "commander": "^7.0.0", 27 | "consolidate": "^0.16.0", 28 | "cross-spawn": "^7.0.3", 29 | "ejs": "^3.1.5", 30 | "fs-extra": "^9.1.0", 31 | "inquirer": "^7.3.3", 32 | "metalsmith": "^2.3.0" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /packages/wokoo-template/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /packages/wokoo-template/README.md: -------------------------------------------------------------------------------- 1 | # wokoo-template 2 | 3 | 是 wokoo 脚手架的模板部分,配合 [wokoo-scripts](https://www.npmjs.com/package/wokoo-scripts),用于初始化一个有基础配置的油猴项目。 4 | 5 | ## 功能 6 | 7 | - 提供 vue 和 react 的基本工程项目,根据用户选择生成指定基础项目 8 | - 提供基础的 webpack 配置 9 | - tampermonkey.txt 提供基本的油猴脚本配置 10 | 11 | ## 使用 12 | 13 | 1. 安装 14 | 15 | ``` 16 | npm i wokoo -g 17 | ``` 18 | 19 | 2. 创建项目 20 | 21 | ``` 22 | wokoo my-plugin 23 | ``` 24 | 25 | 3. 命令行中会弹出询问: 26 | ? which template do you prefer? 27 | [ ] react 28 | [ ] vue 29 | 4. 选择对应模板,生成初始化项目 30 | 31 | ## 使用到的库 32 | 33 | - vue 34 | - react 35 | - less 36 | - webpack 37 | 38 | ## 目录结构 39 | 40 | ``` 41 | . 42 | ├── README.md 43 | ├── package-lock.json 44 | ├── package.json 45 | ├── public 公共资源 46 | │   ├── favicon.ico 47 | │   ├── icon.jpg 48 | │   └── index.html 49 | ├── react-template react模板 50 | │   ├── README.md 51 | │   ├── src 52 | │   │   ├── app.css 53 | │   │   ├── app.js 54 | │   │   └── index.js 55 | │   ├── tampermonkey.js 油猴插件基础配置文件 56 | │   ├── template.json 57 | │   └── webpack.config.base.js 针对react的webpack配置项 58 | ├── vue-template vue模板 59 | │   ├── README.md 60 | │   ├── src 61 | │   │   ├── app.less 62 | │   │   ├── app.vue 63 | │   │   └── index.js 64 | │   ├── tampermonkey.js 油猴插件基础配置文件 65 | │   ├── template.json 66 | │   └── webpack.config.base.js 针对vue的webpack配置项 67 | └── webpack.config.js 68 | ``` 69 | 70 | ## 了解更多 71 | 72 | 如果想了解更多内容,请访问下面的网址: 73 | [油猴脚手架 wokoo 使用说明](https://juejin.cn/post/6922815205575491597) 74 | [油猴脚手架 wokoo git 仓库](https://github.com/kinyaying/wokoo) 75 | -------------------------------------------------------------------------------- /packages/wokoo-template/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wokoo-template", 3 | "version": "0.3.3", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "base64-js": { 8 | "version": "1.5.1", 9 | "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", 10 | "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" 11 | }, 12 | "bl": { 13 | "version": "4.0.3", 14 | "resolved": "https://registry.npmjs.org/bl/-/bl-4.0.3.tgz", 15 | "integrity": "sha512-fs4G6/Hu4/EE+F75J8DuN/0IpQqNjAdC7aEQv7Qt8MHGUH7Ckv2MwTEEeN9QehD0pfIDkMI1bkHYkKy7xHyKIg==", 16 | "requires": { 17 | "buffer": "^5.5.0", 18 | "inherits": "^2.0.4", 19 | "readable-stream": "^3.4.0" 20 | } 21 | }, 22 | "buffer": { 23 | "version": "5.7.1", 24 | "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", 25 | "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", 26 | "requires": { 27 | "base64-js": "^1.3.1", 28 | "ieee754": "^1.1.13" 29 | } 30 | }, 31 | "cli-cursor": { 32 | "version": "3.1.0", 33 | "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", 34 | "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", 35 | "requires": { 36 | "restore-cursor": "^3.1.0" 37 | } 38 | }, 39 | "cli-spinners": { 40 | "version": "2.5.0", 41 | "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.5.0.tgz", 42 | "integrity": "sha512-PC+AmIuK04E6aeSs/pUccSujsTzBhu4HzC2dL+CfJB/Jcc2qTRbEwZQDfIUpt2Xl8BodYBEq8w4fc0kU2I9DjQ==" 43 | }, 44 | "clone": { 45 | "version": "1.0.4", 46 | "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", 47 | "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=" 48 | }, 49 | "defaults": { 50 | "version": "1.0.3", 51 | "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", 52 | "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", 53 | "requires": { 54 | "clone": "^1.0.2" 55 | } 56 | }, 57 | "ieee754": { 58 | "version": "1.2.1", 59 | "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", 60 | "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" 61 | }, 62 | "inherits": { 63 | "version": "2.0.4", 64 | "resolved": "https://registry.npm.taobao.org/inherits/download/inherits-2.0.4.tgz", 65 | "integrity": "sha1-D6LGT5MpF8NDOg3tVTY6rjdBa3w=" 66 | }, 67 | "is-interactive": { 68 | "version": "1.0.0", 69 | "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", 70 | "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==" 71 | }, 72 | "log-symbols": { 73 | "version": "4.0.0", 74 | "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", 75 | "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==", 76 | "requires": { 77 | "chalk": "^4.0.0" 78 | }, 79 | "dependencies": { 80 | "ansi-styles": { 81 | "version": "4.3.0", 82 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 83 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 84 | "requires": { 85 | "color-convert": "^2.0.1" 86 | } 87 | }, 88 | "chalk": { 89 | "version": "4.1.0", 90 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", 91 | "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", 92 | "requires": { 93 | "ansi-styles": "^4.1.0", 94 | "supports-color": "^7.1.0" 95 | } 96 | }, 97 | "color-convert": { 98 | "version": "2.0.1", 99 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 100 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 101 | "requires": { 102 | "color-name": "~1.1.4" 103 | } 104 | }, 105 | "color-name": { 106 | "version": "1.1.4", 107 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 108 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" 109 | }, 110 | "has-flag": { 111 | "version": "4.0.0", 112 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", 113 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" 114 | }, 115 | "supports-color": { 116 | "version": "7.2.0", 117 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", 118 | "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", 119 | "requires": { 120 | "has-flag": "^4.0.0" 121 | } 122 | } 123 | } 124 | }, 125 | "mimic-fn": { 126 | "version": "2.1.0", 127 | "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", 128 | "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" 129 | }, 130 | "onetime": { 131 | "version": "5.1.2", 132 | "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", 133 | "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", 134 | "requires": { 135 | "mimic-fn": "^2.1.0" 136 | } 137 | }, 138 | "ora": { 139 | "version": "5.2.0", 140 | "resolved": "https://registry.npmjs.org/ora/-/ora-5.2.0.tgz", 141 | "integrity": "sha512-+wG2v8TUU8EgzPHun1k/n45pXquQ9fHnbXVetl9rRgO6kjZszGGbraF3XPTIdgeA+s1lbRjSEftAnyT0w8ZMvQ==", 142 | "requires": { 143 | "bl": "^4.0.3", 144 | "chalk": "^4.1.0", 145 | "cli-cursor": "^3.1.0", 146 | "cli-spinners": "^2.5.0", 147 | "is-interactive": "^1.0.0", 148 | "log-symbols": "^4.0.0", 149 | "strip-ansi": "^6.0.0", 150 | "wcwidth": "^1.0.1" 151 | }, 152 | "dependencies": { 153 | "ansi-regex": { 154 | "version": "5.0.0", 155 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", 156 | "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==" 157 | }, 158 | "ansi-styles": { 159 | "version": "4.3.0", 160 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 161 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 162 | "requires": { 163 | "color-convert": "^2.0.1" 164 | } 165 | }, 166 | "chalk": { 167 | "version": "4.1.0", 168 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", 169 | "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", 170 | "requires": { 171 | "ansi-styles": "^4.1.0", 172 | "supports-color": "^7.1.0" 173 | } 174 | }, 175 | "color-convert": { 176 | "version": "2.0.1", 177 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 178 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 179 | "requires": { 180 | "color-name": "~1.1.4" 181 | } 182 | }, 183 | "color-name": { 184 | "version": "1.1.4", 185 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 186 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" 187 | }, 188 | "has-flag": { 189 | "version": "4.0.0", 190 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", 191 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" 192 | }, 193 | "strip-ansi": { 194 | "version": "6.0.0", 195 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", 196 | "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", 197 | "requires": { 198 | "ansi-regex": "^5.0.0" 199 | } 200 | }, 201 | "supports-color": { 202 | "version": "7.2.0", 203 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", 204 | "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", 205 | "requires": { 206 | "has-flag": "^4.0.0" 207 | } 208 | } 209 | } 210 | }, 211 | "readable-stream": { 212 | "version": "3.6.0", 213 | "resolved": "https://registry.npm.taobao.org/readable-stream/download/readable-stream-3.6.0.tgz", 214 | "integrity": "sha1-M3u9o63AcGvT4CRCaihtS0sskZg=", 215 | "requires": { 216 | "inherits": "^2.0.3", 217 | "string_decoder": "^1.1.1", 218 | "util-deprecate": "^1.0.1" 219 | } 220 | }, 221 | "restore-cursor": { 222 | "version": "3.1.0", 223 | "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", 224 | "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", 225 | "requires": { 226 | "onetime": "^5.1.0", 227 | "signal-exit": "^3.0.2" 228 | } 229 | }, 230 | "safe-buffer": { 231 | "version": "5.2.1", 232 | "resolved": "https://registry.npm.taobao.org/safe-buffer/download/safe-buffer-5.2.1.tgz", 233 | "integrity": "sha1-Hq+fqb2x/dTsdfWPnNtOa3gn7sY=" 234 | }, 235 | "signal-exit": { 236 | "version": "3.0.3", 237 | "resolved": "https://registry.npm.taobao.org/signal-exit/download/signal-exit-3.0.3.tgz", 238 | "integrity": "sha1-oUEMLt2PB3sItOJTyOrPyvBXRhw=" 239 | }, 240 | "string_decoder": { 241 | "version": "1.3.0", 242 | "resolved": "https://registry.npm.taobao.org/string_decoder/download/string_decoder-1.3.0.tgz", 243 | "integrity": "sha1-QvEUWUpGzxqOMLCoT1bHjD7awh4=", 244 | "requires": { 245 | "safe-buffer": "~5.2.0" 246 | } 247 | }, 248 | "util-deprecate": { 249 | "version": "1.0.2", 250 | "resolved": "https://registry.npm.taobao.org/util-deprecate/download/util-deprecate-1.0.2.tgz", 251 | "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" 252 | }, 253 | "wcwidth": { 254 | "version": "1.0.1", 255 | "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", 256 | "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", 257 | "requires": { 258 | "defaults": "^1.0.3" 259 | } 260 | } 261 | } 262 | } 263 | -------------------------------------------------------------------------------- /packages/wokoo-template/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wokoo-template", 3 | "version": "0.3.3", 4 | "description": "provide the basic template for wokoo-scrits to create a tampermonkey project", 5 | "author": "kinyaying ", 6 | "homepage": "", 7 | "license": "ISC", 8 | "main": "index.js", 9 | "directories": { 10 | "lib": "lib", 11 | "test": "__tests__" 12 | }, 13 | "files": [ 14 | "react-template", 15 | "vue-template", 16 | "public", 17 | "webpack.config.js", 18 | ".gitignore" 19 | ], 20 | "scripts": { 21 | "test": "echo \"Error: run tests from root\" && exit 1" 22 | }, 23 | "gitHead": "074c60fcb699bbdba2f179efb50a60eb86e09f96" 24 | } 25 | -------------------------------------------------------------------------------- /packages/wokoo-template/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kinyaying/wokoo/2961afcb53c0e85dae8ec0f93b6f73fb0c9eb134/packages/wokoo-template/public/favicon.ico -------------------------------------------------------------------------------- /packages/wokoo-template/public/icon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kinyaying/wokoo/2961afcb53c0e85dae8ec0f93b6f73fb0c9eb134/packages/wokoo-template/public/icon.jpg -------------------------------------------------------------------------------- /packages/wokoo-template/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /packages/wokoo-template/react-template/README.md: -------------------------------------------------------------------------------- 1 | ## <%=projectName%> 2 | 3 | 基于 wokoo 搭建的初始化工程,用于油猴插件开发。 4 | 5 | **基础配置:** 6 | 7 | - <%=basicProject%> 8 | - less 9 | - webpack 10 | 11 | ## 目录结构 12 | 13 | ``` 14 | . 15 | ├── README.md 说明 16 | ├── package-lock.json 17 | ├── package.json 18 | ├── public 静态文件 19 | │   ├── favicon.ico 20 | │   ├── icon.jpg 21 | │   └── index.html html 文件 22 | ├── src 23 | │   ├── app.less 24 | │   ├── app.<% if(basicProject=='vue'){ %>vue<% } %><% if (basicProject=='react') { %>js<% } %> 25 | │   └── index.js 项目入口 26 | ├── tampermonkey.txt 油猴脚本入口文件 27 | ├── webpack.config.base.js 28 | └── webpack.config.js webpack 配置 29 | ``` 30 | 31 | ## 开发 32 | 33 | **启动** 34 | 进入项目目录后,在命令行中输入: 35 | 36 | ```shell 37 | npm start 38 | ``` 39 | 40 | **调试** 41 | 42 | 1. 打开浏览器,输入`localhost:8080`,查看页面展示是否正常。 43 | 2. 安装油猴插件 44 | 3. 打开油猴插件编辑界面,将 tampermonkey.txt 里的内容复制到编辑框中,保存。 45 | 4. 打开任意一个网页,比如`www.baidu.com`, 46 | 47 | - 查看油猴 icon 是否有一个 1 的数字标志,如果有说明油猴脚本已经成功激活 48 | - 网页的右上角会出现初始页面 49 | 50 | **构建** 51 | 52 | ```shell 53 | npm run build 54 | ``` 55 | 56 | **发布插件到油猴市场** 57 | 58 | 油猴市场的优点是不用审核,即发即用,非常方便。 59 | 60 | 1. 将/dist/app.bundle.js 文件部署到 cdn 上,获取到对应 url。(可以放到 github 上,如果托管到 git 上最好做 cdn 加速) 61 | 2. 登录[油猴市场](https://greasyfork.org/),谷歌账号或 github 账号都可使用。 62 | 3. 点击账号名称,再点击**发布你编写的脚本** 63 | 4. 进入编辑页,将 tampermonkey.txt 里的内容复制到编辑框中,记得将里面的`localhost:8080`网址替换成静态资源 url 64 | 5. 点击 「发布脚本」即可 65 | 66 | ## 例子 demo 67 | 68 | 我已经使用 wokoo 脚手架开发了多个 demo,并发布到[油猴市场](https://greasyfork.org/),欢迎安装试用。 69 | [wokoo-demo](https://greasyfork.org/zh-CN/scripts/420327-wokoo-demo): 简单的示例插件 70 | [zhihu-helper](https://greasyfork.org/zh-CN/scripts/421238-zhihu-helper): 知乎目录 71 | [MoveSearch](https://greasyfork.org/zh-CN/scripts/420327-MoveSearch): 划词搜索,默认搜[开发者搜索](http://kaifa.baidu.com) 72 | 73 | [快速上手油猴插件开发(实战篇)](https://juejin.cn/post/6925605904561750030) 详细写了开发过程 74 | 75 | ## 了解更多 76 | 77 | 如果想了解更多内容,请访问下面的网址: 78 | [油猴脚手架 wokoo 使用说明](https://juejin.cn/post/6922815205575491597) 79 | [油猴脚手架 wokoo git 仓库](https://github.com/kinyaying/wokoo) 80 | -------------------------------------------------------------------------------- /packages/wokoo-template/react-template/src/app.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import './app.less' 3 | import logo from '../public/icon.jpg' 4 | export default class extends React.Component { 5 | constructor(props) { 6 | super(props) 7 | this.state = { show: true } 8 | } 9 | handleClose() { 10 | this.setState({ 11 | show: !this.state.show, 12 | }) 13 | } 14 | render() { 15 | let { show } = this.state 16 | return ( 17 | <> 18 | {show ? ( 19 |
20 |
21 | logo 22 | 26 | X 27 | 28 |

29 | Edit App.js and save to reload. 30 |

31 | 37 | Learn Wokoo 38 | 39 |
40 |
41 | ) : ( 42 |
43 | logo 44 | open 45 |
46 | )} 47 | 48 | ) 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /packages/wokoo-template/react-template/src/app.less: -------------------------------------------------------------------------------- 1 | .Wokoo { 2 | position: absolute; 3 | text-align: center; 4 | width: 400px; 5 | height: 400px; 6 | top: 0; 7 | right: 0; 8 | z-index: 999; 9 | } 10 | .Wokoo-logo { 11 | height: 30vmin; 12 | border-radius: 50%; 13 | pointer-events: none; 14 | } 15 | @media (prefers-reduced-motion: no-preference) { 16 | .Wokoo-logo { 17 | animation: Wokoo-app-logo-spin infinite 20s linear; 18 | } 19 | } 20 | 21 | .Wokoo-header { 22 | background-color: #6c4d25; 23 | display: flex; 24 | flex-direction: column; 25 | align-items: center; 26 | justify-content: center; 27 | font-size: calc(10px + 2vmin); 28 | color: white; 29 | height: 100%; 30 | } 31 | 32 | .Wokoo-link { 33 | color: #efb61c; 34 | } 35 | .Wokoo-close-icon { 36 | position: absolute; 37 | top: 10px; 38 | right: 10px; 39 | cursor: pointer; 40 | } 41 | .Wokoo-hide { 42 | position: absolute; 43 | text-align: center; 44 | width: 100px; 45 | height: 40px; 46 | background-color: #6c4d25; 47 | top: 0; 48 | right: 0; 49 | z-index: 999; 50 | display: flex; 51 | align-items: center; 52 | justify-content: center; 53 | color: #fff; 54 | cursor: pointer; 55 | } 56 | .Wokoo-hide-logo { 57 | width: 30px; 58 | height: 30px; 59 | border-radius: 50%; 60 | margin-right: 10px; 61 | } 62 | 63 | @keyframes Wokoo-app-logo-spin { 64 | from { 65 | transform: rotate(0deg); 66 | } 67 | to { 68 | transform: rotate(360deg); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /packages/wokoo-template/react-template/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import ReactDOM from 'react-dom' 3 | import App from './app' 4 | 5 | const wokooApp = document.createElement('div') 6 | wokooApp.id = 'wokooApp-<%=projectName%>-<%=randomNumber%>' 7 | document.body.appendChild(wokooApp) 8 | ReactDOM.render(, wokooApp) 9 | -------------------------------------------------------------------------------- /packages/wokoo-template/react-template/tampermonkey.js: -------------------------------------------------------------------------------- 1 | // ==UserScript== 2 | // @name <%=projectName%> 3 | // @namespace http://tampermonkey.net/ 4 | // @version <%=version%> 5 | // @description try to take over the world! 6 | // @author 7 | // @match https://*/* 8 | // @match http://*/* 9 | 10 | // ==/UserScript== 11 | 12 | ;(function () { 13 | 'use strict' 14 | if (location.href === 'http://localhost:8080/') return 15 | var script = document.createElement('script') 16 | script.src = 'http://localhost:8080/app.bundle.js' 17 | document.body.appendChild(script) 18 | })() 19 | -------------------------------------------------------------------------------- /packages/wokoo-template/react-template/template.json: -------------------------------------------------------------------------------- 1 | { 2 | "package": { 3 | "dependencies": { 4 | "react": "^17.0.1", 5 | "react-dom": "^17.0.1", 6 | "@babel/core": "^7.12.10", 7 | "@babel/preset-react": "^7.12.10", 8 | "babel-loader": "^8.2.2" 9 | }, 10 | "devDependencies": { 11 | "@babel/plugin-proposal-class-properties": "^7.12.1", 12 | "@babel/plugin-proposal-decorators": "^7.12.12", 13 | "@babel/preset-env": "^7.12.11", 14 | "cross-env": "^7.0.3", 15 | "css-loader": "^5.0.1", 16 | "file-loader": "^6.2.0", 17 | "html-webpack-plugin": "^5.0.0", 18 | "less": "^4.1.0", 19 | "less-loader": "^8.0.0", 20 | "style-loader": "^2.0.0", 21 | "url-loader": "^4.1.1", 22 | "webpack": "^5.20.2", 23 | "webpack-cli": "^4.5.0", 24 | "webpack-dev-server": "^3.11.2", 25 | "webpack-merge": "^5.7.3" 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /packages/wokoo-template/react-template/webpack.config.base.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | entry: { 3 | app: '/src/index.js', 4 | }, 5 | module: { 6 | rules: [ 7 | { 8 | test: /\.(js|jsx)$/, //匹配js文件 9 | use: { 10 | loader: 'babel-loader', 11 | options: { 12 | presets: ['@babel/preset-react', '@babel/preset-env'], 13 | plugins: [ 14 | ['@babel/plugin-proposal-decorators', { legacy: true }], 15 | ['@babel/plugin-proposal-class-properties', { loose: true }], 16 | ['@babel/plugin-proposal-private-methods', { loose: true }], 17 | ['@babel/plugin-proposal-private-property-in-object', { loose: true }] 18 | ], 19 | }, 20 | }, 21 | }, 22 | ], 23 | }, 24 | } 25 | -------------------------------------------------------------------------------- /packages/wokoo-template/vue-template/README.md: -------------------------------------------------------------------------------- 1 | ## <%=projectName%> 2 | 3 | 基于 wokoo 搭建的初始化工程,用于油猴插件开发。 4 | 5 | **基础配置:** 6 | 7 | - <%=basicProject%> 8 | - less 9 | - webpack 10 | 11 | ## 目录结构 12 | 13 | ``` 14 | . 15 | ├── README.md 说明 16 | ├── package-lock.json 17 | ├── package.json 18 | ├── public 静态文件 19 | │   ├── favicon.ico 20 | │   ├── icon.jpg 21 | │   └── index.html html 文件 22 | ├── src 23 | │   ├── app.less 24 | │   ├── app.<% if(basicProject=='vue'){ %>vue<% } %><% if (basicProject=='react') { %>js<% } %> 25 | │   └── index.js 项目入口 26 | ├── tampermonkey.txt 油猴脚本入口文件 27 | ├── webpack.config.base.js 28 | └── webpack.config.js webpack 配置 29 | ``` 30 | 31 | ## 开发 32 | 33 | **启动** 34 | 进入项目目录后,在命令行中输入: 35 | 36 | ```shell 37 | npm start 38 | ``` 39 | 40 | **调试** 41 | 42 | 1. 打开浏览器,输入`localhost:8080`,查看页面展示是否正常。 43 | 2. 安装油猴插件 44 | 3. 打开油猴插件编辑界面,将 tampermonkey.txt 里的内容复制到编辑框中,保存。 45 | 4. 打开任意一个网页,比如`www.baidu.com`, 46 | 47 | - 查看油猴 icon 是否有一个 1 的数字标志,如果有说明油猴脚本已经成功激活 48 | - 网页的右上角会出现初始页面 49 | 50 | **构建** 51 | 52 | ```shell 53 | npm run build 54 | ``` 55 | 56 | **发布插件到油猴市场** 57 | 58 | 油猴市场的优点是不用审核,即发即用,非常方便。 59 | 60 | 1. 将/dist/app.bundle.js 文件部署到 cdn 上,获取到对应 url。(可以放到 github 上,如果托管到 git 上最好做 cdn 加速) 61 | 2. 登录[油猴市场](https://greasyfork.org/),谷歌账号或 github 账号都可使用。 62 | 3. 点击账号名称,再点击**发布你编写的脚本** 63 | 4. 进入编辑页,将 tampermonkey.txt 里的内容复制到编辑框中,记得将里面的`localhost:8080`网址替换成静态资源 url 64 | 5. 点击 「发布脚本」即可 65 | 66 | ## 例子 demo 67 | 68 | 我已经使用 wokoo 脚手架开发了多个 demo,并发布到[油猴市场](https://greasyfork.org/),欢迎安装试用。 69 | [wokoo-demo](https://greasyfork.org/zh-CN/scripts/420327-wokoo-demo): 简单的示例插件 70 | [zhihu-helper](https://greasyfork.org/zh-CN/scripts/421238-zhihu-helper): 知乎目录 71 | [MoveSearch](https://greasyfork.org/zh-CN/scripts/420327-MoveSearch): 划词搜索,默认搜[开发者搜索](http://kaifa.baidu.com) 72 | 73 | [快速上手油猴插件开发(实战篇)](https://juejin.cn/post/6925605904561750030) 详细写了开发过程 74 | 75 | ## 了解更多 76 | 77 | 如果想了解更多内容,请访问下面的网址: 78 | [油猴脚手架 wokoo 使用说明](https://juejin.cn/post/6922815205575491597) 79 | [油猴脚手架 wokoo git 仓库](https://github.com/kinyaying/wokoo) 80 | -------------------------------------------------------------------------------- /packages/wokoo-template/vue-template/src/app.less: -------------------------------------------------------------------------------- 1 | .Wokoo { 2 | position: absolute; 3 | text-align: center; 4 | width: 400px; 5 | height: 400px; 6 | top: 0; 7 | right: 0; 8 | z-index: 999; 9 | } 10 | .Wokoo-logo { 11 | height: 30vmin; 12 | border-radius: 50%; 13 | pointer-events: none; 14 | } 15 | @media (prefers-reduced-motion: no-preference) { 16 | .Wokoo-logo { 17 | animation: Wokoo-app-logo-spin infinite 20s linear; 18 | } 19 | } 20 | 21 | .Wokoo-header { 22 | background-color: #6c4d25; 23 | display: flex; 24 | flex-direction: column; 25 | align-items: center; 26 | justify-content: center; 27 | font-size: calc(10px + 2vmin); 28 | color: white; 29 | height: 100%; 30 | } 31 | 32 | .Wokoo-link { 33 | color: #efb61c; 34 | } 35 | .Wokoo-close-icon { 36 | position: absolute; 37 | top: 10px; 38 | right: 10px; 39 | cursor: pointer; 40 | } 41 | .Wokoo-hide { 42 | position: absolute; 43 | text-align: center; 44 | width: 100px; 45 | height: 40px; 46 | background-color: #6c4d25; 47 | top: 0; 48 | right: 0; 49 | z-index: 999; 50 | display: flex; 51 | align-items: center; 52 | justify-content: center; 53 | color: #fff; 54 | cursor: pointer; 55 | } 56 | .Wokoo-hide-logo { 57 | width: 30px; 58 | height: 30px; 59 | border-radius: 50%; 60 | margin-right: 10px; 61 | } 62 | 63 | @keyframes Wokoo-app-logo-spin { 64 | from { 65 | transform: rotate(0deg); 66 | } 67 | to { 68 | transform: rotate(360deg); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /packages/wokoo-template/vue-template/src/app.vue: -------------------------------------------------------------------------------- 1 | 29 | 46 | 48 | -------------------------------------------------------------------------------- /packages/wokoo-template/vue-template/src/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import App from './app.vue' 3 | 4 | const wokooApp = document.createElement('div') 5 | wokooApp.id = 'wokooApp-<%=projectName%>-<%=randomNumber%>' 6 | document.body.appendChild(wokooApp) 7 | const vm = new Vue({ 8 | el: wokooApp, 9 | render: (h) => h(App), 10 | }) 11 | -------------------------------------------------------------------------------- /packages/wokoo-template/vue-template/tampermonkey.js: -------------------------------------------------------------------------------- 1 | // ==UserScript== 2 | // @name <%=projectName%> 3 | // @namespace http://tampermonkey.net/ 4 | // @version <%=version%> 5 | // @description try to take over the world! 6 | // @author 7 | // @match https://*/* 8 | // @match http://*/* 9 | 10 | // ==/UserScript== 11 | 12 | ;(function () { 13 | 'use strict' 14 | if (location.href === 'http://localhost:8080/') return 15 | var script = document.createElement('script') 16 | script.src = 'http://localhost:8080/app.bundle.js' 17 | document.body.appendChild(script) 18 | })() 19 | -------------------------------------------------------------------------------- /packages/wokoo-template/vue-template/template.json: -------------------------------------------------------------------------------- 1 | { 2 | "package": { 3 | "dependencies": { 4 | "vue": "^2.6.12", 5 | "vue-loader": "^15.9.6", 6 | "vue-template-compiler": "^2.6.12" 7 | }, 8 | "devDependencies": { 9 | "css-loader": "^5.0.1", 10 | "file-loader": "^6.2.0", 11 | "html-webpack-plugin": "^5.0.0", 12 | "less": "^4.1.0", 13 | "less-loader": "^8.0.0", 14 | "style-loader": "^2.0.0", 15 | "url-loader": "^4.1.1", 16 | "vue-loader": "^15.9.6", 17 | "webpack": "^5.20.2", 18 | "webpack-cli": "^4.5.0", 19 | "webpack-dev-server": "^3.11.2", 20 | "webpack-merge": "^5.7.3", 21 | "cross-env": "^7.0.3" 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /packages/wokoo-template/vue-template/webpack.config.base.js: -------------------------------------------------------------------------------- 1 | const VueLoaderPlugin = require('vue-loader/lib/plugin') 2 | 3 | module.exports = { 4 | entry: { 5 | app: '/src/index.js', 6 | }, 7 | module: { 8 | rules: [ 9 | { 10 | test: /\.vue$/, 11 | loader: 'vue-loader', 12 | }, 13 | ], 14 | }, 15 | plugins: [new VueLoaderPlugin()], 16 | } 17 | -------------------------------------------------------------------------------- /packages/wokoo-template/webpack.config.js: -------------------------------------------------------------------------------- 1 | const HtmlWebpackPlugin = require('html-webpack-plugin') 2 | const { merge } = require('webpack-merge') 3 | const base = require('./webpack.config.base') 4 | 5 | module.exports = merge(base, { 6 | mode: process.env.NODE_ENV || 'production', 7 | devtool: 'source-map', 8 | output: { 9 | filename: '[name].bundle.js', 10 | path: __dirname + '/dist', 11 | }, 12 | module: { 13 | rules: [ 14 | { 15 | test: /\.(less|css)$/, 16 | use: ['style-loader', 'css-loader', 'less-loader'], 17 | }, 18 | { 19 | test: /\.(woff|woff2|eot|ttf|otf|png|svg|jpg|gif)$/, 20 | use: { 21 | loader: 'url-loader', 22 | options: { 23 | limit: 20480, 24 | }, 25 | }, 26 | }, 27 | ], 28 | }, 29 | plugins: [ 30 | new HtmlWebpackPlugin({ 31 | template: './public/index.html', 32 | }), 33 | ], 34 | }) 35 | --------------------------------------------------------------------------------