From 740c52102acdbed17a5b4c3746600dfb116356c1 Mon Sep 17 00:00:00 2001 From: "l.gersen@visymo.com" Date: Tue, 29 Oct 2019 10:26:15 +0100 Subject: [PATCH] wNumb 1.2.0 - Add Prettier - Change Licence to MIT - Added minified version - Add "files" directive to package --- .gitignore | 1 + LICENSE.MD | 9 + README.md | 11 +- package-lock.json | 36 +++ package.json | 17 +- test.html | 2 +- wNumb.js | 716 ++++++++++++++++++++++++---------------------- wNumb.min.js | 1 + 8 files changed, 441 insertions(+), 352 deletions(-) create mode 100644 .gitignore create mode 100644 LICENSE.MD create mode 100644 package-lock.json create mode 100644 wNumb.min.js diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..07e6e47 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/node_modules diff --git a/LICENSE.MD b/LICENSE.MD new file mode 100644 index 0000000..82ac8ca --- /dev/null +++ b/LICENSE.MD @@ -0,0 +1,9 @@ +MIT License + +Copyright (c) 2019 Léon Gersen + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md index f6d891d..df26842 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,22 @@ -wnumb +wNumb ===== wNumb - JavaScript Number & Money formatting # Documentation -Documentation and examples are available on [refreshless.com/wnumb](http://refreshless.com/wnumb/). +Documentation and examples are available on [refreshless.com/wnumb](https://refreshless.com/wnumb/). # Changelog +### 1.2.0 (*2019-10-29*) +- Changed: License is now MIT +- Added: Prettier code formatter +- Added: Minified version + ### 1.1.0 (*2017-02-04*) - Changed: Renamed `postfix` option to the proper `suffix`. `postfix` is remapped internally for backward compatibility; # License -Licensed [WTFPL](http://www.wtfpl.net/about/), so free for personal and commercial use. +Licensed MIT, so free for personal and commercial use. diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..333174b --- /dev/null +++ b/package-lock.json @@ -0,0 +1,36 @@ +{ + "name": "wnumb", + "version": "1.2.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "prettier": { + "version": "1.18.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.18.2.tgz", + "integrity": "sha512-OeHeMc0JhFE9idD4ZdtNibzY0+TPHSpSSb9h8FqtP+YnoZZ1sl8Vc9b1sasjfymH3SonAF4QcA2+mzHPhMvIiw==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "uglify-js": { + "version": "3.6.5", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.6.5.tgz", + "integrity": "sha512-7L3W+Npia1OCr5Blp4/Vw83tK1mu5gnoIURtT1fUVfQ3Kf8WStWV6NJz0fdoBJZls0KlweruRTLVe6XLafmy5g==", + "dev": true, + "requires": { + "commander": "~2.20.3", + "source-map": "~0.6.1" + } + } + } +} diff --git a/package.json b/package.json index 2cdafa6..10759c6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wnumb", - "version": "1.1.0", + "version": "1.2.0", "description": "wNumb - JavaScript Number & Money formatting", "main": "wNumb.js", "repository": { @@ -8,8 +8,21 @@ "url": "git://github.com/leongersen/wnumb.git" }, "author": "leongersen", - "license": "WTFPL", + "license": "MIT", + "scripts": { + "format": "prettier wNumb.js --write --print-width=120", + "minify": "uglifyjs wNumb.js --compress --mangle --output wNumb.min.js", + "build": "npm run format && npm run minify" + }, + "files": [ + "wNumb.js", + "wNumb.min.js" + ], "bugs": { "url": "https://github.com/leongersen/wnumb/issues" + }, + "devDependencies": { + "prettier": "^1.18.2", + "uglify-js": "^3.6.5" } } diff --git a/test.html b/test.html index 7ddaeb3..7bbb3e1 100644 --- a/test.html +++ b/test.html @@ -3,7 +3,7 @@ - +
diff --git a/wNumb.js b/wNumb.js index 4ab340f..4fef4f0 100644 --- a/wNumb.js +++ b/wNumb.js @@ -1,357 +1,381 @@ -(function (factory) { +(function(factory) { + if (typeof define === "function" && define.amd) { + // AMD. Register as an anonymous module. + define([], factory); + } else if (typeof exports === "object") { + // Node/CommonJS + module.exports = factory(); + } else { + // Browser globals + window.wNumb = factory(); + } +})(function() { + "use strict"; + + var FormatOptions = [ + "decimals", + "thousand", + "mark", + "prefix", + "suffix", + "encoder", + "decoder", + "negativeBefore", + "negative", + "edit", + "undo" + ]; + + // General + + // Reverse a string + function strReverse(a) { + return a + .split("") + .reverse() + .join(""); + } + + // Check if a string starts with a specified prefix. + function strStartsWith(input, match) { + return input.substring(0, match.length) === match; + } + + // Check is a string ends in a specified suffix. + function strEndsWith(input, match) { + return input.slice(-1 * match.length) === match; + } + + // Throw an error if formatting options are incompatible. + function throwEqualError(F, a, b) { + if ((F[a] || F[b]) && F[a] === F[b]) { + throw new Error(a); + } + } + + // Check if a number is finite and not NaN + function isValidNumber(input) { + return typeof input === "number" && isFinite(input); + } + + // Provide rounding-accurate toFixed method. + // Borrowed: http://stackoverflow.com/a/21323330/775265 + function toFixed(value, exp) { + value = value.toString().split("e"); + value = Math.round(+(value[0] + "e" + (value[1] ? +value[1] + exp : exp))); + value = value.toString().split("e"); + return (+(value[0] + "e" + (value[1] ? +value[1] - exp : -exp))).toFixed(exp); + } + + // Formatting + + // Accept a number as input, output formatted string. + function formatTo( + decimals, + thousand, + mark, + prefix, + suffix, + encoder, + decoder, + negativeBefore, + negative, + edit, + undo, + input + ) { + var originalInput = input, + inputIsNegative, + inputPieces, + inputBase, + inputDecimals = "", + output = ""; + + // Apply user encoder to the input. + // Expected outcome: number. + if (encoder) { + input = encoder(input); + } - if ( typeof define === 'function' && define.amd ) { + // Stop if no valid number was provided, the number is infinite or NaN. + if (!isValidNumber(input)) { + return false; + } + + // Rounding away decimals might cause a value of -0 + // when using very small ranges. Remove those cases. + if (decimals !== false && parseFloat(input.toFixed(decimals)) === 0) { + input = 0; + } + + // Formatting is done on absolute numbers, + // decorated by an optional negative symbol. + if (input < 0) { + inputIsNegative = true; + input = Math.abs(input); + } + + // Reduce the number of decimals to the specified option. + if (decimals !== false) { + input = toFixed(input, decimals); + } - // AMD. Register as an anonymous module. - define([], factory); + // Transform the number into a string, so it can be split. + input = input.toString(); - } else if ( typeof exports === 'object' ) { + // Break the number on the decimal separator. + if (input.indexOf(".") !== -1) { + inputPieces = input.split("."); - // Node/CommonJS - module.exports = factory(); + inputBase = inputPieces[0]; + if (mark) { + inputDecimals = mark + inputPieces[1]; + } } else { + // If it isn't split, the entire number will do. + inputBase = input; + } + + // Group numbers in sets of three. + if (thousand) { + inputBase = strReverse(inputBase).match(/.{1,3}/g); + inputBase = strReverse(inputBase.join(strReverse(thousand))); + } + + // If the number is negative, prefix with negation symbol. + if (inputIsNegative && negativeBefore) { + output += negativeBefore; + } + + // Prefix the number + if (prefix) { + output += prefix; + } + + // Normal negative option comes after the prefix. Defaults to '-'. + if (inputIsNegative && negative) { + output += negative; + } + + // Append the actual number. + output += inputBase; + output += inputDecimals; + + // Apply the suffix. + if (suffix) { + output += suffix; + } + + // Run the output through a user-specified post-formatter. + if (edit) { + output = edit(output, originalInput); + } + + // All done. + return output; + } + + // Accept a sting as input, output decoded number. + function formatFrom( + decimals, + thousand, + mark, + prefix, + suffix, + encoder, + decoder, + negativeBefore, + negative, + edit, + undo, + input + ) { + var originalInput = input, + inputIsNegative, + output = ""; + + // User defined pre-decoder. Result must be a non empty string. + if (undo) { + input = undo(input); + } + + // Test the input. Can't be empty. + if (!input || typeof input !== "string") { + return false; + } + + // If the string starts with the negativeBefore value: remove it. + // Remember is was there, the number is negative. + if (negativeBefore && strStartsWith(input, negativeBefore)) { + input = input.replace(negativeBefore, ""); + inputIsNegative = true; + } + + // Repeat the same procedure for the prefix. + if (prefix && strStartsWith(input, prefix)) { + input = input.replace(prefix, ""); + } + + // And again for negative. + if (negative && strStartsWith(input, negative)) { + input = input.replace(negative, ""); + inputIsNegative = true; + } - // Browser globals - window.wNumb = factory(); + // Remove the suffix. + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/slice + if (suffix && strEndsWith(input, suffix)) { + input = input.slice(0, -1 * suffix.length); } -}(function(){ - - 'use strict'; - -var FormatOptions = [ - 'decimals', - 'thousand', - 'mark', - 'prefix', - 'suffix', - 'encoder', - 'decoder', - 'negativeBefore', - 'negative', - 'edit', - 'undo' -]; - -// General - - // Reverse a string - function strReverse ( a ) { - return a.split('').reverse().join(''); - } - - // Check if a string starts with a specified prefix. - function strStartsWith ( input, match ) { - return input.substring(0, match.length) === match; - } - - // Check is a string ends in a specified suffix. - function strEndsWith ( input, match ) { - return input.slice(-1 * match.length) === match; - } - - // Throw an error if formatting options are incompatible. - function throwEqualError( F, a, b ) { - if ( (F[a] || F[b]) && (F[a] === F[b]) ) { - throw new Error(a); - } - } - - // Check if a number is finite and not NaN - function isValidNumber ( input ) { - return typeof input === 'number' && isFinite( input ); - } - - // Provide rounding-accurate toFixed method. - // Borrowed: http://stackoverflow.com/a/21323330/775265 - function toFixed ( value, exp ) { - value = value.toString().split('e'); - value = Math.round(+(value[0] + 'e' + (value[1] ? (+value[1] + exp) : exp))); - value = value.toString().split('e'); - return (+(value[0] + 'e' + (value[1] ? (+value[1] - exp) : -exp))).toFixed(exp); - } - - -// Formatting - - // Accept a number as input, output formatted string. - function formatTo ( decimals, thousand, mark, prefix, suffix, encoder, decoder, negativeBefore, negative, edit, undo, input ) { - - var originalInput = input, inputIsNegative, inputPieces, inputBase, inputDecimals = '', output = ''; - - // Apply user encoder to the input. - // Expected outcome: number. - if ( encoder ) { - input = encoder(input); - } - - // Stop if no valid number was provided, the number is infinite or NaN. - if ( !isValidNumber(input) ) { - return false; - } - - // Rounding away decimals might cause a value of -0 - // when using very small ranges. Remove those cases. - if ( decimals !== false && parseFloat(input.toFixed(decimals)) === 0 ) { - input = 0; - } - - // Formatting is done on absolute numbers, - // decorated by an optional negative symbol. - if ( input < 0 ) { - inputIsNegative = true; - input = Math.abs(input); - } - - // Reduce the number of decimals to the specified option. - if ( decimals !== false ) { - input = toFixed( input, decimals ); - } - - // Transform the number into a string, so it can be split. - input = input.toString(); - - // Break the number on the decimal separator. - if ( input.indexOf('.') !== -1 ) { - inputPieces = input.split('.'); - - inputBase = inputPieces[0]; - - if ( mark ) { - inputDecimals = mark + inputPieces[1]; - } - - } else { - - // If it isn't split, the entire number will do. - inputBase = input; - } - - // Group numbers in sets of three. - if ( thousand ) { - inputBase = strReverse(inputBase).match(/.{1,3}/g); - inputBase = strReverse(inputBase.join( strReverse( thousand ) )); - } - - // If the number is negative, prefix with negation symbol. - if ( inputIsNegative && negativeBefore ) { - output += negativeBefore; - } - - // Prefix the number - if ( prefix ) { - output += prefix; - } - - // Normal negative option comes after the prefix. Defaults to '-'. - if ( inputIsNegative && negative ) { - output += negative; - } - - // Append the actual number. - output += inputBase; - output += inputDecimals; - - // Apply the suffix. - if ( suffix ) { - output += suffix; - } - - // Run the output through a user-specified post-formatter. - if ( edit ) { - output = edit ( output, originalInput ); - } - - // All done. - return output; - } - - // Accept a sting as input, output decoded number. - function formatFrom ( decimals, thousand, mark, prefix, suffix, encoder, decoder, negativeBefore, negative, edit, undo, input ) { + // Remove the thousand grouping. + if (thousand) { + input = input.split(thousand).join(""); + } + + // Set the decimal separator back to period. + if (mark) { + input = input.replace(mark, "."); + } + + // Prepend the negative symbol. + if (inputIsNegative) { + output += "-"; + } + + // Add the number + output += input; + + // Trim all non-numeric characters (allow '.' and '-'); + output = output.replace(/[^0-9\.\-.]/g, ""); + + // The value contains no parse-able number. + if (output === "") { + return false; + } + + // Covert to number. + output = Number(output); + + // Run the user-specified post-decoder. + if (decoder) { + output = decoder(output); + } + + // Check is the output is valid, otherwise: return false. + if (!isValidNumber(output)) { + return false; + } + + return output; + } + + // Framework + + // Validate formatting options + function validate(inputOptions) { + var i, + optionName, + optionValue, + filteredOptions = {}; + + if (inputOptions["suffix"] === undefined) { + inputOptions["suffix"] = inputOptions["postfix"]; + } + + for (i = 0; i < FormatOptions.length; i += 1) { + optionName = FormatOptions[i]; + optionValue = inputOptions[optionName]; + + if (optionValue === undefined) { + // Only default if negativeBefore isn't set. + if (optionName === "negative" && !filteredOptions.negativeBefore) { + filteredOptions[optionName] = "-"; + // Don't set a default for mark when 'thousand' is set. + } else if (optionName === "mark" && filteredOptions.thousand !== ".") { + filteredOptions[optionName] = "."; + } else { + filteredOptions[optionName] = false; + } + + // Floating points in JS are stable up to 7 decimals. + } else if (optionName === "decimals") { + if (optionValue >= 0 && optionValue < 8) { + filteredOptions[optionName] = optionValue; + } else { + throw new Error(optionName); + } + + // These options, when provided, must be functions. + } else if ( + optionName === "encoder" || + optionName === "decoder" || + optionName === "edit" || + optionName === "undo" + ) { + if (typeof optionValue === "function") { + filteredOptions[optionName] = optionValue; + } else { + throw new Error(optionName); + } + + // Other options are strings. + } else { + if (typeof optionValue === "string") { + filteredOptions[optionName] = optionValue; + } else { + throw new Error(optionName); + } + } + } + + // Some values can't be extracted from a + // string if certain combinations are present. + throwEqualError(filteredOptions, "mark", "thousand"); + throwEqualError(filteredOptions, "prefix", "negative"); + throwEqualError(filteredOptions, "prefix", "negativeBefore"); + + return filteredOptions; + } + + // Pass all options as function arguments + function passAll(options, method, input) { + var i, + args = []; + + // Add all options in order of FormatOptions + for (i = 0; i < FormatOptions.length; i += 1) { + args.push(options[FormatOptions[i]]); + } + + // Append the input, then call the method, presenting all + // options as arguments. + args.push(input); + return method.apply("", args); + } + + function wNumb(options) { + if (!(this instanceof wNumb)) { + return new wNumb(options); + } + + if (typeof options !== "object") { + return; + } + + options = validate(options); + + // Call 'formatTo' with proper arguments. + this.to = function(input) { + return passAll(options, formatTo, input); + }; - var originalInput = input, inputIsNegative, output = ''; + // Call 'formatFrom' with proper arguments. + this.from = function(input) { + return passAll(options, formatFrom, input); + }; + } - // User defined pre-decoder. Result must be a non empty string. - if ( undo ) { - input = undo(input); - } - - // Test the input. Can't be empty. - if ( !input || typeof input !== 'string' ) { - return false; - } - - // If the string starts with the negativeBefore value: remove it. - // Remember is was there, the number is negative. - if ( negativeBefore && strStartsWith(input, negativeBefore) ) { - input = input.replace(negativeBefore, ''); - inputIsNegative = true; - } - - // Repeat the same procedure for the prefix. - if ( prefix && strStartsWith(input, prefix) ) { - input = input.replace(prefix, ''); - } - - // And again for negative. - if ( negative && strStartsWith(input, negative) ) { - input = input.replace(negative, ''); - inputIsNegative = true; - } - - // Remove the suffix. - // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/slice - if ( suffix && strEndsWith(input, suffix) ) { - input = input.slice(0, -1 * suffix.length); - } - - // Remove the thousand grouping. - if ( thousand ) { - input = input.split(thousand).join(''); - } - - // Set the decimal separator back to period. - if ( mark ) { - input = input.replace(mark, '.'); - } - - // Prepend the negative symbol. - if ( inputIsNegative ) { - output += '-'; - } - - // Add the number - output += input; - - // Trim all non-numeric characters (allow '.' and '-'); - output = output.replace(/[^0-9\.\-.]/g, ''); - - // The value contains no parse-able number. - if ( output === '' ) { - return false; - } - - // Covert to number. - output = Number(output); - - // Run the user-specified post-decoder. - if ( decoder ) { - output = decoder(output); - } - - // Check is the output is valid, otherwise: return false. - if ( !isValidNumber(output) ) { - return false; - } - - return output; - } - - -// Framework - - // Validate formatting options - function validate ( inputOptions ) { - - var i, optionName, optionValue, - filteredOptions = {}; - - if ( inputOptions['suffix'] === undefined ) { - inputOptions['suffix'] = inputOptions['postfix']; - } - - for ( i = 0; i < FormatOptions.length; i+=1 ) { - - optionName = FormatOptions[i]; - optionValue = inputOptions[optionName]; - - if ( optionValue === undefined ) { - - // Only default if negativeBefore isn't set. - if ( optionName === 'negative' && !filteredOptions.negativeBefore ) { - filteredOptions[optionName] = '-'; - // Don't set a default for mark when 'thousand' is set. - } else if ( optionName === 'mark' && filteredOptions.thousand !== '.' ) { - filteredOptions[optionName] = '.'; - } else { - filteredOptions[optionName] = false; - } - - // Floating points in JS are stable up to 7 decimals. - } else if ( optionName === 'decimals' ) { - if ( optionValue >= 0 && optionValue < 8 ) { - filteredOptions[optionName] = optionValue; - } else { - throw new Error(optionName); - } - - // These options, when provided, must be functions. - } else if ( optionName === 'encoder' || optionName === 'decoder' || optionName === 'edit' || optionName === 'undo' ) { - if ( typeof optionValue === 'function' ) { - filteredOptions[optionName] = optionValue; - } else { - throw new Error(optionName); - } - - // Other options are strings. - } else { - - if ( typeof optionValue === 'string' ) { - filteredOptions[optionName] = optionValue; - } else { - throw new Error(optionName); - } - } - } - - // Some values can't be extracted from a - // string if certain combinations are present. - throwEqualError(filteredOptions, 'mark', 'thousand'); - throwEqualError(filteredOptions, 'prefix', 'negative'); - throwEqualError(filteredOptions, 'prefix', 'negativeBefore'); - - return filteredOptions; - } - - // Pass all options as function arguments - function passAll ( options, method, input ) { - var i, args = []; - - // Add all options in order of FormatOptions - for ( i = 0; i < FormatOptions.length; i+=1 ) { - args.push(options[FormatOptions[i]]); - } - - // Append the input, then call the method, presenting all - // options as arguments. - args.push(input); - return method.apply('', args); - } - - function wNumb ( options ) { - - if ( !(this instanceof wNumb) ) { - return new wNumb ( options ); - } - - if ( typeof options !== "object" ) { - return; - } - - options = validate(options); - - // Call 'formatTo' with proper arguments. - this.to = function ( input ) { - return passAll(options, formatTo, input); - }; - - // Call 'formatFrom' with proper arguments. - this.from = function ( input ) { - return passAll(options, formatFrom, input); - }; - } - - return wNumb; - -})); + return wNumb; +}); diff --git a/wNumb.min.js b/wNumb.min.js new file mode 100644 index 0000000..bb8f177 --- /dev/null +++ b/wNumb.min.js @@ -0,0 +1 @@ +!function(e){"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?module.exports=e():window.wNumb=e()}(function(){"use strict";var o=["decimals","thousand","mark","prefix","suffix","encoder","decoder","negativeBefore","negative","edit","undo"];function w(e){return e.split("").reverse().join("")}function h(e,t){return e.substring(0,t.length)===t}function f(e,t,n){if((e[t]||e[n])&&e[t]===e[n])throw new Error(t)}function x(e){return"number"==typeof e&&isFinite(e)}function n(e,t,n,r,i,o,f,u,s,c,a,p){var d,l,h,g=p,v="",m="";return o&&(p=o(p)),!!x(p)&&(!1!==e&&0===parseFloat(p.toFixed(e))&&(p=0),p<0&&(d=!0,p=Math.abs(p)),!1!==e&&(p=function(e,t){return e=e.toString().split("e"),(+((e=(e=Math.round(+(e[0]+"e"+(e[1]?+e[1]+t:t)))).toString().split("e"))[0]+"e"+(e[1]?e[1]-t:-t))).toFixed(t)}(p,e)),-1!==(p=p.toString()).indexOf(".")?(h=(l=p.split("."))[0],n&&(v=n+l[1])):h=p,t&&(h=w((h=w(h).match(/.{1,3}/g)).join(w(t)))),d&&u&&(m+=u),r&&(m+=r),d&&s&&(m+=s),m+=h,m+=v,i&&(m+=i),c&&(m=c(m,g)),m)}function r(e,t,n,r,i,o,f,u,s,c,a,p){var d,l="";return a&&(p=a(p)),!(!p||"string"!=typeof p)&&(u&&h(p,u)&&(p=p.replace(u,""),d=!0),r&&h(p,r)&&(p=p.replace(r,"")),s&&h(p,s)&&(p=p.replace(s,""),d=!0),i&&function(e,t){return e.slice(-1*t.length)===t}(p,i)&&(p=p.slice(0,-1*i.length)),t&&(p=p.split(t).join("")),n&&(p=p.replace(n,".")),d&&(l+="-"),""!==(l=(l+=p).replace(/[^0-9\.\-.]/g,""))&&(l=Number(l),f&&(l=f(l)),!!x(l)&&l))}function i(e,t,n){var r,i=[];for(r=0;r