mockjs
Version:
生成随机数据 & 拦截 Ajax 请求
1,580 lines (1,396 loc) • 272 kB
JavaScript
(function webpackUniversalModuleDefinition(root, factory) {
if(typeof exports === 'object' && typeof module === 'object')
module.exports = factory();
else if(typeof define === 'function' && define.amd)
define([], factory);
else if(typeof exports === 'object')
exports["Mock"] = factory();
else
root["Mock"] = factory();
})(this, function() {
return /******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId])
/******/ return installedModules[moduleId].exports;
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ exports: {},
/******/ id: moduleId,
/******/ loaded: false
/******/ };
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/ // Flag the module as loaded
/******/ module.loaded = true;
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/ // Load entry module and return exports
/******/ return __webpack_require__(0);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ (function(module, exports, __webpack_require__) {
/* global require, module, window */
var Handler = __webpack_require__(1)
var Util = __webpack_require__(3)
var Random = __webpack_require__(5)
var RE = __webpack_require__(20)
var toJSONSchema = __webpack_require__(23)
var valid = __webpack_require__(25)
var XHR
if (typeof window !== 'undefined') XHR = __webpack_require__(27)
/*!
Mock - 模拟请求 & 模拟数据
https://github.com/nuysoft/Mock
墨智 mozhi.gyy@taobao.com nuysoft@gmail.com
*/
var Mock = {
Handler: Handler,
Random: Random,
Util: Util,
XHR: XHR,
RE: RE,
toJSONSchema: toJSONSchema,
valid: valid,
heredoc: Util.heredoc,
setup: function(settings) {
return XHR.setup(settings)
},
_mocked: {}
}
Mock.version = '1.0.1-beta3'
// 避免循环依赖
if (XHR) XHR.Mock = Mock
/*
* Mock.mock( template )
* Mock.mock( function() )
* Mock.mock( rurl, template )
* Mock.mock( rurl, function(options) )
* Mock.mock( rurl, rtype, template )
* Mock.mock( rurl, rtype, function(options) )
根据数据模板生成模拟数据。
*/
Mock.mock = function(rurl, rtype, template) {
// Mock.mock(template)
if (arguments.length === 1) {
return Handler.gen(rurl)
}
// Mock.mock(rurl, template)
if (arguments.length === 2) {
template = rtype
rtype = undefined
}
// 拦截 XHR
if (XHR) window.XMLHttpRequest = XHR
Mock._mocked[rurl + (rtype || '')] = {
rurl: rurl,
rtype: rtype,
template: template
}
return Mock
}
module.exports = Mock
/***/ }),
/* 1 */
/***/ (function(module, exports, __webpack_require__) {
/*
## Handler
处理数据模板。
* Handler.gen( template, name?, context? )
入口方法。
* Data Template Definition, DTD
处理数据模板定义。
* Handler.array( options )
* Handler.object( options )
* Handler.number( options )
* Handler.boolean( options )
* Handler.string( options )
* Handler.function( options )
* Handler.regexp( options )
处理路径(相对和绝对)。
* Handler.getValueByKeyPath( key, options )
* Data Placeholder Definition, DPD
处理数据占位符定义
* Handler.placeholder( placeholder, context, templateContext, options )
*/
var Constant = __webpack_require__(2)
var Util = __webpack_require__(3)
var Parser = __webpack_require__(4)
var Random = __webpack_require__(5)
var RE = __webpack_require__(20)
var Handler = {
extend: Util.extend
}
/*
template 属性值(即数据模板)
name 属性名
context 数据上下文,生成后的数据
templateContext 模板上下文,
Handle.gen(template, name, options)
context
currentContext, templateCurrentContext,
path, templatePath
root, templateRoot
*/
Handler.gen = function(template, name, context) {
/* jshint -W041 */
name = name == undefined ? '' : (name + '')
context = context || {}
context = {
// 当前访问路径,只有属性名,不包括生成规则
path: context.path || [Constant.GUID],
templatePath: context.templatePath || [Constant.GUID++],
// 最终属性值的上下文
currentContext: context.currentContext,
// 属性值模板的上下文
templateCurrentContext: context.templateCurrentContext || template,
// 最终值的根
root: context.root || context.currentContext,
// 模板的根
templateRoot: context.templateRoot || context.templateCurrentContext || template
}
// console.log('path:', context.path.join('.'), template)
var rule = Parser.parse(name)
var type = Util.type(template)
var data
if (Handler[type]) {
data = Handler[type]({
// 属性值类型
type: type,
// 属性值模板
template: template,
// 属性名 + 生成规则
name: name,
// 属性名
parsedName: name ? name.replace(Constant.RE_KEY, '$1') : name,
// 解析后的生成规则
rule: rule,
// 相关上下文
context: context
})
if (!context.root) context.root = data
return data
}
return template
}
Handler.extend({
array: function(options) {
var result = [],
i, ii;
// 'name|1': []
// 'name|count': []
// 'name|min-max': []
if (options.template.length === 0) return result
// 'arr': [{ 'email': '@EMAIL' }, { 'email': '@EMAIL' }]
if (!options.rule.parameters) {
for (i = 0; i < options.template.length; i++) {
options.context.path.push(i)
options.context.templatePath.push(i)
result.push(
Handler.gen(options.template[i], i, {
path: options.context.path,
templatePath: options.context.templatePath,
currentContext: result,
templateCurrentContext: options.template,
root: options.context.root || result,
templateRoot: options.context.templateRoot || options.template
})
)
options.context.path.pop()
options.context.templatePath.pop()
}
} else {
// 'method|1': ['GET', 'POST', 'HEAD', 'DELETE']
if (options.rule.min === 1 && options.rule.max === undefined) {
// fix #17
options.context.path.push(options.name)
options.context.templatePath.push(options.name)
result = Random.pick(
Handler.gen(options.template, undefined, {
path: options.context.path,
templatePath: options.context.templatePath,
currentContext: result,
templateCurrentContext: options.template,
root: options.context.root || result,
templateRoot: options.context.templateRoot || options.template
})
)
options.context.path.pop()
options.context.templatePath.pop()
} else {
// 'data|+1': [{}, {}]
if (options.rule.parameters[2]) {
options.template.__order_index = options.template.__order_index || 0
options.context.path.push(options.name)
options.context.templatePath.push(options.name)
result = Handler.gen(options.template, undefined, {
path: options.context.path,
templatePath: options.context.templatePath,
currentContext: result,
templateCurrentContext: options.template,
root: options.context.root || result,
templateRoot: options.context.templateRoot || options.template
})[
options.template.__order_index % options.template.length
]
options.template.__order_index += +options.rule.parameters[2]
options.context.path.pop()
options.context.templatePath.pop()
} else {
// 'data|1-10': [{}]
for (i = 0; i < options.rule.count; i++) {
// 'data|1-10': [{}, {}]
for (ii = 0; ii < options.template.length; ii++) {
options.context.path.push(result.length)
options.context.templatePath.push(ii)
result.push(
Handler.gen(options.template[ii], result.length, {
path: options.context.path,
templatePath: options.context.templatePath,
currentContext: result,
templateCurrentContext: options.template,
root: options.context.root || result,
templateRoot: options.context.templateRoot || options.template
})
)
options.context.path.pop()
options.context.templatePath.pop()
}
}
}
}
}
return result
},
object: function(options) {
var result = {},
keys, fnKeys, key, parsedKey, inc, i;
// 'obj|min-max': {}
/* jshint -W041 */
if (options.rule.min != undefined) {
keys = Util.keys(options.template)
keys = Random.shuffle(keys)
keys = keys.slice(0, options.rule.count)
for (i = 0; i < keys.length; i++) {
key = keys[i]
parsedKey = key.replace(Constant.RE_KEY, '$1')
options.context.path.push(parsedKey)
options.context.templatePath.push(key)
result[parsedKey] = Handler.gen(options.template[key], key, {
path: options.context.path,
templatePath: options.context.templatePath,
currentContext: result,
templateCurrentContext: options.template,
root: options.context.root || result,
templateRoot: options.context.templateRoot || options.template
})
options.context.path.pop()
options.context.templatePath.pop()
}
} else {
// 'obj': {}
keys = []
fnKeys = [] // #25 改变了非函数属性的顺序,查找起来不方便
for (key in options.template) {
(typeof options.template[key] === 'function' ? fnKeys : keys).push(key)
}
keys = keys.concat(fnKeys)
/*
会改变非函数属性的顺序
keys = Util.keys(options.template)
keys.sort(function(a, b) {
var afn = typeof options.template[a] === 'function'
var bfn = typeof options.template[b] === 'function'
if (afn === bfn) return 0
if (afn && !bfn) return 1
if (!afn && bfn) return -1
})
*/
for (i = 0; i < keys.length; i++) {
key = keys[i]
parsedKey = key.replace(Constant.RE_KEY, '$1')
options.context.path.push(parsedKey)
options.context.templatePath.push(key)
result[parsedKey] = Handler.gen(options.template[key], key, {
path: options.context.path,
templatePath: options.context.templatePath,
currentContext: result,
templateCurrentContext: options.template,
root: options.context.root || result,
templateRoot: options.context.templateRoot || options.template
})
options.context.path.pop()
options.context.templatePath.pop()
// 'id|+1': 1
inc = key.match(Constant.RE_KEY)
if (inc && inc[2] && Util.type(options.template[key]) === 'number') {
options.template[key] += parseInt(inc[2], 10)
}
}
}
return result
},
number: function(options) {
var result, parts;
if (options.rule.decimal) { // float
options.template += ''
parts = options.template.split('.')
// 'float1|.1-10': 10,
// 'float2|1-100.1-10': 1,
// 'float3|999.1-10': 1,
// 'float4|.3-10': 123.123,
parts[0] = options.rule.range ? options.rule.count : parts[0]
parts[1] = (parts[1] || '').slice(0, options.rule.dcount)
while (parts[1].length < options.rule.dcount) {
parts[1] += (
// 最后一位不能为 0:如果最后一位为 0,会被 JS 引擎忽略掉。
(parts[1].length < options.rule.dcount - 1) ? Random.character('number') : Random.character('123456789')
)
}
result = parseFloat(parts.join('.'), 10)
} else { // integer
// 'grade1|1-100': 1,
result = options.rule.range && !options.rule.parameters[2] ? options.rule.count : options.template
}
return result
},
boolean: function(options) {
var result;
// 'prop|multiple': false, 当前值是相反值的概率倍数
// 'prop|probability-probability': false, 当前值与相反值的概率
result = options.rule.parameters ? Random.bool(options.rule.min, options.rule.max, options.template) : options.template
return result
},
string: function(options) {
var result = '',
i, placeholders, ph, phed;
if (options.template.length) {
// 'foo': '★',
/* jshint -W041 */
if (options.rule.count == undefined) {
result += options.template
}
// 'star|1-5': '★',
for (i = 0; i < options.rule.count; i++) {
result += options.template
}
// 'email|1-10': '@EMAIL, ',
placeholders = result.match(Constant.RE_PLACEHOLDER) || [] // A-Z_0-9 > \w_
for (i = 0; i < placeholders.length; i++) {
ph = placeholders[i]
// 遇到转义斜杠,不需要解析占位符
if (/^\\/.test(ph)) {
placeholders.splice(i--, 1)
continue
}
phed = Handler.placeholder(ph, options.context.currentContext, options.context.templateCurrentContext, options)
// 只有一个占位符,并且没有其他字符
if (placeholders.length === 1 && ph === result && typeof phed !== typeof result) { //
result = phed
break
if (Util.isNumeric(phed)) {
result = parseFloat(phed, 10)
break
}
if (/^(true|false)$/.test(phed)) {
result = phed === 'true' ? true :
phed === 'false' ? false :
phed // 已经是布尔值
break
}
}
result = result.replace(ph, phed)
}
} else {
// 'ASCII|1-10': '',
// 'ASCII': '',
result = options.rule.range ? Random.string(options.rule.count) : options.template
}
return result
},
'function': function(options) {
// ( context, options )
return options.template.call(options.context.currentContext, options)
},
'regexp': function(options) {
var source = ''
// 'name': /regexp/,
/* jshint -W041 */
if (options.rule.count == undefined) {
source += options.template.source // regexp.source
}
// 'name|1-5': /regexp/,
for (var i = 0; i < options.rule.count; i++) {
source += options.template.source
}
return RE.Handler.gen(
RE.Parser.parse(
source
)
)
}
})
Handler.extend({
_all: function() {
var re = {};
for (var key in Random) re[key.toLowerCase()] = key
return re
},
// 处理占位符,转换为最终值
placeholder: function(placeholder, obj, templateContext, options) {
// console.log(options.context.path)
// 1 key, 2 params
Constant.RE_PLACEHOLDER.exec('')
var parts = Constant.RE_PLACEHOLDER.exec(placeholder),
key = parts && parts[1],
lkey = key && key.toLowerCase(),
okey = this._all()[lkey],
params = parts && parts[2] || ''
var pathParts = this.splitPathToArray(key)
// 解析占位符的参数
try {
// 1. 尝试保持参数的类型
/*
#24 [Window Firefox 30.0 引用 占位符 抛错](https://github.com/nuysoft/Mock/issues/24)
[BX9056: 各浏览器下 window.eval 方法的执行上下文存在差异](http://www.w3help.org/zh-cn/causes/BX9056)
应该属于 Window Firefox 30.0 的 BUG
*/
/* jshint -W061 */
params = eval('(function(){ return [].splice.call(arguments, 0 ) })(' + params + ')')
} catch (error) {
// 2. 如果失败,只能解析为字符串
// console.error(error)
// if (error instanceof ReferenceError) params = parts[2].split(/,\s*/);
// else throw error
params = parts[2].split(/,\s*/)
}
// 占位符优先引用数据模板中的属性
if (obj && (key in obj)) return obj[key]
// @index @key
// if (Constant.RE_INDEX.test(key)) return +options.name
// if (Constant.RE_KEY.test(key)) return options.name
// 绝对路径 or 相对路径
if (
key.charAt(0) === '/' ||
pathParts.length > 1
) return this.getValueByKeyPath(key, options)
// 递归引用数据模板中的属性
if (templateContext &&
(typeof templateContext === 'object') &&
(key in templateContext) &&
(placeholder !== templateContext[key]) // fix #15 避免自己依赖自己
) {
// 先计算被引用的属性值
templateContext[key] = Handler.gen(templateContext[key], key, {
currentContext: obj,
templateCurrentContext: templateContext
})
return templateContext[key]
}
// 如果未找到,则原样返回
if (!(key in Random) && !(lkey in Random) && !(okey in Random)) return placeholder
// 递归解析参数中的占位符
for (var i = 0; i < params.length; i++) {
Constant.RE_PLACEHOLDER.exec('')
if (Constant.RE_PLACEHOLDER.test(params[i])) {
params[i] = Handler.placeholder(params[i], obj, templateContext, options)
}
}
var handle = Random[key] || Random[lkey] || Random[okey]
switch (Util.type(handle)) {
case 'array':
// 自动从数组中取一个,例如 @areas
return Random.pick(handle)
case 'function':
// 执行占位符方法(大多数情况)
handle.options = options
var re = handle.apply(Random, params)
if (re === undefined) re = '' // 因为是在字符串中,所以默认为空字符串。
delete handle.options
return re
}
},
getValueByKeyPath: function(key, options) {
var originalKey = key
var keyPathParts = this.splitPathToArray(key)
var absolutePathParts = []
// 绝对路径
if (key.charAt(0) === '/') {
absolutePathParts = [options.context.path[0]].concat(
this.normalizePath(keyPathParts)
)
} else {
// 相对路径
if (keyPathParts.length > 1) {
absolutePathParts = options.context.path.slice(0)
absolutePathParts.pop()
absolutePathParts = this.normalizePath(
absolutePathParts.concat(keyPathParts)
)
}
}
try {
key = keyPathParts[keyPathParts.length - 1]
var currentContext = options.context.root
var templateCurrentContext = options.context.templateRoot
for (var i = 1; i < absolutePathParts.length - 1; i++) {
currentContext = currentContext[absolutePathParts[i]]
templateCurrentContext = templateCurrentContext[absolutePathParts[i]]
}
// 引用的值已经计算好
if (currentContext && (key in currentContext)) return currentContext[key]
// 尚未计算,递归引用数据模板中的属性
if (templateCurrentContext &&
(typeof templateCurrentContext === 'object') &&
(key in templateCurrentContext) &&
(originalKey !== templateCurrentContext[key]) // fix #15 避免自己依赖自己
) {
// 先计算被引用的属性值
templateCurrentContext[key] = Handler.gen(templateCurrentContext[key], key, {
currentContext: currentContext,
templateCurrentContext: templateCurrentContext
})
return templateCurrentContext[key]
}
} catch(err) { }
return '@' + keyPathParts.join('/')
},
// https://github.com/kissyteam/kissy/blob/master/src/path/src/path.js
normalizePath: function(pathParts) {
var newPathParts = []
for (var i = 0; i < pathParts.length; i++) {
switch (pathParts[i]) {
case '..':
newPathParts.pop()
break
case '.':
break
default:
newPathParts.push(pathParts[i])
}
}
return newPathParts
},
splitPathToArray: function(path) {
var parts = path.split(/\/+/);
if (!parts[parts.length - 1]) parts = parts.slice(0, -1)
if (!parts[0]) parts = parts.slice(1)
return parts;
}
})
module.exports = Handler
/***/ }),
/* 2 */
/***/ (function(module, exports) {
/*
## Constant
常量集合。
*/
/*
RE_KEY
'name|min-max': value
'name|count': value
'name|min-max.dmin-dmax': value
'name|min-max.dcount': value
'name|count.dmin-dmax': value
'name|count.dcount': value
'name|+step': value
1 name, 2 step, 3 range [ min, max ], 4 drange [ dmin, dmax ]
RE_PLACEHOLDER
placeholder(*)
[正则查看工具](http://www.regexper.com/)
#26 生成规则 支持 负数,例如 number|-100-100
*/
module.exports = {
GUID: 1,
RE_KEY: /(.+)\|(?:\+(\d+)|([\+\-]?\d+-?[\+\-]?\d*)?(?:\.(\d+-?\d*))?)/,
RE_RANGE: /([\+\-]?\d+)-?([\+\-]?\d+)?/,
RE_PLACEHOLDER: /\\*@([^@#%&()\?\s]+)(?:\((.*?)\))?/g
// /\\*@([^@#%&()\?\s\/\.]+)(?:\((.*?)\))?/g
// RE_INDEX: /^index$/,
// RE_KEY: /^key$/
}
/***/ }),
/* 3 */
/***/ (function(module, exports) {
/*
## Utilities
*/
var Util = {}
Util.extend = function extend() {
var target = arguments[0] || {},
i = 1,
length = arguments.length,
options, name, src, copy, clone
if (length === 1) {
target = this
i = 0
}
for (; i < length; i++) {
options = arguments[i]
if (!options) continue
for (name in options) {
src = target[name]
copy = options[name]
if (target === copy) continue
if (copy === undefined) continue
if (Util.isArray(copy) || Util.isObject(copy)) {
if (Util.isArray(copy)) clone = src && Util.isArray(src) ? src : []
if (Util.isObject(copy)) clone = src && Util.isObject(src) ? src : {}
target[name] = Util.extend(clone, copy)
} else {
target[name] = copy
}
}
}
return target
}
Util.each = function each(obj, iterator, context) {
var i, key
if (this.type(obj) === 'number') {
for (i = 0; i < obj; i++) {
iterator(i, i)
}
} else if (obj.length === +obj.length) {
for (i = 0; i < obj.length; i++) {
if (iterator.call(context, obj[i], i, obj) === false) break
}
} else {
for (key in obj) {
if (iterator.call(context, obj[key], key, obj) === false) break
}
}
}
Util.type = function type(obj) {
return (obj === null || obj === undefined) ? String(obj) : Object.prototype.toString.call(obj).match(/\[object (\w+)\]/)[1].toLowerCase()
}
Util.each('String Object Array RegExp Function'.split(' '), function(value) {
Util['is' + value] = function(obj) {
return Util.type(obj) === value.toLowerCase()
}
})
Util.isObjectOrArray = function(value) {
return Util.isObject(value) || Util.isArray(value)
}
Util.isNumeric = function(value) {
return !isNaN(parseFloat(value)) && isFinite(value)
}
Util.keys = function(obj) {
var keys = [];
for (var key in obj) {
if (obj.hasOwnProperty(key)) keys.push(key)
}
return keys;
}
Util.values = function(obj) {
var values = [];
for (var key in obj) {
if (obj.hasOwnProperty(key)) values.push(obj[key])
}
return values;
}
/*
### Mock.heredoc(fn)
* Mock.heredoc(fn)
以直观、安全的方式书写(多行)HTML 模板。
**使用示例**如下所示:
var tpl = Mock.heredoc(function() {
/*!
{{email}}{{age}}
<!-- Mock {
email: '@EMAIL',
age: '@INT(1,100)'
} -->
*\/
})
**相关阅读**
* [Creating multiline strings in JavaScript](http://stackoverflow.com/questions/805107/creating-multiline-strings-in-javascript)、
*/
Util.heredoc = function heredoc(fn) {
// 1. 移除起始的 function(){ /*!
// 2. 移除末尾的 */ }
// 3. 移除起始和末尾的空格
return fn.toString()
.replace(/^[^\/]+\/\*!?/, '')
.replace(/\*\/[^\/]+$/, '')
.replace(/^[\s\xA0]+/, '').replace(/[\s\xA0]+$/, '') // .trim()
}
Util.noop = function() {}
module.exports = Util
/***/ }),
/* 4 */
/***/ (function(module, exports, __webpack_require__) {
/*
## Parser
解析数据模板(属性名部分)。
* Parser.parse( name )
```json
{
parameters: [ name, inc, range, decimal ],
rnage: [ min , max ],
min: min,
max: max,
count : count,
decimal: decimal,
dmin: dmin,
dmax: dmax,
dcount: dcount
}
```
*/
var Constant = __webpack_require__(2)
var Random = __webpack_require__(5)
/* jshint -W041 */
module.exports = {
parse: function(name) {
name = name == undefined ? '' : (name + '')
var parameters = (name || '').match(Constant.RE_KEY)
var range = parameters && parameters[3] && parameters[3].match(Constant.RE_RANGE)
var min = range && range[1] && parseInt(range[1], 10) // || 1
var max = range && range[2] && parseInt(range[2], 10) // || 1
// repeat || min-max || 1
// var count = range ? !range[2] && parseInt(range[1], 10) || Random.integer(min, max) : 1
var count = range ? !range[2] ? parseInt(range[1], 10) : Random.integer(min, max) : undefined
var decimal = parameters && parameters[4] && parameters[4].match(Constant.RE_RANGE)
var dmin = decimal && decimal[1] && parseInt(decimal[1], 10) // || 0,
var dmax = decimal && decimal[2] && parseInt(decimal[2], 10) // || 0,
// int || dmin-dmax || 0
var dcount = decimal ? !decimal[2] && parseInt(decimal[1], 10) || Random.integer(dmin, dmax) : undefined
var result = {
// 1 name, 2 inc, 3 range, 4 decimal
parameters: parameters,
// 1 min, 2 max
range: range,
min: min,
max: max,
// min-max
count: count,
// 是否有 decimal
decimal: decimal,
dmin: dmin,
dmax: dmax,
// dmin-dimax
dcount: dcount
}
for (var r in result) {
if (result[r] != undefined) return result
}
return {}
}
}
/***/ }),
/* 5 */
/***/ (function(module, exports, __webpack_require__) {
/*
## Mock.Random
工具类,用于生成各种随机数据。
*/
var Util = __webpack_require__(3)
var Random = {
extend: Util.extend
}
Random.extend(__webpack_require__(6))
Random.extend(__webpack_require__(7))
Random.extend(__webpack_require__(8))
Random.extend(__webpack_require__(10))
Random.extend(__webpack_require__(13))
Random.extend(__webpack_require__(15))
Random.extend(__webpack_require__(16))
Random.extend(__webpack_require__(17))
Random.extend(__webpack_require__(14))
Random.extend(__webpack_require__(19))
module.exports = Random
/***/ }),
/* 6 */
/***/ (function(module, exports) {
/*
## Basics
*/
module.exports = {
// 返回一个随机的布尔值。
boolean: function(min, max, cur) {
if (cur !== undefined) {
min = typeof min !== 'undefined' && !isNaN(min) ? parseInt(min, 10) : 1
max = typeof max !== 'undefined' && !isNaN(max) ? parseInt(max, 10) : 1
return Math.random() > 1.0 / (min + max) * min ? !cur : cur
}
return Math.random() >= 0.5
},
bool: function(min, max, cur) {
return this.boolean(min, max, cur)
},
// 返回一个随机的自然数(大于等于 0 的整数)。
natural: function(min, max) {
min = typeof min !== 'undefined' ? parseInt(min, 10) : 0
max = typeof max !== 'undefined' ? parseInt(max, 10) : 9007199254740992 // 2^53
return Math.round(Math.random() * (max - min)) + min
},
// 返回一个随机的整数。
integer: function(min, max) {
min = typeof min !== 'undefined' ? parseInt(min, 10) : -9007199254740992
max = typeof max !== 'undefined' ? parseInt(max, 10) : 9007199254740992 // 2^53
return Math.round(Math.random() * (max - min)) + min
},
int: function(min, max) {
return this.integer(min, max)
},
// 返回一个随机的浮点数。
float: function(min, max, dmin, dmax) {
dmin = dmin === undefined ? 0 : dmin
dmin = Math.max(Math.min(dmin, 17), 0)
dmax = dmax === undefined ? 17 : dmax
dmax = Math.max(Math.min(dmax, 17), 0)
var ret = this.integer(min, max) + '.';
for (var i = 0, dcount = this.natural(dmin, dmax); i < dcount; i++) {
ret += (
// 最后一位不能为 0:如果最后一位为 0,会被 JS 引擎忽略掉。
(i < dcount - 1) ? this.character('number') : this.character('123456789')
)
}
return parseFloat(ret, 10)
},
// 返回一个随机字符。
character: function(pool) {
var pools = {
lower: 'abcdefghijklmnopqrstuvwxyz',
upper: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
number: '0123456789',
symbol: '!@#$%^&*()[]'
}
pools.alpha = pools.lower + pools.upper
pools['undefined'] = pools.lower + pools.upper + pools.number + pools.symbol
pool = pools[('' + pool).toLowerCase()] || pool
return pool.charAt(this.natural(0, pool.length - 1))
},
char: function(pool) {
return this.character(pool)
},
// 返回一个随机字符串。
string: function(pool, min, max) {
var len
switch (arguments.length) {
case 0: // ()
len = this.natural(3, 7)
break
case 1: // ( length )
len = pool
pool = undefined
break
case 2:
// ( pool, length )
if (typeof arguments[0] === 'string') {
len = min
} else {
// ( min, max )
len = this.natural(pool, min)
pool = undefined
}
break
case 3:
len = this.natural(min, max)
break
}
var text = ''
for (var i = 0; i < len; i++) {
text += this.character(pool)
}
return text
},
str: function( /*pool, min, max*/ ) {
return this.string.apply(this, arguments)
},
// 返回一个整型数组。
range: function(start, stop, step) {
// range( stop )
if (arguments.length <= 1) {
stop = start || 0;
start = 0;
}
// range( start, stop )
step = arguments[2] || 1;
start = +start
stop = +stop
step = +step
var len = Math.max(Math.ceil((stop - start) / step), 0);
var idx = 0;
var range = new Array(len);
while (idx < len) {
range[idx++] = start;
start += step;
}
return range;
}
}
/***/ }),
/* 7 */
/***/ (function(module, exports) {
/*
## Date
*/
var patternLetters = {
yyyy: 'getFullYear',
yy: function(date) {
return ('' + date.getFullYear()).slice(2)
},
y: 'yy',
MM: function(date) {
var m = date.getMonth() + 1
return m < 10 ? '0' + m : m
},
M: function(date) {
return date.getMonth() + 1
},
dd: function(date) {
var d = date.getDate()
return d < 10 ? '0' + d : d
},
d: 'getDate',
HH: function(date) {
var h = date.getHours()
return h < 10 ? '0' + h : h
},
H: 'getHours',
hh: function(date) {
var h = date.getHours() % 12
return h < 10 ? '0' + h : h
},
h: function(date) {
return date.getHours() % 12
},
mm: function(date) {
var m = date.getMinutes()
return m < 10 ? '0' + m : m
},
m: 'getMinutes',
ss: function(date) {
var s = date.getSeconds()
return s < 10 ? '0' + s : s
},
s: 'getSeconds',
SS: function(date) {
var ms = date.getMilliseconds()
return ms < 10 && '00' + ms || ms < 100 && '0' + ms || ms
},
S: 'getMilliseconds',
A: function(date) {
return date.getHours() < 12 ? 'AM' : 'PM'
},
a: function(date) {
return date.getHours() < 12 ? 'am' : 'pm'
},
T: 'getTime'
}
module.exports = {
// 日期占位符集合。
_patternLetters: patternLetters,
// 日期占位符正则。
_rformat: new RegExp((function() {
var re = []
for (var i in patternLetters) re.push(i)
return '(' + re.join('|') + ')'
})(), 'g'),
// 格式化日期。
_formatDate: function(date, format) {
return format.replace(this._rformat, function creatNewSubString($0, flag) {
return typeof patternLetters[flag] === 'function' ? patternLetters[flag](date) :
patternLetters[flag] in patternLetters ? creatNewSubString($0, patternLetters[flag]) :
date[patternLetters[flag]]()
})
},
// 生成一个随机的 Date 对象。
_randomDate: function(min, max) { // min, max
min = min === undefined ? new Date(0) : min
max = max === undefined ? new Date() : max
return new Date(Math.random() * (max.getTime() - min.getTime()))
},
// 返回一个随机的日期字符串。
date: function(format) {
format = format || 'yyyy-MM-dd'
return this._formatDate(this._randomDate(), format)
},
// 返回一个随机的时间字符串。
time: function(format) {
format = format || 'HH:mm:ss'
return this._formatDate(this._randomDate(), format)
},
// 返回一个随机的日期和时间字符串。
datetime: function(format) {
format = format || 'yyyy-MM-dd HH:mm:ss'
return this._formatDate(this._randomDate(), format)
},
// 返回当前的日期和时间字符串。
now: function(unit, format) {
// now(unit) now(format)
if (arguments.length === 1) {
// now(format)
if (!/year|month|day|hour|minute|second|week/.test(unit)) {
format = unit
unit = ''
}
}
unit = (unit || '').toLowerCase()
format = format || 'yyyy-MM-dd HH:mm:ss'
var date = new Date()
/* jshint -W086 */
// 参考自 http://momentjs.cn/docs/#/manipulating/start-of/
switch (unit) {
case 'year':
date.setMonth(0)
case 'month':
date.setDate(1)
case 'week':
case 'day':
date.setHours(0)
case 'hour':
date.setMinutes(0)
case 'minute':
date.setSeconds(0)
case 'second':
date.setMilliseconds(0)
}
switch (unit) {
case 'week':
date.setDate(date.getDate() - date.getDay())
}
return this._formatDate(date, format)
}
}
/***/ }),
/* 8 */
/***/ (function(module, exports, __webpack_require__) {
/* WEBPACK VAR INJECTION */(function(module) {/* global document */
/*
## Image
*/
module.exports = {
// 常见的广告宽高
_adSize: [
'300x250', '250x250', '240x400', '336x280', '180x150',
'720x300', '468x60', '234x60', '88x31', '120x90',
'120x60', '120x240', '125x125', '728x90', '160x600',
'120x600', '300x600'
],
// 常见的屏幕宽高
_screenSize: [
'320x200', '320x240', '640x480', '800x480', '800x480',
'1024x600', '1024x768', '1280x800', '1440x900', '1920x1200',
'2560x1600'
],
// 常见的视频宽高
_videoSize: ['720x480', '768x576', '1280x720', '1920x1080'],
/*
生成一个随机的图片地址。
替代图片源
http://fpoimg.com/
参考自
http://rensanning.iteye.com/blog/1933310
http://code.tutsplus.com/articles/the-top-8-placeholders-for-web-designers--net-19485
*/
image: function(size, background, foreground, format, text) {
// Random.image( size, background, foreground, text )
if (arguments.length === 4) {
text = format
format = undefined
}
// Random.image( size, background, text )
if (arguments.length === 3) {
text = foreground
foreground = undefined
}
// Random.image()
if (!size) size = this.pick(this._adSize)
if (background && ~background.indexOf('#')) background = background.slice(1)
if (foreground && ~foreground.indexOf('#')) foreground = foreground.slice(1)
// http://dummyimage.com/600x400/cc00cc/470047.png&text=hello
return 'http://dummyimage.com/' + size +
(background ? '/' + background : '') +
(foreground ? '/' + foreground : '') +
(format ? '.' + format : '') +
(text ? '&text=' + text : '')
},
img: function() {
return this.image.apply(this, arguments)
},
/*
BrandColors
http://brandcolors.net/
A collection of major brand color codes curated by Galen Gidman.
大牌公司的颜色集合
// 获取品牌和颜色
$('h2').each(function(index, item){
item = $(item)
console.log('\'' + item.text() + '\'', ':', '\'' + item.next().text() + '\'', ',')
})
*/
_brandColors: {
'4ormat': '#fb0a2a',
'500px': '#02adea',
'About.me (blue)': '#00405d',
'About.me (yellow)': '#ffcc33',
'Addvocate': '#ff6138',
'Adobe': '#ff0000',
'Aim': '#fcd20b',
'Amazon': '#e47911',
'Android': '#a4c639',
'Angie\'s List': '#7fbb00',
'AOL': '#0060a3',
'Atlassian': '#003366',
'Behance': '#053eff',
'Big Cartel': '#97b538',
'bitly': '#ee6123',
'Blogger': '#fc4f08',
'Boeing': '#0039a6',
'Booking.com': '#003580',
'Carbonmade': '#613854',
'Cheddar': '#ff7243',
'Code School': '#3d4944',
'Delicious': '#205cc0',
'Dell': '#3287c1',
'Designmoo': '#e54a4f',
'Deviantart': '#4e6252',
'Designer News': '#2d72da',
'Devour': '#fd0001',
'DEWALT': '#febd17',
'Disqus (blue)': '#59a3fc',
'Disqus (orange)': '#db7132',
'Dribbble': '#ea4c89',
'Dropbox': '#3d9ae8',
'Drupal': '#0c76ab',
'Dunked': '#2a323a',
'eBay': '#89c507',
'Ember': '#f05e1b',
'Engadget': '#00bdf6',
'Envato': '#528036',
'Etsy': '#eb6d20',
'Evernote': '#5ba525',
'Fab.com': '#dd0017',
'Facebook': '#3b5998',
'Firefox': '#e66000',
'Flickr (blue)': '#0063dc',
'Flickr (pink)': '#ff0084',
'Forrst': '#5b9a68',
'Foursquare': '#25a0ca',
'Garmin': '#007cc3',
'GetGlue': '#2d75a2',
'Gimmebar': '#f70078',
'GitHub': '#171515',
'Google Blue': '#0140ca',
'Google Green': '#16a61e',
'Google Red': '#dd1812',
'Google Yellow': '#fcca03',
'Google+': '#dd4b39',
'Grooveshark': '#f77f00',
'Groupon': '#82b548',
'Hacker News': '#ff6600',
'HelloWallet': '#0085ca',
'Heroku (light)': '#c7c5e6',
'Heroku (dark)': '#6567a5',
'HootSuite': '#003366',
'Houzz': '#73ba37',
'HTML5': '#ec6231',
'IKEA': '#ffcc33',
'IMDb': '#f3ce13',
'Instagram': '#3f729b',
'Intel': '#0071c5',
'Intuit': '#365ebf',
'Kickstarter': '#76cc1e',
'kippt': '#e03500',
'Kodery': '#00af81',
'LastFM': '#c3000d',
'LinkedIn': '#0e76a8',
'Livestream': '#cf0005',
'Lumo': '#576396',
'Mixpanel': '#a086d3',
'Meetup': '#e51937',
'Nokia': '#183693',
'NVIDIA': '#76b900',
'Opera': '#cc0f16',
'Path': '#e41f11',
'PayPal (dark)': '#1e477a',
'PayPal (light)': '#3b7bbf',
'Pinboard': '#0000e6',
'Pinterest': '#c8232c',
'PlayStation': '#665cbe',
'Pocket': '#ee4056',
'Prezi': '#318bff',
'Pusha': '#0f71b4',
'Quora': '#a82400',
'QUOTE.fm': '#66ceff',
'Rdio': '#008fd5',
'Readability': '#9c0000',
'Red Hat': '#cc0000',
'Resource': '#7eb400',
'Rockpack': '#0ba6ab',
'Roon': '#62b0d9',
'RSS': '#ee802f',
'Salesforce': '#1798c1',
'Samsung': '#0c4da2',
'Shopify': '#96bf48',
'Skype': '#00aff0',
'Snagajob': '#f47a20',
'Softonic': '#008ace',
'SoundCloud': '#ff7700',
'Space Box': '#f86960',
'Spotify': '#81b71a',
'Sprint': '#fee100',
'Squarespace': '#121212',
'StackOverflow': '#ef8236',
'Staples': '#cc0000',
'Status Chart': '#d7584f',
'Stripe': '#008cdd',
'StudyBlue': '#00afe1',
'StumbleUpon': '#f74425',
'T-Mobile': '#ea0a8e',
'Technorati': '#40a800',
'The Next Web': '#ef4423',
'Treehouse': '#5cb868',
'Trulia': '#5eab1f',
'Tumblr': '#34526f',
'Twitch.tv': '#6441a5',
'Twitter': '#00acee',
'TYPO3': '#ff8700',
'Ubuntu': '#dd4814',
'Ustream': '#3388ff',
'Verizon': '#ef1d1d',
'Vimeo': '#86c9ef',
'Vine': '#00a478',
'Virb': '#06afd8',
'Virgin Media': '#cc0000',
'Wooga': '#5b009c',
'WordPress (blue)': '#21759b',
'WordPress (orange)': '#d54e21',
'WordPress (grey)': '#464646',
'Wunderlist': '#2b88d9',
'XBOX': '#9bc848',
'XING': '#126567',
'Yahoo!': '#720e9e',
'Yandex': '#ffcc00',
'Yelp': '#c41200',
'YouTube': '#c4302b',
'Zalongo': '#5498dc',
'Zendesk': '#78a300',
'Zerply': '#9dcc7a',
'Zootool': '#5e8b1d'
},
_brandNames: function() {
var brands = [];
for (var b in this._brandColors) {
brands.push(b)
}
return brands
},
/*
生成一段随机的 Base64 图片编码。
https://github.com/imsky/holder
Holder renders image placeholders entirely on the client side.
dataImageHolder: function(size) {
return 'holder.js/' + size
},
*/
dataImage: function(size, text) {
var canvas
if (typeof document !== 'undefined') {
canvas = document.createElement('canvas')
} else {
/*
https://github.com/Automattic/node-canvas
npm install canvas --save
安装问题:
* http://stackoverflow.com/questions/22953206/gulp-issues-with-cario-install-command-not-found-when-trying-to-installing-canva
* https://github.com/Automattic/node-canvas/issues/415
* https://github.com/Automattic/node-canvas/wiki/_pages
PS:node-canvas 的安装过程实在是太繁琐了,所以不放入 package.json 的 dependencies。
*/
var Canvas = module.require('canvas')
canvas = new Canvas()
}
var ctx = canvas && canvas.getContext && canvas.getContext("2d")
if (!canvas || !ctx) return ''
if (!size) size = this.pick(this._adSize)
text = text !== undefined ? text : size
size = size.split('x')
var width = parseInt(size[0], 10),
height = parseInt(size[1], 10),
background = this._brandColors[this.pick(this._brandNames())],
foreground = '#FFF',
text_height = 14,
font = 'sans-serif';
canvas.width = width
canvas.height = height
ctx.textAlign = 'center'
ctx.textBaseline = 'middle'
ctx.fillStyle = background
ctx.fillRect(0, 0, width, height)
ctx.fillStyle = foreground
ctx.font = 'bold ' + text_height + 'px ' + font
ctx.fillText(text, (width / 2), (height / 2), width)
return canvas.toDataURL('image/png')
}
}
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(9)(module)))
/***/ }),
/* 9 */
/***/ (function(module, exports) {
module.exports = function(module) {
if(!module.webpackPolyfill) {
module.deprecate = function() {};
module.paths = [];
// module.parent = undefined by default
module.children = [];
module.webpackPolyfill = 1;
}
return module;
}
/***/ }),
/* 10 */
/***/ (function(module, exports, __webpack_require__) {
/*
## Color
http://llllll.li/randomColor/
A color generator for JavaScript.
randomColor generates attractive colors by default. More specifically, randomColor produces bright colors with a reasonably high saturation. This makes randomColor particularly useful for data visualizations and generative art.
http://randomcolour.com/
var bg_colour = Math.floor(Math.random() * 16777215).toString(16);
bg_colour = "#" + ("000000" + bg_colour).slice(-6);
document.bgColor = bg_colour;
http://martin.ankerl.com/2009/12/09/how-to-create-random-colors-programmatically/
Creating random colors is actually more difficult than it seems. The randomness itself is easy, but aesthetically pleasing randomness is more difficult.
https://github.com/devongovett/color-generator
http://www.paulirish.com/2009/random-hex-color-code-snippets/
Random Hex Color Code Generator in JavaScript
http://chancejs.com/#color
chance.color()
// => '#79c157'
chance.color({format: 'hex'})
// => '#d67118'
chance.color({format: 'shorthex'})
// => '#60f'
chance.color({format: 'rgb'})
// => 'rgb(110,52,164)'
http://tool.c7sky.com/webcolor
网页设计常用色彩搭配表
https://github.com/One-com/one-color
An OO-based JavaScript color parser/computation toolkit with support for RGB, HSV, HSL, CMYK, and alpha channels.
API 很赞
https://github.com/harthur/color
JavaScript color conversion and manipulation library
https://github.com/leaverou/css-colors
Share & convert CSS colors
http://leaverou.github.io/css-colors/#slategray
Type a CSS color keyword, #hex, hsl(), rgba(), whatever:
色调 hue
http://baike.baidu.com/view/23368.htm
色调指的是一幅画中画面色彩的总体倾向,是大的色彩效果。
饱和度