├── tools
├── demo
│ ├── app.wxss
│ ├── package.json
│ ├── app.js
│ ├── pages
│ │ └── index
│ │ │ ├── index.wxss
│ │ │ ├── index.js
│ │ │ ├── index.wxml
│ │ │ └── index.json
│ ├── app.json
│ └── project.config.json
├── config.js
├── checkcomponents.js
├── checkwxss.js
├── utils.js
└── build.js
├── .eslintrc.js
├── src
├── utils.js
├── index.json
├── assets
│ ├── demo1.jpg
│ └── demo2.jpg
├── index.wxml
├── index.wxss
└── index.js
├── .gitignore
├── .babelrc
├── .npmignore
├── test
├── wx.test.js
├── index.test.js
└── utils.js
├── gulpfile.js
├── LICENSE
├── README.md
└── package.json
/tools/demo/app.wxss:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tools/demo/package.json:
--------------------------------------------------------------------------------
1 | {}
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {};
--------------------------------------------------------------------------------
/tools/demo/app.js:
--------------------------------------------------------------------------------
1 | App({})
2 |
--------------------------------------------------------------------------------
/tools/demo/pages/index/index.wxss:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/utils.js:
--------------------------------------------------------------------------------
1 | module.exports = {};
2 |
--------------------------------------------------------------------------------
/tools/demo/pages/index/index.js:
--------------------------------------------------------------------------------
1 | Page({})
2 |
--------------------------------------------------------------------------------
/tools/demo/pages/index/index.wxml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/index.json:
--------------------------------------------------------------------------------
1 | {
2 | "component": true,
3 | "usingComponents": {}
4 | }
--------------------------------------------------------------------------------
/src/assets/demo1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xjh22222228/weapp-input-frame/HEAD/src/assets/demo1.jpg
--------------------------------------------------------------------------------
/src/assets/demo2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xjh22222228/weapp-input-frame/HEAD/src/assets/demo2.jpg
--------------------------------------------------------------------------------
/tools/demo/pages/index/index.json:
--------------------------------------------------------------------------------
1 | {
2 | "usingComponents": {
3 | "comp": "../../components/index"
4 | }
5 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 | .DS_Store
3 | package-lock.json
4 |
5 | logs
6 | *.log
7 | npm-debug.log*
8 | yarn-debug.log*
9 | yarn-error.log*
10 |
11 | miniprogram_dist
12 | miniprogram_dev
13 | node_modules
14 | coverage
--------------------------------------------------------------------------------
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "plugins": [
3 | ["module-resolver", {
4 | "root": ["./src"],
5 | "alias": {}
6 | }]
7 | ],
8 | "presets": [
9 | ["env", {"loose": true, "modules": "commonjs"}]
10 | ]
11 | }
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | .idea
2 | .DS_Store
3 | package-lock.json
4 |
5 | logs
6 | *.log
7 | npm-debug.log*
8 | yarn-debug.log*
9 | yarn-error.log*
10 |
11 | src
12 | test
13 | tools
14 | docs
15 | miniprogram_dev
16 | node_modules
17 | coverage
18 | .babelrc
19 | gulpfile.js
20 | .eslintrc.js
--------------------------------------------------------------------------------
/tools/demo/app.json:
--------------------------------------------------------------------------------
1 | {
2 | "pages":[
3 | "pages/index/index"
4 | ],
5 | "window":{
6 | "backgroundTextStyle":"light",
7 | "navigationBarBackgroundColor": "#fff",
8 | "navigationBarTitleText": "WeChat",
9 | "navigationBarTextStyle":"black"
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/test/wx.test.js:
--------------------------------------------------------------------------------
1 | const _ = require('./utils')
2 |
3 | test('wx.getSystemInfo', async () => {
4 | wx.getSystemInfo({
5 | success(res) {
6 | expect(res.errMsg).toBe('getSystemInfo:ok')
7 | },
8 | complete(res) {
9 | expect(res.errMsg).toBe('getSystemInfo:ok')
10 | },
11 | })
12 | })
13 |
14 | test('wx.getSystemInfoSync', async () => {
15 | const info = wx.getSystemInfoSync()
16 | expect(info.SDKVersion).toBe('2.4.1')
17 | expect(info.version).toBe('6.6.3')
18 | })
19 |
--------------------------------------------------------------------------------
/src/index.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
14 |
15 |
16 |
22 | {{ valueList[index] }}
23 |
24 |
25 |
--------------------------------------------------------------------------------
/test/index.test.js:
--------------------------------------------------------------------------------
1 | const _ = require('./utils')
2 |
3 | test('render', async () => {
4 | const componentId = _.load('index', 'comp')
5 | const component = _.render(componentId, {prop: 'index.test.properties'})
6 |
7 | const parent = document.createElement('parent-wrapper')
8 | component.attach(parent)
9 |
10 | expect(_.match(component.dom, 'index.test.properties-false')).toBe(true)
11 |
12 | await _.sleep(10)
13 |
14 | expect(_.match(component.dom, 'index.test.properties-true')).toBe(true)
15 | })
16 |
--------------------------------------------------------------------------------
/test/utils.js:
--------------------------------------------------------------------------------
1 | const path = require('path')
2 | const simulate = require('miniprogram-simulate')
3 |
4 | const config = require('../tools/config')
5 |
6 | const srcPath = config.srcPath
7 | const oldLoad = simulate.load
8 | simulate.load = function (componentPath, ...args) {
9 | if (typeof componentPath === 'string') componentPath = path.join(srcPath, componentPath)
10 | return oldLoad(componentPath, ...args)
11 | }
12 |
13 | module.exports = simulate
14 |
15 | // adjust the simulated wx api
16 | const oldGetSystemInfoSync = global.wx.getSystemInfoSync
17 | global.wx.getSystemInfoSync = function() {
18 | const res = oldGetSystemInfoSync()
19 | res.SDKVersion = '2.4.1'
20 |
21 | return res
22 | }
23 |
--------------------------------------------------------------------------------
/tools/demo/project.config.json:
--------------------------------------------------------------------------------
1 | {
2 | "description": "项目配置文件。",
3 | "packOptions": {
4 | "ignore": []
5 | },
6 | "setting": {
7 | "urlCheck": true,
8 | "es6": true,
9 | "postcss": true,
10 | "minified": true,
11 | "newFeature": true,
12 | "nodeModules": true
13 | },
14 | "compileType": "miniprogram",
15 | "libVersion": "2.2.3",
16 | "appid": "",
17 | "projectname": "miniprogram-demo",
18 | "isGameTourist": false,
19 | "condition": {
20 | "search": {
21 | "current": -1,
22 | "list": []
23 | },
24 | "conversation": {
25 | "current": -1,
26 | "list": []
27 | },
28 | "game": {
29 | "currentL": -1,
30 | "list": []
31 | },
32 | "miniprogram": {
33 | "current": -1,
34 | "list": []
35 | }
36 | }
37 | }
--------------------------------------------------------------------------------
/gulpfile.js:
--------------------------------------------------------------------------------
1 | const gulp = require('gulp')
2 | const clean = require('gulp-clean')
3 |
4 | const config = require('./tools/config')
5 | const BuildTask = require('./tools/build')
6 | const id = require('./package.json').name || 'miniprogram-custom-component'
7 |
8 | // 构建任务实例
9 | // eslint-disable-next-line no-new
10 | new BuildTask(id, config.entry)
11 |
12 | // 清空生成目录和文件
13 | gulp.task('clean', gulp.series(() => gulp.src(config.distPath, {read: false, allowEmpty: true}).pipe(clean()), done => {
14 | if (config.isDev) {
15 | return gulp.src(config.demoDist, {read: false, allowEmpty: true})
16 | .pipe(clean())
17 | }
18 |
19 | return done()
20 | }))
21 | // 监听文件变化并进行开发模式构建
22 | gulp.task('watch', gulp.series(`${id}-watch`))
23 | // 开发模式构建
24 | gulp.task('dev', gulp.series(`${id}-dev`))
25 | // 生产模式构建
26 | gulp.task('default', gulp.series(`${id}-default`))
27 |
--------------------------------------------------------------------------------
/src/index.wxss:
--------------------------------------------------------------------------------
1 | .input-frame {
2 | position: relative;
3 | display: flex;
4 | justify-content: center;
5 | }
6 |
7 | .input-frame .input-item {
8 | width: 50px;
9 | height: 50px;
10 | display: flex;
11 | justify-content: center;
12 | align-items: center;
13 | border: 1px solid #ccc;
14 | }
15 |
16 | .input-frame__input {
17 | position: absolute;
18 | top: 0;
19 | left: 0;
20 | right: 0;
21 | bottom: 0;
22 | width: 100%;
23 | height: 100%;
24 | opacity: 0;
25 | left: -5000px;
26 | }
27 |
28 | .input-frame .input-item:not(:nth-last-child(1)) {
29 | border-right-color: transparent;
30 | }
31 |
32 | /* divider style */
33 | .input-frame.divider .input-item {
34 | border-top-color: transparent;
35 | border-right-color: transparent;
36 | border-left-color: transparent;
37 | margin: 0 7px;
38 | width: 40px;
39 | height: 40px;
40 | }
41 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 xiejiahe
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # input-frame  
2 |
3 | 小程序输入框组件,适用于支付密码、登录密码 等。
4 |
5 | ## Screenshots
6 |
7 |

8 |

9 |
10 |
11 |
12 | ## 安装
13 | 安装完成在开发者工具执行 `npm build`
14 | ```bash
15 | npm install weapp-input-frame -S
16 | ```
17 |
18 | ## 使用
19 | *.json
20 | ```json
21 | "usingComponents": {
22 | "input-frame": "miniprogram_npm/weapp-input-frame/index"
23 | }
24 | ```
25 |
26 | *.wxml
27 | ```html
28 |
29 | ```
30 |
31 |
32 | ## API
33 | - value 输入框默认值
34 | - plaintext 是否明文显示, 默认 false
35 | - focus 是否获取焦点, 默认 false
36 | - bind:change 输入发生变化触发
37 | - bind:finished 输入完成时触发
38 | - space 输入框的格子数量,一般 4 - 6, 默认 6
39 | - frameStyle 输入框的风格, `divider` / '' , 默认 ''
40 | - custom-class 自定义组件class
41 |
42 | ```html
43 |
50 | ```
51 |
52 | ## 暴露方法
53 | - getValue 获取输入框值
54 | - setValue 动态设置输入框值
55 |
56 | wxml
57 | ```html
58 | {
64 | const {wxss, importList} = res
65 |
66 | importList.forEach(importFile => this.push(importFile))
67 |
68 | file.contents = Buffer.from(wxss, 'utf8')
69 | this.push(file)
70 | // eslint-disable-next-line promise/no-callback-in-promise
71 | cb()
72 | }).catch(err => {
73 | // eslint-disable-next-line no-console
74 | console.warn(`deal with ${file.path} failed: ${err.stack}`)
75 | this.push(file)
76 | // eslint-disable-next-line promise/no-callback-in-promise
77 | cb()
78 | })
79 | } else {
80 | this.push(file)
81 | cb()
82 | }
83 | })
84 | },
85 |
86 | end() {
87 | return through.obj(function (file, enc, cb) {
88 | if (file.isBuffer) {
89 | const reg = /\/\*\s\*updated for miniprogram-custom-component\*\s(@import\s+(?:(?:"([^"]+)")|(?:'([^"]+)'));)\s\*\//ig
90 | const wxss = file.contents.toString('utf8').replace(reg, (all, $1) => $1)
91 |
92 | file.contents = Buffer.from(wxss, 'utf8')
93 | this.push(file)
94 | cb()
95 | } else {
96 | this.push(file)
97 | cb()
98 | }
99 | })
100 | },
101 | }
102 |
--------------------------------------------------------------------------------
/tools/utils.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs')
2 | const path = require('path')
3 |
4 | // eslint-disable-next-line no-unused-vars
5 | const colors = require('colors')
6 | const through = require('through2')
7 |
8 | /**
9 | * 异步函数封装
10 | */
11 | function wrap(func, scope) {
12 | return function (...args) {
13 | if (args.length) {
14 | const temp = args.pop()
15 | if (typeof temp !== 'function') {
16 | args.push(temp)
17 | }
18 | }
19 |
20 | return new Promise(function (resolve, reject) {
21 | args.push(function (err, data) {
22 | if (err) reject(err)
23 | else resolve(data)
24 | })
25 |
26 | func.apply((scope || null), args)
27 | })
28 | }
29 | }
30 |
31 | const accessSync = wrap(fs.access)
32 | const statSync = wrap(fs.stat)
33 | const renameSync = wrap(fs.rename)
34 | const mkdirSync = wrap(fs.mkdir)
35 | const readFileSync = wrap(fs.readFile)
36 | const writeFileSync = wrap(fs.writeFile)
37 |
38 | /**
39 | * 调整路径分隔符
40 | */
41 | function transformPath(filePath, sep = '/') {
42 | return filePath.replace(/[\\/]/g, sep)
43 | }
44 |
45 | /**
46 | * 检查文件是否存在
47 | */
48 | async function checkFileExists(filePath) {
49 | try {
50 | await accessSync(filePath)
51 | return true
52 | } catch (err) {
53 | return false
54 | }
55 | }
56 |
57 | /**
58 | * 递归创建目录
59 | */
60 | async function recursiveMkdir(dirPath) {
61 | const prevDirPath = path.dirname(dirPath)
62 | try {
63 | await accessSync(prevDirPath)
64 | } catch (err) {
65 | // 上一级目录不存在
66 | await recursiveMkdir(prevDirPath)
67 | }
68 |
69 | try {
70 | await accessSync(dirPath)
71 |
72 | const stat = await statSync(dirPath)
73 | if (stat && !stat.isDirectory()) {
74 | // 目标路径存在,但不是目录
75 | await renameSync(dirPath, `${dirPath}.bak`) // 将此文件重命名为 .bak 后缀
76 | await mkdirSync(dirPath)
77 | }
78 | } catch (err) {
79 | // 目标路径不存在
80 | await mkdirSync(dirPath)
81 | }
82 | }
83 |
84 | /**
85 | * 读取 json
86 | */
87 | function readJson(filePath) {
88 | try {
89 | // eslint-disable-next-line import/no-dynamic-require
90 | const content = require(filePath)
91 | delete require.cache[require.resolve(filePath)]
92 | return content
93 | } catch (err) {
94 | return null
95 | }
96 | }
97 |
98 | /**
99 | * 读取文件
100 | */
101 | async function readFile(filePath) {
102 | try {
103 | return await readFileSync(filePath, 'utf8')
104 | } catch (err) {
105 | // eslint-disable-next-line no-console
106 | return console.error(err)
107 | }
108 | }
109 |
110 | /**
111 | * 写文件
112 | */
113 | async function writeFile(filePath, data) {
114 | try {
115 | await recursiveMkdir(path.dirname(filePath))
116 | return await writeFileSync(filePath, data, 'utf8')
117 | } catch (err) {
118 | // eslint-disable-next-line no-console
119 | return console.error(err)
120 | }
121 | }
122 |
123 | /**
124 | * 时间格式化
125 | */
126 | function format(time, reg) {
127 | const date = typeof time === 'string' ? new Date(time) : time
128 | const map = {}
129 | map.yyyy = date.getFullYear()
130 | map.yy = ('' + map.yyyy).substr(2)
131 | map.M = date.getMonth() + 1
132 | map.MM = (map.M < 10 ? '0' : '') + map.M
133 | map.d = date.getDate()
134 | map.dd = (map.d < 10 ? '0' : '') + map.d
135 | map.H = date.getHours()
136 | map.HH = (map.H < 10 ? '0' : '') + map.H
137 | map.m = date.getMinutes()
138 | map.mm = (map.m < 10 ? '0' : '') + map.m
139 | map.s = date.getSeconds()
140 | map.ss = (map.s < 10 ? '0' : '') + map.s
141 |
142 | return reg.replace(/\byyyy|yy|MM|M|dd|d|HH|H|mm|m|ss|s\b/g, $1 => map[$1])
143 | }
144 |
145 | /**
146 | * 日志插件
147 | */
148 | function logger(action = 'copy') {
149 | return through.obj(function (file, enc, cb) {
150 | const type = path.extname(file.path).slice(1).toLowerCase()
151 |
152 | // eslint-disable-next-line no-console
153 | console.log(`[${format(new Date(), 'yyyy-MM-dd HH:mm:ss').grey}] [${action.green} ${type.green}] ${'=>'.cyan} ${file.path}`)
154 |
155 | this.push(file)
156 | cb()
157 | })
158 | }
159 |
160 | /**
161 | * 比较数组是否相等
162 | */
163 | function compareArray(arr1, arr2) {
164 | if (!Array.isArray(arr1) || !Array.isArray(arr2)) return false
165 | if (arr1.length !== arr2.length) return false
166 |
167 | for (let i = 0, len = arr1.length; i < len; i++) {
168 | if (arr1[i] !== arr2[i]) return false
169 | }
170 |
171 | return true
172 | }
173 |
174 | /**
175 | * 合并两个对象
176 | */
177 | function merge(obj1, obj2) {
178 | Object.keys(obj2).forEach(key => {
179 | if (Array.isArray(obj1[key]) && Array.isArray(obj2[key])) {
180 | obj1[key] = obj1[key].concat(obj2[key])
181 | } else if (typeof obj1[key] === 'object' && typeof obj2[key] === 'object') {
182 | obj1[key] = Object.assign(obj1[key], obj2[key])
183 | } else {
184 | obj1[key] = obj2[key]
185 | }
186 | })
187 |
188 | return obj1
189 | }
190 |
191 | /**
192 | * 获取 id
193 | */
194 | let seed = +new Date()
195 | function getId() {
196 | return ++seed
197 | }
198 |
199 | module.exports = {
200 | wrap,
201 | transformPath,
202 |
203 | checkFileExists,
204 | readJson,
205 | readFile,
206 | writeFile,
207 |
208 | logger,
209 | format,
210 | compareArray,
211 | merge,
212 | getId,
213 | }
214 |
--------------------------------------------------------------------------------
/tools/build.js:
--------------------------------------------------------------------------------
1 | const path = require('path')
2 | const fs = require('fs')
3 |
4 | const gulp = require('gulp')
5 | const clean = require('gulp-clean')
6 | const less = require('gulp-less')
7 | const rename = require('gulp-rename')
8 | const gulpif = require('gulp-if')
9 | const sourcemaps = require('gulp-sourcemaps')
10 | const webpack = require('webpack')
11 | const gulpInstall = require('gulp-install')
12 |
13 | const config = require('./config')
14 | const checkComponents = require('./checkcomponents')
15 | const checkWxss = require('./checkwxss')
16 | const _ = require('./utils')
17 |
18 | const jsConfig = config.js || {}
19 | const wxssConfig = config.wxss || {}
20 | const srcPath = config.srcPath
21 | const distPath = config.distPath
22 |
23 | /**
24 | * 获取 wxss 流
25 | */
26 | function wxss(wxssFileList) {
27 | if (!wxssFileList.length) return false
28 |
29 | return gulp.src(wxssFileList, {cwd: srcPath, base: srcPath})
30 | .pipe(checkWxss.start()) // 开始处理 import
31 | .pipe(gulpif(wxssConfig.less && wxssConfig.sourcemap, sourcemaps.init()))
32 | .pipe(gulpif(wxssConfig.less, less({paths: [srcPath]})))
33 | .pipe(checkWxss.end()) // 结束处理 import
34 | .pipe(rename({extname: '.wxss'}))
35 | .pipe(gulpif(wxssConfig.less && wxssConfig.sourcemap, sourcemaps.write('./')))
36 | .pipe(_.logger(wxssConfig.less ? 'generate' : undefined))
37 | .pipe(gulp.dest(distPath))
38 | }
39 |
40 | /**
41 | * 获取 js 流
42 | */
43 | function js(jsFileMap, scope) {
44 | const webpackConfig = config.webpack
45 | const webpackCallback = (err, stats) => {
46 | if (!err) {
47 | // eslint-disable-next-line no-console
48 | console.log(stats.toString({
49 | assets: true,
50 | cached: false,
51 | colors: true,
52 | children: false,
53 | errors: true,
54 | warnings: true,
55 | version: true,
56 | modules: false,
57 | publicPath: true,
58 | }))
59 | } else {
60 | // eslint-disable-next-line no-console
61 | console.log(err)
62 | }
63 | }
64 |
65 | webpackConfig.entry = jsFileMap
66 | webpackConfig.output.path = distPath
67 |
68 | if (scope.webpackWatcher) {
69 | scope.webpackWatcher.close()
70 | scope.webpackWatcher = null
71 | }
72 |
73 | if (config.isWatch) {
74 | scope.webpackWatcher = webpack(webpackConfig).watch({
75 | ignored: /node_modules/,
76 | }, webpackCallback)
77 | } else {
78 | webpack(webpackConfig).run(webpackCallback)
79 | }
80 | }
81 |
82 | /**
83 | * 拷贝文件
84 | */
85 | function copy(copyFileList) {
86 | if (!copyFileList.length) return false
87 |
88 | return gulp.src(copyFileList, {cwd: srcPath, base: srcPath})
89 | .pipe(_.logger())
90 | .pipe(gulp.dest(distPath))
91 | }
92 |
93 | /**
94 | * 安装依赖包
95 | */
96 | function install() {
97 | return gulp.series(async () => {
98 | const demoDist = config.demoDist
99 | const demoPackageJsonPath = path.join(demoDist, 'package.json')
100 | const packageJson = _.readJson(path.resolve(__dirname, '../package.json'))
101 | const dependencies = packageJson.dependencies || {}
102 |
103 | await _.writeFile(demoPackageJsonPath, JSON.stringify({dependencies}, null, '\t')) // write dev demo's package.json
104 | }, () => {
105 | const demoDist = config.demoDist
106 | const demoPackageJsonPath = path.join(demoDist, 'package.json')
107 |
108 | return gulp.src(demoPackageJsonPath)
109 | .pipe(gulpInstall({production: true}))
110 | })
111 | }
112 |
113 | class BuildTask {
114 | constructor(id, entry) {
115 | if (!entry) return
116 |
117 | this.id = id
118 | this.entries = Array.isArray(config.entry) ? config.entry : [config.entry]
119 | this.copyList = Array.isArray(config.copy) ? config.copy : []
120 | this.componentListMap = {}
121 | this.cachedComponentListMap = {}
122 |
123 | this.init()
124 | }
125 |
126 | init() {
127 | const id = this.id
128 |
129 | /**
130 | * 清空目标目录
131 | */
132 | gulp.task(`${id}-clean-dist`, () => gulp.src(distPath, {read: false, allowEmpty: true}).pipe(clean()))
133 |
134 | /**
135 | * 拷贝 demo 到目标目录
136 | */
137 | let isDemoExists = false
138 | gulp.task(`${id}-demo`, gulp.series(async () => {
139 | const demoDist = config.demoDist
140 |
141 | isDemoExists = await _.checkFileExists(path.join(demoDist, 'project.config.json'))
142 | }, done => {
143 | if (!isDemoExists) {
144 | const demoSrc = config.demoSrc
145 | const demoDist = config.demoDist
146 |
147 | return gulp.src('**/*', {cwd: demoSrc, base: demoSrc})
148 | .pipe(gulp.dest(demoDist))
149 | }
150 |
151 | return done()
152 | }))
153 |
154 | /**
155 | * 安装依赖包
156 | */
157 | gulp.task(`${id}-install`, install())
158 |
159 | /**
160 | * 检查自定义组件
161 | */
162 | gulp.task(`${id}-component-check`, async () => {
163 | const entries = this.entries
164 | const mergeComponentListMap = {}
165 | for (let i = 0, len = entries.length; i < len; i++) {
166 | let entry = entries[i]
167 | entry = path.join(srcPath, `${entry}.json`)
168 | const newComponentListMap = await checkComponents(entry)
169 |
170 | _.merge(mergeComponentListMap, newComponentListMap)
171 | }
172 |
173 | this.cachedComponentListMap = this.componentListMap
174 | this.componentListMap = mergeComponentListMap
175 | })
176 |
177 | /**
178 | * 写 json 文件到目标目录
179 | */
180 | gulp.task(`${id}-component-json`, done => {
181 | const jsonFileList = this.componentListMap.jsonFileList
182 |
183 | if (jsonFileList && jsonFileList.length) {
184 | return copy(this.componentListMap.jsonFileList)
185 | }
186 |
187 | return done()
188 | })
189 |
190 | /**
191 | * 拷贝 wxml 文件到目标目录
192 | */
193 | gulp.task(`${id}-component-wxml`, done => {
194 | const wxmlFileList = this.componentListMap.wxmlFileList
195 |
196 | if (wxmlFileList &&
197 | wxmlFileList.length &&
198 | !_.compareArray(this.cachedComponentListMap.wxmlFileList, wxmlFileList)) {
199 | return copy(wxmlFileList)
200 | }
201 |
202 | return done()
203 | })
204 |
205 | /**
206 | * 生成 wxss 文件到目标目录
207 | */
208 | gulp.task(`${id}-component-wxss`, done => {
209 | const wxssFileList = this.componentListMap.wxssFileList
210 |
211 | if (wxssFileList &&
212 | wxssFileList.length &&
213 | !_.compareArray(this.cachedComponentListMap.wxssFileList, wxssFileList)) {
214 | return wxss(wxssFileList, srcPath, distPath)
215 | }
216 |
217 | return done()
218 | })
219 |
220 | /**
221 | * 生成 js 文件到目标目录
222 | */
223 | gulp.task(`${id}-component-js`, done => {
224 | const jsFileList = this.componentListMap.jsFileList
225 |
226 | if (jsFileList &&
227 | jsFileList.length &&
228 | !_.compareArray(this.cachedComponentListMap.jsFileList, jsFileList)) {
229 | if (jsConfig.webpack) {
230 | js(this.componentListMap.jsFileMap, this)
231 | } else {
232 | return copy(jsFileList)
233 | }
234 | }
235 |
236 | return done()
237 | })
238 |
239 | /**
240 | * 拷贝相关资源到目标目录
241 | */
242 | gulp.task(`${id}-copy`, gulp.parallel(done => {
243 | const copyList = this.copyList
244 | const copyFileList = copyList.map(copyFilePath => {
245 | try {
246 | if (fs.statSync(path.join(srcPath, copyFilePath)).isDirectory()) {
247 | return path.join(copyFilePath, '**/*.!(wxss)')
248 | } else {
249 | return copyFilePath
250 | }
251 | } catch (err) {
252 | // eslint-disable-next-line no-console
253 | console.error(err)
254 | return null
255 | }
256 | }).filter(copyFilePath => !!copyFilePath)
257 |
258 | if (copyFileList.length) return copy(copyFileList)
259 |
260 | return done()
261 | }, done => {
262 | const copyList = this.copyList
263 | const copyFileList = copyList.map(copyFilePath => {
264 | try {
265 | if (fs.statSync(path.join(srcPath, copyFilePath)).isDirectory()) {
266 | return path.join(copyFilePath, '**/*.wxss')
267 | } else if (copyFilePath.slice(-5) === '.wxss') {
268 | return copyFilePath
269 | } else {
270 | return null
271 | }
272 | } catch (err) {
273 | // eslint-disable-next-line no-console
274 | console.error(err)
275 | return null
276 | }
277 | }).filter(copyFilePath => !!copyFilePath)
278 |
279 | if (copyFileList.length) return wxss(copyFileList, srcPath, distPath)
280 |
281 | return done()
282 | }))
283 |
284 | /**
285 | * 监听 js 变化
286 | */
287 | gulp.task(`${id}-watch-js`, done => {
288 | if (!jsConfig.webpack) {
289 | return gulp.watch(this.componentListMap.jsFileList, {cwd: srcPath, base: srcPath}, gulp.series(`${id}-component-js`))
290 | }
291 |
292 | return done()
293 | })
294 |
295 | /**
296 | * 监听 json 变化
297 | */
298 | gulp.task(`${id}-watch-json`, () => gulp.watch(this.componentListMap.jsonFileList, {cwd: srcPath, base: srcPath}, gulp.series(`${id}-component-check`, gulp.parallel(`${id}-component-wxml`, `${id}-component-wxss`, `${id}-component-js`, `${id}-component-json`))))
299 |
300 | /**
301 | * 监听 wxml 变化
302 | */
303 | gulp.task(`${id}-watch-wxml`, () => {
304 | this.cachedComponentListMap.wxmlFileList = null
305 | return gulp.watch(this.componentListMap.wxmlFileList, {cwd: srcPath, base: srcPath}, gulp.series(`${id}-component-wxml`))
306 | })
307 |
308 | /**
309 | * 监听 wxss 变化
310 | */
311 | gulp.task(`${id}-watch-wxss`, () => {
312 | this.cachedComponentListMap.wxssFileList = null
313 | return gulp.watch('**/*.wxss', {cwd: srcPath, base: srcPath}, gulp.series(`${id}-component-wxss`))
314 | })
315 |
316 | /**
317 | * 监听相关资源变化
318 | */
319 | gulp.task(`${id}-watch-copy`, () => {
320 | const copyList = this.copyList
321 | const copyFileList = copyList.map(copyFilePath => {
322 | try {
323 | if (fs.statSync(path.join(srcPath, copyFilePath)).isDirectory()) {
324 | return path.join(copyFilePath, '**/*')
325 | } else {
326 | return copyFilePath
327 | }
328 | } catch (err) {
329 | // eslint-disable-next-line no-console
330 | console.error(err)
331 | return null
332 | }
333 | }).filter(copyFilePath => !!copyFilePath)
334 | const watchCallback = filePath => copy([filePath])
335 |
336 | return gulp.watch(copyFileList, {cwd: srcPath, base: srcPath})
337 | .on('change', watchCallback)
338 | .on('add', watchCallback)
339 | .on('unlink', watchCallback)
340 | })
341 |
342 | /**
343 | * 监听 demo 变化
344 | */
345 | gulp.task(`${id}-watch-demo`, () => {
346 | const demoSrc = config.demoSrc
347 | const demoDist = config.demoDist
348 | const watchCallback = filePath => gulp.src(filePath, {cwd: demoSrc, base: demoSrc})
349 | .pipe(gulp.dest(demoDist))
350 |
351 | return gulp.watch('**/*', {cwd: demoSrc, base: demoSrc})
352 | .on('change', watchCallback)
353 | .on('add', watchCallback)
354 | .on('unlink', watchCallback)
355 | })
356 |
357 | /**
358 | * 监听安装包列表变化
359 | */
360 | gulp.task(`${id}-watch-install`, () => gulp.watch(path.resolve(__dirname, '../package.json'), install()))
361 |
362 | /**
363 | * 构建相关任务
364 | */
365 | gulp.task(`${id}-build`, gulp.series(`${id}-clean-dist`, `${id}-component-check`, gulp.parallel(`${id}-component-wxml`, `${id}-component-wxss`, `${id}-component-js`, `${id}-component-json`, `${id}-copy`)))
366 |
367 | gulp.task(`${id}-watch`, gulp.series(`${id}-build`, `${id}-demo`, `${id}-install`, gulp.parallel(`${id}-watch-wxml`, `${id}-watch-wxss`, `${id}-watch-js`, `${id}-watch-json`, `${id}-watch-copy`, `${id}-watch-install`, `${id}-watch-demo`)))
368 |
369 | gulp.task(`${id}-dev`, gulp.series(`${id}-build`, `${id}-demo`, `${id}-install`))
370 |
371 | gulp.task(`${id}-default`, gulp.series(`${id}-build`))
372 | }
373 | }
374 |
375 | module.exports = BuildTask
376 |
--------------------------------------------------------------------------------