Add semantic token highlighting for 'that' variable and comment file references in VS Code extension Add Phone_Text_Input and Currency_Input components with formatting utilities Implement client widgets, form standardization, and soft delete functionality Add modal scroll lock and update documentation Implement comprehensive modal system with form integration and validation Fix modal component instantiation using jQuery plugin API Implement modal system with responsive sizing, queuing, and validation support Implement form submission with validation, error handling, and loading states Implement country/state selectors with dynamic data loading and Bootstrap styling Revert Rsx::Route() highlighting in Blade/PHP files Target specific PHP scopes for Rsx::Route() highlighting in Blade Expand injection selector for Rsx::Route() highlighting Add custom syntax highlighting for Rsx::Route() and Rsx.Route() calls Update jqhtml packages to v2.2.165 Add bundle path validation for common mistakes (development mode only) Create Ajax_Select_Input widget and Rsx_Reference_Data controller Create Country_Select_Input widget with default country support Initialize Tom Select on Select_Input widgets Add Tom Select bundle for enhanced select dropdowns Implement ISO 3166 geographic data system for country/region selection Implement widget-based form system with disabled state support 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
224 lines
6.0 KiB
JavaScript
224 lines
6.0 KiB
JavaScript
'use strict';
|
|
|
|
import utils from '../utils.js';
|
|
import AxiosError from '../core/AxiosError.js';
|
|
// temporary hotfix to avoid circular references until AxiosURLSearchParams is refactored
|
|
import PlatformFormData from '../platform/node/classes/FormData.js';
|
|
|
|
/**
|
|
* Determines if the given thing is a array or js object.
|
|
*
|
|
* @param {string} thing - The object or array to be visited.
|
|
*
|
|
* @returns {boolean}
|
|
*/
|
|
function isVisitable(thing) {
|
|
return utils.isPlainObject(thing) || utils.isArray(thing);
|
|
}
|
|
|
|
/**
|
|
* It removes the brackets from the end of a string
|
|
*
|
|
* @param {string} key - The key of the parameter.
|
|
*
|
|
* @returns {string} the key without the brackets.
|
|
*/
|
|
function removeBrackets(key) {
|
|
return utils.endsWith(key, '[]') ? key.slice(0, -2) : key;
|
|
}
|
|
|
|
/**
|
|
* It takes a path, a key, and a boolean, and returns a string
|
|
*
|
|
* @param {string} path - The path to the current key.
|
|
* @param {string} key - The key of the current object being iterated over.
|
|
* @param {string} dots - If true, the key will be rendered with dots instead of brackets.
|
|
*
|
|
* @returns {string} The path to the current key.
|
|
*/
|
|
function renderKey(path, key, dots) {
|
|
if (!path) return key;
|
|
return path.concat(key).map(function each(token, i) {
|
|
// eslint-disable-next-line no-param-reassign
|
|
token = removeBrackets(token);
|
|
return !dots && i ? '[' + token + ']' : token;
|
|
}).join(dots ? '.' : '');
|
|
}
|
|
|
|
/**
|
|
* If the array is an array and none of its elements are visitable, then it's a flat array.
|
|
*
|
|
* @param {Array<any>} arr - The array to check
|
|
*
|
|
* @returns {boolean}
|
|
*/
|
|
function isFlatArray(arr) {
|
|
return utils.isArray(arr) && !arr.some(isVisitable);
|
|
}
|
|
|
|
const predicates = utils.toFlatObject(utils, {}, null, function filter(prop) {
|
|
return /^is[A-Z]/.test(prop);
|
|
});
|
|
|
|
/**
|
|
* Convert a data object to FormData
|
|
*
|
|
* @param {Object} obj
|
|
* @param {?Object} [formData]
|
|
* @param {?Object} [options]
|
|
* @param {Function} [options.visitor]
|
|
* @param {Boolean} [options.metaTokens = true]
|
|
* @param {Boolean} [options.dots = false]
|
|
* @param {?Boolean} [options.indexes = false]
|
|
*
|
|
* @returns {Object}
|
|
**/
|
|
|
|
/**
|
|
* It converts an object into a FormData object
|
|
*
|
|
* @param {Object<any, any>} obj - The object to convert to form data.
|
|
* @param {string} formData - The FormData object to append to.
|
|
* @param {Object<string, any>} options
|
|
*
|
|
* @returns
|
|
*/
|
|
function toFormData(obj, formData, options) {
|
|
if (!utils.isObject(obj)) {
|
|
throw new TypeError('target must be an object');
|
|
}
|
|
|
|
// eslint-disable-next-line no-param-reassign
|
|
formData = formData || new (PlatformFormData || FormData)();
|
|
|
|
// eslint-disable-next-line no-param-reassign
|
|
options = utils.toFlatObject(options, {
|
|
metaTokens: true,
|
|
dots: false,
|
|
indexes: false
|
|
}, false, function defined(option, source) {
|
|
// eslint-disable-next-line no-eq-null,eqeqeq
|
|
return !utils.isUndefined(source[option]);
|
|
});
|
|
|
|
const metaTokens = options.metaTokens;
|
|
// eslint-disable-next-line no-use-before-define
|
|
const visitor = options.visitor || defaultVisitor;
|
|
const dots = options.dots;
|
|
const indexes = options.indexes;
|
|
const _Blob = options.Blob || typeof Blob !== 'undefined' && Blob;
|
|
const useBlob = _Blob && utils.isSpecCompliantForm(formData);
|
|
|
|
if (!utils.isFunction(visitor)) {
|
|
throw new TypeError('visitor must be a function');
|
|
}
|
|
|
|
function convertValue(value) {
|
|
if (value === null) return '';
|
|
|
|
if (utils.isDate(value)) {
|
|
return value.toISOString();
|
|
}
|
|
|
|
if (utils.isBoolean(value)) {
|
|
return value.toString();
|
|
}
|
|
|
|
if (!useBlob && utils.isBlob(value)) {
|
|
throw new AxiosError('Blob is not supported. Use a Buffer instead.');
|
|
}
|
|
|
|
if (utils.isArrayBuffer(value) || utils.isTypedArray(value)) {
|
|
return useBlob && typeof Blob === 'function' ? new Blob([value]) : Buffer.from(value);
|
|
}
|
|
|
|
return value;
|
|
}
|
|
|
|
/**
|
|
* Default visitor.
|
|
*
|
|
* @param {*} value
|
|
* @param {String|Number} key
|
|
* @param {Array<String|Number>} path
|
|
* @this {FormData}
|
|
*
|
|
* @returns {boolean} return true to visit the each prop of the value recursively
|
|
*/
|
|
function defaultVisitor(value, key, path) {
|
|
let arr = value;
|
|
|
|
if (value && !path && typeof value === 'object') {
|
|
if (utils.endsWith(key, '{}')) {
|
|
// eslint-disable-next-line no-param-reassign
|
|
key = metaTokens ? key : key.slice(0, -2);
|
|
// eslint-disable-next-line no-param-reassign
|
|
value = JSON.stringify(value);
|
|
} else if (
|
|
(utils.isArray(value) && isFlatArray(value)) ||
|
|
((utils.isFileList(value) || utils.endsWith(key, '[]')) && (arr = utils.toArray(value))
|
|
)) {
|
|
// eslint-disable-next-line no-param-reassign
|
|
key = removeBrackets(key);
|
|
|
|
arr.forEach(function each(el, index) {
|
|
!(utils.isUndefined(el) || el === null) && formData.append(
|
|
// eslint-disable-next-line no-nested-ternary
|
|
indexes === true ? renderKey([key], index, dots) : (indexes === null ? key : key + '[]'),
|
|
convertValue(el)
|
|
);
|
|
});
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if (isVisitable(value)) {
|
|
return true;
|
|
}
|
|
|
|
formData.append(renderKey(path, key, dots), convertValue(value));
|
|
|
|
return false;
|
|
}
|
|
|
|
const stack = [];
|
|
|
|
const exposedHelpers = Object.assign(predicates, {
|
|
defaultVisitor,
|
|
convertValue,
|
|
isVisitable
|
|
});
|
|
|
|
function build(value, path) {
|
|
if (utils.isUndefined(value)) return;
|
|
|
|
if (stack.indexOf(value) !== -1) {
|
|
throw Error('Circular reference detected in ' + path.join('.'));
|
|
}
|
|
|
|
stack.push(value);
|
|
|
|
utils.forEach(value, function each(el, key) {
|
|
const result = !(utils.isUndefined(el) || el === null) && visitor.call(
|
|
formData, el, utils.isString(key) ? key.trim() : key, path, exposedHelpers
|
|
);
|
|
|
|
if (result === true) {
|
|
build(el, path ? path.concat(key) : [key]);
|
|
}
|
|
});
|
|
|
|
stack.pop();
|
|
}
|
|
|
|
if (!utils.isObject(obj)) {
|
|
throw new TypeError('data must be an object');
|
|
}
|
|
|
|
build(obj);
|
|
|
|
return formData;
|
|
}
|
|
|
|
export default toFormData;
|