@jalik/form-parser
Advanced tools
Comparing version 2.0.11 to 2.0.12
"use strict"; | ||
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); | ||
Object.defineProperty(exports, "__esModule", { | ||
@@ -10,28 +9,25 @@ value: true | ||
exports.contains = contains; | ||
exports.getFormFields = getFormFields; | ||
exports.isButton = isButton; | ||
exports.isCheckableField = isCheckableField; | ||
exports.isMultipleField = isMultipleField; | ||
exports.nullify = nullify; | ||
exports.trim = trim; | ||
exports.parseBoolean = parseBoolean; | ||
exports.parseField = parseField; | ||
exports.parseForm = parseForm; | ||
exports.parseNumber = parseNumber; | ||
exports.parseValue = parseValue; | ||
exports.parseField = parseField; | ||
exports.parseForm = parseForm; | ||
exports.trim = trim; | ||
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); | ||
var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof")); | ||
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; } | ||
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { (0, _defineProperty2["default"])(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } | ||
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; } | ||
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { (0, _defineProperty2["default"])(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; } | ||
/* | ||
* The MIT License (MIT) | ||
* Copyright (c) 2021 Karl STEIN | ||
* Copyright (c) 2022 Karl STEIN | ||
*/ | ||
/** | ||
* Builds an object from a string (ex: [colors][0][code]) | ||
* @param str | ||
* Builds an object from a string (ex: [colors][0][code]). | ||
* @param {string} str | ||
* @param value | ||
@@ -45,9 +41,8 @@ * @param context | ||
} | ||
var ctx = context; | ||
var ctx = context; // Check missing brackets | ||
// Check missing brackets | ||
if (typeof ctx === 'undefined' || ctx === null) { | ||
var opening = (str.match(/\[/g) || []).length; | ||
var closing = (str.match(/]/g) || []).length; | ||
if (opening !== closing) { | ||
@@ -61,5 +56,3 @@ if (opening > closing) { | ||
} | ||
var index = str.indexOf('['); | ||
if (index === -1) { | ||
@@ -79,18 +72,16 @@ // Field without brackets and without attribute | ||
var end = str.indexOf(']', index + 1); | ||
var _subtree = str.substr(end + 1); | ||
var key = str.substring(index + 1, end); | ||
var key = str.substring(index + 1, end); // Object attribute | ||
// Object attribute | ||
// ex: [customField1] or ["10"] or ['10'] | ||
if (key.length > 0 && (!/^\d+$/.test(key) || /^(["'])[^"']+\1$/.test(key))) { | ||
// Remove quotes in key | ||
key = key.replace(/^["']/, '').replace(/["']$/, ''); // Create empty object if context is not defined | ||
key = key.replace(/^["']/, '').replace(/["']$/, ''); | ||
// Create empty object if context is not defined | ||
if (typeof ctx === 'undefined' || ctx === null) { | ||
ctx = {}; | ||
} | ||
var result = buildObject(_subtree, value, ctx[key]); | ||
if (typeof result !== 'undefined') { | ||
@@ -108,3 +99,2 @@ // Put value in attribute | ||
} | ||
if (key.length === 0) { | ||
@@ -114,3 +104,2 @@ // Array with dynamic index | ||
var _result = buildObject(_subtree, value, null); | ||
if (typeof _result !== 'undefined') { | ||
@@ -124,5 +113,3 @@ // Put value at the end of the array | ||
var _result2 = buildObject(_subtree, value, ctx[key]); | ||
var keyIndex = parseInt(key, 10); | ||
if (typeof _result2 !== 'undefined') { | ||
@@ -138,16 +125,13 @@ // Put value at the specified index | ||
} | ||
return ctx; | ||
} | ||
/** | ||
* Checks if value is in list | ||
* @param list | ||
* @param value | ||
* Checks if value is in list. | ||
* @param {*[]} list | ||
* @param {*} value | ||
* @return {boolean} | ||
*/ | ||
function contains(list, value) { | ||
var result = false; | ||
if (list instanceof Array) { | ||
@@ -161,35 +145,63 @@ for (var i = 0; i < list.length; i += 1) { | ||
} | ||
return result; | ||
} | ||
/** | ||
* Checks if the field is a button | ||
* @param field | ||
* Returns form fields. | ||
* @param {HTMLFormElement} form | ||
* @param {function|undefined} filter | ||
* @returns {*[]} | ||
*/ | ||
function getFormFields(form) { | ||
var filter = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined; | ||
var elements = form.elements; | ||
var fields = []; | ||
for (var i = 0; i < elements.length; i += 1) { | ||
var el = elements[i]; | ||
if (!filter || filter(el)) { | ||
fields.push(el); | ||
} | ||
} | ||
return fields; | ||
} | ||
/** | ||
* Checks if the field is a button. | ||
* @param {HTMLInputElement|HTMLSelectElement|HTMLTextAreaElement} field | ||
* @return {*|boolean} | ||
*/ | ||
function isButton(field) { | ||
return field && (field.localName === 'button' || contains(['button', 'reset', 'submit'], field.type)); | ||
} | ||
/** | ||
* Checks if the field is checkable | ||
* @param field | ||
* Checks if the field is checkable. | ||
* @param {HTMLInputElement|HTMLSelectElement|HTMLTextAreaElement} field | ||
* @return {*|boolean} | ||
*/ | ||
function isCheckableField(field) { | ||
return typeof field.type === 'string' && contains(['checkbox', 'radio'], field.type); | ||
} | ||
/** | ||
* Replaces empty string by null value | ||
* Checks if field has multiple values. | ||
* @param {HTMLInputElement|HTMLSelectElement|HTMLTextAreaElement|HTMLElement} field | ||
* @return {boolean} | ||
*/ | ||
function isMultipleField(field) { | ||
// Field has attribute "multiple". | ||
if (field.multiple) { | ||
return true; | ||
} | ||
// Field name contains an empty array (example: "numbers[]"). | ||
return field.name != null && /\[]$/.test(field.name); | ||
} | ||
/** | ||
* Replaces empty string by null value. | ||
* @param value | ||
* @return {Object|string|Array|*} | ||
* @return {null|*|*[]} | ||
*/ | ||
function nullify(value) { | ||
var newValue = value; | ||
if (newValue instanceof Array) { | ||
@@ -201,3 +213,2 @@ for (var i = 0; i < newValue.length; i += 1) { | ||
var keys = Object.keys(newValue); | ||
for (var _i = 0; _i < keys.length; _i += 1) { | ||
@@ -210,15 +221,12 @@ var key = keys[_i]; | ||
} | ||
return newValue; | ||
} | ||
/** | ||
* Removes extra spaces | ||
* @param value | ||
* Removes extra spaces. | ||
* @param {string|*[]} value | ||
* @return {Object|string|Array|*} | ||
*/ | ||
function trim(value) { | ||
var newValue = value; | ||
if (newValue instanceof Array) { | ||
@@ -230,3 +238,2 @@ for (var i = 0; i < newValue.length; i += 1) { | ||
var keys = Object.keys(newValue); | ||
for (var _i2 = 0; _i2 < keys.length; _i2 += 1) { | ||
@@ -239,116 +246,85 @@ var key = keys[_i2]; | ||
} | ||
return newValue; | ||
} | ||
/** | ||
* Returns a boolean | ||
* @param value | ||
* Returns a boolean. | ||
* @param {string} value | ||
* @return {boolean|null} | ||
*/ | ||
function parseBoolean(value) { | ||
var bool = value; | ||
if (typeof bool === 'string') { | ||
bool = bool.trim(); | ||
} | ||
var bool = String(value).trim(); | ||
if (/^(true|1)$/i.test(bool)) { | ||
return true; | ||
} | ||
if (/^(false|0)$/i.test(bool)) { | ||
return false; | ||
} | ||
return null; | ||
} | ||
/** | ||
* Returns a number | ||
* @param value | ||
* Returns a number. | ||
* @param {string} value | ||
* @return {number|null} | ||
*/ | ||
function parseNumber(value) { | ||
var number = value; | ||
if (typeof value !== 'number') { | ||
if (typeof value === 'string') { | ||
// Remove spaces | ||
number = value.replace(/ /g, ''); | ||
} | ||
if (/^[+-]?[0-9]*[.,][0-9]+$/.test(number)) { | ||
// Replace comma with dot (for languages where number contain a comma instead of a dot) | ||
number = parseFloat(String(number).replace(/,/g, '.')); | ||
} else if (/^[+-]?[0-9]+$/.test(number)) { | ||
number = parseInt(number, 10); | ||
} else { | ||
number = null; | ||
} | ||
var number = String(value).trim() | ||
// Remove spaces | ||
.replace(/ /g, ''); | ||
if (/^[+-]?[0-9]*[.,][0-9]+$/.test(number)) { | ||
// Replace comma with dot (for languages where number contain a comma instead of a dot) | ||
return parseFloat(String(number).replace(/,/g, '.')); | ||
} | ||
if (/^[+-]?[0-9]+$/.test(number)) { | ||
return parseInt(number, 10); | ||
} | ||
return null; | ||
} | ||
return number; | ||
} | ||
/** | ||
* Returns the typed value of a string value | ||
* @param value | ||
* @param type | ||
* @param {string|null} value | ||
* @param {'auto'|'boolean'|'number'} type | ||
* @returns {string|number|boolean|null} | ||
*/ | ||
function parseValue(value) { | ||
var type = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'auto'; | ||
var newVal = value; | ||
if (typeof newVal === 'string') { | ||
if (newVal.length > 0) { | ||
switch (type) { | ||
case 'auto': | ||
{ | ||
var bool = parseBoolean(newVal); | ||
if (typeof bool === 'boolean') { | ||
newVal = bool; | ||
break; | ||
} | ||
var number = parseNumber(newVal); | ||
if (typeof number === 'number') { | ||
newVal = number; | ||
} | ||
if (value == null) { | ||
return null; | ||
} | ||
var result = String(value); | ||
if (result.length > 0) { | ||
switch (type) { | ||
case 'auto': | ||
{ | ||
var bool = parseBoolean(result); | ||
if (typeof bool === 'boolean') { | ||
result = bool; | ||
break; | ||
} | ||
case 'boolean': | ||
newVal = parseBoolean(newVal); | ||
var number = parseNumber(result); | ||
if (typeof number === 'number') { | ||
result = number; | ||
} | ||
break; | ||
case 'number': | ||
newVal = parseNumber(newVal); | ||
break; | ||
case 'string': | ||
break; | ||
default: | ||
} | ||
} | ||
case 'boolean': | ||
result = parseBoolean(result); | ||
break; | ||
case 'number': | ||
result = parseNumber(result); | ||
break; | ||
default: | ||
} | ||
} | ||
return result; | ||
} | ||
return newVal; | ||
} | ||
/** | ||
* Returns the parsed value of the field | ||
* @param field | ||
* @param {HTMLInputElement|HTMLSelectElement|HTMLTextAreaElement} field | ||
* @param options | ||
* @return {*} | ||
*/ | ||
function parseField(field, options) { | ||
@@ -358,10 +334,9 @@ // Check field instance | ||
throw new TypeError('field is not an instance of HTMLElement'); | ||
} // Check field name | ||
} | ||
// Check field name | ||
if (!contains(['button', 'input', 'select', 'textarea'], field.localName)) { | ||
throw new TypeError('field is not a form field (button, input, select, textarea)'); | ||
} // Set default options | ||
} | ||
// Set default options | ||
var opts = _objectSpread({ | ||
@@ -373,19 +348,27 @@ dynamicTyping: true, | ||
}, options); | ||
var isCheckable = isCheckableField(field); | ||
var value = field.value; // Fetch value from special fields | ||
var isMultiple = isMultipleField(field); | ||
var form = field.form; | ||
var value = field.value; | ||
// Fetch value from special fields | ||
switch (field.localName) { | ||
case 'input': | ||
if (isCheckable) { | ||
// Keep value only if element is checked | ||
value = field.checked ? value : undefined; | ||
if (isMultiple) { | ||
value = getFormFields(form, function (el) { | ||
return el.name === field.name && el.checked === true; | ||
}).map(function (el) { | ||
return el.value; | ||
}); | ||
} else { | ||
value = field.checked ? value : null; | ||
} | ||
} | ||
break; | ||
case 'select': | ||
if (field.multiple) { | ||
value = []; // Collect values of selected options | ||
value = []; | ||
// Collect values of selected options | ||
if (field.options instanceof HTMLCollection) { | ||
@@ -399,8 +382,5 @@ for (var o = 0; o < field.options.length; o += 1) { | ||
} | ||
break; | ||
default: | ||
} | ||
if (opts.dynamicTyping) { | ||
@@ -420,5 +400,3 @@ // Parse value excepted for special fields | ||
} | ||
break; | ||
case 'boolean': | ||
@@ -432,5 +410,3 @@ if (value instanceof Array) { | ||
} | ||
break; | ||
case 'number': | ||
@@ -444,9 +420,6 @@ if (value instanceof Array) { | ||
} | ||
break; | ||
case 'string': | ||
// Keep value as string | ||
break; | ||
default: | ||
@@ -468,5 +441,3 @@ // eslint-disable-next-line no-console | ||
} | ||
break; | ||
default: | ||
@@ -483,30 +454,27 @@ } | ||
} | ||
} // Removes extra spaces | ||
} | ||
// Removes extra spaces | ||
if (opts.trim && field.type !== 'password') { | ||
value = trim(value); | ||
} // Replaces empty strings with null | ||
} | ||
// Replaces empty strings with null | ||
if (opts.nullify) { | ||
value = nullify(value); | ||
} | ||
return value; | ||
} | ||
/** | ||
* Returns form values as an object | ||
* @param form | ||
* @param {HTMLFormElement} form | ||
* @param options | ||
* @return {object} | ||
*/ | ||
function parseForm(form, options) { | ||
if (!(form instanceof HTMLFormElement)) { | ||
throw new TypeError('form is not an instance of HTMLFormElement'); | ||
} // Default options | ||
} | ||
// Default options | ||
var opts = _objectSpread({ | ||
@@ -523,68 +491,45 @@ cleanFunction: null, | ||
trim: true | ||
}, options); // Check deprecated options | ||
if (typeof opts.parseValues !== 'undefined') { | ||
// eslint-disable-next-line no-console | ||
console.warn('option "parseValues" is deprecated, rename it to "dynamicTyping" instead'); | ||
opts.dynamicTyping = opts.parseValues; | ||
} | ||
if (typeof opts.smartParsing !== 'undefined') { | ||
// eslint-disable-next-line no-console | ||
console.warn('option "smartParsing" is deprecated, rename it to "smartTyping" instead'); | ||
opts.smartTyping = opts.smartParsing; | ||
} | ||
if (typeof opts.trimValues !== 'undefined') { | ||
// eslint-disable-next-line no-console | ||
console.warn('option "trimValues" is deprecated, rename it to "trim" instead'); | ||
opts.trim = opts.trimValues; | ||
} | ||
}, options); | ||
var fields = {}; | ||
var elements = form.elements; | ||
for (var i = 0; i < elements.length; i += 1) { | ||
var field = elements[i]; | ||
var isCheckable = isCheckableField(field); // Ignore element without a valid name | ||
var isCheckable = isCheckableField(field); | ||
var isMultiple = isMultipleField(field); | ||
// Ignore element without a valid name | ||
if (typeof field.name !== 'string' || field.name.length < 1) { | ||
// eslint-disable-next-line | ||
continue; | ||
} // Ignore non-form element | ||
} | ||
// Ignore non-form element | ||
if (!contains(['button', 'input', 'select', 'textarea'], field.localName)) { | ||
// eslint-disable-next-line | ||
continue; | ||
} // Ignore buttons | ||
} | ||
// Ignore buttons | ||
if (opts.ignoreButtons && isButton(field)) { | ||
// eslint-disable-next-line | ||
continue; | ||
} // Ignore disabled element | ||
} | ||
// Ignore disabled element | ||
if (opts.ignoreDisabled && field.disabled) { | ||
// eslint-disable-next-line | ||
continue; | ||
} // Ignore unchecked element | ||
} | ||
// Ignore unchecked element | ||
if (opts.ignoreUnchecked && isCheckable && !field.checked) { | ||
// eslint-disable-next-line | ||
continue; | ||
} // Ignore element based on filter | ||
} | ||
// Ignore element based on filter | ||
if (typeof opts.filterFunction === 'function' && opts.filterFunction(field) !== true) { | ||
// eslint-disable-next-line | ||
continue; | ||
} // Parse field value | ||
} | ||
// Parse field value | ||
var value = parseField(field, opts); | ||
var value = parseField(field, opts); // Execute custom clean function on fields with type different of password | ||
// Execute custom clean function on fields with type different of password | ||
if (typeof opts.cleanFunction === 'function' && field.type !== 'password') { | ||
@@ -600,5 +545,5 @@ if (value instanceof Array) { | ||
} | ||
} // Ignore empty value | ||
} | ||
// Ignore empty value | ||
if (opts.ignoreEmpty && (value === '' || value === null || typeof value === 'undefined')) { | ||
@@ -608,25 +553,21 @@ // eslint-disable-next-line | ||
} | ||
var name = field.name; | ||
var name = field.name; // Handle multiple select specific case | ||
if (field.multiple) { | ||
// Handle multiple select specific case | ||
if (isMultiple) { | ||
name = name.replace(/\[]$/g, ''); | ||
} // Reconstruct array or object | ||
} | ||
// Reconstruct array or object | ||
if (name.indexOf('[') !== -1) { | ||
var rootName = name.substr(0, name.indexOf('[')); | ||
var tree = name.substr(name.indexOf('[')); | ||
fields[rootName] = buildObject(tree, value, fields[rootName]); // eslint-disable-next-line | ||
fields[rootName] = buildObject(tree, value, fields[rootName]); | ||
// eslint-disable-next-line | ||
continue; | ||
} // Add field to list | ||
} | ||
if (isCheckable) { | ||
if (field.checked) { | ||
fields[name] = value; | ||
} else if (typeof fields[name] === 'undefined') { | ||
fields[name] = null; | ||
} | ||
// Add field to list | ||
if (isCheckable && !isMultiple && !field.checked) { | ||
fields[name] = null; | ||
} else { | ||
@@ -636,4 +577,3 @@ fields[name] = value; | ||
} | ||
return fields; | ||
} |
{ | ||
"name": "@jalik/form-parser", | ||
"version": "2.0.11", | ||
"version": "2.0.12", | ||
"description": "A utility to parse complex forms with minimum effort.", | ||
@@ -37,3 +37,3 @@ "license": "MIT", | ||
"prepublishOnly": "npm test", | ||
"test": "jest --passWithNoTests" | ||
"test": "jest --passWithNoTests --coverage=true" | ||
}, | ||
@@ -45,17 +45,19 @@ "files": [ | ||
"dependencies": { | ||
"@babel/runtime": "^7.15.4" | ||
"@babel/runtime": "^7.19.4" | ||
}, | ||
"devDependencies": { | ||
"@babel/cli": "^7.15.7", | ||
"@babel/core": "^7.15.5", | ||
"@babel/plugin-transform-runtime": "^7.15.0", | ||
"@babel/preset-env": "^7.15.6", | ||
"acorn": "^8.5.0", | ||
"eslint": "^7.32.0", | ||
"eslint-config-airbnb-base": "^14.2.1", | ||
"eslint-plugin-import": "^2.24.2", | ||
"eslint-plugin-jest": "^24.4.2", | ||
"jest": "^27.2.1", | ||
"typescript": "^4.4.3" | ||
"@babel/cli": "^7.19.3", | ||
"@babel/core": "^7.19.3", | ||
"@babel/plugin-transform-runtime": "^7.19.1", | ||
"@babel/preset-env": "^7.19.4", | ||
"@jest/globals": "^29.2.1", | ||
"acorn": "^8.8.0", | ||
"eslint": "^8.25.0", | ||
"eslint-config-airbnb-base": "^15.0.0", | ||
"eslint-plugin-import": "^2.26.0", | ||
"eslint-plugin-jest": "^27.1.3", | ||
"jest": "^29.2.1", | ||
"jest-environment-jsdom": "^29.2.1", | ||
"typescript": "^4.8.4" | ||
} | ||
} |
197
src/index.js
/* | ||
* The MIT License (MIT) | ||
* Copyright (c) 2021 Karl STEIN | ||
* Copyright (c) 2022 Karl STEIN | ||
*/ | ||
/** | ||
* Builds an object from a string (ex: [colors][0][code]) | ||
* @param str | ||
* Builds an object from a string (ex: [colors][0][code]). | ||
* @param {string} str | ||
* @param value | ||
@@ -107,5 +107,5 @@ * @param context | ||
/** | ||
* Checks if value is in list | ||
* @param list | ||
* @param value | ||
* Checks if value is in list. | ||
* @param {*[]} list | ||
* @param {*} value | ||
* @return {boolean} | ||
@@ -128,4 +128,24 @@ */ | ||
/** | ||
* Checks if the field is a button | ||
* @param field | ||
* Returns form fields. | ||
* @param {HTMLFormElement} form | ||
* @param {function|undefined} filter | ||
* @returns {*[]} | ||
*/ | ||
export function getFormFields(form, filter = undefined) { | ||
const { elements } = form; | ||
const fields = []; | ||
for (let i = 0; i < elements.length; i += 1) { | ||
const el = elements[i]; | ||
if (!filter || filter(el)) { | ||
fields.push(el); | ||
} | ||
} | ||
return fields; | ||
} | ||
/** | ||
* Checks if the field is a button. | ||
* @param {HTMLInputElement|HTMLSelectElement|HTMLTextAreaElement} field | ||
* @return {*|boolean} | ||
@@ -138,4 +158,4 @@ */ | ||
/** | ||
* Checks if the field is checkable | ||
* @param field | ||
* Checks if the field is checkable. | ||
* @param {HTMLInputElement|HTMLSelectElement|HTMLTextAreaElement} field | ||
* @return {*|boolean} | ||
@@ -148,5 +168,19 @@ */ | ||
/** | ||
* Replaces empty string by null value | ||
* Checks if field has multiple values. | ||
* @param {HTMLInputElement|HTMLSelectElement|HTMLTextAreaElement|HTMLElement} field | ||
* @return {boolean} | ||
*/ | ||
export function isMultipleField(field) { | ||
// Field has attribute "multiple". | ||
if (field.multiple) { | ||
return true; | ||
} | ||
// Field name contains an empty array (example: "numbers[]"). | ||
return field.name != null && /\[]$/.test(field.name); | ||
} | ||
/** | ||
* Replaces empty string by null value. | ||
* @param value | ||
* @return {Object|string|Array|*} | ||
* @return {null|*|*[]} | ||
*/ | ||
@@ -174,4 +208,4 @@ export function nullify(value) { | ||
/** | ||
* Removes extra spaces | ||
* @param value | ||
* Removes extra spaces. | ||
* @param {string|*[]} value | ||
* @return {Object|string|Array|*} | ||
@@ -200,12 +234,9 @@ */ | ||
/** | ||
* Returns a boolean | ||
* @param value | ||
* Returns a boolean. | ||
* @param {string} value | ||
* @return {boolean|null} | ||
*/ | ||
export function parseBoolean(value) { | ||
let bool = value; | ||
const bool = String(value).trim(); | ||
if (typeof bool === 'string') { | ||
bool = bool.trim(); | ||
} | ||
if (/^(true|1)$/i.test(bool)) { | ||
@@ -221,25 +252,19 @@ return true; | ||
/** | ||
* Returns a number | ||
* @param value | ||
* Returns a number. | ||
* @param {string} value | ||
* @return {number|null} | ||
*/ | ||
export function parseNumber(value) { | ||
let number = value; | ||
const number = String(value).trim() | ||
// Remove spaces | ||
.replace(/ /g, ''); | ||
if (typeof value !== 'number') { | ||
if (typeof value === 'string') { | ||
// Remove spaces | ||
number = value.replace(/ /g, ''); | ||
} | ||
if (/^[+-]?[0-9]*[.,][0-9]+$/.test(number)) { | ||
// Replace comma with dot (for languages where number contain a comma instead of a dot) | ||
number = parseFloat(String(number).replace(/,/g, '.')); | ||
} else if (/^[+-]?[0-9]+$/.test(number)) { | ||
number = parseInt(number, 10); | ||
} else { | ||
number = null; | ||
} | ||
if (/^[+-]?[0-9]*[.,][0-9]+$/.test(number)) { | ||
// Replace comma with dot (for languages where number contain a comma instead of a dot) | ||
return parseFloat(String(number).replace(/,/g, '.')); | ||
} | ||
return number; | ||
if (/^[+-]?[0-9]+$/.test(number)) { | ||
return parseInt(number, 10); | ||
} | ||
return null; | ||
} | ||
@@ -249,40 +274,39 @@ | ||
* Returns the typed value of a string value | ||
* @param value | ||
* @param type | ||
* @param {string|null} value | ||
* @param {'auto'|'boolean'|'number'} type | ||
* @returns {string|number|boolean|null} | ||
*/ | ||
export function parseValue(value, type = 'auto') { | ||
let newVal = value; | ||
if (value == null) { | ||
return null; | ||
} | ||
let result = String(value); | ||
if (typeof newVal === 'string') { | ||
if (newVal.length > 0) { | ||
switch (type) { | ||
case 'auto': { | ||
const bool = parseBoolean(newVal); | ||
if (result.length > 0) { | ||
switch (type) { | ||
case 'auto': { | ||
const bool = parseBoolean(result); | ||
if (typeof bool === 'boolean') { | ||
newVal = bool; | ||
break; | ||
} | ||
if (typeof bool === 'boolean') { | ||
result = bool; | ||
break; | ||
} | ||
const number = parseNumber(newVal); | ||
const number = parseNumber(result); | ||
if (typeof number === 'number') { | ||
newVal = number; | ||
} | ||
break; | ||
if (typeof number === 'number') { | ||
result = number; | ||
} | ||
case 'boolean': | ||
newVal = parseBoolean(newVal); | ||
break; | ||
case 'number': | ||
newVal = parseNumber(newVal); | ||
break; | ||
case 'string': | ||
break; | ||
default: | ||
break; | ||
} | ||
case 'boolean': | ||
result = parseBoolean(result); | ||
break; | ||
case 'number': | ||
result = parseNumber(result); | ||
break; | ||
default: | ||
} | ||
} | ||
return newVal; | ||
return result; | ||
} | ||
@@ -292,3 +316,3 @@ | ||
* Returns the parsed value of the field | ||
* @param field | ||
* @param {HTMLInputElement|HTMLSelectElement|HTMLTextAreaElement} field | ||
* @param options | ||
@@ -317,2 +341,5 @@ * @return {*} | ||
const isCheckable = isCheckableField(field); | ||
const isMultiple = isMultipleField(field); | ||
const { form } = field; | ||
let { value } = field; | ||
@@ -324,4 +351,8 @@ | ||
if (isCheckable) { | ||
// Keep value only if element is checked | ||
value = field.checked ? value : undefined; | ||
if (isMultiple) { | ||
value = getFormFields(form, (el) => el.name === field.name && el.checked === true) | ||
.map((el) => el.value); | ||
} else { | ||
value = field.checked ? value : null; | ||
} | ||
} | ||
@@ -431,3 +462,3 @@ break; | ||
* Returns form values as an object | ||
* @param form | ||
* @param {HTMLFormElement} form | ||
* @param options | ||
@@ -456,19 +487,2 @@ * @return {object} | ||
// Check deprecated options | ||
if (typeof opts.parseValues !== 'undefined') { | ||
// eslint-disable-next-line no-console | ||
console.warn('option "parseValues" is deprecated, rename it to "dynamicTyping" instead'); | ||
opts.dynamicTyping = opts.parseValues; | ||
} | ||
if (typeof opts.smartParsing !== 'undefined') { | ||
// eslint-disable-next-line no-console | ||
console.warn('option "smartParsing" is deprecated, rename it to "smartTyping" instead'); | ||
opts.smartTyping = opts.smartParsing; | ||
} | ||
if (typeof opts.trimValues !== 'undefined') { | ||
// eslint-disable-next-line no-console | ||
console.warn('option "trimValues" is deprecated, rename it to "trim" instead'); | ||
opts.trim = opts.trimValues; | ||
} | ||
const fields = {}; | ||
@@ -480,2 +494,3 @@ const { elements } = form; | ||
const isCheckable = isCheckableField(field); | ||
const isMultiple = isMultipleField(field); | ||
@@ -538,3 +553,3 @@ // Ignore element without a valid name | ||
// Handle multiple select specific case | ||
if (field.multiple) { | ||
if (isMultiple) { | ||
name = name.replace(/\[]$/g, ''); | ||
@@ -553,8 +568,4 @@ } | ||
// Add field to list | ||
if (isCheckable) { | ||
if (field.checked) { | ||
fields[name] = value; | ||
} else if (typeof fields[name] === 'undefined') { | ||
fields[name] = null; | ||
} | ||
if (isCheckable && !isMultiple && !field.checked) { | ||
fields[name] = null; | ||
} else { | ||
@@ -561,0 +572,0 @@ fields[name] = value; |
1027
47650
13
5
Updated@babel/runtime@^7.19.4