├── example
├── wechat
│ ├── app.js
│ ├── pages
│ │ └── index
│ │ │ ├── index.json
│ │ │ ├── index.wxss
│ │ │ ├── index.wxml
│ │ │ └── index.js
│ ├── app.json
│ ├── project.config.json
│ └── js
│ │ └── we-validator.js
├── mpvue
│ ├── static
│ │ └── .gitkeep
│ ├── config
│ │ ├── prod.env.js
│ │ ├── dev.env.js
│ │ └── index.js
│ ├── src
│ │ ├── pages
│ │ │ └── index
│ │ │ │ ├── main.js
│ │ │ │ └── index.vue
│ │ ├── main.js
│ │ └── App.vue
│ ├── .postcssrc.js
│ ├── .editorconfig
│ ├── .gitignore
│ ├── index.html
│ ├── build
│ │ ├── dev-client.js
│ │ ├── vue-loader.conf.js
│ │ ├── build.js
│ │ ├── check-versions.js
│ │ ├── utils.js
│ │ ├── webpack.base.conf.js
│ │ ├── webpack.dev.conf.js
│ │ ├── dev-server.js
│ │ └── webpack.prod.conf.js
│ ├── .babelrc
│ ├── README.md
│ ├── project.config.json
│ └── package.json
├── nodejs
│ ├── server
│ │ ├── router
│ │ │ ├── router.js
│ │ │ └── home.js
│ │ └── view
│ │ │ └── index.ejs
│ ├── package.json
│ └── app.js
├── web
│ └── index.html
└── complex
│ └── index.html
├── assets
├── v2.png
└── demo_multi.png
├── .npmignore
├── .travis.yml
├── .gitignore
├── types
└── index.d.ts
├── LICENSE
├── package.json
├── webpack.config.js
├── UPGRADE.md
├── CHANGELOG.md
├── test
└── we-validator.test.js
├── src
├── rules.js
└── we-validator.js
├── dist
├── we-validator.min.js
└── we-validator.js
├── README.md
└── lib
└── we-validator.js
/example/wechat/app.js:
--------------------------------------------------------------------------------
1 | App({})
--------------------------------------------------------------------------------
/example/mpvue/static/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/assets/v2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChanceYu/we-validator/HEAD/assets/v2.png
--------------------------------------------------------------------------------
/example/mpvue/config/prod.env.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | NODE_ENV: '"production"'
3 | }
4 |
--------------------------------------------------------------------------------
/example/wechat/pages/index/index.json:
--------------------------------------------------------------------------------
1 | {
2 | "navigationBarTitleText": "we-validator"
3 | }
--------------------------------------------------------------------------------
/assets/demo_multi.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChanceYu/we-validator/HEAD/assets/demo_multi.png
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | src
2 | dist
3 | example
4 | test
5 | node_modules
6 | *.js.map
7 | webpack.config.js
8 | UPGRADE.md
--------------------------------------------------------------------------------
/example/mpvue/src/pages/index/main.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import App from './index'
3 |
4 | const app = new Vue(App)
5 | app.$mount()
6 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - 6
4 | install:
5 | - npm install
6 | script:
7 | - npm run build
8 | after_success:
9 | - npm run test
10 |
--------------------------------------------------------------------------------
/example/mpvue/.postcssrc.js:
--------------------------------------------------------------------------------
1 | // https://github.com/michael-ciniawsky/postcss-load-config
2 |
3 | module.exports = {
4 | "plugins": {
5 | "postcss-mpvue-wxss": {}
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/example/mpvue/config/dev.env.js:
--------------------------------------------------------------------------------
1 | var merge = require('webpack-merge')
2 | var prodEnv = require('./prod.env')
3 |
4 | module.exports = merge(prodEnv, {
5 | NODE_ENV: '"development"'
6 | })
7 |
--------------------------------------------------------------------------------
/example/wechat/pages/index/index.wxss:
--------------------------------------------------------------------------------
1 | input{
2 | margin: 10px;
3 | padding: 10px;
4 | border: 1px solid #eee;
5 | font-size: 16px;
6 | }
7 |
8 | button{
9 | margin: 10px;
10 | }
--------------------------------------------------------------------------------
/example/mpvue/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf-8
5 | indent_style = space
6 | indent_size = 2
7 | end_of_line = lf
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
10 |
--------------------------------------------------------------------------------
/example/mpvue/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules/
3 | dist/
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 |
8 | # Editor directories and files
9 | .idea
10 | *.suo
11 | *.ntvs*
12 | *.njsproj
13 | *.sln
14 |
--------------------------------------------------------------------------------
/example/mpvue/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | mpvue
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/example/nodejs/server/router/router.js:
--------------------------------------------------------------------------------
1 | const Router = require('koa-router')
2 |
3 | const home = require('./home')
4 |
5 | // 装载所有子路由
6 | let router = new Router()
7 |
8 | router.use('', home.routes(), home.allowedMethods())
9 |
10 | module.exports = router;
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | .AppleDouble
3 | .LSOverride
4 | package-lock.json
5 |
6 | ._*
7 |
8 | .Spotlight-V100
9 | .Trashes
10 |
11 | Thumbs.db
12 | ehthumbs.db
13 |
14 | Desktop.ini
15 |
16 | $RECYCLE.BIN/
17 |
18 | .idea
19 |
20 | *.sublime-*
21 |
22 | .vscode
23 |
24 | node_modules
25 | *.js.map
--------------------------------------------------------------------------------
/example/mpvue/build/dev-client.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | require('eventsource-polyfill')
3 | var hotClient = require('webpack-hot-middleware/client?noInfo=true&reload=true')
4 |
5 | hotClient.subscribe(function (event) {
6 | if (event.action === 'reload') {
7 | window.location.reload()
8 | }
9 | })
10 |
--------------------------------------------------------------------------------
/example/wechat/app.json:
--------------------------------------------------------------------------------
1 | {
2 | "pages": [
3 | "pages/index/index"
4 | ],
5 | "window": {
6 | "backgroundTextStyle": "light",
7 | "navigationBarBackgroundColor": "#32b16c",
8 | "navigationBarTitleText": "we-validator",
9 | "navigationBarTextStyle": "white"
10 | }
11 | }
--------------------------------------------------------------------------------
/example/wechat/pages/index/index.wxml:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/example/nodejs/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "example",
3 | "version": "1.0.0",
4 | "scripts": {
5 | "test": "echo \"Error: no test specified\" && exit 1"
6 | },
7 | "dependencies": {
8 | "ejs": "^2.5.7",
9 | "koa": "^2.5.1",
10 | "koa-bodyparser": "^3.2.0",
11 | "koa-router": "^7.4.0",
12 | "koa-views": "^5.2.1",
13 | "we-validator": "^2.1.10"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/example/mpvue/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | ["env", {
4 | "modules": false,
5 | "targets": {
6 | "browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
7 | }
8 | }],
9 | "stage-2"
10 | ],
11 | "plugins": ["transform-runtime"],
12 | "env": {
13 | "test": {
14 | "presets": ["env", "stage-2"],
15 | "plugins": ["istanbul"]
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/example/mpvue/README.md:
--------------------------------------------------------------------------------
1 | # mpvue
2 |
3 | > A Mpvue project
4 |
5 | ## Build Setup
6 |
7 | ``` bash
8 | # install dependencies
9 | npm install
10 |
11 | # serve with hot reload at localhost:8080
12 | npm run dev
13 |
14 | # build for production with minification
15 | npm run build
16 |
17 | # build for production and view the bundle analyzer report
18 | npm run build --report
19 | ```
20 |
21 | For detailed explanation on how things work, checkout the [guide](http://vuejs-templates.github.io/webpack/) and [docs for vue-loader](http://vuejs.github.io/vue-loader).
22 |
--------------------------------------------------------------------------------
/example/mpvue/build/vue-loader.conf.js:
--------------------------------------------------------------------------------
1 | var utils = require('./utils')
2 | var config = require('../config')
3 | // var isProduction = process.env.NODE_ENV === 'production'
4 | // for mp
5 | var isProduction = true
6 |
7 | module.exports = {
8 | loaders: utils.cssLoaders({
9 | sourceMap: isProduction
10 | ? config.build.productionSourceMap
11 | : config.dev.cssSourceMap,
12 | extract: isProduction
13 | }),
14 | transformToRequire: {
15 | video: 'src',
16 | source: 'src',
17 | img: 'src',
18 | image: 'xlink:href'
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/example/mpvue/src/main.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import App from './App'
3 |
4 | Vue.config.productionTip = false
5 | App.mpType = 'app'
6 |
7 | const app = new Vue(App)
8 | app.$mount()
9 |
10 | export default {
11 | // 这个字段走 app.json
12 | config: {
13 | // 页面前带有 ^ 符号的,会被编译成首页,其他页面可以选填,我们会自动把 webpack entry 里面的入口页面加进去
14 | pages: ['^pages/index/main'],
15 | window: {
16 | backgroundTextStyle: 'light',
17 | navigationBarBackgroundColor: '#fff',
18 | navigationBarTitleText: 'WeChat',
19 | navigationBarTextStyle: 'black'
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/example/mpvue/project.config.json:
--------------------------------------------------------------------------------
1 | {
2 | "description": "项目配置文件。",
3 | "setting": {
4 | "urlCheck": true,
5 | "es6": false,
6 | "postcss": true,
7 | "minified": true,
8 | "newFeature": true
9 | },
10 | "miniprogramRoot": "./dist/",
11 | "compileType": "miniprogram",
12 | "appid": "touristappid",
13 | "projectname": "mpvue",
14 | "condition": {
15 | "search": {
16 | "current": -1,
17 | "list": []
18 | },
19 | "conversation": {
20 | "current": -1,
21 | "list": []
22 | },
23 | "game": {
24 | "currentL": -1,
25 | "list": []
26 | },
27 | "miniprogram": {
28 | "current": -1,
29 | "list": []
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/example/wechat/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 | },
13 | "compileType": "miniprogram",
14 | "libVersion": "2.2.1",
15 | "appid": "wxd15c2ae504af0dca",
16 | "projectname": "we-validator-wechat",
17 | "isGameTourist": false,
18 | "condition": {
19 | "search": {
20 | "current": -1,
21 | "list": []
22 | },
23 | "conversation": {
24 | "current": -1,
25 | "list": []
26 | },
27 | "game": {
28 | "currentL": -1,
29 | "list": []
30 | },
31 | "miniprogram": {
32 | "current": -1,
33 | "list": []
34 | }
35 | }
36 | }
--------------------------------------------------------------------------------
/example/mpvue/src/App.vue:
--------------------------------------------------------------------------------
1 |
13 |
14 |
32 |
--------------------------------------------------------------------------------
/example/nodejs/app.js:
--------------------------------------------------------------------------------
1 | const Koa = require('koa')
2 | const path = require('path')
3 | const views = require('koa-views')
4 | const Router = require('koa-router')
5 | const bodyParser = require('koa-bodyparser')
6 |
7 | const routers = require('./server/router/router')
8 |
9 | const app = new Koa()
10 |
11 | app.use(bodyParser())
12 |
13 | // 加载模板引擎
14 | app.use(views(path.join(__dirname, './server/view'), {
15 | extension: 'ejs'
16 | }))
17 |
18 | app.use(async (ctx, next) => {
19 | let url = ctx.request.url
20 |
21 | console.log(url);
22 | await next();
23 | })
24 |
25 | // 加载路由中间件
26 | app.use(routers.routes()).use(routers.allowedMethods())
27 |
28 | app.use(async (ctx) => {
29 | let url = ctx.request.url
30 |
31 | url = 'router: ' + url
32 |
33 | ctx.body = url
34 | })
35 |
36 | app.listen(3000, () => {
37 | console.log('server is starting at http://localhost:3000/')
38 | })
--------------------------------------------------------------------------------
/types/index.d.ts:
--------------------------------------------------------------------------------
1 | declare module "we-validator" {
2 | type Rule = Function | RegExp;
3 | type RuleOption = { rule: Rule; message: string };
4 | type Options = {
5 | rules: object,
6 | messages: object,
7 | onMessage?: Function,
8 | multiCheck?: boolean
9 | }
10 | class WeValidator {
11 | constructor(options: Options);
12 | static RULES: object;
13 | static addRule(ruleName: string, ruleOption: RuleOption): void;
14 | static checkValue(ruleName: string, value: string, param: any, skip: boolean): boolean;
15 | options: Options;
16 | required: Function;
17 | checkData(data: object, onMessage?: Function, showMessage?: boolean, fieldMap?: object): boolean;
18 | checkFields(data: object, onMessage?: Function, showMessage?: boolean): boolean;
19 | isValid(data: object, fields: Array): boolean;
20 | addRules(options: Options): void;
21 | removeRules(fields: Array): void;
22 | }
23 | export = WeValidator
24 | }
25 |
26 |
--------------------------------------------------------------------------------
/example/wechat/pages/index/index.js:
--------------------------------------------------------------------------------
1 | const WeValidator = require('../../js/we-validator')
2 |
3 | Page({
4 | onReady() {
5 | this.initValidator()
6 | },
7 | onSubmitForm(e) {
8 | let { value } = e.detail
9 |
10 | console.log(value)
11 | if (!this.validatorInstance.checkData(value)) return
12 |
13 | // 开始提交表单
14 | // wx.request
15 | console.log('submiting')
16 | },
17 | initValidator() {
18 | this.validatorInstance = new WeValidator({
19 | rules: {
20 | username: {
21 | required: true
22 | },
23 | phoneno: {
24 | required: true,
25 | mobile: true
26 | },
27 | str: {
28 | length: 3
29 | },
30 | },
31 | messages: {
32 | username: {
33 | required: '请输入用户名'
34 | },
35 | phoneno: {
36 | required: '请输入手机号',
37 | mobile: '手机号格式不正确'
38 | },
39 | str: {
40 | length: '请输入长度为3的字符串'
41 | },
42 | },
43 | })
44 | },
45 | })
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 ChanceYu
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 |
--------------------------------------------------------------------------------
/example/mpvue/build/build.js:
--------------------------------------------------------------------------------
1 | require('./check-versions')()
2 |
3 | process.env.NODE_ENV = 'production'
4 |
5 | var ora = require('ora')
6 | var rm = require('rimraf')
7 | var path = require('path')
8 | var chalk = require('chalk')
9 | var webpack = require('webpack')
10 | var config = require('../config')
11 | var webpackConfig = require('./webpack.prod.conf')
12 |
13 | var spinner = ora('building for production...')
14 | spinner.start()
15 |
16 | rm(path.join(config.build.assetsRoot, '*'), err => {
17 | if (err) throw err
18 | webpack(webpackConfig, function (err, stats) {
19 | spinner.stop()
20 | if (err) throw err
21 | process.stdout.write(stats.toString({
22 | colors: true,
23 | modules: false,
24 | children: false,
25 | chunks: false,
26 | chunkModules: false
27 | }) + '\n\n')
28 |
29 | if (stats.hasErrors()) {
30 | console.log(chalk.red(' Build failed with errors.\n'))
31 | process.exit(1)
32 | }
33 |
34 | console.log(chalk.cyan(' Build complete.\n'))
35 | console.log(chalk.yellow(
36 | ' Tip: built files are meant to be served over an HTTP server.\n' +
37 | ' Opening index.html over file:// won\'t work.\n'
38 | ))
39 | })
40 | })
41 |
--------------------------------------------------------------------------------
/example/mpvue/build/check-versions.js:
--------------------------------------------------------------------------------
1 | var chalk = require('chalk')
2 | var semver = require('semver')
3 | var packageConfig = require('../package.json')
4 | var shell = require('shelljs')
5 | function exec (cmd) {
6 | return require('child_process').execSync(cmd).toString().trim()
7 | }
8 |
9 | var versionRequirements = [
10 | {
11 | name: 'node',
12 | currentVersion: semver.clean(process.version),
13 | versionRequirement: packageConfig.engines.node
14 | }
15 | ]
16 |
17 | if (shell.which('npm')) {
18 | versionRequirements.push({
19 | name: 'npm',
20 | currentVersion: exec('npm --version'),
21 | versionRequirement: packageConfig.engines.npm
22 | })
23 | }
24 |
25 | module.exports = function () {
26 | var warnings = []
27 | for (var i = 0; i < versionRequirements.length; i++) {
28 | var mod = versionRequirements[i]
29 | if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) {
30 | warnings.push(mod.name + ': ' +
31 | chalk.red(mod.currentVersion) + ' should be ' +
32 | chalk.green(mod.versionRequirement)
33 | )
34 | }
35 | }
36 |
37 | if (warnings.length) {
38 | console.log('')
39 | console.log(chalk.yellow('To use this template, you must update following to modules:'))
40 | console.log()
41 | for (var i = 0; i < warnings.length; i++) {
42 | var warning = warnings[i]
43 | console.log(' ' + warning)
44 | }
45 | console.log()
46 | process.exit(1)
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/example/nodejs/server/router/home.js:
--------------------------------------------------------------------------------
1 | const Router = require('koa-router')
2 | const WeValidator = require('we-validator')
3 |
4 | let router = new Router()
5 |
6 | let validatorInstance = new WeValidator({
7 | multiCheck: true,
8 | rules: {
9 | username: {
10 | required: true
11 | },
12 | pwd: {
13 | required: true
14 | },
15 | repeatPwd: {
16 | required: true,
17 | equalTo: 'pwd'
18 | },
19 | phoneno: {
20 | required: true,
21 | mobile: true
22 | },
23 | str: {
24 | rangeChinese: [1,4]
25 | }
26 | },
27 | messages: {
28 | username: {
29 | required: '请输入用户名'
30 | },
31 | pwd: {
32 | required: '请输入密码'
33 | },
34 | repeatPwd: {
35 | required: '请输入确认密码',
36 | equalTo: '两次密码不一致'
37 | },
38 | phoneno: {
39 | required: '请输入手机号',
40 | mobile: '手机号格式不正确'
41 | }
42 | }
43 | });
44 |
45 | // 首页
46 | router.get('/', async (ctx) => {
47 | await ctx.render('index')
48 | })
49 |
50 | // 提交表单
51 | router.post('/form', async (ctx) => {
52 | let formData = ctx.request.body
53 |
54 | if(!validatorInstance.checkData(formData, onMessage)) return
55 |
56 | ctx.body = {
57 | status: 'success',
58 | msg: '校验通过'
59 | }
60 |
61 | function onMessage(params){
62 | ctx.body = {
63 | status: 'failure',
64 | errors: params
65 | }
66 | }
67 | })
68 |
69 | module.exports = router;
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "we-validator",
3 | "version": "2.1.17",
4 | "description": "简单灵活的表单验证插件,支持小程序、浏览器、Nodejs",
5 | "main": "lib/we-validator.js",
6 | "scripts": {
7 | "dev": "NODE_ENV=development webpack --watch --config webpack.config --colors",
8 | "build": "NODE_ENV=production webpack --config webpack.config --colors",
9 | "test": "mocha test/*.js",
10 | "prepublish": "npm run build"
11 | },
12 | "types": "./types/index.d.ts",
13 | "files": [
14 | "lib",
15 | "dist",
16 | "types"
17 | ],
18 | "repository": {
19 | "type": "git",
20 | "url": "git://github.com/ChanceYu/we-validator.git"
21 | },
22 | "keywords": [
23 | "we-validator",
24 | "validator",
25 | "validation",
26 | "weapp",
27 | "wechat",
28 | "mini-program",
29 | "weapp-validator",
30 | "node-validator"
31 | ],
32 | "author": "ChanceYu ",
33 | "license": "MIT",
34 | "devDependencies": {
35 | "babel-cli": "^6.26.0",
36 | "babel-core": "^6.26.0",
37 | "babel-loader": "^7.1.2",
38 | "babel-plugin-add-module-exports": "^0.2.1",
39 | "babel-plugin-transform-object-assign": "^6.22.0",
40 | "babel-preset-es2015": "^6.24.1",
41 | "babel-preset-stage-0": "^6.24.1",
42 | "babel-register": "^6.26.0",
43 | "babelify": "^7.3.0",
44 | "chai": "^3.5.0",
45 | "mocha": "^2.4.5",
46 | "uglify-js": "^3.1.3",
47 | "webpack": "^3.6.0"
48 | },
49 | "bugs": {
50 | "url": "https://github.com/ChanceYu/we-validator/issues"
51 | },
52 | "homepage": "https://github.com/ChanceYu/we-validator#readme"
53 | }
54 |
--------------------------------------------------------------------------------
/example/mpvue/config/index.js:
--------------------------------------------------------------------------------
1 | // see http://vuejs-templates.github.io/webpack for documentation.
2 | var path = require('path')
3 |
4 | module.exports = {
5 | build: {
6 | env: require('./prod.env'),
7 | index: path.resolve(__dirname, '../dist/index.html'),
8 | assetsRoot: path.resolve(__dirname, '../dist'),
9 | assetsSubDirectory: 'static',
10 | assetsPublicPath: '/',
11 | productionSourceMap: false,
12 | // Gzip off by default as many popular static hosts such as
13 | // Surge or Netlify already gzip all static assets for you.
14 | // Before setting to `true`, make sure to:
15 | // npm install --save-dev compression-webpack-plugin
16 | productionGzip: false,
17 | productionGzipExtensions: ['js', 'css'],
18 | // Run the build command with an extra argument to
19 | // View the bundle analyzer report after build finishes:
20 | // `npm run build --report`
21 | // Set to `true` or `false` to always turn it on or off
22 | bundleAnalyzerReport: process.env.npm_config_report
23 | },
24 | dev: {
25 | env: require('./dev.env'),
26 | port: 8080,
27 | // 在小程序开发者工具中不需要自动打开浏览器
28 | autoOpenBrowser: false,
29 | assetsSubDirectory: 'static',
30 | assetsPublicPath: '/',
31 | proxyTable: {},
32 | // CSS Sourcemaps off by default because relative paths are "buggy"
33 | // with this option, according to the CSS-Loader README
34 | // (https://github.com/webpack/css-loader#sourcemaps)
35 | // In our experience, they generally work as expected,
36 | // just be aware of this issue when enabling this option.
37 | cssSourceMap: false
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const webpack = require('webpack');
4 | const path = require('path');
5 | const isProduction = process.env.NODE_ENV === 'production';
6 |
7 | const packageJSON = require('./package.json');
8 |
9 | const getConfig = function (outputPath, min) {
10 | let config = {
11 | entry: path.join(__dirname, 'src/we-validator.js'),
12 | output: {
13 | path: outputPath,
14 | filename: min ? 'we-validator.min.js' : 'we-validator.js',
15 | library: 'WeValidator',
16 | libraryTarget: 'umd',
17 | umdNamedDefine: true
18 | },
19 | module: {
20 | rules: [{
21 | test: /\.(js)$/,
22 | exclude: /node_modules/,
23 | loader: 'babel-loader',
24 | options: {
25 | presets: ['es2015', 'stage-0']
26 | }
27 | }]
28 | },
29 | plugins: [
30 | new webpack.BannerPlugin(
31 | `${packageJSON.name}
32 | version: ${packageJSON.version}
33 | address: ${packageJSON.homepage}
34 | author: ${packageJSON.author}
35 | license: ${packageJSON.license}`)
36 | ],
37 | resolve: {
38 | extensions: ['.js']
39 | }
40 | }
41 |
42 | if(min){
43 | config.plugins.push(
44 | new webpack.optimize.UglifyJsPlugin({
45 | warnings: false,
46 | sourceMap: false,
47 | mangle: false
48 | })
49 | )
50 | }
51 |
52 | return config
53 | }
54 |
55 | let configs = [
56 | getConfig(path.join(__dirname, 'lib')),
57 | getConfig(path.join(__dirname, 'example/wechat/js'))
58 | ]
59 |
60 | if(isProduction){
61 | configs.push( getConfig(path.join(__dirname, 'dist')) )
62 | configs.push( getConfig(path.join(__dirname, 'dist'), true) )
63 | }
64 |
65 | module.exports = configs
--------------------------------------------------------------------------------
/example/mpvue/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "mpvue",
3 | "version": "1.0.0",
4 | "description": "A Mpvue project",
5 | "author": "ChanceYu ",
6 | "private": true,
7 | "scripts": {
8 | "dev": "node build/dev-server.js",
9 | "start": "node build/dev-server.js",
10 | "build": "node build/build.js"
11 | },
12 | "dependencies": {
13 | "mpvue": "^1.0.11",
14 | "vuex": "^3.0.1",
15 | "we-validator": "^2.1.10"
16 | },
17 | "devDependencies": {
18 | "mpvue-loader": "1.0.13",
19 | "mpvue-webpack-target": "^1.0.0",
20 | "mpvue-template-compiler": "^1.0.11",
21 | "portfinder": "^1.0.13",
22 | "postcss-mpvue-wxss": "^1.0.0",
23 | "prettier": "~1.12.1",
24 | "px2rpx-loader": "^0.1.10",
25 | "babel-core": "^6.22.1",
26 | "glob": "^7.1.2",
27 | "webpack-mpvue-asset-plugin": "0.0.2",
28 | "babel-loader": "^7.1.1",
29 | "babel-plugin-transform-runtime": "^6.22.0",
30 | "babel-preset-env": "^1.3.2",
31 | "babel-preset-stage-2": "^6.22.0",
32 | "babel-register": "^6.22.0",
33 | "chalk": "^2.4.0",
34 | "connect-history-api-fallback": "^1.3.0",
35 | "copy-webpack-plugin": "^4.5.1",
36 | "css-loader": "^0.28.11",
37 | "cssnano": "^3.10.0",
38 | "eventsource-polyfill": "^0.9.6",
39 | "express": "^4.16.3",
40 | "extract-text-webpack-plugin": "^3.0.2",
41 | "file-loader": "^1.1.11",
42 | "friendly-errors-webpack-plugin": "^1.7.0",
43 | "html-webpack-plugin": "^3.2.0",
44 | "http-proxy-middleware": "^0.18.0",
45 | "webpack-bundle-analyzer": "^2.2.1",
46 | "semver": "^5.3.0",
47 | "shelljs": "^0.8.1",
48 | "uglifyjs-webpack-plugin": "^1.2.5",
49 | "optimize-css-assets-webpack-plugin": "^3.2.0",
50 | "ora": "^2.0.0",
51 | "rimraf": "^2.6.0",
52 | "url-loader": "^1.0.1",
53 | "vue-style-loader": "^4.1.0",
54 | "webpack": "^3.11.0",
55 | "webpack-dev-middleware-hard-disk": "^1.12.0",
56 | "webpack-merge": "^4.1.0",
57 | "postcss-loader": "^2.1.4"
58 | },
59 | "engines": {
60 | "node": ">= 4.0.0",
61 | "npm": ">= 3.0.0"
62 | },
63 | "browserslist": [
64 | "> 1%",
65 | "last 2 versions",
66 | "not ie <= 8"
67 | ]
68 | }
69 |
--------------------------------------------------------------------------------
/example/mpvue/build/utils.js:
--------------------------------------------------------------------------------
1 | var path = require('path')
2 | var config = require('../config')
3 | var ExtractTextPlugin = require('extract-text-webpack-plugin')
4 |
5 | exports.assetsPath = function (_path) {
6 | var assetsSubDirectory = process.env.NODE_ENV === 'production'
7 | ? config.build.assetsSubDirectory
8 | : config.dev.assetsSubDirectory
9 | return path.posix.join(assetsSubDirectory, _path)
10 | }
11 |
12 | exports.cssLoaders = function (options) {
13 | options = options || {}
14 |
15 | var cssLoader = {
16 | loader: 'css-loader',
17 | options: {
18 | minimize: process.env.NODE_ENV === 'production',
19 | sourceMap: options.sourceMap
20 | }
21 | }
22 |
23 | var postcssLoader = {
24 | loader: 'postcss-loader',
25 | options: {
26 | sourceMap: true
27 | }
28 | }
29 |
30 | var px2rpxLoader = {
31 | loader: 'px2rpx-loader',
32 | options: {
33 | baseDpr: 1,
34 | rpxUnit: 0.5
35 | }
36 | }
37 |
38 | // generate loader string to be used with extract text plugin
39 | function generateLoaders (loader, loaderOptions) {
40 | var loaders = [cssLoader, px2rpxLoader, postcssLoader]
41 | if (loader) {
42 | loaders.push({
43 | loader: loader + '-loader',
44 | options: Object.assign({}, loaderOptions, {
45 | sourceMap: options.sourceMap
46 | })
47 | })
48 | }
49 |
50 | // Extract CSS when that option is specified
51 | // (which is the case during production build)
52 | if (options.extract) {
53 | return ExtractTextPlugin.extract({
54 | use: loaders,
55 | fallback: 'vue-style-loader'
56 | })
57 | } else {
58 | return ['vue-style-loader'].concat(loaders)
59 | }
60 | }
61 |
62 | // https://vue-loader.vuejs.org/en/configurations/extract-css.html
63 | return {
64 | css: generateLoaders(),
65 | wxss: generateLoaders(),
66 | postcss: generateLoaders(),
67 | less: generateLoaders('less'),
68 | sass: generateLoaders('sass', { indentedSyntax: true }),
69 | scss: generateLoaders('sass'),
70 | stylus: generateLoaders('stylus'),
71 | styl: generateLoaders('stylus')
72 | }
73 | }
74 |
75 | // Generate loaders for standalone style files (outside of .vue)
76 | exports.styleLoaders = function (options) {
77 | var output = []
78 | var loaders = exports.cssLoaders(options)
79 | for (var extension in loaders) {
80 | var loader = loaders[extension]
81 | output.push({
82 | test: new RegExp('\\.' + extension + '$'),
83 | use: loader
84 | })
85 | }
86 | return output
87 | }
88 |
--------------------------------------------------------------------------------
/UPGRADE.md:
--------------------------------------------------------------------------------
1 | ## 1.x 升级到 2.x 指南
2 |
3 | 2.x 和 1.x 版本有所差别,如果您要升级到 2.x 版本,请根据以下内容做修改。
4 |
5 | ### 添加自定义规则
6 | > WeValidator.addRule
7 |
8 | 1.x 版本
9 | ```javascript
10 | WeValidator.addRule('theRuleName', function(value, param){
11 | return /\d/.test(value)
12 | })
13 | ```
14 | 2.x 版本
15 | ```javascript
16 | WeValidator.addRule('theRuleName', {
17 | message: '默认错误提示文字',
18 | rule(value, param){
19 | return /\d/.test(value)
20 | }
21 | })
22 |
23 | // 或者
24 | WeValidator.addRule('theRuleName', {
25 | message: '默认错误提示文字',
26 | rule: /\d/
27 | })
28 | ```
29 |
30 | ### 单独校验某个内容
31 | > WeValidator.checkValue
32 |
33 | 1.x 版本
34 | ```javascript
35 | let b1 = WeValidator.mobile('str')
36 | let b2 = WeValidator.chinese('str')
37 | ```
38 | 2.x 版本
39 | ```javascript
40 | let b1 = WeValidator.checkValue('mobile', 'str')
41 | let b2 = WeValidator.checkValue('chinese', 'str')
42 | ```
43 |
44 | ### 默认校验规则的变化
45 | 2.x 的校验规则大部分重写,删除了不常用的规则,并添加了新的规则
46 |
47 | ##### 删除的规则(可使用 2.x 相关规则替代)
48 | ```diff
49 | - bankCard: true
50 | + range: [16, 19]
51 |
52 | - mobileWithSpace
53 | + pattern: /^1\d{2}\s?\d{4}\s?\d{4}$/
54 |
55 | - noZeroStart
56 | + pattern: /^([1-9][0-9]*)$/
57 |
58 | - specialStr
59 | + pattern: /[^%&',;=?$\x22]+/
60 |
61 | - money
62 | + pattern: /^\d+\.\d{2}$/
63 |
64 | - month
65 | + pattern: /^(0?[1-9]|1[0-2])$/
66 |
67 | - day
68 | + pattern: /^((0?[1-9])|((1|2)[0-9])|30|31)$/
69 |
70 | - html
71 | + pattern: /<(.*)>(.*)<\/(.*)>|<(.*)\/>/
72 |
73 | - spaceEnter
74 | + pattern: /\n[\s| ]*\r/
75 |
76 | - qq
77 | + pattern: /^[1-9][0-9]{4,}$/
78 |
79 | - zip
80 | + pattern: /^[\d]{6}/
81 |
82 | - doubleByte
83 | + pattern: /[^\x00-\xff]/
84 |
85 | - intLength: 2
86 | + pattern: /^\d{2}$/
87 |
88 | - decimalLength: 2
89 | + pattern: /^[0-9]+(.[0-9]{2}$/
90 |
91 | - decimalLengthRange: [2, 4]
92 | + pattern: /^[0-9]+(.[0-9]{2,4}$/
93 |
94 | - stringLetter: 'a'
95 | + pattern: /^[a-z]+$/
96 |
97 | - stringLetterDefault
98 | + pattern: /^\w+$/
99 | ```
100 |
101 | ##### 规则名称变化
102 | ```diff
103 | - idCard
104 | + idcard
105 |
106 | - chinese2to8: true
107 | + rangeChinese: [2, 8]
108 |
109 | - intOrFloat
110 | + number
111 |
112 | - int
113 | + digits
114 |
115 | - httpUrl
116 | + url
117 |
118 | - equal: WeValidator.$value('field')
119 | + equalTo: 'field'
120 |
121 | - intLessLength: 2
122 | + min: 2
123 |
124 | - intGreater: 2
125 | + max: 2
126 |
127 | - intLengthRange: [2, 6]
128 | + range: [2, 6]
129 |
130 | - stringLength: 6
131 | + length: 6
132 | ```
133 |
134 | ##### 2.x 新增规则[参考](./README.md#默认支持的规则)
--------------------------------------------------------------------------------
/example/nodejs/server/view/index.ejs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | we-validator (nodejs端校验)
8 |
38 |
39 |
40 |
58 |
59 |
60 |
61 |
62 |
90 |
91 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | > 更新日志(推荐使用最新版本)
4 |
5 | ## Released
6 |
7 | ### [v2.1.17](https://github.com/ChanceYu/we-validator/releases/tag/v2.1.17)
8 | - 修复:multiple 类型声明错误[issue](https://github.com/ChanceYu/we-validator/issues/25)
9 |
10 |
11 | ### [v2.1.16](https://github.com/ChanceYu/we-validator/releases/tag/v2.1.16)
12 | - 修复:错误 message 的显示优化[pull](https://github.com/ChanceYu/we-validator/pull/16)
13 | - 修复:修改空指针和语法修改[pull](https://github.com/ChanceYu/we-validator/pull/17)
14 | - 修复:required: false 不进行“必须”验证[pull](https://github.com/ChanceYu/we-validator/pull/18)
15 |
16 |
17 | ### [v2.1.15](https://github.com/ChanceYu/we-validator/releases/tag/v2.1.15)
18 | - 修复:部分ts定义错误[issue](https://github.com/ChanceYu/we-validator/issues/15)
19 |
20 |
21 | ### [v2.1.14](https://github.com/ChanceYu/we-validator/releases/tag/v2.1.14)
22 | - 新增:添加ts的定义文件[merge](https://github.com/ChanceYu/we-validator/pull/14)
23 |
24 |
25 | ### [v2.1.11](https://github.com/ChanceYu/we-validator/releases/tag/v2.1.11)
26 | - 修复:手机号以 `16` 开头的校验问题[issue](https://github.com/ChanceYu/we-validator/issues/12)
27 |
28 |
29 | ### [v2.1.10](https://github.com/ChanceYu/we-validator/releases/tag/v2.1.10)
30 | - 新增:`.checkFields` 方法,可校验对应的字段,[参考](./README.md#checkfieldsdata-fields-onmessage)
31 | - 修改:`.isValid` 方法,可校验对应的字段,[参考](./README.md#isvaliddata-fields)
32 |
33 |
34 | ### [v2.1.9](https://github.com/ChanceYu/we-validator/releases/tag/v2.1.9)
35 | - 优化:部分规则
36 | - 补充文档和增加动态字段校验使用示例
37 |
38 |
39 | ### [v2.1.8](https://github.com/ChanceYu/we-validator/releases/tag/v2.1.8)
40 | - 修复:中文校验规则
41 | - 修复:多个实例参数覆盖问题
42 |
43 |
44 | ### [v2.1.7](https://github.com/ChanceYu/we-validator/releases/tag/v2.1.7)
45 | - 优化:校验逻辑
46 |
47 |
48 | ### [v2.1.6](https://github.com/ChanceYu/we-validator/releases/tag/v2.1.6)
49 | - 修复:`WeValidator.checkValue` 校验空字段不符合预期
50 | - 优化:`multiCheck` 为 `true` 时错误显示
51 |
52 |
53 | ### [v2.1.5](https://github.com/ChanceYu/we-validator/releases/tag/v2.1.5)
54 | - 修改:通用正则校验
55 | ```diff
56 | - regex
57 | + pattern
58 | ```
59 | - 增加:1.x 到 2.x [升级指南](./UPGRADE.md)
60 |
61 |
62 | ### [v2.1.4](https://github.com/ChanceYu/we-validator/releases/tag/v2.1.4)
63 | - 优化:自定义规则添加方式
64 |
65 |
66 | ### [v2.1.2](https://github.com/ChanceYu/we-validator/releases/tag/v2.1.2)
67 | - 修改:静态方法 `WeValidator.checkValue`
68 | ```diff
69 | - WeValidator.checkField
70 | + WeValidator.checkValue
71 | ```
72 | - 修改文档
73 |
74 |
75 | ### [v2.1.1](https://github.com/ChanceYu/we-validator/releases/tag/v2.1.1)
76 | - 新增:规则:`notEqualTo、notContains、integer、ipv4、ipv6`
77 | - 新增:示例:[复杂的校验案例-自定义规则](./example/complex/index.html)
78 |
79 |
80 | ### [v2.1.0](https://github.com/ChanceYu/we-validator/releases/tag/v2.1.0)
81 | - 重构:核心方法
82 | - 重写:核心校验规则和默认提供的自定义规则
83 | - 单独校验字段方法修改
84 |
85 |
86 | ### [v1](https://github.com/ChanceYu/we-validator/releases/tag/v1)(v1.0.0 - v1.4.3)
87 | - v1 版本 `we-validator`
--------------------------------------------------------------------------------
/example/mpvue/build/webpack.base.conf.js:
--------------------------------------------------------------------------------
1 | var path = require('path')
2 | var fs = require('fs')
3 | var utils = require('./utils')
4 | var config = require('../config')
5 | var vueLoaderConfig = require('./vue-loader.conf')
6 | var MpvuePlugin = require('webpack-mpvue-asset-plugin')
7 | var glob = require('glob')
8 |
9 | function resolve (dir) {
10 | return path.join(__dirname, '..', dir)
11 | }
12 |
13 | function getEntry (rootSrc, pattern) {
14 | var files = glob.sync(path.resolve(rootSrc, pattern))
15 | return files.reduce((res, file) => {
16 | var info = path.parse(file)
17 | var key = info.dir.slice(rootSrc.length + 1) + '/' + info.name
18 | res[key] = path.resolve(file)
19 | return res
20 | }, {})
21 | }
22 |
23 | const appEntry = { app: resolve('./src/main.js') }
24 | const pagesEntry = getEntry(resolve('./src'), 'pages/**/main.js')
25 | const entry = Object.assign({}, appEntry, pagesEntry)
26 |
27 | module.exports = {
28 | // 如果要自定义生成的 dist 目录里面的文件路径,
29 | // 可以将 entry 写成 {'toPath': 'fromPath'} 的形式,
30 | // toPath 为相对于 dist 的路径, 例:index/demo,则生成的文件地址为 dist/index/demo.js
31 | entry,
32 | target: require('mpvue-webpack-target'),
33 | output: {
34 | path: config.build.assetsRoot,
35 | filename: '[name].js',
36 | publicPath: process.env.NODE_ENV === 'production'
37 | ? config.build.assetsPublicPath
38 | : config.dev.assetsPublicPath
39 | },
40 | resolve: {
41 | extensions: ['.js', '.vue', '.json'],
42 | alias: {
43 | 'vue': 'mpvue',
44 | '@': resolve('src')
45 | },
46 | symlinks: false,
47 | aliasFields: ['mpvue', 'weapp', 'browser'],
48 | mainFields: ['browser', 'module', 'main']
49 | },
50 | module: {
51 | rules: [
52 | {
53 | test: /\.vue$/,
54 | loader: 'mpvue-loader',
55 | options: vueLoaderConfig
56 | },
57 | {
58 | test: /\.js$/,
59 | include: [resolve('src'), resolve('test')],
60 | use: [
61 | 'babel-loader',
62 | {
63 | loader: 'mpvue-loader',
64 | options: {
65 | checkMPEntry: true
66 | }
67 | },
68 | ]
69 | },
70 | {
71 | test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
72 | loader: 'url-loader',
73 | options: {
74 | limit: 10000,
75 | name: utils.assetsPath('img/[name].[ext]')
76 | }
77 | },
78 | {
79 | test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
80 | loader: 'url-loader',
81 | options: {
82 | limit: 10000,
83 | name: utils.assetsPath('media/[name].[ext]')
84 | }
85 | },
86 | {
87 | test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
88 | loader: 'url-loader',
89 | options: {
90 | limit: 10000,
91 | name: utils.assetsPath('fonts/[name].[ext]')
92 | }
93 | }
94 | ]
95 | },
96 | plugins: [
97 | new MpvuePlugin()
98 | ]
99 | }
100 |
--------------------------------------------------------------------------------
/example/mpvue/build/webpack.dev.conf.js:
--------------------------------------------------------------------------------
1 | var utils = require('./utils')
2 | var webpack = require('webpack')
3 | var config = require('../config')
4 | var merge = require('webpack-merge')
5 | var baseWebpackConfig = require('./webpack.base.conf')
6 | // var HtmlWebpackPlugin = require('html-webpack-plugin')
7 | var FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
8 |
9 | // copy from ./webpack.prod.conf.js
10 | var path = require('path')
11 | var ExtractTextPlugin = require('extract-text-webpack-plugin')
12 | var CopyWebpackPlugin = require('copy-webpack-plugin')
13 | var OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
14 |
15 | // add hot-reload related code to entry chunks
16 | // Object.keys(baseWebpackConfig.entry).forEach(function (name) {
17 | // baseWebpackConfig.entry[name] = ['./build/dev-client'].concat(baseWebpackConfig.entry[name])
18 | // })
19 |
20 | module.exports = merge(baseWebpackConfig, {
21 | module: {
22 | rules: utils.styleLoaders({
23 | sourceMap: config.dev.cssSourceMap,
24 | extract: true
25 | })
26 | },
27 | // cheap-module-eval-source-map is faster for development
28 | // devtool: '#cheap-module-eval-source-map',
29 | devtool: '#source-map',
30 | output: {
31 | path: config.build.assetsRoot,
32 | // filename: utils.assetsPath('js/[name].[chunkhash].js'),
33 | // chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
34 | filename: utils.assetsPath('js/[name].js'),
35 | chunkFilename: utils.assetsPath('js/[id].js')
36 | },
37 | plugins: [
38 | new webpack.DefinePlugin({
39 | 'process.env': config.dev.env
40 | }),
41 |
42 | // copy from ./webpack.prod.conf.js
43 | // extract css into its own file
44 | new ExtractTextPlugin({
45 | // filename: utils.assetsPath('css/[name].[contenthash].css')
46 | filename: utils.assetsPath('css/[name].wxss')
47 | }),
48 | // Compress extracted CSS. We are using this plugin so that possible
49 | // duplicated CSS from different components can be deduped.
50 | new OptimizeCSSPlugin({
51 | cssProcessorOptions: {
52 | safe: true
53 | }
54 | }),
55 | new webpack.optimize.CommonsChunkPlugin({
56 | name: 'vendor',
57 | minChunks: function (module, count) {
58 | // any required modules inside node_modules are extracted to vendor
59 | return (
60 | module.resource &&
61 | /\.js$/.test(module.resource) &&
62 | module.resource.indexOf('node_modules') >= 0
63 | ) || count > 1
64 | }
65 | }),
66 | new webpack.optimize.CommonsChunkPlugin({
67 | name: 'manifest',
68 | chunks: ['vendor']
69 | }),
70 | // copy custom static assets
71 | new CopyWebpackPlugin([
72 | {
73 | from: path.resolve(__dirname, '../static'),
74 | to: config.build.assetsSubDirectory,
75 | ignore: ['.*']
76 | }
77 | ]),
78 |
79 | // https://github.com/glenjamin/webpack-hot-middleware#installation--usage
80 | // new webpack.HotModuleReplacementPlugin(),
81 | new webpack.NoEmitOnErrorsPlugin(),
82 | // https://github.com/ampedandwired/html-webpack-plugin
83 | // new HtmlWebpackPlugin({
84 | // filename: 'index.html',
85 | // template: 'index.html',
86 | // inject: true
87 | // }),
88 | new FriendlyErrorsPlugin()
89 | ]
90 | })
91 |
--------------------------------------------------------------------------------
/example/mpvue/src/pages/index/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
14 |
15 |
16 |
102 |
103 |
133 |
--------------------------------------------------------------------------------
/example/mpvue/build/dev-server.js:
--------------------------------------------------------------------------------
1 | require('./check-versions')()
2 |
3 | var config = require('../config')
4 | if (!process.env.NODE_ENV) {
5 | process.env.NODE_ENV = JSON.parse(config.dev.env.NODE_ENV)
6 | }
7 |
8 | // var opn = require('opn')
9 | var path = require('path')
10 | var express = require('express')
11 | var webpack = require('webpack')
12 | var proxyMiddleware = require('http-proxy-middleware')
13 | var portfinder = require('portfinder')
14 | var webpackConfig = require('./webpack.dev.conf')
15 |
16 | // default port where dev server listens for incoming traffic
17 | var port = process.env.PORT || config.dev.port
18 | // automatically open browser, if not set will be false
19 | var autoOpenBrowser = !!config.dev.autoOpenBrowser
20 | // Define HTTP proxies to your custom API backend
21 | // https://github.com/chimurai/http-proxy-middleware
22 | var proxyTable = config.dev.proxyTable
23 |
24 | var app = express()
25 | var compiler = webpack(webpackConfig)
26 |
27 | // var devMiddleware = require('webpack-dev-middleware')(compiler, {
28 | // publicPath: webpackConfig.output.publicPath,
29 | // quiet: true
30 | // })
31 |
32 | // var hotMiddleware = require('webpack-hot-middleware')(compiler, {
33 | // log: false,
34 | // heartbeat: 2000
35 | // })
36 | // force page reload when html-webpack-plugin template changes
37 | // compiler.plugin('compilation', function (compilation) {
38 | // compilation.plugin('html-webpack-plugin-after-emit', function (data, cb) {
39 | // hotMiddleware.publish({ action: 'reload' })
40 | // cb()
41 | // })
42 | // })
43 |
44 | // proxy api requests
45 | Object.keys(proxyTable).forEach(function (context) {
46 | var options = proxyTable[context]
47 | if (typeof options === 'string') {
48 | options = { target: options }
49 | }
50 | app.use(proxyMiddleware(options.filter || context, options))
51 | })
52 |
53 | // handle fallback for HTML5 history API
54 | app.use(require('connect-history-api-fallback')())
55 |
56 | // serve webpack bundle output
57 | // app.use(devMiddleware)
58 |
59 | // enable hot-reload and state-preserving
60 | // compilation error display
61 | // app.use(hotMiddleware)
62 |
63 | // serve pure static assets
64 | var staticPath = path.posix.join(config.dev.assetsPublicPath, config.dev.assetsSubDirectory)
65 | app.use(staticPath, express.static('./static'))
66 |
67 | // var uri = 'http://localhost:' + port
68 |
69 | var _resolve
70 | var readyPromise = new Promise(resolve => {
71 | _resolve = resolve
72 | })
73 |
74 | // console.log('> Starting dev server...')
75 | // devMiddleware.waitUntilValid(() => {
76 | // console.log('> Listening at ' + uri + '\n')
77 | // // when env is testing, don't need open it
78 | // if (autoOpenBrowser && process.env.NODE_ENV !== 'testing') {
79 | // opn(uri)
80 | // }
81 | // _resolve()
82 | // })
83 |
84 | module.exports = new Promise((resolve, reject) => {
85 | portfinder.basePort = port
86 | portfinder.getPortPromise()
87 | .then(newPort => {
88 | if (port !== newPort) {
89 | console.log(`${port}端口被占用,开启新端口${newPort}`)
90 | }
91 | var server = app.listen(newPort, 'localhost')
92 | // for 小程序的文件保存机制
93 | require('webpack-dev-middleware-hard-disk')(compiler, {
94 | publicPath: webpackConfig.output.publicPath,
95 | quiet: true
96 | })
97 | resolve({
98 | ready: readyPromise,
99 | close: () => {
100 | server.close()
101 | }
102 | })
103 | }).catch(error => {
104 | console.log('没有找到空闲端口,请打开任务管理器杀死进程端口再试', error)
105 | })
106 | })
107 |
--------------------------------------------------------------------------------
/test/we-validator.test.js:
--------------------------------------------------------------------------------
1 | const expect = require('chai').expect
2 | const WeValidator = require('../lib/we-validator')
3 |
4 | describe('testing: we-validator', () => {
5 |
6 | it('WeValidator.checkValue', () => {
7 | expect(WeValidator.checkValue('required')).to.not.be.ok
8 | expect(WeValidator.checkValue('required', '')).to.not.be.ok
9 | expect(WeValidator.checkValue('required', 'a')).to.be.ok
10 |
11 | expect(WeValidator.checkValue('chinese')).to.not.be.ok
12 | expect(WeValidator.checkValue('chinese', '')).to.not.be.ok
13 | expect(WeValidator.checkValue('chinese', 'a')).to.not.be.ok
14 | expect(WeValidator.checkValue('chinese', '好的')).to.be.ok
15 |
16 | expect(WeValidator.checkValue('mobile')).to.not.be.ok
17 | expect(WeValidator.checkValue('mobile', '')).to.not.be.ok
18 | expect(WeValidator.checkValue('mobile', '111')).to.not.be.ok
19 | expect(WeValidator.checkValue('mobile', '15812345678')).to.be.ok
20 | })
21 |
22 | it('WeValidator.addRule', () => {
23 | WeValidator.addRule('theRuleName', {
24 | rule(value){
25 | return /\d/.test(value)
26 | }
27 | })
28 | expect(WeValidator.checkValue('theRuleName')).to.not.be.ok
29 | expect(WeValidator.checkValue('theRuleName', '')).to.not.be.ok
30 | expect(WeValidator.checkValue('theRuleName', 'a')).to.not.be.ok
31 | expect(WeValidator.checkValue('theRuleName', '1')).to.be.ok
32 | })
33 |
34 | it('new WeValidator({ onMessage })', () => {
35 | let validatorInstance = null
36 | let _name = 'username'
37 | let _rule= 'required'
38 | let _msg = '提示信息'
39 |
40 | validatorInstance = new WeValidator({
41 | rules: {
42 | username: {
43 | required: true
44 | }
45 | },
46 | messages: {
47 | username: {
48 | required: _msg
49 | }
50 | },
51 | onMessage: function(data){
52 | expect(data.msg).to.equal(_msg)
53 | expect(data.name).to.equal(_name)
54 | expect(data.rule).to.equal(_rule)
55 | }
56 | })
57 |
58 | validatorInstance.checkData({})
59 | })
60 |
61 | it('validatorInstance.checkData', () => {
62 | let validatorInstance = new WeValidator({
63 | rules: {
64 | username: {
65 | required: true
66 | }
67 | },
68 | messages: {
69 | username: {
70 | required: '提示信息'
71 | }
72 | }
73 | })
74 |
75 | expect(validatorInstance.checkData({})).to.not.be.ok
76 |
77 | })
78 |
79 | it('WeValidator.onMessage', () => {
80 | let validatorInstance = null
81 | let _name = 'username'
82 | let _rule= 'required'
83 | let _msg = '提示信息'
84 |
85 | WeValidator.onMessage = function(data){
86 | expect(data.msg).to.equal(_msg)
87 | expect(data.name).to.equal(_name)
88 | expect(data.rule).to.equal(_rule)
89 | }
90 |
91 | validatorInstance = new WeValidator({
92 | rules: {
93 | username: {
94 | required: true
95 | }
96 | },
97 | messages: {
98 | username: {
99 | required: _msg
100 | }
101 | },
102 | })
103 |
104 | validatorInstance.checkData({})
105 | })
106 |
107 | })
--------------------------------------------------------------------------------
/example/web/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | we-validator
8 |
38 |
39 |
40 |
58 |
59 |
60 |
61 |
62 |
63 |
128 |
129 |
--------------------------------------------------------------------------------
/example/mpvue/build/webpack.prod.conf.js:
--------------------------------------------------------------------------------
1 | var path = require('path')
2 | var utils = require('./utils')
3 | var webpack = require('webpack')
4 | var config = require('../config')
5 | var merge = require('webpack-merge')
6 | var baseWebpackConfig = require('./webpack.base.conf')
7 | var UglifyJsPlugin = require('uglifyjs-webpack-plugin')
8 | var CopyWebpackPlugin = require('copy-webpack-plugin')
9 | // var HtmlWebpackPlugin = require('html-webpack-plugin')
10 | var ExtractTextPlugin = require('extract-text-webpack-plugin')
11 | var OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
12 |
13 | var env = config.build.env
14 |
15 | var webpackConfig = merge(baseWebpackConfig, {
16 | module: {
17 | rules: utils.styleLoaders({
18 | sourceMap: config.build.productionSourceMap,
19 | extract: true
20 | })
21 | },
22 | devtool: config.build.productionSourceMap ? '#source-map' : false,
23 | output: {
24 | path: config.build.assetsRoot,
25 | // filename: utils.assetsPath('js/[name].[chunkhash].js'),
26 | // chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
27 | filename: utils.assetsPath('js/[name].js'),
28 | chunkFilename: utils.assetsPath('js/[id].js')
29 | },
30 | plugins: [
31 | // http://vuejs.github.io/vue-loader/en/workflow/production.html
32 | new webpack.DefinePlugin({
33 | 'process.env': env
34 | }),
35 | new UglifyJsPlugin({
36 | sourceMap: true
37 | }),
38 | // extract css into its own file
39 | new ExtractTextPlugin({
40 | // filename: utils.assetsPath('css/[name].[contenthash].css')
41 | filename: utils.assetsPath('css/[name].wxss')
42 | }),
43 | // Compress extracted CSS. We are using this plugin so that possible
44 | // duplicated CSS from different components can be deduped.
45 | new OptimizeCSSPlugin({
46 | cssProcessorOptions: {
47 | safe: true
48 | }
49 | }),
50 | // generate dist index.html with correct asset hash for caching.
51 | // you can customize output by editing /index.html
52 | // see https://github.com/ampedandwired/html-webpack-plugin
53 | // new HtmlWebpackPlugin({
54 | // filename: config.build.index,
55 | // template: 'index.html',
56 | // inject: true,
57 | // minify: {
58 | // removeComments: true,
59 | // collapseWhitespace: true,
60 | // removeAttributeQuotes: true
61 | // // more options:
62 | // // https://github.com/kangax/html-minifier#options-quick-reference
63 | // },
64 | // // necessary to consistently work with multiple chunks via CommonsChunkPlugin
65 | // chunksSortMode: 'dependency'
66 | // }),
67 | // keep module.id stable when vender modules does not change
68 | new webpack.HashedModuleIdsPlugin(),
69 | // split vendor js into its own file
70 | new webpack.optimize.CommonsChunkPlugin({
71 | name: 'vendor',
72 | minChunks: function (module, count) {
73 | // any required modules inside node_modules are extracted to vendor
74 | return (
75 | module.resource &&
76 | /\.js$/.test(module.resource) &&
77 | module.resource.indexOf('node_modules') >= 0
78 | ) || count > 1
79 | }
80 | }),
81 | // extract webpack runtime and module manifest to its own file in order to
82 | // prevent vendor hash from being updated whenever app bundle is updated
83 | new webpack.optimize.CommonsChunkPlugin({
84 | name: 'manifest',
85 | chunks: ['vendor']
86 | }),
87 | // copy custom static assets
88 | new CopyWebpackPlugin([
89 | {
90 | from: path.resolve(__dirname, '../static'),
91 | to: config.build.assetsSubDirectory,
92 | ignore: ['.*']
93 | }
94 | ])
95 | ]
96 | })
97 |
98 | // if (config.build.productionGzip) {
99 | // var CompressionWebpackPlugin = require('compression-webpack-plugin')
100 |
101 | // webpackConfig.plugins.push(
102 | // new CompressionWebpackPlugin({
103 | // asset: '[path].gz[query]',
104 | // algorithm: 'gzip',
105 | // test: new RegExp(
106 | // '\\.(' +
107 | // config.build.productionGzipExtensions.join('|') +
108 | // ')$'
109 | // ),
110 | // threshold: 10240,
111 | // minRatio: 0.8
112 | // })
113 | // )
114 | // }
115 |
116 | if (config.build.bundleAnalyzerReport) {
117 | var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
118 | webpackConfig.plugins.push(new BundleAnalyzerPlugin())
119 | }
120 |
121 | module.exports = webpackConfig
122 |
--------------------------------------------------------------------------------
/src/rules.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | /**
3 | * 必填
4 | */
5 | required: {
6 | message: '此字段必填',
7 | rule(value){
8 | if(typeof value === 'number'){
9 | value = value.toString()
10 | }else if(typeof value === 'boolean'){
11 | return true
12 | }
13 | return !!(value && value.length > 0)
14 | }
15 | },
16 | /**
17 | * 正则通用
18 | */
19 | pattern: {
20 | message: '不符合此验证规则',
21 | rule(value, param){
22 | return param.test(value)
23 | }
24 | },
25 | /**
26 | * 电子邮件
27 | */
28 | email: {
29 | message: '请输入有效的电子邮件地址',
30 | rule: /^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/
31 | },
32 | /**
33 | * 手机号码
34 | */
35 | mobile: {
36 | message: '请输入 11 位的手机号码',
37 | rule: /^1[3456789]\d{9}$/
38 | },
39 | /**
40 | * 座机号,例如:010-1234567、0551-1234567
41 | */
42 | tel: {
43 | message: '请输入座机号',
44 | rule: /^(\d{3,4}-)?\d{7,8}$/
45 | },
46 | /**
47 | * URL网址
48 | */
49 | url: {
50 | message: '请输入有效的网址',
51 | rule: /^(?:(?:(?:https?|ftp):)?\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})).?)(?::\d{2,5})?(?:[/?#]\S*)?$/i
52 | },
53 | /**
54 | * 身份证号
55 | */
56 | idcard: {
57 | message: '请输入 18 位的有效身份证',
58 | rule: /^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$/
59 | },
60 | /**
61 | * 字段值相同校验(例如:密码和确认密码)
62 | */
63 | equalTo: {
64 | message: '输入值必须和字段 {0} 相同',
65 | rule(value, param){
66 | return value === this.data[param]
67 | }
68 | },
69 | /**
70 | * 字段值不相同校验,与 equalTo 相反
71 | */
72 | notEqualTo: {
73 | message: '输入值不能和字段 {0} 相同',
74 | rule(value, param){
75 | return value !== this.data[param]
76 | }
77 | },
78 | /**
79 | * 是否包含某字符
80 | */
81 | contains: {
82 | message: '输入值必须包含 {0}',
83 | rule(value, param){
84 | return value.indexOf(param) > -1
85 | }
86 | },
87 | /**
88 | * 不能包含某字符
89 | */
90 | notContains: {
91 | message: '输入值不能包含 {0}',
92 | rule(value, param){
93 | return value.indexOf(param) === -1
94 | }
95 | },
96 | /**
97 | * 长度为多少的字符串
98 | */
99 | length: {
100 | message: '请输入 {0} 个字符',
101 | rule(value, param){
102 | return value.length == param
103 | }
104 | },
105 | /**
106 | * 最少多长的字符串
107 | */
108 | minlength: {
109 | message: '最少要输入 {0} 个字符',
110 | rule(value, param){
111 | return value.length >= param
112 | }
113 | },
114 | /**
115 | * 最多多长的字符串
116 | */
117 | maxlength: {
118 | message: '最多可以输入 {0} 个字符',
119 | rule(value, param){
120 | return value.length <= param
121 | }
122 | },
123 | /**
124 | * 某个范围长度的字符串
125 | */
126 | rangelength: {
127 | message: '请输入长度在 {0} 到 {1} 之间的字符',
128 | rule(value, param){
129 | return value.length >= param[0] && value.length <= param[1]
130 | }
131 | },
132 | /**
133 | * 数字
134 | */
135 | number: {
136 | message: '请输入有效的数字',
137 | rule: /^(?:-?\d+|-?\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/
138 | },
139 | /**
140 | * 正整数数字
141 | */
142 | digits: {
143 | message: '只能输入正整数数字',
144 | rule: /^\d+$/
145 | },
146 | /**
147 | * 正整数或负整数数字
148 | */
149 | integer: {
150 | message: '只能输入整数数字',
151 | rule: /^-?\d+$/
152 | },
153 | /**
154 | * 大于多少的数字/字段值
155 | */
156 | min: {
157 | message: '请输入大于 {0} 的数字',
158 | rule(value, param){
159 | if(typeof param === 'string') param = this.data[param]
160 |
161 | return value >= param
162 | }
163 | },
164 | /**
165 | * 小于多少的数字/字段值
166 | */
167 | max: {
168 | message: '请输入小于 {0} 的数字',
169 | rule(value, param){
170 | if(typeof param === 'string') param = this.data[param]
171 |
172 | return value <= param
173 | }
174 | },
175 | /**
176 | * 大于且小于多少的数字
177 | */
178 | range: {
179 | message: '请输入大于 {0} 且小于 {1} 的数字',
180 | rule(value, param){
181 | return value >= param[0] && value <= param[1]
182 | }
183 | },
184 | /**
185 | * 中文字符
186 | */
187 | chinese: {
188 | message: '只能输入中文字符',
189 | rule: /^[\u4e00-\u9fa5]+$/
190 | },
191 | /**
192 | * 最少多少个中文字符
193 | */
194 | minChinese: {
195 | message: '最少输入 {0} 个中文字符',
196 | rule(value, param){
197 | return new RegExp(`^[\u4e00-\u9fa5]{${param},}$`).test(value)
198 | }
199 | },
200 | /**
201 | * 最多多少个中文字符
202 | */
203 | maxChinese: {
204 | message: '最多输入 {0} 个中文字符',
205 | rule(value, param){
206 | return new RegExp(`^[\u4e00-\u9fa5]{1,${param}}$`).test(value)
207 | }
208 | },
209 | /**
210 | * 大于且小于多少个中文字符
211 | */
212 | rangeChinese: {
213 | message: '只能输入 {0} 到 {1} 个中文字符',
214 | rule(value, param){
215 | return new RegExp(`^[\u4e00-\u9fa5]{${param[0]},${param[1]}}$`).test(value)
216 | }
217 | },
218 | /**
219 | * 日期
220 | */
221 | date: {
222 | message: '请输入有效的日期',
223 | rule(value){
224 | return !/Invalid|NaN/.test(new Date(value).toString())
225 | }
226 | },
227 | /**
228 | * 日期(ISO标准格式)例如:2019-09-19,2019/09/19
229 | */
230 | dateISO: {
231 | message: '请输入有效的日期(ISO 标准格式)',
232 | rule: /^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$/
233 | },
234 | /**
235 | * ipv4地址
236 | */
237 | ipv4: {
238 | message: '请输入有效的 IPv4 地址',
239 | rule: /^(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)$/i
240 | },
241 | /**
242 | * ipv6地址
243 | */
244 | ipv6: {
245 | message: '请输入有效的 IPv6 地址',
246 | rule: /^((([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}:[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){5}:([0-9A-Fa-f]{1,4}:)?[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){4}:([0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){3}:([0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){2}:([0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(([0-9A-Fa-f]{1,4}:){0,5}:((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(::([0-9A-Fa-f]{1,4}:){0,5}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|([0-9A-Fa-f]{1,4}::([0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})|(::([0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){1,7}:))$/i
247 | }
248 | }
249 |
--------------------------------------------------------------------------------
/example/complex/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | 复杂案例 we-validator
8 |
66 |
67 |
68 |
139 |
140 |
141 |
142 |
143 |
144 |
260 |
261 |
--------------------------------------------------------------------------------
/dist/we-validator.min.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * we-validator
3 | * version: 2.1.17
4 | * address: https://github.com/ChanceYu/we-validator#readme
5 | * author: ChanceYu
6 | * license: MIT
7 | */
8 | !function(root,factory){"object"==typeof exports&&"object"==typeof module?module.exports=factory():"function"==typeof define&&define.amd?define("WeValidator",[],factory):"object"==typeof exports?exports.WeValidator=factory():root.WeValidator=factory()}("undefined"!=typeof self?self:this,function(){return function(modules){function __webpack_require__(moduleId){if(installedModules[moduleId])return installedModules[moduleId].exports;var module=installedModules[moduleId]={i:moduleId,l:!1,exports:{}};return modules[moduleId].call(module.exports,module,module.exports,__webpack_require__),module.l=!0,module.exports}var installedModules={};return __webpack_require__.m=modules,__webpack_require__.c=installedModules,__webpack_require__.d=function(exports,name,getter){__webpack_require__.o(exports,name)||Object.defineProperty(exports,name,{configurable:!1,enumerable:!0,get:getter})},__webpack_require__.n=function(module){var getter=module&&module.__esModule?function(){return module.default}:function(){return module};return __webpack_require__.d(getter,"a",getter),getter},__webpack_require__.o=function(object,property){return Object.prototype.hasOwnProperty.call(object,property)},__webpack_require__.p="",__webpack_require__(__webpack_require__.s=0)}([function(module,exports,__webpack_require__){"use strict";function _classCallCheck(instance,Constructor){if(!(instance instanceof Constructor))throw new TypeError("Cannot call a class as a function")}var _createClass=function(){function defineProperties(target,props){for(var i=0;i0&&void 0!==arguments[0]?arguments[0]:{};_classCallCheck(this,WeValidator),this.options=options,this.required=requiredFn,this._checkAllRules()}return _createClass(WeValidator,[{key:"_showErrorMessage",value:function(params,onMessage){return isFunction(onMessage)?onMessage(params):isFunction(this.options.onMessage)?this.options.onMessage(params):isFunction(WeValidator.onMessage)?WeValidator.onMessage(params):isWx?wx.showToast({title:params.msg,icon:"none"}):isMy?my.showToast({content:params.msg,type:"none"}):isSwan?swan.showToast({title:params.msg,icon:"none"}):isTt?tt.showToast({title:params.msg,icon:"none"}):void(isBrowser&&alert(params.msg))}},{key:"_getErrorMessage",value:function(ruleName,attr,param){var messages=this.options.messages,defaultMessage=WeValidator.RULES[ruleName].message;if(messages&&messages.hasOwnProperty(attr)&&messages[attr][ruleName]&&(defaultMessage=messages[attr][ruleName]),defaultMessage)return defaultMessage=defaultMessage.replace(/\{(\d)\}/g,function($0,$1){return isArray(param)?param[$1]:param})}},{key:"_isRuleInvalid",value:function(ruleName,attr){if(!WeValidator.RULES.hasOwnProperty(ruleName))return console.warn&&console.warn("没有此验证规则:"+ruleName+",字段:"+attr),!0}},{key:"_checkAllRules",value:function(){var _rules_=this.options.rules;for(var attr in _rules_)for(var ruleName in _rules_[attr])this._isRuleInvalid(ruleName,attr)}},{key:"checkData",value:function(data,onMessage){var showMessage=!(arguments.length>2&&void 0!==arguments[2])||arguments[2],fieldMap=arguments[3],_rules_=this.options.rules,multiCheck=this.options.multiCheck,hasError=!1,errorData={};this.data=data;for(var attr in _rules_)if(!fieldMap||fieldMap.hasOwnProperty(attr))for(var ruleName in _rules_[attr])if(!this._isRuleInvalid(ruleName,attr)){if(fieldMap){var res=fieldMap[attr];if(isArray(res)&&-1===res.indexOf(ruleName))continue}var ruleParam=_rules_[attr][ruleName],value="";data.hasOwnProperty(attr)&&(value=data[attr]),isFunction(ruleParam)&&(ruleParam=ruleParam.call(this,value));var isFieldValid=WeValidator.checkValue.call(this,ruleName,value,ruleParam,!0);if(!isFieldValid){hasError=!0;var msg=this._getErrorMessage(ruleName,attr,ruleParam),errorParam=null;if(showMessage&&msg&&(errorParam={name:attr,value:value,param:ruleParam,rule:ruleName,msg:msg},errorData[attr]=errorParam),!multiCheck)return errorParam&&this._showErrorMessage(errorParam,onMessage),!1}}return!hasError||(multiCheck&&showMessage&&this._showErrorMessage(errorData,onMessage),!1)}},{key:"checkFields",value:function(data,fields,onMessage){var showMessage=!(arguments.length>3&&void 0!==arguments[3])||arguments[3];if(!isArray(fields))throw new Error("第二个参数须为数组");var fieldMap={};return fields.forEach(function(item){var arr=item.split(":"),field=arr[0],rules=arr[1];rules?(rules=rules.split(","),fieldMap[field]=rules):fieldMap[field]=!0}),this.checkData(data,onMessage,showMessage,fieldMap)}},{key:"isValid",value:function(data,fields){return isArray(fields)?this.checkFields(data,fields,null,!1):this.checkData(data,null,!1)}},{key:"addRules",value:function(){var options=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};Object.assign(this.options.rules,options.rules||{}),Object.assign(this.options.messages,options.messages||{}),this._checkAllRules()}},{key:"removeRules",value:function(fields){if(!isArray(fields))throw new Error("参数须为数组");for(var i=0;i0)}},pattern:{message:"不符合此验证规则",rule:function(value,param){return param.test(value)}},email:{message:"请输入有效的电子邮件地址",rule:/^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/},mobile:{message:"请输入 11 位的手机号码",rule:/^1[3456789]\d{9}$/},tel:{message:"请输入座机号",rule:/^(\d{3,4}-)?\d{7,8}$/},url:{message:"请输入有效的网址",rule:/^(?:(?:(?:https?|ftp):)?\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})).?)(?::\d{2,5})?(?:[/?#]\S*)?$/i},idcard:{message:"请输入 18 位的有效身份证",rule:/^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$/},equalTo:{message:"输入值必须和字段 {0} 相同",rule:function(value,param){return value===this.data[param]}},notEqualTo:{message:"输入值不能和字段 {0} 相同",rule:function(value,param){return value!==this.data[param]}},contains:{message:"输入值必须包含 {0}",rule:function(value,param){return value.indexOf(param)>-1}},notContains:{message:"输入值不能包含 {0}",rule:function(value,param){return-1===value.indexOf(param)}},length:{message:"请输入 {0} 个字符",rule:function(value,param){return value.length==param}},minlength:{message:"最少要输入 {0} 个字符",rule:function(value,param){return value.length>=param}},maxlength:{message:"最多可以输入 {0} 个字符",rule:function(value,param){return value.length<=param}},rangelength:{message:"请输入长度在 {0} 到 {1} 之间的字符",rule:function(value,param){return value.length>=param[0]&&value.length<=param[1]}},number:{message:"请输入有效的数字",rule:/^(?:-?\d+|-?\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/},digits:{message:"只能输入正整数数字",rule:/^\d+$/},integer:{message:"只能输入整数数字",rule:/^-?\d+$/},min:{message:"请输入大于 {0} 的数字",rule:function(value,param){return"string"==typeof param&&(param=this.data[param]),value>=param}},max:{message:"请输入小于 {0} 的数字",rule:function(value,param){return"string"==typeof param&&(param=this.data[param]),value<=param}},range:{message:"请输入大于 {0} 且小于 {1} 的数字",rule:function(value,param){return value>=param[0]&&value<=param[1]}},chinese:{message:"只能输入中文字符",rule:/^[\u4e00-\u9fa5]+$/},minChinese:{message:"最少输入 {0} 个中文字符",rule:function(value,param){return new RegExp("^[一-龥]{"+param+",}$").test(value)}},maxChinese:{message:"最多输入 {0} 个中文字符",rule:function(value,param){return new RegExp("^[一-龥]{1,"+param+"}$").test(value)}},rangeChinese:{message:"只能输入 {0} 到 {1} 个中文字符",rule:function(value,param){return new RegExp("^[一-龥]{"+param[0]+","+param[1]+"}$").test(value)}},date:{message:"请输入有效的日期",rule:function(value){return!/Invalid|NaN/.test(new Date(value).toString())}},dateISO:{message:"请输入有效的日期(ISO 标准格式)",rule:/^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$/},ipv4:{message:"请输入有效的 IPv4 地址",rule:/^(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)$/i},ipv6:{message:"请输入有效的 IPv6 地址",rule:/^((([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}:[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){5}:([0-9A-Fa-f]{1,4}:)?[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){4}:([0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){3}:([0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){2}:([0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(([0-9A-Fa-f]{1,4}:){0,5}:((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(::([0-9A-Fa-f]{1,4}:){0,5}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|([0-9A-Fa-f]{1,4}::([0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})|(::([0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){1,7}:))$/i}}}])});
--------------------------------------------------------------------------------
/src/we-validator.js:
--------------------------------------------------------------------------------
1 | import RULES from './rules'
2 |
3 | const requiredFn = RULES.required.rule
4 |
5 | /**
6 | * 环境检测
7 | */
8 | const isWx = typeof wx !== 'undefined' && !!wx.showToast // 微信小程序
9 | const isMy = typeof my !== 'undefined' && !!my.showToast // 支付宝小程序
10 | const isSwan = typeof swan !== 'undefined' && !!swan.showToast // 百度智能小程序
11 | const isTt = typeof tt !== 'undefined' && !!tt.showToast // 字节跳动小程序
12 | const isBrowser = typeof window !== 'undefined' && !!window.alert // 普通浏览器
13 |
14 | const objString = Object.prototype.toString
15 |
16 | const isArray = Array.isArray || ((v) => objString.call(v) === '[object Array]')
17 | const isFunction = (v) => (objString.call(v) === '[object Function]')
18 | const isRegExp = (v) => (objString.call(v) === '[object RegExp]')
19 |
20 | class WeValidator {
21 |
22 | /**
23 | * 默认参数
24 | * @param {object} options
25 | * @param {object} [options.rules] 验证字段的规则
26 | * @param {object} [options.messages] 验证字段错误的提示信息
27 | * @param {function} [options.onMessage] 错误信息显示方式
28 | * @param {boolean} [options.multiCheck] 是否同时校验多个字段
29 | */
30 | constructor(options = {}) {
31 | this.options = options
32 |
33 | this.required = requiredFn
34 | this._checkAllRules()
35 | }
36 |
37 | /**
38 | * 所有校验规则
39 | */
40 | static RULES = {}
41 |
42 | /**
43 | * 动态添加验证规则
44 | * @param {string} ruleName 规则名称
45 | * @param {object} ruleOption 规则配置
46 | * @param {string} [ruleOption.message] 默认错误信息文字
47 | * @param {regexp|function} [ruleOption.rule] 验证规则
48 | */
49 | static addRule = function (ruleName, ruleOption) {
50 | WeValidator.RULES[ruleName] = ruleOption
51 | }
52 |
53 | /**
54 | * 验证单个字段数据
55 | * @param {string} ruleName 规则名称
56 | * @param {string} value 要验证的值
57 | * @param {any} param 传递的验证参数
58 | * @param {boolean} skip 未填跳过校验,仅供内部使用
59 | */
60 | static checkValue = function (ruleName, value, param, skip){
61 | let rule = WeValidator.RULES[ruleName].rule
62 |
63 | if(isRegExp(rule)){
64 | if(skip){
65 | return !requiredFn(value) || rule.test(value)
66 | }else{
67 | return rule.test(value)
68 | }
69 | }
70 |
71 | if(isFunction(rule)){
72 | if(ruleName === 'required'){
73 | return param && requiredFn(value)
74 | }else{
75 | if(skip){
76 | return !requiredFn(value) || rule.call(this, value, param)
77 | }else{
78 | return rule.call(this, value, param)
79 | }
80 | }
81 | }
82 | }
83 |
84 | /**
85 | * 显示错误信息
86 | * @param {object} params 错误信息
87 | * @param {function} onMessage 自定义提示函数
88 | */
89 | _showErrorMessage(params, onMessage) {
90 | // validatorInstance.checkData(data, onMessage)
91 | if(isFunction(onMessage)){
92 | return onMessage(params)
93 | }
94 |
95 | // 参数形式 new WeValidator({ onMessage })
96 | if(isFunction(this.options.onMessage)){
97 | return this.options.onMessage(params)
98 | }
99 |
100 | // 全局配置 WeValidator.onMessage
101 | if(isFunction(WeValidator.onMessage)){
102 | return WeValidator.onMessage(params)
103 | }
104 |
105 | // 微信小程序
106 | if(isWx) {
107 | return wx.showToast({
108 | title: params.msg,
109 | icon: 'none'
110 | })
111 | }
112 |
113 | // 支付宝小程序
114 | if(isMy){
115 | return my.showToast({
116 | content: params.msg,
117 | type: 'none'
118 | })
119 | }
120 |
121 | // 百度小程序
122 | if(isSwan){
123 | return swan.showToast({
124 | title: params.msg,
125 | icon: 'none'
126 | })
127 | }
128 |
129 | // 字节跳动小程序
130 | if(isTt){
131 | return tt.showToast({
132 | title: params.msg,
133 | icon: 'none'
134 | })
135 | }
136 |
137 | // 浏览器端
138 | if(isBrowser) alert(params.msg)
139 | }
140 |
141 | /**
142 | * 获取错误信息内容
143 | * @param {string} ruleName 规则名称
144 | * @param {string} attr 字段名称
145 | * @param {any} param 规则参数
146 | */
147 | _getErrorMessage(ruleName, attr, param){
148 | let messages = this.options.messages
149 | let defaultMessage = WeValidator.RULES[ruleName].message
150 |
151 | if(messages && messages.hasOwnProperty(attr) && messages[attr][ruleName]){
152 | defaultMessage = messages[attr][ruleName]
153 | }
154 |
155 | if(defaultMessage){
156 | defaultMessage = defaultMessage.replace(/\{(\d)\}/g, function($0, $1){
157 | if(isArray(param)){
158 | return param[$1]
159 | }else{
160 | return param
161 | }
162 | })
163 |
164 | return defaultMessage
165 | }
166 | }
167 |
168 | /**
169 | * 验证配置规则是否无效
170 | * @param {string} ruleName 规则名称
171 | * @param {string} attr 字段名称
172 | */
173 | _isRuleInvalid(ruleName, attr) {
174 | if (!WeValidator.RULES.hasOwnProperty(ruleName)) {
175 | console.warn && console.warn(`没有此验证规则:${ruleName},字段:${attr}`)
176 | return true
177 | }
178 | }
179 |
180 | /**
181 | * 验证所有配置规则是否正确
182 | */
183 | _checkAllRules() {
184 | let _rules_ = this.options.rules
185 |
186 | // 遍历字段
187 | for (let attr in _rules_) {
188 | // 遍历验证规则
189 | for (let ruleName in _rules_[attr]) {
190 | if (this._isRuleInvalid(ruleName, attr)) continue
191 | }
192 | }
193 | }
194 |
195 | /**
196 | * 校验数据,会验证所有配置的字段规则
197 | * @param {object} data 验证的数据对象
198 | * @param {function} onMessage 自定义错误信息提示
199 | * @param {boolean} showMessage 是否显示提示信息,默认显示(内部使用)
200 | * @param {object} fieldMap 校验的字段,默认校验所有字段(内部使用)
201 | */
202 | checkData(data, onMessage, showMessage = true, fieldMap) {
203 | let _rules_ = this.options.rules
204 | let multiCheck = this.options.multiCheck
205 | let hasError = false
206 | let errorData = {}
207 |
208 | this.data = data
209 |
210 | // 遍历字段
211 | for (let attr in _rules_) {
212 | if(fieldMap && !fieldMap.hasOwnProperty(attr)) continue
213 |
214 | // 遍历验证规则
215 | for (let ruleName in _rules_[attr]) {
216 | if (this._isRuleInvalid(ruleName, attr)) continue
217 |
218 | if(fieldMap){
219 | let res = fieldMap[attr]
220 | if(isArray(res) && res.indexOf(ruleName) === -1) continue
221 | }
222 |
223 | let ruleParam = _rules_[attr][ruleName]
224 | let value = ''
225 |
226 | if (data.hasOwnProperty(attr)) {
227 | value = data[attr]
228 | }
229 |
230 | if(isFunction(ruleParam)){
231 | ruleParam = ruleParam.call(this, value)
232 | }
233 |
234 | let isFieldValid = WeValidator.checkValue.call(this, ruleName, value, ruleParam, true)
235 |
236 | // 验证不通过
237 | if (!isFieldValid) {
238 | hasError = true
239 |
240 | let msg = this._getErrorMessage(ruleName, attr, ruleParam)
241 | let errorParam = null
242 |
243 | if (showMessage && msg) {
244 | errorParam = {
245 | name: attr,
246 | value: value,
247 | param: ruleParam,
248 | rule: ruleName,
249 | msg: msg
250 | }
251 | errorData[attr] = errorParam
252 | }
253 |
254 | if(!multiCheck){
255 | if (errorParam) {
256 | this._showErrorMessage(errorParam, onMessage);
257 | }
258 | return false
259 | }
260 | }
261 | }
262 | }
263 |
264 | if(hasError){
265 | if(multiCheck && showMessage){
266 | this._showErrorMessage(errorData, onMessage)
267 | }
268 | return false
269 | }
270 |
271 | return true
272 | }
273 |
274 | /**
275 | * 校验数据,只校验对应的字段规则
276 | * @param {object} data 验证的数据对象
277 | * @param {array} fields 校验的字段
278 | * @param {function} onMessage 自定义错误信息提示
279 | * @param {boolean} showMessage 是否显示提示信息,默认显示(内部使用)
280 | */
281 | checkFields(data, fields, onMessage, showMessage = true) {
282 | if(!isArray(fields)) throw new Error('第二个参数须为数组')
283 |
284 | // fields: [ '[field]:[rule]' ]
285 | // fields: [ 'phoneNo' ] => { phoneNo: true }
286 | // fields: [ 'phoneNo:required' ] => { phoneNo: ['required'] }
287 | // fields: [ 'phoneNo:required,mobile' ] => { phoneNo: ['required', 'mobile'] }
288 | let fieldMap = {}
289 |
290 | fields.forEach((item) => {
291 | let arr = item.split(':')
292 | let field = arr[0]
293 | let rules = arr[1]
294 |
295 | if(rules){
296 | // 只校验特定规则
297 | rules = rules.split(',')
298 | fieldMap[field] = rules
299 | }else{
300 | // 校验 field 字段的所有规则
301 | fieldMap[field] = true
302 | }
303 | })
304 |
305 | return this.checkData(data, onMessage, showMessage, fieldMap)
306 | }
307 |
308 | /**
309 | * 校验数据,不会提示错误信息
310 | * @param {object} data 验证的数据对象
311 | * @param {array} fields 校验的字段。如果有,只校验对应的字段规则,默认校验所有配置的字段规则
312 | */
313 | isValid(data, fields) {
314 | if(isArray(fields)){
315 | return this.checkFields(data, fields, null, false)
316 | }else{
317 | return this.checkData(data, null, false)
318 | }
319 | }
320 |
321 | /**
322 | * 动态添加字段校验
323 | * @param {object} options 配置参数
324 | * @param {object} [options.rules] 规则
325 | * @param {object} [options.messages] 提示消息
326 | */
327 | addRules(options = {}) {
328 | Object.assign(this.options.rules, options.rules || {})
329 | Object.assign(this.options.messages, options.messages || {})
330 |
331 | this._checkAllRules()
332 | }
333 |
334 | /**
335 | * 动态移除字段校验
336 | * @param {array} fields 要删除校验的字段
337 | */
338 | removeRules(fields) {
339 | if(!isArray(fields)) throw new Error('参数须为数组')
340 |
341 | for(let i = 0; i < fields.length; i++){
342 | let key = fields[i]
343 |
344 | delete this.options.rules[key]
345 | }
346 | }
347 |
348 | }
349 |
350 | WeValidator.RULES = RULES
351 | WeValidator.required = requiredFn
352 |
353 | module.exports = WeValidator
354 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | > 2.x 和 1.x 版本有所差别,如果您继续使用老版本,可以查看 [1.x 版本](https://github.com/ChanceYu/we-validator/tree/v1)。如果您要升级到 2.x 请先阅读[升级指南](./UPGRADE.md),推荐使用 2.x 版本。
11 |
12 | 简单灵活的表单验证插件,支持小程序、浏览器、Nodejs。小程序端支持:微信、支付宝、百度智能、字节跳动,小程序默认提示使用 `showToast`。
13 |
14 | [API 文档](#api) | [示例 Examples](#examples),如果你 :sparkling_heart: 就点击 **★Star** 吧。
15 |
16 | ## 特点
17 |
18 | - 使用简单灵活,不依赖任何框架
19 | - 既支持原生小程序方式,也支持 mpvue、wepy、taro 等小程序框架使用
20 | - 支持浏览器以及 Nodejs 端使用
21 | - [支持自定义规则](#wevalidatoraddrulerulename-ruleoption)
22 | - [支持自定义错误信息提示](#wevalidatoronmessage)
23 | - [支持动态添加或移除字段校验](#addrulesoptions)
24 | - [支持单独校验一个或多个字段规则](#checkfieldsdata-fields-onmessage)
25 | - [支持函数校验](#wevalidatorcheckvaluerulename-value-param)
26 | - [支持多个字段同时校验并显示错误](#多个字段同时校验并显示错误)
27 | - [默认支持常用校验规则](#默认支持的规则)
28 |
29 |
30 |
31 | ## 安装
32 | 使用 npm:
33 |
34 | ```bash
35 | npm install we-validator --save
36 | ```
37 |
38 | 使用 cdn:
39 |
40 | ```html
41 |
42 | ```
43 |
44 |
45 | ## 使用
46 | 下面是微信小程序的用法,其它小程序类似
47 |
48 |
49 | 点击查看栗子 :chestnut:
50 |
51 | ```html
52 |
59 | ```
60 |
61 | ```javascript
62 | const WeValidator = require('we-validator')
63 |
64 | Page({
65 | onReady(){
66 | this.initValidator()
67 | },
68 | onSubmitForm(e){
69 | let { value } = e.detail
70 |
71 | if(!this.validatorInstance.checkData(value)) return
72 |
73 | // 开始提交表单
74 | // wx.request
75 | },
76 | initValidator(){
77 | // 实例化
78 | this.validatorInstance = new WeValidator({
79 | rules: {
80 | username: {
81 | required: true
82 | },
83 | phoneno: {
84 | required: true,
85 | mobile: true
86 | },
87 | str: {
88 | length: 3
89 | },
90 | },
91 | messages: {
92 | username: {
93 | required: '请输入用户名'
94 | },
95 | phoneno: {
96 | required: '请输入手机号',
97 | mobile: '手机号格式不正确'
98 | },
99 | str: { // 非必填字段
100 | length: '请输入长度为3的字符串'
101 | },
102 | },
103 | })
104 | },
105 | })
106 | ```
107 |
108 |
109 |
110 | ## Examples
111 | 您也可参考当前项目下对应示例
112 |
113 | - [原生微信小程序使用方式](./example/wechat/pages/index/index.js)
114 | - [mpvue 使用方式](./example/mpvue/src/pages/index/index.vue)
115 | - [web 浏览器使用方式](./example/web/index.html)
116 | - [Nodejs 端使用方式](./example/nodejs/server/router/home.js)
117 | - [复杂的校验案例-自定义规则-动态添加字段校验](./example/complex/index.html)
118 |
119 |
120 | ## API
121 | - [new WeValidator(options)](#new-wevalidatoroptions)
122 | - [.checkData(data, onMessage)](#checkdatadata-onmessage) 校验数据,会显示错误信息
123 | - [.checkFields(data, fields, onMessage)](#checkfieldsdata-fields-onmessage) 校验数据,会显示错误信息,只校验对应的字段
124 | - [.isValid(data, fields)](#isvaliddata-fields) 校验数据,不会显示错误信息,可单独校验特定字段
125 | - [.addRules(options)](#addrulesoptions) 动态添加字段校验
126 | - [.removeRules(fields)](#removerulesfields) 动态移除字段校验
127 |
128 |
129 | ## Static API
130 | - [WeValidator](#static-api)
131 | - [.addRule(ruleName, ruleOption)](#wevalidatoraddrulerulename-ruleoption) 添加自定义规则
132 | - [.checkValue(ruleName, value, param)](#wevalidatorcheckvaluerulename-value-param) 函数校验,单独校验某个内容
133 | - [.onMessage](#wevalidatoronmessage) 设置全局错误信息显示
134 |
135 |
136 | ## 默认支持的规则
137 |
138 | > 注意: 非必填字段只有字段有值才会校验配置的规则
139 |
140 | | 规则 | 描述 | 默认提示 |
141 | | --- | --- | --- |
142 | | `required: true` | 必填 | 此字段必填 |
143 | | `pattern: /^\d+$/` | 正则通用 | 不符合此验证规则 |
144 | | `email: true` | 电子邮件格式 | 请输入有效的电子邮件地址 |
145 | | `mobile: true` | 11位手机号 | 请输入11位的手机号码 |
146 | | `tel: true` | 座机号
例如:010-1234567、0551-1234567 | 请输入座机号 |
147 | | `url: true` | URL网址 | 请输入有效的网址 |
148 | | `idcard: true` | 身份证号 | 请输入18位的有效身份证 |
149 | | `equalTo: 'field'` | 字段值相同校验
例如:密码和确认密码,[参考](./example/web/index.html#L82) | 输入值必须和字段 `field` 相同 |
150 | | `notEqualTo: 'field'` | 字段值不能相同校验
与 `equalTo` 相反 | 输入值不能和字段 `field` 相同 |
151 | | `contains: 'str'` | 是否包含某字符 | 输入值必须包含 `str` |
152 | | `notContains: 'str'` | 不能包含某字符 | 输入值不能包含 `str` |
153 | | `length: 5` | 长度为多少的字符串 | 请输入 `5` 个字符 |
154 | | `minlength: 2` | 最少多长的字符串 | 最少要输入 `2` 个字符 |
155 | | `maxlength: 6` | 最多多长的字符串 | 最多可以输入 `6` 个字符 |
156 | | `rangelength: [2, 6]` | 某个范围长度的字符串 | 请输入长度在 `2` 到 `6` 之间的字符 |
157 | | `number: true` | 数字 | 请输入有效的数字 |
158 | | `digits: true` | 正整数数字 | 只能输入正整数数字 |
159 | | `integer: true` | 正整数或负整数数字 | 只能输入整数数字 |
160 | | `min: 3` | 大于多少的数字
(最小只能多少),也可以比较字段的值,[参考](./example/complex/index.html#L180) | 请输入大于 `3` 的数字 |
161 | | `max: 9` | 小于多少的数字
(最大只能多少),也可以比较字段的值 | 请输入小于 `9` 的数字 |
162 | | `range: [3, 9]` | 大于且小于多少的数字 | 请输入大于 `3` 且小于 `9` 的数字 |
163 | | `chinese: true` | 中文字符 | 只能输入中文字符 |
164 | | `minChinese: 3` | 最少多少个中文字符 | 最少输入 `3` 个中文字符 |
165 | | `maxChinese: 9` | 最多多少个中文字符 | 最多输入 `9` 个中文字符 |
166 | | `rangeChinese: [3, 9]` | 大于且小于多少个中文字符 | 只能输入 `3` 到 `9` 个中文字符 |
167 | | `date: true` | 日期(默认使用 `new Date(value)` 校验) | 请输入有效的日期 |
168 | | `dateISO: true` | 日期(ISO标准格式)
例如:2019-09-19,2019/09/19 | 请输入有效的日期(ISO标准格式) |
169 | | `ipv4: true` | ipv4地址 | 请输入有效的IPv4地址 |
170 | | `ipv6: true` | ipv6地址 | 请输入有效的IPv6地址 |
171 |
172 |
173 | ## new WeValidator(options)
174 | > 实例化
175 |
176 | **返回**: object - validatorInstance
177 |
178 | | 参数 | 类型 | 默认值 | 描述 |
179 | | --- | --- | --- | --- |
180 | | options | object | | |
181 | | [options.rules] | object | | 验证字段的规则 |
182 | | [options.messages] | object | | 验证字段错误的提示信息 |
183 | | [options.onMessage] | function | | 错误信息显示方式
默认会自动检测环境。小程序默认使用`showToast`
普通web浏览器默认使用`alert`
Nodejs端不做处理建议自己配置,[详情](#wevalidatoronmessage) |
184 | | [options.multiCheck] | boolean | `false` | 是否校验多个字段
需要一次校验多个字段并显示错误信息时使用,[详情](#多个字段同时校验并显示错误) |
185 |
186 |
187 | 点击查看栗子 :chestnut:
188 |
189 | ```javascript
190 | const WeValidator = require('we-validator')
191 |
192 | new WeValidator({
193 | rules: {
194 | username: {
195 | required: true
196 | },
197 | phoneno: {
198 | required: true,
199 | mobile: true
200 | }
201 | },
202 | messages: {
203 | username: {
204 | required: '请输入用户名'
205 | },
206 | phoneno: {
207 | required: '请输入手机号',
208 | mobile: '手机号格式不正确'
209 | }
210 | }
211 | })
212 | ```
213 |
214 |
215 |
216 | ### .checkData(data, onMessage)
217 | > 校验数据,会显示错误信息,校验所有字段规则
218 |
219 | **返回**: boolean
220 |
221 | | 参数 | 类型 | 默认值 | 描述 |
222 | | --- | --- | --- | --- |
223 | | data | object | | 需要校验的表单数据 |
224 | | onMessage | function | | 自定义错误信息提示,[详情](#wevalidatoronmessage) |
225 |
226 | ### .checkFields(data, fields, onMessage)
227 | > 校验数据,会显示错误信息,只校验对应的字段,[参考](./example/mpvue/src/pages/index/index.vue)。
228 |
229 | 通常用于单独校验一个或多个字段规则
230 |
231 | **返回**: boolean
232 |
233 | | 参数 | 类型 | 默认值 | 描述 |
234 | | --- | --- | --- | --- |
235 | | data | object | | 需要校验的表单数据 |
236 | | fields | array | | 校验的字段规则,必填
例如:
`['phoneNo']` 只校验此字段的所有规则
`['phoneNo:required']` 只校验此字段的 `required` 规则
`['phoneNo:required,mobile']` 只校验此字段的 `required` 和 `mobile` 规则
`['phoneNo', 'code']` 只校验这两个字段的所有规则 |
237 | | onMessage | function | | 自定义错误信息提示,[详情](#wevalidatoronmessage) |
238 |
239 | ### .isValid(data, fields)
240 | > 校验数据是否有效,不会提示错误信息
241 |
242 | 使用场景例如:表单中某些字段校验通过按钮才可点击的场景,[参考](./example/mpvue/src/pages/index/index.vue)。
243 |
244 | **返回**: boolean
245 |
246 | | 参数 | 类型 | 默认值 | 描述 |
247 | | --- | --- | --- | --- |
248 | | data | object | | 需要校验的表单数据 |
249 | | fields | array | | 校验的字段
不传,默认校验所有字段规则
如果有,只校验对应的字段规则
配置方法同 `.checkFields(data, fields)` |
250 |
251 | ### .addRules(options)
252 | > 动态添加字段校验,[参考](./example/complex/index.html#L235)
253 |
254 | | 参数 | 类型 | 默认值 | 描述 |
255 | | --- | --- | --- | --- |
256 | | options | object | | 同 `new WeValidator(options)` ,[详情](#new-wevalidatoroptions) |
257 |
258 |
259 |
260 | 点击查看栗子 :chestnut:
261 |
262 | ```javascript
263 | const WeValidator = require('we-validator')
264 |
265 | const validatorInstance = new WeValidator({
266 | rules: {
267 | username: {
268 | required: true
269 | }
270 | },
271 | messages: {
272 | username: {
273 | required: '请输入用户名'
274 | }
275 | }
276 | })
277 |
278 | // 动态添加校验
279 | validatorInstance.addRules({
280 | rules: {
281 | phoneno: {
282 | required: true,
283 | mobile: true
284 | }
285 | },
286 | messages: {
287 | phoneno: {
288 | required: '请输入手机号',
289 | mobile: '手机号格式不正确'
290 | }
291 | }
292 | })
293 | ```
294 |
295 |
296 |
297 | ### .removeRules(fields)
298 | > 动态移除字段校验,[参考](./example/complex/index.html#L235)
299 |
300 | | 参数 | 类型 | 默认值 | 描述 |
301 | | --- | --- | --- | --- |
302 | | fields | array | | 需要移除校验的表单字段 |
303 |
304 | ```javascript
305 | validatorInstance.removeRules(['username'])
306 | ```
307 |
308 | ## WeValidator.addRule(ruleName, ruleOption)
309 | > 静态方法:添加自定义规则,[参考](./example/complex/index.html)
310 |
311 | | 参数 | 类型 | 默认值 | 描述 |
312 | | --- | --- | --- | --- |
313 | | ruleName | string | | 规则名称 |
314 | | ruleOption | object | | 规则配置 |
315 | | [ruleOption.message] | string | | 默认错误信息文字
可以动态插入参数,例如 `请输入长度在 {0} 到 {1} 之间的字符`,[参考](./src/rules.js#L127) |
316 | | [ruleOption.rule] | function\|regexp | | 规则校验函数,需要返回一个 `boolean`。
也可以直接写一个正则表达式(如果只是正则类型的校验)。 |
317 |
318 |
319 | 点击查看栗子 :chestnut:
320 |
321 | ```javascript
322 | const WeValidator = require('we-validator')
323 |
324 | // 添加自定义规则(这两种写法一样)
325 | WeValidator.addRule('theRuleName', {
326 | message: '默认错误信息文字',
327 | rule(value, param){
328 | return /\d/.test(value)
329 | }
330 | })
331 | WeValidator.addRule('theRuleName', {
332 | message: '默认错误信息文字',
333 | rule: /\d/
334 | })
335 |
336 | // 使用方式一,实例化
337 | new WeValidator({
338 | rules: {
339 | field1: {
340 | theRuleName: true
341 | }
342 | },
343 | messages: {
344 | field1: {
345 | theRuleName: '提示信息'
346 | }
347 | }
348 | })
349 |
350 | // 使用方式二,调用函数
351 | WeValidator.checkValue('theRuleName', 'str')
352 | ```
353 |
354 |
355 |
356 |
357 | ## WeValidator.checkValue(ruleName, value, param)
358 | > 静态方法:函数校验
359 |
360 | | 参数 | 类型 | 默认值 | 描述 |
361 | | --- | --- | --- | --- |
362 | | ruleName | string | | 规则名称 |
363 | | value | string | | 需要校验的内容 |
364 | | param | any | | 传递给规则参数 |
365 |
366 | 支持所有[默认支持的规则](#默认支持的规则),也支持自定义的规则。
367 |
368 | ```javascript
369 | // 必填
370 | let b1 = WeValidator.checkValue('required', 'str') // true
371 |
372 | // 不能小于6的数字
373 | let b2 = WeValidator.checkValue('min', 'str', 6) // false
374 |
375 | // 大于2小于5的数字
376 | let b3 = WeValidator.checkValue('range', 'str', [2, 5]) // false
377 | ```
378 |
379 | ## WeValidator.onMessage
380 | > 自定义错误信息提示
381 |
382 | 可以全局配置一个,也可以单独配置,非常灵活。
383 |
384 | 优先级是:`.checkData(data, onMessage)` > `new WeValidator({ onMessage })` > `WeValidator.onMessage` > 默认检测
385 |
386 | 默认的消息提示方式:小程序默认使用`showToast`,浏览器默认使用`alert`,Nodejs端无处理建议自己配置。
387 |
388 |
389 | 点击查看栗子 :chestnut:
390 |
391 | ```javascript
392 | const WeValidator = require('we-validator')
393 |
394 | // 1、全局配置
395 | WeValidator.onMessage = function(data){
396 | /*
397 | data 参数
398 | {
399 | msg, // 提示文字
400 | name, // 表单控件的 name
401 | value, // 表单控件的值
402 | param // rules 验证字段传递的参数
403 | }
404 | */
405 | }
406 |
407 | // 2、实例化配置
408 | new WeValidator({
409 | rules: {},
410 | message: {},
411 | onMessage: function(data){
412 | alert(data.msg)
413 | }
414 | })
415 |
416 | // 3、验证的时候配置 onMessage(nodejs端校验可以使用此方式)
417 | if(!obj.checkData(formData, onMessage)) return
418 |
419 | function onMessage(data){
420 | alert(data.msg)
421 | }
422 | ```
423 |
424 |
425 |
426 | ### 多个字段同时校验并显示错误
427 | 使用场景如下,**注意:当`multiCheck`为`true`时,建议使用自定义`onMessage`**,[参考](./example/web/index.html)
428 |
429 | 
430 |
431 |
432 | 点击查看栗子 :chestnut:
433 |
434 | ```javascript
435 | var validatorInstance = new WeValidator({
436 | multiCheck: true,
437 | onMessage: function(data){
438 | console.log(data);
439 |
440 | // 根据自己的项目去处理,控制错误信息的显示
441 | },
442 | rules: {
443 | username: {
444 | required: true
445 | },
446 | phoneno: {
447 | required: true,
448 | mobile: true
449 | }
450 | },
451 | messages: {
452 | username: {
453 | required: '请输入用户名'
454 | },
455 | phoneno: {
456 | required: '请输入手机号',
457 | mobile: '手机号格式不正确'
458 | }
459 | }
460 | });
461 | ```
462 |
463 |
464 |
465 | ## Changelog
466 | [查看更新日志](./CHANGELOG.md)
467 |
468 | ## Issues
469 | 如果您在使用过程中发现 Bug,或者有好的建议,欢迎[报告问题](https://github.com/ChanceYu/we-validator/issues)。
470 |
471 | ## License
472 |
473 | [![license][img-mit]][url-mit]
474 |
475 | Copyright (c) 2019 ChanceYu
476 |
477 | [url-github]: https://github.com/ChanceYu/we-validator
478 | [url-npm]: https://www.npmjs.com/package/we-validator
479 | [url-travis]: https://travis-ci.org/ChanceYu/we-validator
480 | [url-mit]: https://opensource.org/licenses/mit-license.php
481 |
482 | [img-npm]: https://nodei.co/npm/we-validator.png?compact=true
483 | [img-travis]: https://travis-ci.org/ChanceYu/we-validator.svg?branch=master
484 | [img-javascript]: https://img.shields.io/badge/language-JavaScript-brightgreen.svg
485 | [img-mit]: https://img.shields.io/npm/l/we-validator.svg
486 |
487 |
--------------------------------------------------------------------------------
/dist/we-validator.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * we-validator
3 | * version: 2.1.17
4 | * address: https://github.com/ChanceYu/we-validator#readme
5 | * author: ChanceYu
6 | * license: MIT
7 | */
8 | (function webpackUniversalModuleDefinition(root, factory) {
9 | if(typeof exports === 'object' && typeof module === 'object')
10 | module.exports = factory();
11 | else if(typeof define === 'function' && define.amd)
12 | define("WeValidator", [], factory);
13 | else if(typeof exports === 'object')
14 | exports["WeValidator"] = factory();
15 | else
16 | root["WeValidator"] = factory();
17 | })(typeof self !== 'undefined' ? self : this, function() {
18 | return /******/ (function(modules) { // webpackBootstrap
19 | /******/ // The module cache
20 | /******/ var installedModules = {};
21 | /******/
22 | /******/ // The require function
23 | /******/ function __webpack_require__(moduleId) {
24 | /******/
25 | /******/ // Check if module is in cache
26 | /******/ if(installedModules[moduleId]) {
27 | /******/ return installedModules[moduleId].exports;
28 | /******/ }
29 | /******/ // Create a new module (and put it into the cache)
30 | /******/ var module = installedModules[moduleId] = {
31 | /******/ i: moduleId,
32 | /******/ l: false,
33 | /******/ exports: {}
34 | /******/ };
35 | /******/
36 | /******/ // Execute the module function
37 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
38 | /******/
39 | /******/ // Flag the module as loaded
40 | /******/ module.l = true;
41 | /******/
42 | /******/ // Return the exports of the module
43 | /******/ return module.exports;
44 | /******/ }
45 | /******/
46 | /******/
47 | /******/ // expose the modules object (__webpack_modules__)
48 | /******/ __webpack_require__.m = modules;
49 | /******/
50 | /******/ // expose the module cache
51 | /******/ __webpack_require__.c = installedModules;
52 | /******/
53 | /******/ // define getter function for harmony exports
54 | /******/ __webpack_require__.d = function(exports, name, getter) {
55 | /******/ if(!__webpack_require__.o(exports, name)) {
56 | /******/ Object.defineProperty(exports, name, {
57 | /******/ configurable: false,
58 | /******/ enumerable: true,
59 | /******/ get: getter
60 | /******/ });
61 | /******/ }
62 | /******/ };
63 | /******/
64 | /******/ // getDefaultExport function for compatibility with non-harmony modules
65 | /******/ __webpack_require__.n = function(module) {
66 | /******/ var getter = module && module.__esModule ?
67 | /******/ function getDefault() { return module['default']; } :
68 | /******/ function getModuleExports() { return module; };
69 | /******/ __webpack_require__.d(getter, 'a', getter);
70 | /******/ return getter;
71 | /******/ };
72 | /******/
73 | /******/ // Object.prototype.hasOwnProperty.call
74 | /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
75 | /******/
76 | /******/ // __webpack_public_path__
77 | /******/ __webpack_require__.p = "";
78 | /******/
79 | /******/ // Load entry module and return exports
80 | /******/ return __webpack_require__(__webpack_require__.s = 0);
81 | /******/ })
82 | /************************************************************************/
83 | /******/ ([
84 | /* 0 */
85 | /***/ (function(module, exports, __webpack_require__) {
86 |
87 | "use strict";
88 |
89 |
90 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
91 |
92 | var _rules = __webpack_require__(1);
93 |
94 | var _rules2 = _interopRequireDefault(_rules);
95 |
96 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
97 |
98 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
99 |
100 | var requiredFn = _rules2.default.required.rule;
101 |
102 | /**
103 | * 环境检测
104 | */
105 | var isWx = typeof wx !== 'undefined' && !!wx.showToast; // 微信小程序
106 | var isMy = typeof my !== 'undefined' && !!my.showToast; // 支付宝小程序
107 | var isSwan = typeof swan !== 'undefined' && !!swan.showToast; // 百度智能小程序
108 | var isTt = typeof tt !== 'undefined' && !!tt.showToast; // 字节跳动小程序
109 | var isBrowser = typeof window !== 'undefined' && !!window.alert; // 普通浏览器
110 |
111 | var objString = Object.prototype.toString;
112 |
113 | var isArray = Array.isArray || function (v) {
114 | return objString.call(v) === '[object Array]';
115 | };
116 | var isFunction = function isFunction(v) {
117 | return objString.call(v) === '[object Function]';
118 | };
119 | var isRegExp = function isRegExp(v) {
120 | return objString.call(v) === '[object RegExp]';
121 | };
122 |
123 | var WeValidator = function () {
124 |
125 | /**
126 | * 默认参数
127 | * @param {object} options
128 | * @param {object} [options.rules] 验证字段的规则
129 | * @param {object} [options.messages] 验证字段错误的提示信息
130 | * @param {function} [options.onMessage] 错误信息显示方式
131 | * @param {boolean} [options.multiCheck] 是否同时校验多个字段
132 | */
133 | function WeValidator() {
134 | var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
135 |
136 | _classCallCheck(this, WeValidator);
137 |
138 | this.options = options;
139 |
140 | this.required = requiredFn;
141 | this._checkAllRules();
142 | }
143 |
144 | /**
145 | * 所有校验规则
146 | */
147 |
148 |
149 | /**
150 | * 动态添加验证规则
151 | * @param {string} ruleName 规则名称
152 | * @param {object} ruleOption 规则配置
153 | * @param {string} [ruleOption.message] 默认错误信息文字
154 | * @param {regexp|function} [ruleOption.rule] 验证规则
155 | */
156 |
157 |
158 | /**
159 | * 验证单个字段数据
160 | * @param {string} ruleName 规则名称
161 | * @param {string} value 要验证的值
162 | * @param {any} param 传递的验证参数
163 | * @param {boolean} skip 未填跳过校验,仅供内部使用
164 | */
165 |
166 |
167 | _createClass(WeValidator, [{
168 | key: '_showErrorMessage',
169 |
170 |
171 | /**
172 | * 显示错误信息
173 | * @param {object} params 错误信息
174 | * @param {function} onMessage 自定义提示函数
175 | */
176 | value: function _showErrorMessage(params, onMessage) {
177 | // validatorInstance.checkData(data, onMessage)
178 | if (isFunction(onMessage)) {
179 | return onMessage(params);
180 | }
181 |
182 | // 参数形式 new WeValidator({ onMessage })
183 | if (isFunction(this.options.onMessage)) {
184 | return this.options.onMessage(params);
185 | }
186 |
187 | // 全局配置 WeValidator.onMessage
188 | if (isFunction(WeValidator.onMessage)) {
189 | return WeValidator.onMessage(params);
190 | }
191 |
192 | // 微信小程序
193 | if (isWx) {
194 | return wx.showToast({
195 | title: params.msg,
196 | icon: 'none'
197 | });
198 | }
199 |
200 | // 支付宝小程序
201 | if (isMy) {
202 | return my.showToast({
203 | content: params.msg,
204 | type: 'none'
205 | });
206 | }
207 |
208 | // 百度小程序
209 | if (isSwan) {
210 | return swan.showToast({
211 | title: params.msg,
212 | icon: 'none'
213 | });
214 | }
215 |
216 | // 字节跳动小程序
217 | if (isTt) {
218 | return tt.showToast({
219 | title: params.msg,
220 | icon: 'none'
221 | });
222 | }
223 |
224 | // 浏览器端
225 | if (isBrowser) alert(params.msg);
226 | }
227 |
228 | /**
229 | * 获取错误信息内容
230 | * @param {string} ruleName 规则名称
231 | * @param {string} attr 字段名称
232 | * @param {any} param 规则参数
233 | */
234 |
235 | }, {
236 | key: '_getErrorMessage',
237 | value: function _getErrorMessage(ruleName, attr, param) {
238 | var messages = this.options.messages;
239 | var defaultMessage = WeValidator.RULES[ruleName].message;
240 |
241 | if (messages && messages.hasOwnProperty(attr) && messages[attr][ruleName]) {
242 | defaultMessage = messages[attr][ruleName];
243 | }
244 |
245 | if (defaultMessage) {
246 | defaultMessage = defaultMessage.replace(/\{(\d)\}/g, function ($0, $1) {
247 | if (isArray(param)) {
248 | return param[$1];
249 | } else {
250 | return param;
251 | }
252 | });
253 |
254 | return defaultMessage;
255 | }
256 | }
257 |
258 | /**
259 | * 验证配置规则是否无效
260 | * @param {string} ruleName 规则名称
261 | * @param {string} attr 字段名称
262 | */
263 |
264 | }, {
265 | key: '_isRuleInvalid',
266 | value: function _isRuleInvalid(ruleName, attr) {
267 | if (!WeValidator.RULES.hasOwnProperty(ruleName)) {
268 | console.warn && console.warn('\u6CA1\u6709\u6B64\u9A8C\u8BC1\u89C4\u5219\uFF1A' + ruleName + '\uFF0C\u5B57\u6BB5\uFF1A' + attr);
269 | return true;
270 | }
271 | }
272 |
273 | /**
274 | * 验证所有配置规则是否正确
275 | */
276 |
277 | }, {
278 | key: '_checkAllRules',
279 | value: function _checkAllRules() {
280 | var _rules_ = this.options.rules;
281 |
282 | // 遍历字段
283 | for (var attr in _rules_) {
284 | // 遍历验证规则
285 | for (var ruleName in _rules_[attr]) {
286 | if (this._isRuleInvalid(ruleName, attr)) continue;
287 | }
288 | }
289 | }
290 |
291 | /**
292 | * 校验数据,会验证所有配置的字段规则
293 | * @param {object} data 验证的数据对象
294 | * @param {function} onMessage 自定义错误信息提示
295 | * @param {boolean} showMessage 是否显示提示信息,默认显示(内部使用)
296 | * @param {object} fieldMap 校验的字段,默认校验所有字段(内部使用)
297 | */
298 |
299 | }, {
300 | key: 'checkData',
301 | value: function checkData(data, onMessage) {
302 | var showMessage = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
303 | var fieldMap = arguments[3];
304 |
305 | var _rules_ = this.options.rules;
306 | var multiCheck = this.options.multiCheck;
307 | var hasError = false;
308 | var errorData = {};
309 |
310 | this.data = data;
311 |
312 | // 遍历字段
313 | for (var attr in _rules_) {
314 | if (fieldMap && !fieldMap.hasOwnProperty(attr)) continue;
315 |
316 | // 遍历验证规则
317 | for (var ruleName in _rules_[attr]) {
318 | if (this._isRuleInvalid(ruleName, attr)) continue;
319 |
320 | if (fieldMap) {
321 | var res = fieldMap[attr];
322 | if (isArray(res) && res.indexOf(ruleName) === -1) continue;
323 | }
324 |
325 | var ruleParam = _rules_[attr][ruleName];
326 | var value = '';
327 |
328 | if (data.hasOwnProperty(attr)) {
329 | value = data[attr];
330 | }
331 |
332 | if (isFunction(ruleParam)) {
333 | ruleParam = ruleParam.call(this, value);
334 | }
335 |
336 | var isFieldValid = WeValidator.checkValue.call(this, ruleName, value, ruleParam, true);
337 |
338 | // 验证不通过
339 | if (!isFieldValid) {
340 | hasError = true;
341 |
342 | var msg = this._getErrorMessage(ruleName, attr, ruleParam);
343 | var errorParam = null;
344 |
345 | if (showMessage && msg) {
346 | errorParam = {
347 | name: attr,
348 | value: value,
349 | param: ruleParam,
350 | rule: ruleName,
351 | msg: msg
352 | };
353 | errorData[attr] = errorParam;
354 | }
355 |
356 | if (!multiCheck) {
357 | if (errorParam) {
358 | this._showErrorMessage(errorParam, onMessage);
359 | }
360 | return false;
361 | }
362 | }
363 | }
364 | }
365 |
366 | if (hasError) {
367 | if (multiCheck && showMessage) {
368 | this._showErrorMessage(errorData, onMessage);
369 | }
370 | return false;
371 | }
372 |
373 | return true;
374 | }
375 |
376 | /**
377 | * 校验数据,只校验对应的字段规则
378 | * @param {object} data 验证的数据对象
379 | * @param {array} fields 校验的字段
380 | * @param {function} onMessage 自定义错误信息提示
381 | * @param {boolean} showMessage 是否显示提示信息,默认显示(内部使用)
382 | */
383 |
384 | }, {
385 | key: 'checkFields',
386 | value: function checkFields(data, fields, onMessage) {
387 | var showMessage = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true;
388 |
389 | if (!isArray(fields)) throw new Error('第二个参数须为数组');
390 |
391 | // fields: [ '[field]:[rule]' ]
392 | // fields: [ 'phoneNo' ] => { phoneNo: true }
393 | // fields: [ 'phoneNo:required' ] => { phoneNo: ['required'] }
394 | // fields: [ 'phoneNo:required,mobile' ] => { phoneNo: ['required', 'mobile'] }
395 | var fieldMap = {};
396 |
397 | fields.forEach(function (item) {
398 | var arr = item.split(':');
399 | var field = arr[0];
400 | var rules = arr[1];
401 |
402 | if (rules) {
403 | // 只校验特定规则
404 | rules = rules.split(',');
405 | fieldMap[field] = rules;
406 | } else {
407 | // 校验 field 字段的所有规则
408 | fieldMap[field] = true;
409 | }
410 | });
411 |
412 | return this.checkData(data, onMessage, showMessage, fieldMap);
413 | }
414 |
415 | /**
416 | * 校验数据,不会提示错误信息
417 | * @param {object} data 验证的数据对象
418 | * @param {array} fields 校验的字段。如果有,只校验对应的字段规则,默认校验所有配置的字段规则
419 | */
420 |
421 | }, {
422 | key: 'isValid',
423 | value: function isValid(data, fields) {
424 | if (isArray(fields)) {
425 | return this.checkFields(data, fields, null, false);
426 | } else {
427 | return this.checkData(data, null, false);
428 | }
429 | }
430 |
431 | /**
432 | * 动态添加字段校验
433 | * @param {object} options 配置参数
434 | * @param {object} [options.rules] 规则
435 | * @param {object} [options.messages] 提示消息
436 | */
437 |
438 | }, {
439 | key: 'addRules',
440 | value: function addRules() {
441 | var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
442 |
443 | Object.assign(this.options.rules, options.rules || {});
444 | Object.assign(this.options.messages, options.messages || {});
445 |
446 | this._checkAllRules();
447 | }
448 |
449 | /**
450 | * 动态移除字段校验
451 | * @param {array} fields 要删除校验的字段
452 | */
453 |
454 | }, {
455 | key: 'removeRules',
456 | value: function removeRules(fields) {
457 | if (!isArray(fields)) throw new Error('参数须为数组');
458 |
459 | for (var i = 0; i < fields.length; i++) {
460 | var key = fields[i];
461 |
462 | delete this.options.rules[key];
463 | }
464 | }
465 | }]);
466 |
467 | return WeValidator;
468 | }();
469 |
470 | WeValidator.RULES = {};
471 |
472 | WeValidator.addRule = function (ruleName, ruleOption) {
473 | WeValidator.RULES[ruleName] = ruleOption;
474 | };
475 |
476 | WeValidator.checkValue = function (ruleName, value, param, skip) {
477 | var rule = WeValidator.RULES[ruleName].rule;
478 |
479 | if (isRegExp(rule)) {
480 | if (skip) {
481 | return !requiredFn(value) || rule.test(value);
482 | } else {
483 | return rule.test(value);
484 | }
485 | }
486 |
487 | if (isFunction(rule)) {
488 | if (ruleName === 'required') {
489 | return param && requiredFn(value);
490 | } else {
491 | if (skip) {
492 | return !requiredFn(value) || rule.call(this, value, param);
493 | } else {
494 | return rule.call(this, value, param);
495 | }
496 | }
497 | }
498 | };
499 |
500 | WeValidator.RULES = _rules2.default;
501 | WeValidator.required = requiredFn;
502 |
503 | module.exports = WeValidator;
504 |
505 | /***/ }),
506 | /* 1 */
507 | /***/ (function(module, exports, __webpack_require__) {
508 |
509 | "use strict";
510 |
511 |
512 | module.exports = {
513 | /**
514 | * 必填
515 | */
516 | required: {
517 | message: '此字段必填',
518 | rule: function rule(value) {
519 | if (typeof value === 'number') {
520 | value = value.toString();
521 | } else if (typeof value === 'boolean') {
522 | return true;
523 | }
524 | return !!(value && value.length > 0);
525 | }
526 | },
527 | /**
528 | * 正则通用
529 | */
530 | pattern: {
531 | message: '不符合此验证规则',
532 | rule: function rule(value, param) {
533 | return param.test(value);
534 | }
535 | },
536 | /**
537 | * 电子邮件
538 | */
539 | email: {
540 | message: '请输入有效的电子邮件地址',
541 | rule: /^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/
542 | },
543 | /**
544 | * 手机号码
545 | */
546 | mobile: {
547 | message: '请输入 11 位的手机号码',
548 | rule: /^1[3456789]\d{9}$/
549 | },
550 | /**
551 | * 座机号,例如:010-1234567、0551-1234567
552 | */
553 | tel: {
554 | message: '请输入座机号',
555 | rule: /^(\d{3,4}-)?\d{7,8}$/
556 | },
557 | /**
558 | * URL网址
559 | */
560 | url: {
561 | message: '请输入有效的网址',
562 | rule: /^(?:(?:(?:https?|ftp):)?\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})).?)(?::\d{2,5})?(?:[/?#]\S*)?$/i
563 | },
564 | /**
565 | * 身份证号
566 | */
567 | idcard: {
568 | message: '请输入 18 位的有效身份证',
569 | rule: /^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$/
570 | },
571 | /**
572 | * 字段值相同校验(例如:密码和确认密码)
573 | */
574 | equalTo: {
575 | message: '输入值必须和字段 {0} 相同',
576 | rule: function rule(value, param) {
577 | return value === this.data[param];
578 | }
579 | },
580 | /**
581 | * 字段值不相同校验,与 equalTo 相反
582 | */
583 | notEqualTo: {
584 | message: '输入值不能和字段 {0} 相同',
585 | rule: function rule(value, param) {
586 | return value !== this.data[param];
587 | }
588 | },
589 | /**
590 | * 是否包含某字符
591 | */
592 | contains: {
593 | message: '输入值必须包含 {0}',
594 | rule: function rule(value, param) {
595 | return value.indexOf(param) > -1;
596 | }
597 | },
598 | /**
599 | * 不能包含某字符
600 | */
601 | notContains: {
602 | message: '输入值不能包含 {0}',
603 | rule: function rule(value, param) {
604 | return value.indexOf(param) === -1;
605 | }
606 | },
607 | /**
608 | * 长度为多少的字符串
609 | */
610 | length: {
611 | message: '请输入 {0} 个字符',
612 | rule: function rule(value, param) {
613 | return value.length == param;
614 | }
615 | },
616 | /**
617 | * 最少多长的字符串
618 | */
619 | minlength: {
620 | message: '最少要输入 {0} 个字符',
621 | rule: function rule(value, param) {
622 | return value.length >= param;
623 | }
624 | },
625 | /**
626 | * 最多多长的字符串
627 | */
628 | maxlength: {
629 | message: '最多可以输入 {0} 个字符',
630 | rule: function rule(value, param) {
631 | return value.length <= param;
632 | }
633 | },
634 | /**
635 | * 某个范围长度的字符串
636 | */
637 | rangelength: {
638 | message: '请输入长度在 {0} 到 {1} 之间的字符',
639 | rule: function rule(value, param) {
640 | return value.length >= param[0] && value.length <= param[1];
641 | }
642 | },
643 | /**
644 | * 数字
645 | */
646 | number: {
647 | message: '请输入有效的数字',
648 | rule: /^(?:-?\d+|-?\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/
649 | },
650 | /**
651 | * 正整数数字
652 | */
653 | digits: {
654 | message: '只能输入正整数数字',
655 | rule: /^\d+$/
656 | },
657 | /**
658 | * 正整数或负整数数字
659 | */
660 | integer: {
661 | message: '只能输入整数数字',
662 | rule: /^-?\d+$/
663 | },
664 | /**
665 | * 大于多少的数字/字段值
666 | */
667 | min: {
668 | message: '请输入大于 {0} 的数字',
669 | rule: function rule(value, param) {
670 | if (typeof param === 'string') param = this.data[param];
671 |
672 | return value >= param;
673 | }
674 | },
675 | /**
676 | * 小于多少的数字/字段值
677 | */
678 | max: {
679 | message: '请输入小于 {0} 的数字',
680 | rule: function rule(value, param) {
681 | if (typeof param === 'string') param = this.data[param];
682 |
683 | return value <= param;
684 | }
685 | },
686 | /**
687 | * 大于且小于多少的数字
688 | */
689 | range: {
690 | message: '请输入大于 {0} 且小于 {1} 的数字',
691 | rule: function rule(value, param) {
692 | return value >= param[0] && value <= param[1];
693 | }
694 | },
695 | /**
696 | * 中文字符
697 | */
698 | chinese: {
699 | message: '只能输入中文字符',
700 | rule: /^[\u4e00-\u9fa5]+$/
701 | },
702 | /**
703 | * 最少多少个中文字符
704 | */
705 | minChinese: {
706 | message: '最少输入 {0} 个中文字符',
707 | rule: function rule(value, param) {
708 | return new RegExp('^[\u4E00-\u9FA5]{' + param + ',}$').test(value);
709 | }
710 | },
711 | /**
712 | * 最多多少个中文字符
713 | */
714 | maxChinese: {
715 | message: '最多输入 {0} 个中文字符',
716 | rule: function rule(value, param) {
717 | return new RegExp('^[\u4E00-\u9FA5]{1,' + param + '}$').test(value);
718 | }
719 | },
720 | /**
721 | * 大于且小于多少个中文字符
722 | */
723 | rangeChinese: {
724 | message: '只能输入 {0} 到 {1} 个中文字符',
725 | rule: function rule(value, param) {
726 | return new RegExp('^[\u4E00-\u9FA5]{' + param[0] + ',' + param[1] + '}$').test(value);
727 | }
728 | },
729 | /**
730 | * 日期
731 | */
732 | date: {
733 | message: '请输入有效的日期',
734 | rule: function rule(value) {
735 | return !/Invalid|NaN/.test(new Date(value).toString());
736 | }
737 | },
738 | /**
739 | * 日期(ISO标准格式)例如:2019-09-19,2019/09/19
740 | */
741 | dateISO: {
742 | message: '请输入有效的日期(ISO 标准格式)',
743 | rule: /^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$/
744 | },
745 | /**
746 | * ipv4地址
747 | */
748 | ipv4: {
749 | message: '请输入有效的 IPv4 地址',
750 | rule: /^(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)$/i
751 | },
752 | /**
753 | * ipv6地址
754 | */
755 | ipv6: {
756 | message: '请输入有效的 IPv6 地址',
757 | rule: /^((([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}:[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){5}:([0-9A-Fa-f]{1,4}:)?[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){4}:([0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){3}:([0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){2}:([0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(([0-9A-Fa-f]{1,4}:){0,5}:((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(::([0-9A-Fa-f]{1,4}:){0,5}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|([0-9A-Fa-f]{1,4}::([0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})|(::([0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){1,7}:))$/i
758 | }
759 | };
760 |
761 | /***/ })
762 | /******/ ]);
763 | });
--------------------------------------------------------------------------------
/lib/we-validator.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * we-validator
3 | * version: 2.1.17
4 | * address: https://github.com/ChanceYu/we-validator#readme
5 | * author: ChanceYu
6 | * license: MIT
7 | */
8 | (function webpackUniversalModuleDefinition(root, factory) {
9 | if(typeof exports === 'object' && typeof module === 'object')
10 | module.exports = factory();
11 | else if(typeof define === 'function' && define.amd)
12 | define("WeValidator", [], factory);
13 | else if(typeof exports === 'object')
14 | exports["WeValidator"] = factory();
15 | else
16 | root["WeValidator"] = factory();
17 | })(typeof self !== 'undefined' ? self : this, function() {
18 | return /******/ (function(modules) { // webpackBootstrap
19 | /******/ // The module cache
20 | /******/ var installedModules = {};
21 | /******/
22 | /******/ // The require function
23 | /******/ function __webpack_require__(moduleId) {
24 | /******/
25 | /******/ // Check if module is in cache
26 | /******/ if(installedModules[moduleId]) {
27 | /******/ return installedModules[moduleId].exports;
28 | /******/ }
29 | /******/ // Create a new module (and put it into the cache)
30 | /******/ var module = installedModules[moduleId] = {
31 | /******/ i: moduleId,
32 | /******/ l: false,
33 | /******/ exports: {}
34 | /******/ };
35 | /******/
36 | /******/ // Execute the module function
37 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
38 | /******/
39 | /******/ // Flag the module as loaded
40 | /******/ module.l = true;
41 | /******/
42 | /******/ // Return the exports of the module
43 | /******/ return module.exports;
44 | /******/ }
45 | /******/
46 | /******/
47 | /******/ // expose the modules object (__webpack_modules__)
48 | /******/ __webpack_require__.m = modules;
49 | /******/
50 | /******/ // expose the module cache
51 | /******/ __webpack_require__.c = installedModules;
52 | /******/
53 | /******/ // define getter function for harmony exports
54 | /******/ __webpack_require__.d = function(exports, name, getter) {
55 | /******/ if(!__webpack_require__.o(exports, name)) {
56 | /******/ Object.defineProperty(exports, name, {
57 | /******/ configurable: false,
58 | /******/ enumerable: true,
59 | /******/ get: getter
60 | /******/ });
61 | /******/ }
62 | /******/ };
63 | /******/
64 | /******/ // getDefaultExport function for compatibility with non-harmony modules
65 | /******/ __webpack_require__.n = function(module) {
66 | /******/ var getter = module && module.__esModule ?
67 | /******/ function getDefault() { return module['default']; } :
68 | /******/ function getModuleExports() { return module; };
69 | /******/ __webpack_require__.d(getter, 'a', getter);
70 | /******/ return getter;
71 | /******/ };
72 | /******/
73 | /******/ // Object.prototype.hasOwnProperty.call
74 | /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
75 | /******/
76 | /******/ // __webpack_public_path__
77 | /******/ __webpack_require__.p = "";
78 | /******/
79 | /******/ // Load entry module and return exports
80 | /******/ return __webpack_require__(__webpack_require__.s = 0);
81 | /******/ })
82 | /************************************************************************/
83 | /******/ ([
84 | /* 0 */
85 | /***/ (function(module, exports, __webpack_require__) {
86 |
87 | "use strict";
88 |
89 |
90 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
91 |
92 | var _rules = __webpack_require__(1);
93 |
94 | var _rules2 = _interopRequireDefault(_rules);
95 |
96 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
97 |
98 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
99 |
100 | var requiredFn = _rules2.default.required.rule;
101 |
102 | /**
103 | * 环境检测
104 | */
105 | var isWx = typeof wx !== 'undefined' && !!wx.showToast; // 微信小程序
106 | var isMy = typeof my !== 'undefined' && !!my.showToast; // 支付宝小程序
107 | var isSwan = typeof swan !== 'undefined' && !!swan.showToast; // 百度智能小程序
108 | var isTt = typeof tt !== 'undefined' && !!tt.showToast; // 字节跳动小程序
109 | var isBrowser = typeof window !== 'undefined' && !!window.alert; // 普通浏览器
110 |
111 | var objString = Object.prototype.toString;
112 |
113 | var isArray = Array.isArray || function (v) {
114 | return objString.call(v) === '[object Array]';
115 | };
116 | var isFunction = function isFunction(v) {
117 | return objString.call(v) === '[object Function]';
118 | };
119 | var isRegExp = function isRegExp(v) {
120 | return objString.call(v) === '[object RegExp]';
121 | };
122 |
123 | var WeValidator = function () {
124 |
125 | /**
126 | * 默认参数
127 | * @param {object} options
128 | * @param {object} [options.rules] 验证字段的规则
129 | * @param {object} [options.messages] 验证字段错误的提示信息
130 | * @param {function} [options.onMessage] 错误信息显示方式
131 | * @param {boolean} [options.multiCheck] 是否同时校验多个字段
132 | */
133 | function WeValidator() {
134 | var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
135 |
136 | _classCallCheck(this, WeValidator);
137 |
138 | this.options = options;
139 |
140 | this.required = requiredFn;
141 | this._checkAllRules();
142 | }
143 |
144 | /**
145 | * 所有校验规则
146 | */
147 |
148 |
149 | /**
150 | * 动态添加验证规则
151 | * @param {string} ruleName 规则名称
152 | * @param {object} ruleOption 规则配置
153 | * @param {string} [ruleOption.message] 默认错误信息文字
154 | * @param {regexp|function} [ruleOption.rule] 验证规则
155 | */
156 |
157 |
158 | /**
159 | * 验证单个字段数据
160 | * @param {string} ruleName 规则名称
161 | * @param {string} value 要验证的值
162 | * @param {any} param 传递的验证参数
163 | * @param {boolean} skip 未填跳过校验,仅供内部使用
164 | */
165 |
166 |
167 | _createClass(WeValidator, [{
168 | key: '_showErrorMessage',
169 |
170 |
171 | /**
172 | * 显示错误信息
173 | * @param {object} params 错误信息
174 | * @param {function} onMessage 自定义提示函数
175 | */
176 | value: function _showErrorMessage(params, onMessage) {
177 | // validatorInstance.checkData(data, onMessage)
178 | if (isFunction(onMessage)) {
179 | return onMessage(params);
180 | }
181 |
182 | // 参数形式 new WeValidator({ onMessage })
183 | if (isFunction(this.options.onMessage)) {
184 | return this.options.onMessage(params);
185 | }
186 |
187 | // 全局配置 WeValidator.onMessage
188 | if (isFunction(WeValidator.onMessage)) {
189 | return WeValidator.onMessage(params);
190 | }
191 |
192 | // 微信小程序
193 | if (isWx) {
194 | return wx.showToast({
195 | title: params.msg,
196 | icon: 'none'
197 | });
198 | }
199 |
200 | // 支付宝小程序
201 | if (isMy) {
202 | return my.showToast({
203 | content: params.msg,
204 | type: 'none'
205 | });
206 | }
207 |
208 | // 百度小程序
209 | if (isSwan) {
210 | return swan.showToast({
211 | title: params.msg,
212 | icon: 'none'
213 | });
214 | }
215 |
216 | // 字节跳动小程序
217 | if (isTt) {
218 | return tt.showToast({
219 | title: params.msg,
220 | icon: 'none'
221 | });
222 | }
223 |
224 | // 浏览器端
225 | if (isBrowser) alert(params.msg);
226 | }
227 |
228 | /**
229 | * 获取错误信息内容
230 | * @param {string} ruleName 规则名称
231 | * @param {string} attr 字段名称
232 | * @param {any} param 规则参数
233 | */
234 |
235 | }, {
236 | key: '_getErrorMessage',
237 | value: function _getErrorMessage(ruleName, attr, param) {
238 | var messages = this.options.messages;
239 | var defaultMessage = WeValidator.RULES[ruleName].message;
240 |
241 | if (messages && messages.hasOwnProperty(attr) && messages[attr][ruleName]) {
242 | defaultMessage = messages[attr][ruleName];
243 | }
244 |
245 | if (defaultMessage) {
246 | defaultMessage = defaultMessage.replace(/\{(\d)\}/g, function ($0, $1) {
247 | if (isArray(param)) {
248 | return param[$1];
249 | } else {
250 | return param;
251 | }
252 | });
253 |
254 | return defaultMessage;
255 | }
256 | }
257 |
258 | /**
259 | * 验证配置规则是否无效
260 | * @param {string} ruleName 规则名称
261 | * @param {string} attr 字段名称
262 | */
263 |
264 | }, {
265 | key: '_isRuleInvalid',
266 | value: function _isRuleInvalid(ruleName, attr) {
267 | if (!WeValidator.RULES.hasOwnProperty(ruleName)) {
268 | console.warn && console.warn('\u6CA1\u6709\u6B64\u9A8C\u8BC1\u89C4\u5219\uFF1A' + ruleName + '\uFF0C\u5B57\u6BB5\uFF1A' + attr);
269 | return true;
270 | }
271 | }
272 |
273 | /**
274 | * 验证所有配置规则是否正确
275 | */
276 |
277 | }, {
278 | key: '_checkAllRules',
279 | value: function _checkAllRules() {
280 | var _rules_ = this.options.rules;
281 |
282 | // 遍历字段
283 | for (var attr in _rules_) {
284 | // 遍历验证规则
285 | for (var ruleName in _rules_[attr]) {
286 | if (this._isRuleInvalid(ruleName, attr)) continue;
287 | }
288 | }
289 | }
290 |
291 | /**
292 | * 校验数据,会验证所有配置的字段规则
293 | * @param {object} data 验证的数据对象
294 | * @param {function} onMessage 自定义错误信息提示
295 | * @param {boolean} showMessage 是否显示提示信息,默认显示(内部使用)
296 | * @param {object} fieldMap 校验的字段,默认校验所有字段(内部使用)
297 | */
298 |
299 | }, {
300 | key: 'checkData',
301 | value: function checkData(data, onMessage) {
302 | var showMessage = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
303 | var fieldMap = arguments[3];
304 |
305 | var _rules_ = this.options.rules;
306 | var multiCheck = this.options.multiCheck;
307 | var hasError = false;
308 | var errorData = {};
309 |
310 | this.data = data;
311 |
312 | // 遍历字段
313 | for (var attr in _rules_) {
314 | if (fieldMap && !fieldMap.hasOwnProperty(attr)) continue;
315 |
316 | // 遍历验证规则
317 | for (var ruleName in _rules_[attr]) {
318 | if (this._isRuleInvalid(ruleName, attr)) continue;
319 |
320 | if (fieldMap) {
321 | var res = fieldMap[attr];
322 | if (isArray(res) && res.indexOf(ruleName) === -1) continue;
323 | }
324 |
325 | var ruleParam = _rules_[attr][ruleName];
326 | var value = '';
327 |
328 | if (data.hasOwnProperty(attr)) {
329 | value = data[attr];
330 | }
331 |
332 | if (isFunction(ruleParam)) {
333 | ruleParam = ruleParam.call(this, value);
334 | }
335 |
336 | var isFieldValid = WeValidator.checkValue.call(this, ruleName, value, ruleParam, true);
337 |
338 | // 验证不通过
339 | if (!isFieldValid) {
340 | hasError = true;
341 |
342 | var msg = this._getErrorMessage(ruleName, attr, ruleParam);
343 | var errorParam = null;
344 |
345 | if (showMessage && msg) {
346 | errorParam = {
347 | name: attr,
348 | value: value,
349 | param: ruleParam,
350 | rule: ruleName,
351 | msg: msg
352 | };
353 | errorData[attr] = errorParam;
354 | }
355 |
356 | if (!multiCheck) {
357 | if (errorParam) {
358 | this._showErrorMessage(errorParam, onMessage);
359 | }
360 | return false;
361 | }
362 | }
363 | }
364 | }
365 |
366 | if (hasError) {
367 | if (multiCheck && showMessage) {
368 | this._showErrorMessage(errorData, onMessage);
369 | }
370 | return false;
371 | }
372 |
373 | return true;
374 | }
375 |
376 | /**
377 | * 校验数据,只校验对应的字段规则
378 | * @param {object} data 验证的数据对象
379 | * @param {array} fields 校验的字段
380 | * @param {function} onMessage 自定义错误信息提示
381 | * @param {boolean} showMessage 是否显示提示信息,默认显示(内部使用)
382 | */
383 |
384 | }, {
385 | key: 'checkFields',
386 | value: function checkFields(data, fields, onMessage) {
387 | var showMessage = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true;
388 |
389 | if (!isArray(fields)) throw new Error('第二个参数须为数组');
390 |
391 | // fields: [ '[field]:[rule]' ]
392 | // fields: [ 'phoneNo' ] => { phoneNo: true }
393 | // fields: [ 'phoneNo:required' ] => { phoneNo: ['required'] }
394 | // fields: [ 'phoneNo:required,mobile' ] => { phoneNo: ['required', 'mobile'] }
395 | var fieldMap = {};
396 |
397 | fields.forEach(function (item) {
398 | var arr = item.split(':');
399 | var field = arr[0];
400 | var rules = arr[1];
401 |
402 | if (rules) {
403 | // 只校验特定规则
404 | rules = rules.split(',');
405 | fieldMap[field] = rules;
406 | } else {
407 | // 校验 field 字段的所有规则
408 | fieldMap[field] = true;
409 | }
410 | });
411 |
412 | return this.checkData(data, onMessage, showMessage, fieldMap);
413 | }
414 |
415 | /**
416 | * 校验数据,不会提示错误信息
417 | * @param {object} data 验证的数据对象
418 | * @param {array} fields 校验的字段。如果有,只校验对应的字段规则,默认校验所有配置的字段规则
419 | */
420 |
421 | }, {
422 | key: 'isValid',
423 | value: function isValid(data, fields) {
424 | if (isArray(fields)) {
425 | return this.checkFields(data, fields, null, false);
426 | } else {
427 | return this.checkData(data, null, false);
428 | }
429 | }
430 |
431 | /**
432 | * 动态添加字段校验
433 | * @param {object} options 配置参数
434 | * @param {object} [options.rules] 规则
435 | * @param {object} [options.messages] 提示消息
436 | */
437 |
438 | }, {
439 | key: 'addRules',
440 | value: function addRules() {
441 | var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
442 |
443 | Object.assign(this.options.rules, options.rules || {});
444 | Object.assign(this.options.messages, options.messages || {});
445 |
446 | this._checkAllRules();
447 | }
448 |
449 | /**
450 | * 动态移除字段校验
451 | * @param {array} fields 要删除校验的字段
452 | */
453 |
454 | }, {
455 | key: 'removeRules',
456 | value: function removeRules(fields) {
457 | if (!isArray(fields)) throw new Error('参数须为数组');
458 |
459 | for (var i = 0; i < fields.length; i++) {
460 | var key = fields[i];
461 |
462 | delete this.options.rules[key];
463 | }
464 | }
465 | }]);
466 |
467 | return WeValidator;
468 | }();
469 |
470 | WeValidator.RULES = {};
471 |
472 | WeValidator.addRule = function (ruleName, ruleOption) {
473 | WeValidator.RULES[ruleName] = ruleOption;
474 | };
475 |
476 | WeValidator.checkValue = function (ruleName, value, param, skip) {
477 | var rule = WeValidator.RULES[ruleName].rule;
478 |
479 | if (isRegExp(rule)) {
480 | if (skip) {
481 | return !requiredFn(value) || rule.test(value);
482 | } else {
483 | return rule.test(value);
484 | }
485 | }
486 |
487 | if (isFunction(rule)) {
488 | if (ruleName === 'required') {
489 | return param && requiredFn(value);
490 | } else {
491 | if (skip) {
492 | return !requiredFn(value) || rule.call(this, value, param);
493 | } else {
494 | return rule.call(this, value, param);
495 | }
496 | }
497 | }
498 | };
499 |
500 | WeValidator.RULES = _rules2.default;
501 | WeValidator.required = requiredFn;
502 |
503 | module.exports = WeValidator;
504 |
505 | /***/ }),
506 | /* 1 */
507 | /***/ (function(module, exports, __webpack_require__) {
508 |
509 | "use strict";
510 |
511 |
512 | module.exports = {
513 | /**
514 | * 必填
515 | */
516 | required: {
517 | message: '此字段必填',
518 | rule: function rule(value) {
519 | if (typeof value === 'number') {
520 | value = value.toString();
521 | } else if (typeof value === 'boolean') {
522 | return true;
523 | }
524 | return !!(value && value.length > 0);
525 | }
526 | },
527 | /**
528 | * 正则通用
529 | */
530 | pattern: {
531 | message: '不符合此验证规则',
532 | rule: function rule(value, param) {
533 | return param.test(value);
534 | }
535 | },
536 | /**
537 | * 电子邮件
538 | */
539 | email: {
540 | message: '请输入有效的电子邮件地址',
541 | rule: /^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/
542 | },
543 | /**
544 | * 手机号码
545 | */
546 | mobile: {
547 | message: '请输入 11 位的手机号码',
548 | rule: /^1[3456789]\d{9}$/
549 | },
550 | /**
551 | * 座机号,例如:010-1234567、0551-1234567
552 | */
553 | tel: {
554 | message: '请输入座机号',
555 | rule: /^(\d{3,4}-)?\d{7,8}$/
556 | },
557 | /**
558 | * URL网址
559 | */
560 | url: {
561 | message: '请输入有效的网址',
562 | rule: /^(?:(?:(?:https?|ftp):)?\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})).?)(?::\d{2,5})?(?:[/?#]\S*)?$/i
563 | },
564 | /**
565 | * 身份证号
566 | */
567 | idcard: {
568 | message: '请输入 18 位的有效身份证',
569 | rule: /^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$/
570 | },
571 | /**
572 | * 字段值相同校验(例如:密码和确认密码)
573 | */
574 | equalTo: {
575 | message: '输入值必须和字段 {0} 相同',
576 | rule: function rule(value, param) {
577 | return value === this.data[param];
578 | }
579 | },
580 | /**
581 | * 字段值不相同校验,与 equalTo 相反
582 | */
583 | notEqualTo: {
584 | message: '输入值不能和字段 {0} 相同',
585 | rule: function rule(value, param) {
586 | return value !== this.data[param];
587 | }
588 | },
589 | /**
590 | * 是否包含某字符
591 | */
592 | contains: {
593 | message: '输入值必须包含 {0}',
594 | rule: function rule(value, param) {
595 | return value.indexOf(param) > -1;
596 | }
597 | },
598 | /**
599 | * 不能包含某字符
600 | */
601 | notContains: {
602 | message: '输入值不能包含 {0}',
603 | rule: function rule(value, param) {
604 | return value.indexOf(param) === -1;
605 | }
606 | },
607 | /**
608 | * 长度为多少的字符串
609 | */
610 | length: {
611 | message: '请输入 {0} 个字符',
612 | rule: function rule(value, param) {
613 | return value.length == param;
614 | }
615 | },
616 | /**
617 | * 最少多长的字符串
618 | */
619 | minlength: {
620 | message: '最少要输入 {0} 个字符',
621 | rule: function rule(value, param) {
622 | return value.length >= param;
623 | }
624 | },
625 | /**
626 | * 最多多长的字符串
627 | */
628 | maxlength: {
629 | message: '最多可以输入 {0} 个字符',
630 | rule: function rule(value, param) {
631 | return value.length <= param;
632 | }
633 | },
634 | /**
635 | * 某个范围长度的字符串
636 | */
637 | rangelength: {
638 | message: '请输入长度在 {0} 到 {1} 之间的字符',
639 | rule: function rule(value, param) {
640 | return value.length >= param[0] && value.length <= param[1];
641 | }
642 | },
643 | /**
644 | * 数字
645 | */
646 | number: {
647 | message: '请输入有效的数字',
648 | rule: /^(?:-?\d+|-?\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/
649 | },
650 | /**
651 | * 正整数数字
652 | */
653 | digits: {
654 | message: '只能输入正整数数字',
655 | rule: /^\d+$/
656 | },
657 | /**
658 | * 正整数或负整数数字
659 | */
660 | integer: {
661 | message: '只能输入整数数字',
662 | rule: /^-?\d+$/
663 | },
664 | /**
665 | * 大于多少的数字/字段值
666 | */
667 | min: {
668 | message: '请输入大于 {0} 的数字',
669 | rule: function rule(value, param) {
670 | if (typeof param === 'string') param = this.data[param];
671 |
672 | return value >= param;
673 | }
674 | },
675 | /**
676 | * 小于多少的数字/字段值
677 | */
678 | max: {
679 | message: '请输入小于 {0} 的数字',
680 | rule: function rule(value, param) {
681 | if (typeof param === 'string') param = this.data[param];
682 |
683 | return value <= param;
684 | }
685 | },
686 | /**
687 | * 大于且小于多少的数字
688 | */
689 | range: {
690 | message: '请输入大于 {0} 且小于 {1} 的数字',
691 | rule: function rule(value, param) {
692 | return value >= param[0] && value <= param[1];
693 | }
694 | },
695 | /**
696 | * 中文字符
697 | */
698 | chinese: {
699 | message: '只能输入中文字符',
700 | rule: /^[\u4e00-\u9fa5]+$/
701 | },
702 | /**
703 | * 最少多少个中文字符
704 | */
705 | minChinese: {
706 | message: '最少输入 {0} 个中文字符',
707 | rule: function rule(value, param) {
708 | return new RegExp('^[\u4E00-\u9FA5]{' + param + ',}$').test(value);
709 | }
710 | },
711 | /**
712 | * 最多多少个中文字符
713 | */
714 | maxChinese: {
715 | message: '最多输入 {0} 个中文字符',
716 | rule: function rule(value, param) {
717 | return new RegExp('^[\u4E00-\u9FA5]{1,' + param + '}$').test(value);
718 | }
719 | },
720 | /**
721 | * 大于且小于多少个中文字符
722 | */
723 | rangeChinese: {
724 | message: '只能输入 {0} 到 {1} 个中文字符',
725 | rule: function rule(value, param) {
726 | return new RegExp('^[\u4E00-\u9FA5]{' + param[0] + ',' + param[1] + '}$').test(value);
727 | }
728 | },
729 | /**
730 | * 日期
731 | */
732 | date: {
733 | message: '请输入有效的日期',
734 | rule: function rule(value) {
735 | return !/Invalid|NaN/.test(new Date(value).toString());
736 | }
737 | },
738 | /**
739 | * 日期(ISO标准格式)例如:2019-09-19,2019/09/19
740 | */
741 | dateISO: {
742 | message: '请输入有效的日期(ISO 标准格式)',
743 | rule: /^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$/
744 | },
745 | /**
746 | * ipv4地址
747 | */
748 | ipv4: {
749 | message: '请输入有效的 IPv4 地址',
750 | rule: /^(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)$/i
751 | },
752 | /**
753 | * ipv6地址
754 | */
755 | ipv6: {
756 | message: '请输入有效的 IPv6 地址',
757 | rule: /^((([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}:[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){5}:([0-9A-Fa-f]{1,4}:)?[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){4}:([0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){3}:([0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){2}:([0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(([0-9A-Fa-f]{1,4}:){0,5}:((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(::([0-9A-Fa-f]{1,4}:){0,5}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|([0-9A-Fa-f]{1,4}::([0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})|(::([0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){1,7}:))$/i
758 | }
759 | };
760 |
761 | /***/ })
762 | /******/ ]);
763 | });
--------------------------------------------------------------------------------
/example/wechat/js/we-validator.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * we-validator
3 | * version: 2.1.17
4 | * address: https://github.com/ChanceYu/we-validator#readme
5 | * author: ChanceYu
6 | * license: MIT
7 | */
8 | (function webpackUniversalModuleDefinition(root, factory) {
9 | if(typeof exports === 'object' && typeof module === 'object')
10 | module.exports = factory();
11 | else if(typeof define === 'function' && define.amd)
12 | define("WeValidator", [], factory);
13 | else if(typeof exports === 'object')
14 | exports["WeValidator"] = factory();
15 | else
16 | root["WeValidator"] = factory();
17 | })(typeof self !== 'undefined' ? self : this, function() {
18 | return /******/ (function(modules) { // webpackBootstrap
19 | /******/ // The module cache
20 | /******/ var installedModules = {};
21 | /******/
22 | /******/ // The require function
23 | /******/ function __webpack_require__(moduleId) {
24 | /******/
25 | /******/ // Check if module is in cache
26 | /******/ if(installedModules[moduleId]) {
27 | /******/ return installedModules[moduleId].exports;
28 | /******/ }
29 | /******/ // Create a new module (and put it into the cache)
30 | /******/ var module = installedModules[moduleId] = {
31 | /******/ i: moduleId,
32 | /******/ l: false,
33 | /******/ exports: {}
34 | /******/ };
35 | /******/
36 | /******/ // Execute the module function
37 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
38 | /******/
39 | /******/ // Flag the module as loaded
40 | /******/ module.l = true;
41 | /******/
42 | /******/ // Return the exports of the module
43 | /******/ return module.exports;
44 | /******/ }
45 | /******/
46 | /******/
47 | /******/ // expose the modules object (__webpack_modules__)
48 | /******/ __webpack_require__.m = modules;
49 | /******/
50 | /******/ // expose the module cache
51 | /******/ __webpack_require__.c = installedModules;
52 | /******/
53 | /******/ // define getter function for harmony exports
54 | /******/ __webpack_require__.d = function(exports, name, getter) {
55 | /******/ if(!__webpack_require__.o(exports, name)) {
56 | /******/ Object.defineProperty(exports, name, {
57 | /******/ configurable: false,
58 | /******/ enumerable: true,
59 | /******/ get: getter
60 | /******/ });
61 | /******/ }
62 | /******/ };
63 | /******/
64 | /******/ // getDefaultExport function for compatibility with non-harmony modules
65 | /******/ __webpack_require__.n = function(module) {
66 | /******/ var getter = module && module.__esModule ?
67 | /******/ function getDefault() { return module['default']; } :
68 | /******/ function getModuleExports() { return module; };
69 | /******/ __webpack_require__.d(getter, 'a', getter);
70 | /******/ return getter;
71 | /******/ };
72 | /******/
73 | /******/ // Object.prototype.hasOwnProperty.call
74 | /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
75 | /******/
76 | /******/ // __webpack_public_path__
77 | /******/ __webpack_require__.p = "";
78 | /******/
79 | /******/ // Load entry module and return exports
80 | /******/ return __webpack_require__(__webpack_require__.s = 0);
81 | /******/ })
82 | /************************************************************************/
83 | /******/ ([
84 | /* 0 */
85 | /***/ (function(module, exports, __webpack_require__) {
86 |
87 | "use strict";
88 |
89 |
90 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
91 |
92 | var _rules = __webpack_require__(1);
93 |
94 | var _rules2 = _interopRequireDefault(_rules);
95 |
96 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
97 |
98 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
99 |
100 | var requiredFn = _rules2.default.required.rule;
101 |
102 | /**
103 | * 环境检测
104 | */
105 | var isWx = typeof wx !== 'undefined' && !!wx.showToast; // 微信小程序
106 | var isMy = typeof my !== 'undefined' && !!my.showToast; // 支付宝小程序
107 | var isSwan = typeof swan !== 'undefined' && !!swan.showToast; // 百度智能小程序
108 | var isTt = typeof tt !== 'undefined' && !!tt.showToast; // 字节跳动小程序
109 | var isBrowser = typeof window !== 'undefined' && !!window.alert; // 普通浏览器
110 |
111 | var objString = Object.prototype.toString;
112 |
113 | var isArray = Array.isArray || function (v) {
114 | return objString.call(v) === '[object Array]';
115 | };
116 | var isFunction = function isFunction(v) {
117 | return objString.call(v) === '[object Function]';
118 | };
119 | var isRegExp = function isRegExp(v) {
120 | return objString.call(v) === '[object RegExp]';
121 | };
122 |
123 | var WeValidator = function () {
124 |
125 | /**
126 | * 默认参数
127 | * @param {object} options
128 | * @param {object} [options.rules] 验证字段的规则
129 | * @param {object} [options.messages] 验证字段错误的提示信息
130 | * @param {function} [options.onMessage] 错误信息显示方式
131 | * @param {boolean} [options.multiCheck] 是否同时校验多个字段
132 | */
133 | function WeValidator() {
134 | var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
135 |
136 | _classCallCheck(this, WeValidator);
137 |
138 | this.options = options;
139 |
140 | this.required = requiredFn;
141 | this._checkAllRules();
142 | }
143 |
144 | /**
145 | * 所有校验规则
146 | */
147 |
148 |
149 | /**
150 | * 动态添加验证规则
151 | * @param {string} ruleName 规则名称
152 | * @param {object} ruleOption 规则配置
153 | * @param {string} [ruleOption.message] 默认错误信息文字
154 | * @param {regexp|function} [ruleOption.rule] 验证规则
155 | */
156 |
157 |
158 | /**
159 | * 验证单个字段数据
160 | * @param {string} ruleName 规则名称
161 | * @param {string} value 要验证的值
162 | * @param {any} param 传递的验证参数
163 | * @param {boolean} skip 未填跳过校验,仅供内部使用
164 | */
165 |
166 |
167 | _createClass(WeValidator, [{
168 | key: '_showErrorMessage',
169 |
170 |
171 | /**
172 | * 显示错误信息
173 | * @param {object} params 错误信息
174 | * @param {function} onMessage 自定义提示函数
175 | */
176 | value: function _showErrorMessage(params, onMessage) {
177 | // validatorInstance.checkData(data, onMessage)
178 | if (isFunction(onMessage)) {
179 | return onMessage(params);
180 | }
181 |
182 | // 参数形式 new WeValidator({ onMessage })
183 | if (isFunction(this.options.onMessage)) {
184 | return this.options.onMessage(params);
185 | }
186 |
187 | // 全局配置 WeValidator.onMessage
188 | if (isFunction(WeValidator.onMessage)) {
189 | return WeValidator.onMessage(params);
190 | }
191 |
192 | // 微信小程序
193 | if (isWx) {
194 | return wx.showToast({
195 | title: params.msg,
196 | icon: 'none'
197 | });
198 | }
199 |
200 | // 支付宝小程序
201 | if (isMy) {
202 | return my.showToast({
203 | content: params.msg,
204 | type: 'none'
205 | });
206 | }
207 |
208 | // 百度小程序
209 | if (isSwan) {
210 | return swan.showToast({
211 | title: params.msg,
212 | icon: 'none'
213 | });
214 | }
215 |
216 | // 字节跳动小程序
217 | if (isTt) {
218 | return tt.showToast({
219 | title: params.msg,
220 | icon: 'none'
221 | });
222 | }
223 |
224 | // 浏览器端
225 | if (isBrowser) alert(params.msg);
226 | }
227 |
228 | /**
229 | * 获取错误信息内容
230 | * @param {string} ruleName 规则名称
231 | * @param {string} attr 字段名称
232 | * @param {any} param 规则参数
233 | */
234 |
235 | }, {
236 | key: '_getErrorMessage',
237 | value: function _getErrorMessage(ruleName, attr, param) {
238 | var messages = this.options.messages;
239 | var defaultMessage = WeValidator.RULES[ruleName].message;
240 |
241 | if (messages && messages.hasOwnProperty(attr) && messages[attr][ruleName]) {
242 | defaultMessage = messages[attr][ruleName];
243 | }
244 |
245 | if (defaultMessage) {
246 | defaultMessage = defaultMessage.replace(/\{(\d)\}/g, function ($0, $1) {
247 | if (isArray(param)) {
248 | return param[$1];
249 | } else {
250 | return param;
251 | }
252 | });
253 |
254 | return defaultMessage;
255 | }
256 | }
257 |
258 | /**
259 | * 验证配置规则是否无效
260 | * @param {string} ruleName 规则名称
261 | * @param {string} attr 字段名称
262 | */
263 |
264 | }, {
265 | key: '_isRuleInvalid',
266 | value: function _isRuleInvalid(ruleName, attr) {
267 | if (!WeValidator.RULES.hasOwnProperty(ruleName)) {
268 | console.warn && console.warn('\u6CA1\u6709\u6B64\u9A8C\u8BC1\u89C4\u5219\uFF1A' + ruleName + '\uFF0C\u5B57\u6BB5\uFF1A' + attr);
269 | return true;
270 | }
271 | }
272 |
273 | /**
274 | * 验证所有配置规则是否正确
275 | */
276 |
277 | }, {
278 | key: '_checkAllRules',
279 | value: function _checkAllRules() {
280 | var _rules_ = this.options.rules;
281 |
282 | // 遍历字段
283 | for (var attr in _rules_) {
284 | // 遍历验证规则
285 | for (var ruleName in _rules_[attr]) {
286 | if (this._isRuleInvalid(ruleName, attr)) continue;
287 | }
288 | }
289 | }
290 |
291 | /**
292 | * 校验数据,会验证所有配置的字段规则
293 | * @param {object} data 验证的数据对象
294 | * @param {function} onMessage 自定义错误信息提示
295 | * @param {boolean} showMessage 是否显示提示信息,默认显示(内部使用)
296 | * @param {object} fieldMap 校验的字段,默认校验所有字段(内部使用)
297 | */
298 |
299 | }, {
300 | key: 'checkData',
301 | value: function checkData(data, onMessage) {
302 | var showMessage = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
303 | var fieldMap = arguments[3];
304 |
305 | var _rules_ = this.options.rules;
306 | var multiCheck = this.options.multiCheck;
307 | var hasError = false;
308 | var errorData = {};
309 |
310 | this.data = data;
311 |
312 | // 遍历字段
313 | for (var attr in _rules_) {
314 | if (fieldMap && !fieldMap.hasOwnProperty(attr)) continue;
315 |
316 | // 遍历验证规则
317 | for (var ruleName in _rules_[attr]) {
318 | if (this._isRuleInvalid(ruleName, attr)) continue;
319 |
320 | if (fieldMap) {
321 | var res = fieldMap[attr];
322 | if (isArray(res) && res.indexOf(ruleName) === -1) continue;
323 | }
324 |
325 | var ruleParam = _rules_[attr][ruleName];
326 | var value = '';
327 |
328 | if (data.hasOwnProperty(attr)) {
329 | value = data[attr];
330 | }
331 |
332 | if (isFunction(ruleParam)) {
333 | ruleParam = ruleParam.call(this, value);
334 | }
335 |
336 | var isFieldValid = WeValidator.checkValue.call(this, ruleName, value, ruleParam, true);
337 |
338 | // 验证不通过
339 | if (!isFieldValid) {
340 | hasError = true;
341 |
342 | var msg = this._getErrorMessage(ruleName, attr, ruleParam);
343 | var errorParam = null;
344 |
345 | if (showMessage && msg) {
346 | errorParam = {
347 | name: attr,
348 | value: value,
349 | param: ruleParam,
350 | rule: ruleName,
351 | msg: msg
352 | };
353 | errorData[attr] = errorParam;
354 | }
355 |
356 | if (!multiCheck) {
357 | if (errorParam) {
358 | this._showErrorMessage(errorParam, onMessage);
359 | }
360 | return false;
361 | }
362 | }
363 | }
364 | }
365 |
366 | if (hasError) {
367 | if (multiCheck && showMessage) {
368 | this._showErrorMessage(errorData, onMessage);
369 | }
370 | return false;
371 | }
372 |
373 | return true;
374 | }
375 |
376 | /**
377 | * 校验数据,只校验对应的字段规则
378 | * @param {object} data 验证的数据对象
379 | * @param {array} fields 校验的字段
380 | * @param {function} onMessage 自定义错误信息提示
381 | * @param {boolean} showMessage 是否显示提示信息,默认显示(内部使用)
382 | */
383 |
384 | }, {
385 | key: 'checkFields',
386 | value: function checkFields(data, fields, onMessage) {
387 | var showMessage = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true;
388 |
389 | if (!isArray(fields)) throw new Error('第二个参数须为数组');
390 |
391 | // fields: [ '[field]:[rule]' ]
392 | // fields: [ 'phoneNo' ] => { phoneNo: true }
393 | // fields: [ 'phoneNo:required' ] => { phoneNo: ['required'] }
394 | // fields: [ 'phoneNo:required,mobile' ] => { phoneNo: ['required', 'mobile'] }
395 | var fieldMap = {};
396 |
397 | fields.forEach(function (item) {
398 | var arr = item.split(':');
399 | var field = arr[0];
400 | var rules = arr[1];
401 |
402 | if (rules) {
403 | // 只校验特定规则
404 | rules = rules.split(',');
405 | fieldMap[field] = rules;
406 | } else {
407 | // 校验 field 字段的所有规则
408 | fieldMap[field] = true;
409 | }
410 | });
411 |
412 | return this.checkData(data, onMessage, showMessage, fieldMap);
413 | }
414 |
415 | /**
416 | * 校验数据,不会提示错误信息
417 | * @param {object} data 验证的数据对象
418 | * @param {array} fields 校验的字段。如果有,只校验对应的字段规则,默认校验所有配置的字段规则
419 | */
420 |
421 | }, {
422 | key: 'isValid',
423 | value: function isValid(data, fields) {
424 | if (isArray(fields)) {
425 | return this.checkFields(data, fields, null, false);
426 | } else {
427 | return this.checkData(data, null, false);
428 | }
429 | }
430 |
431 | /**
432 | * 动态添加字段校验
433 | * @param {object} options 配置参数
434 | * @param {object} [options.rules] 规则
435 | * @param {object} [options.messages] 提示消息
436 | */
437 |
438 | }, {
439 | key: 'addRules',
440 | value: function addRules() {
441 | var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
442 |
443 | Object.assign(this.options.rules, options.rules || {});
444 | Object.assign(this.options.messages, options.messages || {});
445 |
446 | this._checkAllRules();
447 | }
448 |
449 | /**
450 | * 动态移除字段校验
451 | * @param {array} fields 要删除校验的字段
452 | */
453 |
454 | }, {
455 | key: 'removeRules',
456 | value: function removeRules(fields) {
457 | if (!isArray(fields)) throw new Error('参数须为数组');
458 |
459 | for (var i = 0; i < fields.length; i++) {
460 | var key = fields[i];
461 |
462 | delete this.options.rules[key];
463 | }
464 | }
465 | }]);
466 |
467 | return WeValidator;
468 | }();
469 |
470 | WeValidator.RULES = {};
471 |
472 | WeValidator.addRule = function (ruleName, ruleOption) {
473 | WeValidator.RULES[ruleName] = ruleOption;
474 | };
475 |
476 | WeValidator.checkValue = function (ruleName, value, param, skip) {
477 | var rule = WeValidator.RULES[ruleName].rule;
478 |
479 | if (isRegExp(rule)) {
480 | if (skip) {
481 | return !requiredFn(value) || rule.test(value);
482 | } else {
483 | return rule.test(value);
484 | }
485 | }
486 |
487 | if (isFunction(rule)) {
488 | if (ruleName === 'required') {
489 | return param && requiredFn(value);
490 | } else {
491 | if (skip) {
492 | return !requiredFn(value) || rule.call(this, value, param);
493 | } else {
494 | return rule.call(this, value, param);
495 | }
496 | }
497 | }
498 | };
499 |
500 | WeValidator.RULES = _rules2.default;
501 | WeValidator.required = requiredFn;
502 |
503 | module.exports = WeValidator;
504 |
505 | /***/ }),
506 | /* 1 */
507 | /***/ (function(module, exports, __webpack_require__) {
508 |
509 | "use strict";
510 |
511 |
512 | module.exports = {
513 | /**
514 | * 必填
515 | */
516 | required: {
517 | message: '此字段必填',
518 | rule: function rule(value) {
519 | if (typeof value === 'number') {
520 | value = value.toString();
521 | } else if (typeof value === 'boolean') {
522 | return true;
523 | }
524 | return !!(value && value.length > 0);
525 | }
526 | },
527 | /**
528 | * 正则通用
529 | */
530 | pattern: {
531 | message: '不符合此验证规则',
532 | rule: function rule(value, param) {
533 | return param.test(value);
534 | }
535 | },
536 | /**
537 | * 电子邮件
538 | */
539 | email: {
540 | message: '请输入有效的电子邮件地址',
541 | rule: /^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/
542 | },
543 | /**
544 | * 手机号码
545 | */
546 | mobile: {
547 | message: '请输入 11 位的手机号码',
548 | rule: /^1[3456789]\d{9}$/
549 | },
550 | /**
551 | * 座机号,例如:010-1234567、0551-1234567
552 | */
553 | tel: {
554 | message: '请输入座机号',
555 | rule: /^(\d{3,4}-)?\d{7,8}$/
556 | },
557 | /**
558 | * URL网址
559 | */
560 | url: {
561 | message: '请输入有效的网址',
562 | rule: /^(?:(?:(?:https?|ftp):)?\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})).?)(?::\d{2,5})?(?:[/?#]\S*)?$/i
563 | },
564 | /**
565 | * 身份证号
566 | */
567 | idcard: {
568 | message: '请输入 18 位的有效身份证',
569 | rule: /^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$/
570 | },
571 | /**
572 | * 字段值相同校验(例如:密码和确认密码)
573 | */
574 | equalTo: {
575 | message: '输入值必须和字段 {0} 相同',
576 | rule: function rule(value, param) {
577 | return value === this.data[param];
578 | }
579 | },
580 | /**
581 | * 字段值不相同校验,与 equalTo 相反
582 | */
583 | notEqualTo: {
584 | message: '输入值不能和字段 {0} 相同',
585 | rule: function rule(value, param) {
586 | return value !== this.data[param];
587 | }
588 | },
589 | /**
590 | * 是否包含某字符
591 | */
592 | contains: {
593 | message: '输入值必须包含 {0}',
594 | rule: function rule(value, param) {
595 | return value.indexOf(param) > -1;
596 | }
597 | },
598 | /**
599 | * 不能包含某字符
600 | */
601 | notContains: {
602 | message: '输入值不能包含 {0}',
603 | rule: function rule(value, param) {
604 | return value.indexOf(param) === -1;
605 | }
606 | },
607 | /**
608 | * 长度为多少的字符串
609 | */
610 | length: {
611 | message: '请输入 {0} 个字符',
612 | rule: function rule(value, param) {
613 | return value.length == param;
614 | }
615 | },
616 | /**
617 | * 最少多长的字符串
618 | */
619 | minlength: {
620 | message: '最少要输入 {0} 个字符',
621 | rule: function rule(value, param) {
622 | return value.length >= param;
623 | }
624 | },
625 | /**
626 | * 最多多长的字符串
627 | */
628 | maxlength: {
629 | message: '最多可以输入 {0} 个字符',
630 | rule: function rule(value, param) {
631 | return value.length <= param;
632 | }
633 | },
634 | /**
635 | * 某个范围长度的字符串
636 | */
637 | rangelength: {
638 | message: '请输入长度在 {0} 到 {1} 之间的字符',
639 | rule: function rule(value, param) {
640 | return value.length >= param[0] && value.length <= param[1];
641 | }
642 | },
643 | /**
644 | * 数字
645 | */
646 | number: {
647 | message: '请输入有效的数字',
648 | rule: /^(?:-?\d+|-?\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/
649 | },
650 | /**
651 | * 正整数数字
652 | */
653 | digits: {
654 | message: '只能输入正整数数字',
655 | rule: /^\d+$/
656 | },
657 | /**
658 | * 正整数或负整数数字
659 | */
660 | integer: {
661 | message: '只能输入整数数字',
662 | rule: /^-?\d+$/
663 | },
664 | /**
665 | * 大于多少的数字/字段值
666 | */
667 | min: {
668 | message: '请输入大于 {0} 的数字',
669 | rule: function rule(value, param) {
670 | if (typeof param === 'string') param = this.data[param];
671 |
672 | return value >= param;
673 | }
674 | },
675 | /**
676 | * 小于多少的数字/字段值
677 | */
678 | max: {
679 | message: '请输入小于 {0} 的数字',
680 | rule: function rule(value, param) {
681 | if (typeof param === 'string') param = this.data[param];
682 |
683 | return value <= param;
684 | }
685 | },
686 | /**
687 | * 大于且小于多少的数字
688 | */
689 | range: {
690 | message: '请输入大于 {0} 且小于 {1} 的数字',
691 | rule: function rule(value, param) {
692 | return value >= param[0] && value <= param[1];
693 | }
694 | },
695 | /**
696 | * 中文字符
697 | */
698 | chinese: {
699 | message: '只能输入中文字符',
700 | rule: /^[\u4e00-\u9fa5]+$/
701 | },
702 | /**
703 | * 最少多少个中文字符
704 | */
705 | minChinese: {
706 | message: '最少输入 {0} 个中文字符',
707 | rule: function rule(value, param) {
708 | return new RegExp('^[\u4E00-\u9FA5]{' + param + ',}$').test(value);
709 | }
710 | },
711 | /**
712 | * 最多多少个中文字符
713 | */
714 | maxChinese: {
715 | message: '最多输入 {0} 个中文字符',
716 | rule: function rule(value, param) {
717 | return new RegExp('^[\u4E00-\u9FA5]{1,' + param + '}$').test(value);
718 | }
719 | },
720 | /**
721 | * 大于且小于多少个中文字符
722 | */
723 | rangeChinese: {
724 | message: '只能输入 {0} 到 {1} 个中文字符',
725 | rule: function rule(value, param) {
726 | return new RegExp('^[\u4E00-\u9FA5]{' + param[0] + ',' + param[1] + '}$').test(value);
727 | }
728 | },
729 | /**
730 | * 日期
731 | */
732 | date: {
733 | message: '请输入有效的日期',
734 | rule: function rule(value) {
735 | return !/Invalid|NaN/.test(new Date(value).toString());
736 | }
737 | },
738 | /**
739 | * 日期(ISO标准格式)例如:2019-09-19,2019/09/19
740 | */
741 | dateISO: {
742 | message: '请输入有效的日期(ISO 标准格式)',
743 | rule: /^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$/
744 | },
745 | /**
746 | * ipv4地址
747 | */
748 | ipv4: {
749 | message: '请输入有效的 IPv4 地址',
750 | rule: /^(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)$/i
751 | },
752 | /**
753 | * ipv6地址
754 | */
755 | ipv6: {
756 | message: '请输入有效的 IPv6 地址',
757 | rule: /^((([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}:[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){5}:([0-9A-Fa-f]{1,4}:)?[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){4}:([0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){3}:([0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){2}:([0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(([0-9A-Fa-f]{1,4}:){0,5}:((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(::([0-9A-Fa-f]{1,4}:){0,5}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|([0-9A-Fa-f]{1,4}::([0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})|(::([0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){1,7}:))$/i
758 | }
759 | };
760 |
761 | /***/ })
762 | /******/ ]);
763 | });
--------------------------------------------------------------------------------