1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174 | 1×
1×
1×
1×
1×
1×
1×
2×
26×
26×
26×
52×
36×
1×
788×
788×
495×
495×
49×
739×
698×
1×
27×
1×
739×
1×
1202×
1×
27×
1×
27×
27×
27×
35×
35×
35×
16×
19×
19×
19×
19×
1×
383×
334×
49×
2×
49×
12×
49×
14×
10×
4×
35×
1×
18×
4×
1×
18×
18×
18×
866×
866×
1×
130×
130×
70×
70×
70×
70×
1563×
1563×
74×
1563×
144×
70×
35×
19×
19×
16×
35×
1×
906×
906×
906×
965×
965×
965×
906×
1×
967×
1×
1016×
| import format from './format'
import Validators from './index'
import MESSAGES from './messages'
export const HAS_PROP = ({}).hasOwnProperty
export const TO_STRING = ({}).toString
export var DEFAULT_OPTIONS = {
allowBlank: false,
urlProtocols: ['http', 'https'],
dateFormat: 'yyyy-mm-dd', // ISO
dateYmd: 'ymd',
accept: ['1', 'true'],
caseSensitive: true, // confirmation, inclusion, exclusion
pluralRules: {
0: 'zero',
1: 'one'
}
};
export function regFormat (func, messageType) {
return memoize(function(options) {
options = options || {}
let msg = options.msg || options.message
return prepare(options['if'], options.unless, options.allowBlank, function (value) {
if (!value.match(func(options))) {
return Validators.formatMessage(prepareMsg(msg, messageType))
}
})
})
}
export function prepare (ifCond, unlessCond, allowBlank, func) {
return function (value, allValues={}) {
if (!value || 'object' !== typeof value) {
value = null == value ? '' : '' + value
if ((null != allowBlank ? allowBlank : Validators.defaultOptions.allowBlank) && !value.trim()) {
return
}
}
if (('function' !== typeof ifCond || ifCond(allValues, value)) &&
('function' !== typeof unlessCond || !unlessCond(allValues, value))) {
return func(value, allValues)
}
}
}
export function trunc (num) {
/* istanbul ignore next */
return Math.trunc ? Math.trunc(num) : num < 0 ? Math.ceil(num) : Math.floor(num)
}
export function selectNum (var1, var2) {
return isNumber(var1) ? +var1 : (arguments.length > 1 && isNumber(var2) ? +var2 : null)
}
export function isNumber (num) {
return !isNaN(num) && (0 != num || '' !== ('' + num).trim())
}
export function formatMsg (msg) {
if (msg.props) {
msg = msg.props
}
let text = msg.defaultMessage || msg.id || ''
let rules = Validators.defaultOptions.pluralRules
return !msg.values ? text : parseMsg(text, function(part) {
let parts = part.split(',')
let count = msg.values[parts[0]]
// {value} OR {count, number}
if (parts.length <= 2) {
return null == count ? '' : ('' + count)
}
// plural
let plural = parts.slice(2).join(',').trim()
let info = {}
let result = parseMsg(plural, null, rules[+count] || 'other', info)
return info.found ? result : parseMsg(plural, null, 'other', {})
})
}
export function prepareMsg (msg, type, values) {
if (null == msg) {
return Object.assign({}, MESSAGES[type], { values: values })
}
if (HAS_PROP.call(msg, 'props') && isReactElement(msg)) {
msg = msg.props
}
if (null != msg[type]) {
msg = msg[type]
}
if (isObject(msg)) {
if (HAS_PROP.call(msg, 'id') || HAS_PROP.call(msg, 'defaultMessage')) {
return Object.assign({}, msg, { values: values })
}
return Object.assign({}, MESSAGES[type], { values: values })
}
return { id: msg, defaultMessage: msg, values: values }
}
export function toObjectMsg (msg) {
if (null == msg) return null
return isObject(msg) ? msg : { id: msg, defaultMessage: msg }
}
export function memoize (func) {
Eif (!func.cache) {
func.cache = {}
}
return function(options) {
let key = stringify(options)
return HAS_PROP.call(func.cache, key) ? func.cache[key] : (func.cache[key] = func(options))
}
}
// private
function parseMsg (msg, func, pattern, info) {
let start = msg.indexOf('{')
if (start < 0) return pattern ? '' : msg
let index = start
let count = 1
let len = msg.length
while (count > 0 && index < len) {
++index;
if ('{' === msg.charAt(index)) {
++count;
}
if ('}' === msg.charAt(index)) {
--count;
}
}
if (pattern) {
if (pattern === msg.slice(0, start).trim()) {
info.found = true
return msg.slice(start + 1, index).trim()
}
return parseMsg(msg.slice(index + 1), null, pattern, info)
}
// func gets all '{.*}' parts
// e.g:
// - {count}
// - {count, plural, one {1 thing} other {many things}}
// - ...
return msg.slice(0, start) +
parseMsg(func(msg.slice(start + 1, index).trim()), func) +
parseMsg(msg.slice(index + 1), func)
}
function stringify (options) {
let arr = []
let value
for (var k in options) {
Eif (HAS_PROP.call(options, k)) {
value = options[k]
arr.push(k, isReactElement(value)
? stringify(value.props)
: isObject(value) ? stringify(value) : value.toString())
}
}
return JSON.stringify(arr)
}
function isReactElement (object) {
return typeof object === 'object' && object !== null && '$$typeof' in object;
}
function isObject (obj) {
return 'object' === typeof obj && '[object Object]' === TO_STRING.call(obj) && null !== obj;
} |