UNPKG

redux-form-validators

Version:

Simple validations with redux-form / react-final-form

162 lines (147 loc) 4.41 kB
import Validators from './validators' import { prepareMsg, prepare, selectNum, memoize, TO_STRING, stringToReg } from './helpers' let ACCEPT_SEP_REG = ',' let file = memoize(function ({ message, msg, accept, minSize, maxSize, minFiles, maxFiles, if: ifCond, unless, allowBlank } = {}) { msg = msg || message minFiles = selectNum(minFiles) maxFiles = selectNum(maxFiles) if (maxFiles < 0) { maxFiles = null } if (minFiles === null) { minFiles = 1 } if (typeof accept === 'string' && accept.trim()) { accept = accept .trim() .toLowerCase() .split(ACCEPT_SEP_REG) .map(function (type) { type = type.trim() return type.charAt(0) === '.' || type.indexOf('*') < 0 ? type : stringToReg(type) }) } else { accept = null } let min = minSize != null ? sizeToInt(minSize) : null let max = maxSize != null ? sizeToInt(maxSize) : null return prepare(ifCond, unless, false, function (value) { let isAFileList = isFileList(value) // special blank check if ( (allowBlank != null ? allowBlank : Validators.defaultOptions.allowBlank) && (typeof value === 'string' ? value.trim() === '' : isAFileList && value.length === 0) ) { return } if (!isAFileList) { return Validators.formatMessage(prepareMsg(msg, 'file')) } if (isNaN(value.length)) { value = [value] } if (value.length < minFiles) { return Validators.formatMessage(prepareMsg(msg, 'fileTooFew', 'tooFew', 'minFiles', { count: minFiles })) } if (maxFiles !== null && value.length > maxFiles) { return Validators.formatMessage(prepareMsg(msg, 'fileTooMany', 'tooMany', 'maxFiles', { count: maxFiles })) } let acceptError = [] let tooSmallError = [] let tooBigError = [] for (let i = 0, len = value.length, val, ftype, fext; i < len; ++i) { val = value[i] if (accept) { ftype = val.type || /* istanbul ignore next */ '' fext = fileExt(val.name || /* istanbul ignore next */ '') if ( !accept.some(function (type) { return typeof type === 'string' ? type === (type.charAt(0) === '.' ? fext : ftype) : type.test(ftype) }) ) { acceptError.push(val) } } if (min != null && val.size < min) { tooSmallError.push(val) } if (max != null && val.size > max) { tooBigError.push(val) } } if (acceptError.length) { return Validators.formatMessage( prepareMsg(msg, 'fileAccept', 'accept', { files: acceptError, count: acceptError.length }) ) } if (tooSmallError.length) { let pair = parse(minSize) return Validators.formatMessage( prepareMsg(msg, 'fileTooSmall', 'tooSmall', 'minSize', { files: tooSmallError, count: tooSmallError.length, size: Validators.formatSize(pair[1], pair[2] || 'B') }) ) } if (tooBigError.length) { let pair = parse(maxSize) return Validators.formatMessage( prepareMsg(msg, 'fileTooBig', 'tooBig', 'maxSize', { files: tooBigError, count: tooBigError.length, size: Validators.formatSize(pair[1], pair[2] || 'B') }) ) } }) }) export default file export function isFileList (value) { if ( (typeof FileList !== 'undefined' && value instanceof FileList) || (typeof File !== 'undefined' && (value instanceof File || value[0] instanceof File)) ) { return true } let str = TO_STRING.call(value) return str === '[object FileList]' || str === '[object File]' || TO_STRING.call(value[0]) === '[object File]' } // private // eslint-disable-next-line no-useless-escape const SIZE_REG = /^([\d\.]+)\s*([KMGTPE]?B)?$/ const SIZE_UNITS = { B: 1, KB: 1024, MB: 1048576, GB: 1073741824, TB: 1099511627776, PB: 1125899906842624, EB: 1152921504606847000 } function parse (size) { return SIZE_REG.exec(('' + size).trim()) } function sizeToInt (size) { let pair = parse(size) if (pair) return pair[1] * (SIZE_UNITS[pair[2]] || 1) /* istanbul ignore else */ if (typeof console !== 'undefined') { console.error(`file validator: size "${size}" unknown`) } return null } function fileExt (filename) { return filename.slice(((filename.lastIndexOf('.') - 1) >>> 0) + 1).toLowerCase() }