diff --git a/.esdoc.json b/.esdoc.json new file mode 100644 index 0000000000..214fcb0f34 --- /dev/null +++ b/.esdoc.json @@ -0,0 +1,8 @@ +{ + "source": "./src", + "destination": "./docs", + "plugins": [ + {"name": "esdoc-standard-plugin"}, + {"name": "esdoc-ecmascript-proposal-plugin", "option": {"all": true}} + ] + } diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index 6575178e0a..0000000000 --- a/.eslintignore +++ /dev/null @@ -1,10 +0,0 @@ -node_modules -lib -dist -app -test -types -*.spec.js -*.unit.js -_site -docs diff --git a/.eslintrc.js b/.eslintrc.js deleted file mode 100644 index 52e6c54d63..0000000000 --- a/.eslintrc.js +++ /dev/null @@ -1,17 +0,0 @@ -module.exports = { - "env": { - "browser": true, - "es2021": true, - "node": true - }, - "extends": ["eslint:recommended", "plugin:jsdoc/recommended-typescript-flavor"], - "parserOptions": { - "ecmaVersion": "latest", - "sourceType": "module" - }, - "plugins": ["jsdoc"], - "rules": { - "no-prototype-builtins": "off", - "no-unused-vars": ["error", { "argsIgnorePattern": "^_" }], - } -} diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000000..7417481951 --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,38 @@ +{ + "parser": "@typescript-eslint/parser", + "extends": "formio", + "parserOptions": { + "ecmaVersion": 2020, + "sourceType": "module" + }, + "plugins": ["@typescript-eslint"], + "env": { + "browser": true, + "es2020": true, + "node": true, + "mocha": true + }, + "ignorePatterns": [ + "!.*rc.js" + ], + "rules": { + "max-len": [ + "off", + { + "code": 160, + "ignoreComments": true, + "ignoreStrings": true + } + ], + "max-statements": [2, 40], + "max-depth": [2, 10], + "no-console": "off", + "no-prototype-builtins": "off", + "prefer-const": "error", + "prefer-template": "error", + "object-curly-spacing": [ + "error", + "always" + ] + } +} diff --git a/gulpfile.js b/gulpfile.js index aad43eaec5..d0bd609d64 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -6,6 +6,7 @@ const concat = require('gulp-concat'); const replace = require('gulp-replace'); const rename = require('gulp-rename'); const cleanCSS = require('gulp-clean-css'); +const eslint = require('gulp-eslint'); const clean = require('gulp-clean'); // Clean lib folder. @@ -17,6 +18,14 @@ gulp.task('clean:lib', () => { }); gulp.task('clean', gulp.parallel('clean:dist', 'clean:lib')); +// ESLint +gulp.task('eslint', function eslintTask() { + return gulp.src(['./src/**/*.js', '!./src/**/*.spec.js']) + .pipe(eslint()) + .pipe(eslint.format()) + .pipe(eslint.failAfterError()); +}); + // Move font-awesome fonts into dist folder. gulp.task('builder-fonts', function builderFonts() { return gulp.src('./node_modules/bootstrap-icons/font/fonts/*').pipe(gulp.dest('dist/fonts')); diff --git a/package.json b/package.json index c4c803c818..31c0f1fa06 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,7 @@ ], "scripts": { "build": "yarn doc && yarn lib && yarn dist", - "doc": "typedoc", + "doc": "esdoc", "dist": "gulp clean:dist && webpack --config webpack.config.js && webpack --config webpack.prod.js && gulp build", "lib": "gulp clean:lib && tsc --project tsconfig.cjs.json && tsc --project tsconfig.mjs.json && yarn lib:package", "lib:package": "node ./libpackage.js", @@ -50,7 +50,7 @@ "release": "yarn build-app && yarn deploy-s3", "tag": "VERSION=$(yarn version);git add -A; git commit -m \"Build $Version\";git push origin master;git tag v$VERSION;git push origin --tags;", "dopublish": "npm run build && npm run tag && npm publish", - "lint": "eslint ./src --fix", + "lint": "gulp eslint", "serve": "jekyll serve --config _config.yml,_config.dev.yml", "test": "mocha 'src/**/*.unit.js'", "test:updateRenders": "npm run lib && TZ=UTC node --require jsdom-global/register test/updateRenders.js", @@ -124,8 +124,11 @@ "chance": "^1.1.9", "ejs-loader": "^0.5.0", "escape-string-regexp": "^5.0.0", + "esdoc": "^1.1.0", + "esdoc-ecmascript-proposal-plugin": "^1.0.0", + "esdoc-standard-plugin": "^1.0.0", "eslint": "^8.57.0", - "eslint-plugin-jsdoc": "^48.2.3", + "eslint-config-formio": "^1.1.4", "fetch-mock": "^9.11.0", "file-loader": "^6.2.0", "flatpickr": "^4.6.13", @@ -134,6 +137,7 @@ "gulp-clean": "^0.4.0", "gulp-clean-css": "^4.3.0", "gulp-concat": "^2.6.1", + "gulp-eslint": "^6.0.0", "gulp-filter": "^7.0.0", "gulp-rename": "^2.0.0", "gulp-replace": "^1.1.3", @@ -164,7 +168,6 @@ "ts-loader": "^9.4.4", "ts-node": "^10.9.1", "tsc": "^2.0.4", - "typedoc": "^0.25.13", "typescript": "5.3.2", "webpack": "^5.90.3", "webpack-bundle-analyzer": "^4.10.2", diff --git a/src/Element.js b/src/Element.js index e40f112cb6..91385e9bac 100644 --- a/src/Element.js +++ b/src/Element.js @@ -45,6 +45,7 @@ export default class Element { /** * An instance of the EventEmitter class to handle the emitting and registration of events. + * * @type {EventEmitter} */ this.events = (options && options.events) ? options.events : new EventEmitter(); @@ -52,6 +53,7 @@ export default class Element { this.defaultMask = null; /** * Conditional to show or hide helplinks in editForm + * * @type {*|boolean} */ this.helplinks = (this.options.helplinks === 'false') ? false : (this.options.helplinks || 'https://help.form.io'); @@ -59,6 +61,7 @@ export default class Element { /** * Register for a new event within this component. + * * @example * let component = new BaseComponent({ * type: 'textfield', @@ -68,11 +71,12 @@ export default class Element { * component.on('componentChange', (changed) => { * console.log('this element is changed.'); * }); + * + * * @param {string} event - The event you wish to register the handler for. - * @param {Function} cb - The callback handler to handle this event. + * @param {function} cb - The callback handler to handle this event. * @param {boolean} [internal] - This is an internal event handler. * @param {boolean} [once] - This event should only fire once. - * @returns {EventEmitter | void} - The event emitter instance. */ on(event, cb, internal, once = false) { if (!this.events) { @@ -91,10 +95,9 @@ export default class Element { /** * Register for a new single-fire event within this component. + * * @param {string} event - The event you wish to register the handler for. - * @param {Function} cb - The callback handler to handle this event. - * @param {boolean} internal - This is an internal event handler. - * @returns {EventEmitter} - The event emitter instance. + * @param {function} cb - The callback handler to handle this event. */ once(event, cb, internal) { return this.on(event, cb, internal, true); @@ -102,8 +105,9 @@ export default class Element { /** * Allow catching any event. - * @param {Function} cb - The callback handler to handle this event. - * @returns {EventEmitter | void} - The event emitter instance. + * + * @param cb + * @returns {this} */ onAny(cb) { if (!this.events) { @@ -115,8 +119,9 @@ export default class Element { /** * Removes the listener that will be fired when any event is emitted. - * @param {Function} cb - The callback handler to handle this event. - * @returns {EventEmitter | void} - The event emitter instance. + * + * @param cb + * @returns {this} */ offAny(cb) { if (!this.events) { @@ -128,8 +133,9 @@ export default class Element { /** * Removes a listener for a certain event. Not passing the 2nd arg will remove all listeners for that event. + * * @param {string} event - The event you wish to register the handler for. - * @param {Function | undefined} cb - The callback handler to handle this event. + * @param {function|undefined} cb - The callback handler to handle this event. */ off(event, cb) { if (!this.events) { @@ -155,8 +161,9 @@ export default class Element { /** * Emit a new event. + * * @param {string} event - The event to emit. - * @param {object} data - The data to emit with the handler. + * @param {Object} data - The data to emit with the handler. */ emit(event, ...data) { if (this.events) { @@ -166,8 +173,9 @@ export default class Element { /** * Check if the component has an event handler set up for the event. + * * @param {string} event - The event name. - * @returns {boolean} - TRUE if the event is registered, FALSE otherwise. + * @returns {boolean} */ hasEventHandler(event) { if (!this.events) { @@ -187,12 +195,15 @@ export default class Element { /** * Wrapper method to add an event listener to an HTML element. - * @param {HtmlElement} obj - The DOM element to add the event to. - * @param {string} type - The event name to add. - * @param {Function} func - The callback function to be executed when the listener is triggered. - * @param {boolean} persistent - If this listener should persist beyond "destroy" commands. - * @param {boolean} capture - If this listener should be executed in the capture phase. - * @returns {void | this} - The instance of the element. + * + * @param obj + * The DOM element to add the event to. + * @param type + * The event name to add. + * @param func + * The callback function to be executed when the listener is triggered. + * @param persistent + * If this listener should persist beyond "destroy" commands. */ addEventListener(obj, type, func, persistent, capture) { if (!obj) { @@ -213,10 +224,9 @@ export default class Element { /** * Remove an event listener from the object. - * @param {HTMLElement} obj - The DOM element to remove the event from. - * @param {string} type - The event name to remove. - * @param {Function} func - The callback function to remove. - * @returns {this | void} - The instance of the element. + * + * @param obj + * @param type */ removeEventListener(obj, type, func = null) { const indexes = []; @@ -270,7 +280,6 @@ export default class Element { /** * Removes all event listeners attached to this component. - * @param {boolean} all - If all events should be removed, including external events. */ destroy(all = false) { this.removeEventListeners(); @@ -282,9 +291,9 @@ export default class Element { /** * Append an HTML DOM element to a container. - * @param {HTMLElement} element - The DOM element to append. - * @param {HTMLElement} container - The DOM element that is the container of the element getting appended. - * @returns {this} - The instance of the element. + * + * @param element + * @param container */ appendTo(element, container) { container?.appendChild(element); @@ -293,9 +302,9 @@ export default class Element { /** * Prepend an HTML DOM element to a container. + * * @param {HTMLElement} element - The DOM element to prepend. * @param {HTMLElement} container - The DOM element that is the container of the element getting prepended. - * @returns {this} - The instance of the element. */ prependTo(element, container) { if (container) { @@ -318,9 +327,9 @@ export default class Element { /** * Removes an HTML DOM element from its bounding container. + * * @param {HTMLElement} element - The element to remove. * @param {HTMLElement} container - The DOM element that is the container of the element to remove. - * @returns {this} - The instance of the element. */ removeChildFrom(element, container) { if (container && container.contains(element)) { @@ -337,10 +346,12 @@ export default class Element { /** * Alias for document.createElement. + * * @param {string} type - The type of element to create - * @param {object} attr - The element attributes to add to the created element. + * @param {Object} attr - The element attributes to add to the created element. * @param {Various} children - Child elements. Can be a DOM Element, string or array of both. - * @returns {HTMLElement} - The created element. + * + * @return {HTMLElement} - The created element. */ ce(type, attr, children = null) { // console.warn('Call to deprecated this.ce(). Dom elements should be created with templates, not manually with ce.'); @@ -359,9 +370,8 @@ export default class Element { /** * Append different types of children. - * @param {HTMLElement} element - The element to append to. - * @param {HTMLElement} child - The child element to append. - * @returns {this} - The instance of the element. + * + * @param child */ appendChild(element, child) { if (Array.isArray(child)) { @@ -386,19 +396,16 @@ export default class Element { return mask.map((char) => (char instanceof RegExp) ? this.placeholderChar : char).join(''); } - /** - * Get the placeholder character for the input mask. - * @returns {string} - The placeholder character. - */ get placeholderChar() { return this.component?.inputMaskPlaceholderChar || '_'; } /** * Sets the input mask for an input. + * * @param {HTMLElement} input - The html input to apply the mask to. - * @param {string} inputMask - The input mask to add to this input. - * @param {boolean} usePlaceholder - Set the mask placeholder on the input. + * @param {String} inputMask - The input mask to add to this input. + * @param {Boolean} usePlaceholder - Set the mask placeholder on the input. */ setInputMask(input, inputMask, usePlaceholder) { if (input && inputMask) { @@ -434,9 +441,9 @@ export default class Element { /** * Translate a text using the i18n system. + * * @param {string|Array} text - The i18n identifier. - * @param {...any} args - The arguments to pass to the i18n translation. - * @returns {string} - The translated text. + * @param {Object} params - The i18n parameters to use for translation. */ t(text, ...args) { return this.i18next ? this.i18next.t(text, ...args): text; @@ -444,8 +451,8 @@ export default class Element { /** * Alias to create a text node. - * @param {string} text - The text to create. - * @returns {HtmlElement} - The created text node. + * @param text + * @returns {Text} */ text(text) { return document.createTextNode(this.t(text)); @@ -454,7 +461,7 @@ export default class Element { /** * Adds an object of attributes onto an element. * @param {HtmlElement} element - The element to add the attributes to. - * @param {object} attr - The attributes to add to the input element. + * @param {Object} attr - The attributes to add to the input element. */ attr(element, attr) { if (!element) { @@ -478,9 +485,6 @@ export default class Element { * Determines if an element has a class. * * Taken from jQuery https://j11y.io/jquery/#v=1.5.0&fn=jQuery.fn.hasClass - * @param {HTMLElement} element - The element to check for the class. - * @param {string} className - The class to check for. - * @returns {boolean} - TRUE if the element has the class, FALSE otherwise. */ hasClass(element, className) { if (!element) { @@ -493,9 +497,11 @@ export default class Element { /** * Adds a class to a DOM element. - * @param {HTMLElement} element - The element to add a class to. - * @param {string} className - The name of the class to add. - * @returns {this} - The instance of the element. + * + * @param element + * The element to add a class to. + * @param className + * The name of the class to add. */ addClass(element, className) { if (!element || !(element instanceof HTMLElement)) { @@ -512,9 +518,11 @@ export default class Element { /** * Remove a class from a DOM element. - * @param {HTMLElement} element - The DOM element to remove the class from. - * @param {string} className - The name of the class that is to be removed. - * @returns {this} - The instance of the element. + * + * @param element + * The DOM element to remove the class from. + * @param className + * The name of the class that is to be removed. */ removeClass(element, className) { if (!element || !className || !(element instanceof HTMLElement)) { @@ -532,6 +540,7 @@ export default class Element { /** * Empty's an HTML DOM element. + * * @param {HTMLElement} element - The element you wish to empty. */ empty(element) { @@ -544,8 +553,9 @@ export default class Element { /** * Create an evaluation context for all script executions and interpolations. - * @param {object} additional - Additional context to apply to the evaluation context. - * @returns {*} - The evaluation context. + * + * @param additional + * @return {*} */ evalContext(additional) { return Object.assign({ @@ -570,10 +580,10 @@ export default class Element { /** * Performs an interpolation using the evaluation context of this component. - * @param {string} string - The string to interpolate. - * @param {object} data - The data to use in the interpolation. - * @param {object} options - The options to pass to the interpolation. - * @returns {XML|string|*|void} - The interpolated string. + * + * @param string + * @param data + * @return {XML|string|*|void} */ interpolate(string, data, options = {}) { if (typeof string !== 'function' && (this.component.content || this.component.html) @@ -591,11 +601,12 @@ export default class Element { /** * Performs an evaluation using the evaluation context of this component. - * @param {string|Function|object} func - The function or string to evaluate. - * @param {object} args - The arguments to pass to the evaluation. - * @param {string} ret - The name of the variable within the evaluation context to return. - * @param {boolean} tokenize - Determines if it should replace all {{ }} token references with actual data. - * @returns {*} - The result of the evaluation. + * + * @param func + * @param args + * @param ret + * @param tokenize + * @return {*} */ evaluate(func, args, ret, tokenize) { return FormioUtils.evaluate(func, this.evalContext(args), ret, tokenize); @@ -603,7 +614,7 @@ export default class Element { /** * Allow for options to hook into the functionality of this renderer. - * @returns {*} - The result of the hook function. + * @return {*} */ hook() { const name = arguments[0]; diff --git a/src/Form.js b/src/Form.js index a016ab88d8..adce853a8c 100644 --- a/src/Form.js +++ b/src/Form.js @@ -5,129 +5,29 @@ import templates from './templates'; import * as FormioUtils from './utils/utils'; export default class Form extends Element { - /** - * Represents a JSON value. - * @typedef {(string | number | boolean | null | JSONArray | JSONObject)} JSON - */ - -/** - * Represents a JSON array. - * @typedef {Array} JSONArray - */ - -/** - * Represents a JSON object. - * @typedef {{[key: string]: JSON}} JSONObject - */ - -/** - * @typedef {object} FormioHooks - * @property {Function} [beforeSubmit] - Called before a submission is made. - * @property {Function} [beforeCancel] - Called before a cancel is made. - * @property {Function} [beforeNext] - Called before the next page is navigated to. - * @property {Function} [beforePrev] - Called before the previous page is navigated to. - * @property {Function} [attachComponent] - Called when a component is attached. - * @property {Function} [setDataValue] - Called when a data value is set. - * @property {Function} [addComponents] - Called when components are added. - * @property {Function} [addComponent] - Called when a component is added. - * @property {Function} [customValidation] - Called when a custom validation is made. - * @property {Function} [attachWebform] - Called when a webform is attached. - */ - -/** - * @typedef {object} SanitizeConfig - * @property {string[]} [addAttr] - The html attributes to allow with sanitization. - * @property {string[]} [addTags] - The html tags to allow with sanitization. - * @property {string[]} [allowedAttrs] - The html attributes to allow with sanitization. - * @property {string[]} [allowedTags] - The html tags to allow with sanitization. - * @property {string[]} [allowedUriRegex] - The regex for allowed URIs. - * @property {string[]} [addUriSafeAttr] - The URI attributes to allow with sanitization. - */ - -/** - * @typedef {object} ButtonSettings - * @property {boolean} [showPrevious] - Show the previous button in wizard forms. - * @property {boolean} [showNext] - Show the next button in wizard forms. - * @property {boolean} [showCancel] - Show the cancel button in wizard forms. - * @property {boolean} [showSubmit] - Show the submit button in wizard forms. - */ - -/** - * @typedef {object} FormOptions - * @property {boolean} [saveDraft] - Enable the save draft feature. - * @property {number} [saveDraftThrottle] - The throttle for the save draft feature. - * @property {boolean} [readOnly] - Set this form to readOnly. - * @property {boolean} [noAlerts] - Disable the alerts dialog. - * @property {{[key: string]: string}} [i18n] - The translation file for this rendering. - * @property {string} [template] - Custom logic for creation of elements. - * @property {boolean} [noDefaults] - Exclude default values from the settings. - * @property {any} [fileService] - The file service for this form. - * @property {EventEmitter} [events] - The EventEmitter for this form. - * @property {string} [language] - The language to render this form in. - * @property {{[key: string]: string}} [i18next] - The i18next configuration for this form. - * @property {boolean} [viewAsHtml] - View the form as raw HTML. - * @property {'form' | 'html' | 'flat' | 'builder' | 'pdf'} [renderMode] - The render mode for this form. - * @property {boolean} [highlightErrors] - Highlight any errors on the form. - * @property {string} [componentErrorClass] - The error class for components. - * @property {any} [templates] - The templates for this form. - * @property {string} [iconset] - The iconset for this form. - * @property {import('@formio/core').Component[]} [components] - The components for this form. - * @property {{[key: string]: boolean}} [disabled] - Disabled components for this form. - * @property {boolean} [showHiddenFields] - Show hidden fields. - * @property {{[key: string]: boolean}} [hide] - Hidden components for this form. - * @property {{[key: string]: boolean}} [show] - Components to show for this form. - * @property {Formio} [formio] - The Formio instance for this form. - * @property {string} [decimalSeparator] - The decimal separator for this form. - * @property {string} [thousandsSeparator] - The thousands separator for this form. - * @property {FormioHooks} [hooks] - The hooks for this form. - * @property {boolean} [alwaysDirty] - Always be dirty. - * @property {boolean} [skipDraftRestore] - Skip restoring a draft. - * @property {'form' | 'wizard' | 'pdf'} [display] - The display for this form. - * @property {string} [cdnUrl] - The CDN url for this form. - * @property {boolean} [flatten] - Flatten the form. - * @property {boolean} [sanitize] - Sanitize the form. - * @property {SanitizeConfig} [sanitizeConfig] - The sanitize configuration for this form. - * @property {ButtonSettings} [buttonSettings] - The button settings for this form. - * @property {object} [breadcrumbSettings] - The breadcrumb settings for this form. - * @property {boolean} [allowPrevious] - Allow the previous button (for Wizard forms). - * @property {string[]} [wizardButtonOrder] - The order of the buttons (for Wizard forms). - * @property {boolean} [showCheckboxBackground] - Show the checkbox background. - * @property {number} [zoom] - The zoom for PDF forms. - */ - /** * Creates an easy to use interface for embedding webforms, pdfs, and wizards into your application. - * @param {object} elementOrForm - The DOM element you wish to render this form within, or the form definition. - * @param {object | string | FormOptions} formOrOptions - A Form JSON schema, the URL of a hosted form, or the form options. - * @param {FormOptions} [options] - The options to create a new form instance. + * + * @param {Object} element - The DOM element you wish to render this form within. + * @param {Object | string} form - Either a Form JSON schema or the URL of a hosted form via. form.io. + * @param {Object} options - The options to create a new form instance. + * @param {boolean} options.readOnly - Set this form to readOnly + * @param {boolean} options.noAlerts - Set to true to disable the alerts dialog. + * @param {boolean} options.i18n - The translation file for this rendering. @see https://github.com/formio/formio.js/blob/master/i18n.js + * @param {boolean} options.template - Provides a way to inject custom logic into the creation of every element rendered within the form. + * * @example * import Form from '@formio/js/Form'; * const form = new Form(document.getElementById('formio'), 'https://examples.form.io/example'); * form.build(); */ - - /** - * @type {FormOptions} - the options for this Form. - */ - options; - - constructor(elementOrForm, formOrOptions, options = {}) { - let element, form, formOptions; - if (elementOrForm instanceof HTMLElement) { - element = elementOrForm; - form = formOrOptions; - formOptions = options; - } - else { - element = null; - form = elementOrForm; - formOptions = formOrOptions || {}; - } + constructor(...args) { + let options = args[0] instanceof HTMLElement ? args[2] : args[1]; if (Formio.options && Formio.options.form) { - formOptions = Object.assign(formOptions, Formio.options.form); + options = Object.assign(options, Formio.options.form); } - super(formOptions); + super(options); if (this.options.useSessionToken) { Formio.useSessionToken(this.options); @@ -139,22 +39,30 @@ export default class Form extends Element { }); this.instance = null; - if (element) { + if (args[0] instanceof HTMLElement) { if (this.element) { delete this.element.component; } - this.element = element; + this.element = args[0]; + this.options = args[2] || {}; + this.options.events = this.events; + this.setForm(args[1]) + .then(() => this.readyResolve(this.instance)) + .catch(this.readyReject); } - else { + else if (args[0]) { this.element = null; - } - if (form) { - this.setForm(form) + this.options = args[1] || {}; + this.options.events = this.events; + this.setForm(args[0]) .then(() => this.readyResolve(this.instance)) .catch(this.readyReject); } - this.options = formOptions; - this.options.events = this.events; + else { + this.element = null; + this.options = {}; + this.options.events = this.events; + } this.display = ''; } @@ -205,8 +113,9 @@ export default class Form extends Element { /** * Create a new form instance provided the display of the form. + * * @param {string} display - The display of the form, either "wizard", "form", or "pdf" - * @returns {Webform|Wizard|PDF} - The new form instance for the display. + * @return {*} */ create(display) { if (this.options && (this.options.flatten || this.options.renderMode === 'flat')) { @@ -224,8 +133,9 @@ export default class Form extends Element { /** * Sets the form. Either as JSON or a URL to a form JSON schema. + * * @param {string|object} formParam - Either the form JSON or the URL of the form json. - * @returns {void} + * @return {*} */ set form(formParam) { this.setForm(formParam); @@ -254,11 +164,12 @@ export default class Form extends Element { } /** - * Check Subdirectories path and provide correct options - * @param {string} url - The the URL of the form json. - * @param {import('@formio/core').Form} form - The form json. - * @returns {object} The initial options with base and project. - */ + * Check Subdirectories path and provide correct options + * + * @param {string} url - The the URL of the form json. + * @param {form} object - The form json. + * @return {object} The initial options with base and project. + */ getFormInitOptions(url, form) { const options = {}; const index = url.indexOf(form?.path); @@ -284,11 +195,6 @@ export default class Form extends Element { return {}; } - /** - * Sets the form to the JSON schema of a form. - * @param {import('@formio/core').Form} formParam - The form JSON to set this form to. - * @returns {Promise} - The webform instance that was created. - */ setForm(formParam) { let result; formParam = formParam || this.form; @@ -352,7 +258,8 @@ export default class Form extends Element { /** * Returns the loaded forms JSON. - * @returns {object} - The loaded form's JSON + * + * @return {object} - The loaded form's JSON */ get form() { return this._form; @@ -360,8 +267,9 @@ export default class Form extends Element { /** * Changes the display of the form. + * * @param {string} display - The display to set this form. Either "wizard", "form", or "pdf" - * @returns {Promise} - The form instance that was created after changing the display. + * @return {Promise} */ setDisplay(display) { if ((this.display === display) && this.instance) { @@ -406,9 +314,9 @@ export default class Form extends Element { /** * Sanitize an html string. - * @param {string} dirty - The dirty html string to sanitize. - * @param {boolean} forceSanitize - If the string should be force sanitized. - * @returns {string} - The sanitized html string. + * + * @param string + * @returns {*} */ sanitize(dirty, forceSanitize) { // If Sanitize is turned off @@ -428,7 +336,8 @@ export default class Form extends Element { /** * Build a new form. - * @returns {Promise} - The form instance that was created. + * + * @return {Promise} */ build() { if (!this.instance) { @@ -491,20 +400,16 @@ export default class Form extends Element { Formio.embedForm = (embed) => Form.embed(embed); /** - * Creates an easy to use interface for embedding webforms, pdfs, and wizards into your application. - * @param {object} elementOrForm - The DOM element you wish to render this form within, or the form definition. - * @param {object | string | FormOptions} formOrOptions - A Form JSON schema, the URL of a hosted form, or the form options. - * @param {FormOptions} [options] - The options to create a new form instance. - * @returns {Promise} - The form instance that was created. - * @example - * import { Formio } from '@formio/js'; - * Formio.createForm(document.getElementById('formio'), 'https://examples.form.io/example'); + * Factory that creates a new form based on the form parameters. + * + * @param element {HMTLElement} - The HTML Element to add this form to. + * @param form {string|Object} - The src of the form, or a form object. + * @param options {Object} - The options to create this form. + * + * @return {Promise} - When the form is instance is ready. */ -Formio.createForm = (elementOrForm, formOrOptions, options) => { - return (new Form(elementOrForm, formOrOptions, options)).ready; +Formio.createForm = (...args) => { + return (new Form(...args)).ready; }; Formio.Form = Form; - - -export { }; diff --git a/src/FormBuilder.js b/src/FormBuilder.js index 8595037f21..56e7a2e404 100644 --- a/src/FormBuilder.js +++ b/src/FormBuilder.js @@ -3,36 +3,7 @@ import Builders from './builders'; import Form from './Form'; export default class FormBuilder extends Form { - /** - * @typedef FormBuilderOptions - * @property {string[]} [disabled] - An array of "keys" of components that should be disabled within the form builder. Example: ['firstName', 'lastName'] - * @property {boolean} [noNewEdit] - When set to TRUE no modal is shown when a component is dragged onto the form. - * @property {boolean} [noDefaultSubmitButton] - Set to TRUE to not include the default submit button in Webforms. - * @property {boolean} [alwaysConfirmComponentRemoval] - Set to TRUE to always require confirmation before removing a component. - * @property {object} [formConfig] - Form configurations to apply to forms being created. These configurations are added to the "config" property of the form object. - * @property {string} [resourceTag] - The tag to use to query for the "Existing Resource Fields" section of the builder. - * @property {import('./Form').FormOptions} [editForm] - The options to apply to the Edit Form (the form that shows inside the modal when you edit a component). - * @property {string} [language] - The language to load into the form builder. - * @property {object} [builder] - The builder options to pass to the builder. - * @property {'form'|'wizard'|'pdf'} [display] - The display mode of the builder. - * @property {string} [resourceFilter] - Filter applied to the resources that appear in the builder's Existing Resource Fields. - * @property {boolean} [noSource] - When set to TRUE, the resource ID in the builder's Existing Resource Fields will not be linked. - * @property {boolean} [showFullJsonSchema] - When set to TRUE, the full JSON schema will be displayed in the JSON edit menu. - */ - - /** @type {FormBuilderOptions} */ static options = {}; - - /** @type {FormBuilderOptions} */ - options; - - /** - * Creates a new form builder. - * @param {HTMLElement} element - The HTML element to place the form builder. - * @param {string | object} form - The form to pass to the builder - * @param {FormBuilderOptions} options - The options to create this builder. - * @returns {FormBuilder} - The form builder instance. - */ constructor(element, form, options) { form = form || {}; options = options || {}; @@ -56,13 +27,15 @@ export default class FormBuilder extends Form { /** * Factory that creates a new form builder based on the form parameter. - * @param {HTMLElement} element - The HTML Element to add this form to. - * @param {string|object} form - The src of the form, or a form object. - * @param {object} options - The options to create this form. - * @returns {Promise} - When the form is instance is ready. + * + * @param element {HMTLElement} - The HTML Element to add this form to. + * @param form {string|Object} - The src of the form, or a form object. + * @param options {Object} - The options to create this form. + * + * @return {Promise} - When the form is instance is ready. */ -Formio.builder = (element, form, options) => { - return (new FormBuilder(element, form, options)).ready; +Formio.builder = (...args) => { + return (new FormBuilder(...args)).ready; }; Formio.FormBuilder = FormBuilder; diff --git a/src/PDF.js b/src/PDF.js index c99fdaeb9a..7f5192d441 100644 --- a/src/PDF.js +++ b/src/PDF.js @@ -162,7 +162,8 @@ export default class PDF extends Webform { /** * Get the submission from the iframe. - * @returns {Promise} - The submission from the iframe. + * + * @return {Promise} */ getSubmission() { return new Promise((resolve) => { @@ -173,8 +174,9 @@ export default class PDF extends Webform { /** * Ensure we have the submission from the iframe before we submit the form. - * @param {any} options - The options for submission. - * @returns {Promise} - Resolves when the form is submitted. + * + * @param options + * @return {*} */ submitForm(options = {}) { this.postMessage({ name: 'getErrors' }); @@ -226,9 +228,9 @@ export default class PDF extends Webform { /** * Set's the value of this form component. - * @param {import('@formio/core').Submission} submission - The submission JSON to set the value of this form. - * @param {any} flags - The flags to use when setting the submission. - * @returns {boolean} - If the value changed or not. + * + * @param submission + * @param flags */ setValue(submission, flags = {}) { const changed = super.setValue(submission, flags); diff --git a/src/Webform.js b/src/Webform.js index d89b8c9d1b..2f306ce240 100644 --- a/src/Webform.js +++ b/src/Webform.js @@ -1,21 +1,22 @@ -import _ from "lodash"; -import moment from "moment"; -import { compareVersions } from "compare-versions"; -import EventEmitter from "./EventEmitter"; -import i18nDefaults from "./i18n"; -import { Formio } from "./Formio"; -import Components from "./components/Components"; -import NestedDataComponent from "./components/_classes/nesteddata/NestedDataComponent"; +import _ from 'lodash'; +import moment from 'moment'; +import { compareVersions } from 'compare-versions'; +import { Component } from '@formio/core'; +import EventEmitter from './EventEmitter'; +import i18nDefaults from './i18n'; +import { Formio } from './Formio'; +import Components from './components/Components'; +import NestedDataComponent from './components/_classes/nesteddata/NestedDataComponent'; import { - fastCloneDeep, - currentTimezone, - unescapeHTML, - getStringFromComponentPath, - searchComponents, - convertStringToHTMLElement, - getArrayFromComponentPath, -} from "./utils/utils"; -import { eachComponent } from "./utils/formUtils"; + fastCloneDeep, + currentTimezone, + unescapeHTML, + getStringFromComponentPath, + searchComponents, + convertStringToHTMLElement, + getArrayFromComponentPath, +} from './utils/utils'; +import { eachComponent } from './utils/formUtils'; // Initialize the available forms. Formio.forms = {}; @@ -23,1662 +24,1706 @@ Formio.forms = {}; // Allow people to register components. Formio.registerComponent = Components.setComponent; -/** - * - * @param {any} icons - The icons to use. - * @returns {any} - The icon set. - */ function getIconSet(icons) { - if (icons === "fontawesome") { - return "fa"; - } - return icons || ""; + if (icons === 'fontawesome') { + return 'fa'; + } + return icons || ''; } -/** - * - * @param {any} options - The options to get. - * @returns {any} - The options. - */ function getOptions(options) { - options = _.defaults(options, { - submitOnEnter: false, - iconset: getIconSet(options && options.icons ? options.icons : Formio.icons), - i18next: null, - saveDraft: false, - alwaysDirty: false, - saveDraftThrottle: 5000, - display: "form", - cdnUrl: Formio.cdn.baseUrl, - }); - if (!options.events) { - options.events = new EventEmitter(); - } - return options; + options = _.defaults(options, { + submitOnEnter: false, + iconset: getIconSet((options && options.icons) ? options.icons : Formio.icons), + i18next: null, + saveDraft: false, + alwaysDirty: false, + saveDraftThrottle: 5000, + display: 'form', + cdnUrl: Formio.cdn.baseUrl + }); + if (!options.events) { + options.events = new EventEmitter(); + } + return options; } /** - * Renders a Form.io form within the webpage. + * Represents a JSON value. + * @typedef {(string | number | boolean | null | JSONArray | JSONObject)} JSON */ -export default class Webform extends NestedDataComponent { - /** - * @type {import('Form').FormOptions} - the options for this Webform. - */ - options; - - /** - * Creates a new Form instance. - * @param {HTMLElement | object | import('Form').FormOptions} [elementOrOptions] - The DOM element to render this form within or the options to create this form instance. - * @param {import('Form').FormOptions} [options] - The options to create a new form instance. - */ - constructor(elementOrOptions, options) { - let element, formOptions; - if (elementOrOptions instanceof HTMLElement || options) { - element = elementOrOptions; - formOptions = options; - } else { - formOptions = elementOrOptions; - } - super(null, getOptions(formOptions)); - - this.setElement(element); - - // Keep track of all available forms globally. - Formio.forms[this.id] = this; - - // Set the base url. - if (this.options.baseUrl) { - Formio.setBaseUrl(this.options.baseUrl); - } - - /** - * The type of this element. - * @type {string} - */ - this.type = "form"; - this._src = ""; - this._loading = false; - this._form = {}; - this.draftEnabled = false; - this.savingDraft = true; - if (this.options.saveDraftThrottle) { - this.triggerSaveDraft = _.throttle( - this.saveDraft.bind(this), - this.options.saveDraftThrottle - ); - } else { - this.triggerSaveDraft = this.saveDraft.bind(this); - } - - /** - * Determines if this form should submit the API on submit. - * @type {boolean} - */ - this.nosubmit = false; - - /** - * Determines if the form has tried to be submitted, error or not. - * @type {boolean} - */ - this.submitted = false; - - /** - * Determines if the form is being submitted at the moment. - * @type {boolean} - */ - this.submitting = false; - - /** - * The Formio instance for this form. - * @type {Formio} - */ - this.formio = null; - - /** - * The loader HTML element. - * @type {HTMLElement} - */ - this.loader = null; - - /** - * The alert HTML element - * @type {HTMLElement} - */ - this.alert = null; - /** - * Promise that is triggered when the submission is done loading. - * @type {Promise} - */ - this.onSubmission = null; - - /** - * Determines if this submission is explicitly set. - * @type {boolean} - */ - this.submissionSet = false; - - /** - * Promise that executes when the form is ready and rendered. - * @type {Promise} - * @example - * import Webform from '@formio/js/Webform'; - * let form = new Webform(document.getElementById('formio')); - * form.formReady.then(() => { - * console.log('The form is ready!'); - * }); - * form.src = 'https://examples.form.io/example'; - */ - this.formReady = new Promise((resolve, reject) => { - /** - * Called when the formReady state of this form has been resolved. - * @type {Function} - */ - this.formReadyResolve = resolve; - - /** - * Called when this form could not load and is rejected. - * @type {Function} - */ - this.formReadyReject = reject; - }); - - /** - * Promise that executes when the submission is ready and rendered. - * @type {Promise} - * @example - * import Webform from '@formio/js/Webform'; - * let form = new Webform(document.getElementById('formio')); - * form.submissionReady.then(() => { - * console.log('The submission is ready!'); - * }); - * form.src = 'https://examples.form.io/example/submission/234234234234234243'; - */ - this.submissionReady = new Promise((resolve, reject) => { - /** - * Called when the formReady state of this form has been resolved. - * @type {Function} - */ - this.submissionReadyResolve = resolve; - - /** - * Called when this form could not load and is rejected. - * @type {Function} - */ - this.submissionReadyReject = reject; - }); +/** + * Represents a JSON array. + * @typedef {Array} JSONArray + */ - this.shortcuts = []; +/** + * Represents a JSON object. + * @typedef {{[key: string]: JSON}} JSONObject + */ - // Set language after everything is established. - this.language = this.i18next.language; +/** + * @typedef {Object} FormioHooks + * @property {function} [beforeSubmit] + * @property {function} [beforeCancel] + * @property {function} [beforeNext] + * @property {function} [beforePrev] + * @property {function} [attachComponent] + * @property {function} [setDataValue] + * @property {function} [addComponents] + * @property {function} [addComponent] + * @property {function} [customValidation] + * @property {function} [attachWebform] + */ - // See if we need to restore the draft from a user. - if (this.options.saveDraft && !this.options.skipDraftRestore) { - this.formReady.then(() => { - const user = Formio.getUser(); - // Only restore a draft if the submission isn't explicitly set. - if (user && !this.submissionSet) { - this.restoreDraft(user._id); - } - }); - } +/** + * @typedef {Object} SanitizeConfig + * @property {string[]} [addAttr] + * @property {string[]} [addTags] + * @property {string[]} [allowedAttrs] + * @property {string[]} [allowedTags] + * @property {string[]} [allowedUriRegex] + * @property {string[]} [addUriSafeAttr] + */ - this.component.clearOnHide = false; +/** + * @typedef {Object} ButtonSettings + * @property {boolean} [showPrevious] + * @property {boolean} [showNext] + * @property {boolean} [showCancel] + * @property {boolean} [showSubmit] + */ - // Ensure the root is set to this component. - this.root = this; - this.localRoot = this; - } - /* eslint-enable max-statements */ +/** + * @typedef {Object} FormOptions + * @property {boolean} [saveDraft] - Enable the save draft feature. + * @property {number} [saveDraftThrottle] - The throttle for the save draft feature. + * @property {boolean} [readOnly] - Set this form to readOnly. + * @property {boolean} [noAlerts] - Disable the alerts dialog. + * @property {{[key: string]: string}} [i18n] - The translation file for this rendering. + * @property {string} [template] - Custom logic for creation of elements. + * @property {boolean} [noDefaults] - Exclude default values from the settings. + * @property {any} [fileService] - The file service for this form. + * @property {EventEmitter} [events] - The EventEmitter for this form. + * @property {string} [language] - The language to render this form in. + * @property {{[key: string]: string}} [i18next] - The i18next configuration for this form. + * @property {boolean} [viewAsHtml] - View the form as raw HTML. + * @property {'form' | 'html' | 'flat' | 'builder' | 'pdf'} [renderMode] - The render mode for this form. + * @property {boolean} [highlightErrors] - Highlight any errors on the form. + * @property {string} [componentErrorClass] - The error class for components. + * @property {any} [templates] - The templates for this form. + * @property {string} [iconset] - The iconset for this form. + * @property {Component[]} [components] - The components for this form. + * @property {{[key: string]: boolean}} [disabled] - Disabled components for this form. + * @property {boolean} [showHiddenFields] - Show hidden fields. + * @property {{[key: string]: boolean}} [hide] - Hidden components for this form. + * @property {{[key: string]: boolean}} [show] - Components to show for this form. + * @property {Formio} [formio] - The Formio instance for this form. + * @property {string} [decimalSeparator] - The decimal separator for this form. + * @property {string} [thousandsSeparator] - The thousands separator for this form. + * @property {FormioHooks} [hooks] - The hooks for this form. + * @property {boolean} [alwaysDirty] - Always be dirty. + * @property {boolean} [skipDraftRestore] - Skip restoring a draft. + * @property {'form' | 'wizard' | 'pdf'} [display] - The display for this form. + * @property {string} [cdnUrl] - The CDN url for this form. + * @property {boolean} [flatten] - Flatten the form. + * @property {boolean} [sanitize] - Sanitize the form. + * @property {SanitizeConfig} [sanitizeConfig] - The sanitize configuration for this form. + * @property {ButtonSettings} [buttonSettings] - The button settings for this form. + * @property {Object} [breadCrumbSettings] - The breadcrumb settings for this form. + * @property {boolean} [allowPrevious] - Allow the previous button (for Wizard forms). + * @property {string[]} [wizardButtonOrder] - The order of the buttons (for Wizard forms). + * @property {boolean} [showCheckboxBackground] - Show the checkbox background. + * @property {number} [zoom] - The zoom for PDF forms. + */ - get language() { - return this.options.language; - } +/** + * Renders a Form.io form within the webpage. + */ +export default class Webform extends NestedDataComponent { + /** + * @type {FormOptions} - the options for this Webform. + */ + options; - get emptyValue() { - return null; + /** + * Creates a new Form instance. + * + * @param {HTMLElement | Object | FormOptions} [elementOrOptions] - The DOM element to render this form within or the options to create this form instance. + * @param {FormOptions} [options] - The options to create a new form instance. + */ + constructor(elementOrOptions, options) { + let element, formOptions; + if (elementOrOptions instanceof HTMLElement || options) { + element = elementOrOptions; + formOptions = options; } - - componentContext() { - return this._data; + else { + formOptions = elementOrOptions; } + super(null, getOptions(formOptions)); - /** - * Sets the language for this form. - * @param {string} lang - The language to use (e.g. 'en', 'sp', etc.) - */ - set language(lang) { - if (!this.i18next) { - return; - } - this.options.language = lang; - if (this.i18next.language === lang) { - return; - } - this.i18next.changeLanguage(lang, (err) => { - if (err) { - return; - } - this.rebuild(); - this.emit("languageChanged"); - }); - } + this.setElement(element); - get componentComponents() { - return this.form.components; - } + // Keep track of all available forms globally. + Formio.forms[this.id] = this; - get shadowRoot() { - return this.options.shadowRoot; + // Set the base url. + if (this.options.baseUrl) { + Formio.setBaseUrl(this.options.baseUrl); } /** - * Add a language for translations - * @param {string} code - The language code for the language being added. - * @param {object} lang - The language translations. - * @param {boolean} [active] - If this language should be set as the active language. + * The type of this element. + * @type {string} */ - addLanguage(code, lang, active = false) { - if (this.i18next) { - var translations = _.assign(fastCloneDeep(i18nDefaults.resources.en.translation), lang); - this.i18next.addResourceBundle(code, "translation", translations, true, true); - if (active) { - this.language = code; - } - } - } - - keyboardCatchableElement(element) { - if (element.nodeName === "TEXTAREA") { - return false; - } - - if (element.nodeName === "INPUT") { - return ["text", "email", "password"].indexOf(element.type) === -1; - } - - return true; - } - - executeShortcuts = (event) => { - const { target } = event; - if (!this.keyboardCatchableElement(target)) { - return; - } - - const ctrl = event.ctrlKey || event.metaKey; - const keyCode = event.keyCode; - let char = ""; - - if (65 <= keyCode && keyCode <= 90) { - char = String.fromCharCode(keyCode); - } else if (keyCode === 13) { - char = "Enter"; - } else if (keyCode === 27) { - char = "Esc"; - } - - _.each(this.shortcuts, (shortcut) => { - if (shortcut.ctrl && !ctrl) { - return; - } - - if (shortcut.shortcut === char) { - shortcut.element.click(); - event.preventDefault(); - } - }); - }; - - addShortcut(element, shortcut) { - if (!shortcut || !/^([A-Z]|Enter|Esc)$/i.test(shortcut)) { - return; - } - - shortcut = _.capitalize(shortcut); - - if (shortcut === "Enter" || shortcut === "Esc") { - // Restrict Enter and Esc only for buttons - if (element.tagName !== "BUTTON") { - return; - } - - this.shortcuts.push({ - shortcut, - element, - }); - } else { - this.shortcuts.push({ - ctrl: true, - shortcut, - element, - }); - } + this.type = 'form'; + this._src = ''; + this._loading = false; + this._form = {}; + this.draftEnabled = false; + this.savingDraft = true; + if (this.options.saveDraftThrottle) { + this.triggerSaveDraft = _.throttle(this.saveDraft.bind(this), this.options.saveDraftThrottle); } - - removeShortcut(element, shortcut) { - if (!shortcut || !/^([A-Z]|Enter|Esc)$/i.test(shortcut)) { - return; - } - - _.remove(this.shortcuts, { - shortcut, - element, - }); + else { + this.triggerSaveDraft = this.saveDraft.bind(this); } /** - * Get the embed source of the form. - * @returns {string} - The source of the form. + * Determines if this form should submit the API on submit. + * @type {boolean} */ - get src() { - return this._src; - } - - /** - * Loads the submission if applicable. - * @returns {Promise} - The promise that is triggered when the submission is loaded. - */ - loadSubmission() { - this.loadingSubmission = true; - if (this.formio.submissionId) { - this.onSubmission = this.formio - .loadSubmission() - .then( - (submission) => this.setSubmission(submission), - (err) => this.submissionReadyReject(err) - ) - .catch((err) => this.submissionReadyReject(err)); - } else { - this.submissionReadyResolve(); - } - return this.submissionReady; - } + this.nosubmit = false; /** - * Set the src of the form renderer. - * @param {string} value - The source value to set. - * @param {any} options - The options to set. - * @returns {Promise} - The promise that is triggered when the form is set. + * Determines if the form has tried to be submitted, error or not. + * + * @type {boolean} */ - setSrc(value, options) { - if (this.setUrl(value, options)) { - this.nosubmit = false; - return this.formio - .loadForm({ params: { live: 1 } }) - .then((form) => { - const setForm = this.setForm(form); - this.loadSubmission(); - return setForm; - }) - .catch((err) => { - console.warn(err); - this.formReadyReject(err); - }); - } - return Promise.resolve(); - } + this.submitted = false; /** - * Set the Form source, which is typically the Form.io embed URL. - * @param {string} value - The value of the form embed url. - * @example - * import Webform from '@formio/js/Webform'; - * let form = new Webform(document.getElementById('formio')); - * form.formReady.then(() => { - * console.log('The form is formReady!'); - * }); - * form.src = 'https://examples.form.io/example'; + * Determines if the form is being submitted at the moment. + * + * @type {boolean} */ - set src(value) { - this.setSrc(value); - } + this.submitting = false; /** - * Get the embed source of the form. - * @returns {string} - returns the source of the form. + * The Formio instance for this form. + * @type {Formio} */ - get url() { - return this._src; - } + this.formio = null; /** - * Sets the url of the form renderer. - * @param {string} value - The value to set the url to. - * @param {any} options - The options to set. - * @returns {boolean} - TRUE means the url was set, FALSE otherwise. + * The loader HTML element. + * @type {HTMLElement} */ - setUrl(value, options) { - if (!value || typeof value !== "string" || value === this._src) { - return false; - } - this._src = value; - this.nosubmit = true; - this.formio = this.options.formio = new Formio(value, options); - - if (this.type === "form") { - // Set the options source so this can be passed to other components. - this.options.src = value; - } - return true; - } + this.loader = null; /** - * Set the form source but don't initialize the form and submission from the url. - * @param {string} value - The value of the form embed url. + * The alert HTML element + * @type {HTMLElement} */ - set url(value) { - this.setUrl(value); - } + this.alert = null; /** - * Called when both the form and submission have been loaded. - * @returns {Promise} - The promise to trigger when both form and submission have loaded. + * Promise that is triggered when the submission is done loading. + * @type {Promise} */ - get ready() { - return this.formReady.then(() => { - return super.ready.then(() => { - return this.loadingSubmission ? this.submissionReady : true; - }); - }); - } + this.onSubmission = null; /** - * Returns if this form is loading. - * @returns {boolean} - TRUE means the form is loading, FALSE otherwise. + * Determines if this submission is explicitly set. + * @type {boolean} */ - get loading() { - return this._loading; - } + this.submissionSet = false; /** - * Set the loading state for this form, and also show the loader spinner. - * @param {boolean} loading - If this form should be "loading" or not. + * Promise that executes when the form is ready and rendered. + * @type {Promise} + * + * @example + * import Webform from '@formio/js/Webform'; + * let form = new Webform(document.getElementById('formio')); + * form.formReady.then(() => { + * console.log('The form is ready!'); + * }); + * form.src = 'https://examples.form.io/example'; */ - set loading(loading) { - if (this._loading !== loading) { - this._loading = loading; - if (!this.loader && loading) { - this.loader = this.ce("div", { - class: "loader-wrapper", - }); - const spinner = this.ce("div", { - class: "loader text-center", - }); - this.loader.appendChild(spinner); - } - /* eslint-disable max-depth */ - if (this.loader) { - try { - if (loading) { - this.prependTo(this.loader, this.wrapper); - } else { - this.removeChildFrom(this.loader, this.wrapper); - } - } catch (err) { - // ingore - } - } - /* eslint-enable max-depth */ - } - } + this.formReady = new Promise((resolve, reject) => { + /** + * Called when the formReady state of this form has been resolved. + * + * @type {function} + */ + this.formReadyResolve = resolve; + + /** + * Called when this form could not load and is rejected. + * + * @type {function} + */ + this.formReadyReject = reject; + }); /** - * Sets the JSON schema for the form to be rendered. + * Promise that executes when the submission is ready and rendered. + * @type {Promise} + * * @example * import Webform from '@formio/js/Webform'; * let form = new Webform(document.getElementById('formio')); - * form.setForm({ - * components: [ - * { - * type: 'textfield', - * key: 'firstName', - * label: 'First Name', - * placeholder: 'Enter your first name.', - * input: true - * }, - * { - * type: 'textfield', - * key: 'lastName', - * label: 'Last Name', - * placeholder: 'Enter your last name', - * input: true - * }, - * { - * type: 'button', - * action: 'submit', - * label: 'Submit', - * theme: 'primary' - * } - * ] + * form.submissionReady.then(() => { + * console.log('The submission is ready!'); * }); - * @param {object} form - The JSON schema of the form @see https://examples.form.io/example for an example JSON schema. - * @param {any} flags - Any flags to apply when setting the form. - * @returns {Promise} - The promise that is triggered when the form is set. + * form.src = 'https://examples.form.io/example/submission/234234234234234243'; */ - setForm(form, flags) { - const isFormAlreadySet = this._form && this._form.components?.length; - try { - // Do not set the form again if it has been already set - if (isFormAlreadySet && JSON.stringify(this._form) === JSON.stringify(form)) { - return Promise.resolve(); - } - - // Create the form. - this._form = flags?.keepAsReference ? form : _.cloneDeep(form); - - if (this.onSetForm) { - this.onSetForm(_.cloneDeep(this._form), form); - } - - if (this.parent?.component?.modalEdit) { - return Promise.resolve(); - } - } catch (err) { - console.warn(err); - // If provided form is not a valid JSON object, do not set it too - return Promise.resolve(); - } - - // Allow the form to provide component overrides. - if (form && form.settings && form.settings.components) { - this.options.components = form.settings.components; - } - - if (form && form.properties) { - this.options.properties = form.properties; - } - // Use the sanitize config from the form settings or the global sanitize config if it is not provided in the options - if (!this.options.sanitizeConfig && !this.builderMode) { - this.options.sanitizeConfig = - _.get(form, "settings.sanitizeConfig") || - _.get(form, "globalSettings.sanitizeConfig"); - } + this.submissionReady = new Promise((resolve, reject) => { + /** + * Called when the formReady state of this form has been resolved. + * + * @type {function} + */ + this.submissionReadyResolve = resolve; + + /** + * Called when this form could not load and is rejected. + * + * @type {function} + */ + this.submissionReadyReject = reject; + }); - if ("schema" in form && compareVersions(form.schema, "1.x") > 0) { - this.ready.then(() => { - this.setAlert( - "alert alert-danger", - "Form schema is for a newer version, please upgrade your renderer. Some functionality may not work." - ); - }); - } + this.shortcuts = []; + + // Set language after everything is established. + this.language = this.i18next.language; + + // See if we need to restore the draft from a user. + if (this.options.saveDraft) { + this.formReady.then(()=> { + if (!this.options.skipDraftRestore) { + const user = Formio.getUser(); + // Only restore a draft if the submission isn't explicitly set. + if (user && !this.submissionSet) { + this.restoreDraft(user._id); + } + } + else { + // Enable drafts + this.draftEnabled = true; + this.savingDraft = false; + } + }); + } + + this.component.clearOnHide = false; + + // Ensure the root is set to this component. + this.root = this; + this.localRoot = this; + } + /* eslint-enable max-statements */ + + get language() { + return this.options.language; + } + + get emptyValue() { + return null; + } + + componentContext() { + return this._data; + } + + /** + * Sets the language for this form. + * + * @param lang + * @return {Promise} + */ + set language(lang) { + if (!this.i18next) { + return; + } + this.options.language = lang; + if (this.i18next.language === lang) { + return; + } + this.i18next.changeLanguage(lang, (err) => { + if (err) { + return; + } + this.rebuild(); + this.emit('languageChanged'); + }); + } - // See if they pass a module, and evaluate it if so. - if (form && form.module) { - let formModule = null; - if (typeof form.module === "string") { - try { - formModule = this.evaluate(`return ${form.module}`); - } catch (err) { - console.warn(err); - } - } else { - formModule = form.module; - } - if (formModule) { - Formio.use(formModule); + get componentComponents() { + return this.form.components; + } - // Since we got here after instantiation, we need to manually apply form options. - if (formModule.options && formModule.options.form) { - this.options = Object.assign(this.options, formModule.options.form); - } - } - } + get shadowRoot() { + return this.options.shadowRoot; + } - this.initialized = false; - const rebuild = this.rebuild() || Promise.resolve(); - return rebuild.then(() => { - this.emit("formLoad", form); - this.triggerRecaptcha(); - // Make sure to trigger onChange after a render event occurs to speed up form rendering. - setTimeout(() => { - this.onChange(flags); - this.formReadyResolve(); - }, 0); - - return this.formReady; - }); + /** + * Add a language for translations + * + * @param code + * @param lang + * @param active + * @return {*} + */ + addLanguage(code, lang, active = false) { + if (this.i18next) { + var translations = _.assign(fastCloneDeep(i18nDefaults.resources.en.translation), lang); + this.i18next.addResourceBundle(code, 'translation', translations, true, true); + if (active) { + this.language = code; + } } + } - /** - * Gets the form object. - * @returns {object} - The form JSON schema. - */ - get form() { - if (!this._form) { - this._form = { - components: [], - }; - } - return this._form; + keyboardCatchableElement(element) { + if (element.nodeName === 'TEXTAREA') { + return false; } - /** - * Sets the form value. - * @alias setForm - * @param {object} form - The form schema object. - */ - set form(form) { - this.setForm(form); + if (element.nodeName === 'INPUT') { + return [ + 'text', + 'email', + 'password' + ].indexOf(element.type) === -1; } - /** - * Returns the submission object that was set within this form. - * @returns {object} - The submission object. - */ - get submission() { - return this.getValue(); - } + return true; + } - /** - * Sets the submission of a form. - * @example - * import Webform from '@formio/js/Webform'; - * let form = new Webform(document.getElementById('formio')); - * form.src = 'https://examples.form.io/example'; - * form.submission = {data: { - * firstName: 'Joe', - * lastName: 'Smith', - * email: 'joe@example.com' - * }}; - * @param {object} submission - The Form.io submission object. - */ - set submission(submission) { - this.setSubmission(submission); + executeShortcuts = (event) => { + const { target } = event; + if (!this.keyboardCatchableElement(target)) { + return; } - /** - * Sets a submission and returns the promise when it is ready. - * @param {any} submission - The submission to set. - * @param {any} flags - Any flags to apply when setting the submission. - * @returns {Promise} - The promise that is triggered when the submission is set. - */ - setSubmission(submission, flags = {}) { - flags = { - ...flags, - fromSubmission: _.has(flags, "fromSubmission") ? flags.fromSubmission : true, - }; - return (this.onSubmission = this.formReady - .then( - (resolveFlags) => { - if (resolveFlags) { - flags = { - ...flags, - ...resolveFlags, - }; - } - this.submissionSet = true; - this.triggerChange(flags); - this.emit("beforeSetSubmission", submission); - this.setValue(submission, flags); - return this.submissionReadyResolve(submission); - }, - (err) => this.submissionReadyReject(err) - ) - .catch((err) => this.submissionReadyReject(err))); - } - - handleDraftError(errName, errDetails, restoreDraft) { - const errorMessage = _.trim(`${this.t(errName)} ${errDetails || ""}`); - console.warn(errorMessage); - this.emit( - restoreDraft ? "restoreDraftError" : "saveDraftError", - errDetails || errorMessage - ); - } - - saveDraft() { - if (!this.draftEnabled) { - return; - } - if (!this.formio) { - this.handleDraftError("saveDraftInstanceError"); - return; - } - if (!Formio.getUser()) { - this.handleDraftError("saveDraftAuthError"); - return; - } - const draft = fastCloneDeep(this.submission); - draft.state = "draft"; - - if (!this.savingDraft) { - this.emit("saveDraftBegin"); - this.savingDraft = true; - this.formio - .saveSubmission(draft) - .then((sub) => { - // Set id to submission to avoid creating new draft submission - this.submission._id = sub._id; - this.savingDraft = false; - this.emit("saveDraft", sub); - }) - .catch((err) => { - this.savingDraft = false; - this.handleDraftError("saveDraftError", err); - }); - } - } + const ctrl = event.ctrlKey || event.metaKey; + const keyCode = event.keyCode; + let char = ''; - /** - * Restores a draft submission based on the user who is authenticated. - * @param {string} userId - The user id where we need to restore the draft from. - */ - restoreDraft(userId) { - const formio = this.formio || this.options.formio; - if (!formio) { - this.handleDraftError("restoreDraftInstanceError", null, true); - return; - } - this.savingDraft = true; - formio - .loadSubmissions({ - params: { - state: "draft", - owner: userId, - }, - }) - .then((submissions) => { - if (submissions.length > 0 && !this.options.skipDraftRestore) { - const draft = fastCloneDeep(submissions[0]); - return this.setSubmission(draft).then(() => { - this.draftEnabled = true; - this.savingDraft = false; - this.emit("restoreDraft", draft); - }); - } - // Enable drafts so that we can keep track of changes. - this.draftEnabled = true; - this.savingDraft = false; - this.emit("restoreDraft", null); - }) - .catch((err) => { - this.draftEnabled = true; - this.savingDraft = false; - this.handleDraftError("restoreDraftError", err, true); - }); + if (65 <= keyCode && keyCode <= 90) { + char = String.fromCharCode(keyCode); } - - get schema() { - const schema = fastCloneDeep(_.omit(this._form, ["components"])); - schema.components = []; - this.eachComponent((component) => schema.components.push(component.schema)); - return schema; + else if (keyCode === 13) { + char = 'Enter'; } - - mergeData(_this, _that) { - _.mergeWith(_this, _that, (thisValue, thatValue) => { - if ( - Array.isArray(thisValue) && - Array.isArray(thatValue) && - thisValue.length !== thatValue.length - ) { - return thatValue; - } - }); + else if (keyCode === 27) { + char = 'Esc'; } - setValue(submission, flags = {}) { - if (!submission || !submission.data) { - submission = { - data: {}, - metadata: submission.metadata, - }; - } - // Metadata needs to be available before setValue - this._submission.metadata = submission.metadata || {}; - this.editing = !!submission._id; - - // Set the timezone in the options if available. - if ( - !this.options.submissionTimezone && - submission.metadata && - submission.metadata.timezone - ) { - this.options.submissionTimezone = submission.metadata.timezone; - } + _.each(this.shortcuts, (shortcut) => { + if (shortcut.ctrl && !ctrl) { + return; + } - const changed = super.setValue(submission.data, flags); - if (!flags.sanitize) { - this.mergeData(this.data, submission.data); - } - - submission.data = this.data; - this._submission = submission; - return changed; - } + if (shortcut.shortcut === char) { + shortcut.element.click(); + event.preventDefault(); + } + }); + }; - getValue() { - if (!this._submission.data) { - this._submission.data = {}; - } - if (this.viewOnly) { - return this._submission; - } - const submission = this._submission; - submission.data = this.data; - return this._submission; + addShortcut(element, shortcut) { + if (!shortcut || !/^([A-Z]|Enter|Esc)$/i.test(shortcut)) { + return; } - /** - * Build the form. - * @returns {Promise} - The promise that is triggered when the form is built. - */ - init() { - if (this.options.submission) { - const submission = _.extend({}, this.options.submission); - this._submission = submission; - this._data = submission.data; - } else { - this._submission = this._submission || { data: {} }; - } - - // Remove any existing components. - if (this.components && this.components.length) { - this.destroyComponents(); - this.components = []; - } - - if (this.component) { - this.component.components = this.form ? this.form.components : []; - } else { - this.component = this.form; - } - this.component.type = "form"; - this.component.input = false; - - this.addComponents(); - this.on( - "submitButton", - (options) => { - this.submit(false, options).catch((e) => { - options.instance.loading = false; - return e !== false && e !== undefined && console.log(e); - }); - }, - true - ); - - this.on( - "checkValidity", - (data) => this.validate(data, { dirty: true, process: "change" }), - true - ); - this.on("requestUrl", (args) => this.submitUrl(args.url, args.headers), true); - this.on("resetForm", () => this.resetValue(), true); - this.on("deleteSubmission", () => this.deleteSubmission(), true); - this.on("refreshData", () => this.updateValue(), true); - - this.executeFormController(); - - return this.formReady; - } - - executeFormController() { - // If no controller value or - // hidden and set to clearOnHide (Don't calculate a value for a hidden field set to clear when hidden) - if ( - !this.form || - !this.form.controller || - ((!this.visible || this.component.hidden) && - this.component.clearOnHide && - !this.rootPristine) - ) { - return false; - } + shortcut = _.capitalize(shortcut); - this.formReady.then(() => { - this.evaluate(this.form.controller, { - components: this.components, - instance: this, - }); - }); - } + if (shortcut === 'Enter' || shortcut === 'Esc') { + // Restrict Enter and Esc only for buttons + if (element.tagName !== 'BUTTON') { + return; + } - /** - * - */ - teardown() { - this.emit("formDelete", this.id); - delete Formio.forms[this.id]; - delete this.executeShortcuts; - delete this.triggerSaveDraft; - super.teardown(); - } - - destroy(all = false) { - this.off("submitButton"); - this.off("checkValidity"); - this.off("requestUrl"); - this.off("resetForm"); - this.off("deleteSubmission"); - this.off("refreshData"); - - return super.destroy(all); - } - - build(element) { - if (element || this.element) { - return this.ready.then(() => { - element = element || this.element; - super.build(element); - }); - } - return this.ready; + this.shortcuts.push({ + shortcut, + element + }); } - - getClassName() { - let classes = "formio-form"; - if (this.options.readOnly) { - classes += " formio-read-only"; - } - return classes; + else { + this.shortcuts.push({ + ctrl: true, + shortcut, + element + }); } + } - render() { - return super.render( - this.renderTemplate("webform", { - classes: this.getClassName(), - children: this.renderComponents(), - }), - this.builderMode ? "builder" : "form", - true - ); + removeShortcut(element, shortcut) { + if (!shortcut || !/^([A-Z]|Enter|Esc)$/i.test(shortcut)) { + return; } - redraw() { - // Don't bother if we have not built yet. - if (!this.element) { - return Promise.resolve(); - } - this.clear(); - this.setContent(this.element, this.render()); - return this.attach(this.element); - } - - attach(element) { - this.setElement(element); - this.loadRefs(element, { webform: "single" }); - const childPromise = this.attachComponents(this.refs.webform); - this.addEventListener(document, "keydown", this.executeShortcuts); - this.currentForm = this; - this.hook("attachWebform", element, this); - return childPromise.then(() => { - this.emit("render", this.element); - - return this.setValue(this._submission, { - noUpdateEvent: true, - }); + _.remove(this.shortcuts, { + shortcut, + element + }); + } + + /** + * Get the embed source of the form. + * + * @returns {string} + */ + get src() { + return this._src; + } + + /** + * Loads the submission if applicable. + */ + loadSubmission() { + this.loadingSubmission = true; + if (this.formio.submissionId) { + this.onSubmission = this.formio.loadSubmission().then( + (submission) => this.setSubmission(submission), + (err) => this.submissionReadyReject(err) + ).catch( + (err) => this.submissionReadyReject(err) + ); + } + else { + this.submissionReadyResolve(); + } + return this.submissionReady; + } + + /** + * Set the src of the form renderer. + * + * @param value + * @param options + */ + setSrc(value, options) { + if (this.setUrl(value, options)) { + this.nosubmit = false; + return this.formio.loadForm({ params: { live: 1 } }).then( + (form) => { + const setForm = this.setForm(form); + this.loadSubmission(); + return setForm; + }).catch((err) => { + console.warn(err); + this.formReadyReject(err); + }); + } + return Promise.resolve(); + } + + /** + * Set the Form source, which is typically the Form.io embed URL. + * + * @param {string} value - The value of the form embed url. + * + * @example + * import Webform from '@formio/js/Webform'; + * let form = new Webform(document.getElementById('formio')); + * form.formReady.then(() => { + * console.log('The form is formReady!'); + * }); + * form.src = 'https://examples.form.io/example'; + */ + set src(value) { + this.setSrc(value); + } + + /** + * Get the embed source of the form. + * + * @returns {string} + */ + get url() { + return this._src; + } + + /** + * Sets the url of the form renderer. + * + * @param value + * @param options + */ + setUrl(value, options) { + if ( + !value || + (typeof value !== 'string') || + (value === this._src) + ) { + return false; + } + this._src = value; + this.nosubmit = true; + this.formio = this.options.formio = new Formio(value, options); + + if (this.type === 'form') { + // Set the options source so this can be passed to other components. + this.options.src = value; + } + return true; + } + + /** + * Set the form source but don't initialize the form and submission from the url. + * + * @param {string} value - The value of the form embed url. + */ + set url(value) { + this.setUrl(value); + } + + /** + * Called when both the form and submission have been loaded. + * + * @returns {Promise} - The promise to trigger when both form and submission have loaded. + */ + get ready() { + return this.formReady.then(() => { + return super.ready.then(() => { + return this.loadingSubmission ? this.submissionReady : true; + }); + }); + } + + /** + * Returns if this form is loading. + * + * @returns {boolean} - TRUE means the form is loading, FALSE otherwise. + */ + get loading() { + return this._loading; + } + + /** + * Set the loading state for this form, and also show the loader spinner. + * + * @param {boolean} loading - If this form should be "loading" or not. + */ + set loading(loading) { + if (this._loading !== loading) { + this._loading = loading; + if (!this.loader && loading) { + this.loader = this.ce('div', { + class: 'loader-wrapper' }); - } + const spinner = this.ce('div', { + class: 'loader text-center' + }); + this.loader.appendChild(spinner); + } + /* eslint-disable max-depth */ + if (this.loader) { + try { + if (loading) { + this.prependTo(this.loader, this.wrapper); + } + else { + this.removeChildFrom(this.loader, this.wrapper); + } + } + catch (err) { + // ingore + } + } + /* eslint-enable max-depth */ + } + } + + /** + * Sets the JSON schema for the form to be rendered. + * + * @example + * import Webform from '@formio/js/Webform'; + * let form = new Webform(document.getElementById('formio')); + * form.setForm({ + * components: [ + * { + * type: 'textfield', + * key: 'firstName', + * label: 'First Name', + * placeholder: 'Enter your first name.', + * input: true + * }, + * { + * type: 'textfield', + * key: 'lastName', + * label: 'Last Name', + * placeholder: 'Enter your last name', + * input: true + * }, + * { + * type: 'button', + * action: 'submit', + * label: 'Submit', + * theme: 'primary' + * } + * ] + * }); + * + * @param {Object} form - The JSON schema of the form @see https://examples.form.io/example for an example JSON schema. + * @param flags + * @returns {*} + */ + setForm(form, flags) { + const isFormAlreadySet = this._form && this._form.components?.length; + try { + // Do not set the form again if it has been already set + if (isFormAlreadySet && JSON.stringify(this._form) === JSON.stringify(form)) { + return Promise.resolve(); + } - hasRequiredFields() { - let result = false; + // Create the form. + this._form = flags?.keepAsReference ? form : _.cloneDeep(form); - eachComponent( - this.form.components, - (component) => { - if (component.validate.required) { - result = true; - return true; - } - }, - true - ); + if (this.onSetForm) { + this.onSetForm(_.cloneDeep(this._form), form); + } - return result; + if (this.parent?.component?.modalEdit) { + return Promise.resolve(); + } } - - resetValue() { - _.each(this.getComponents(), (comp) => comp.resetValue()); - this.setPristine(true); - this.onChange({ resetValue: true }); + catch (err) { + console.warn(err); + // If provided form is not a valid JSON object, do not set it too + return Promise.resolve(); } - /** - * Sets a new alert to display in the error dialog of the form. - * @param {string} type - The type of alert to display. "danger", "success", "warning", etc. - * @param {string} message - The message to show in the alert. - * @param {object} options - The options for the alert. - */ - setAlert(type, message, options) { - if (!type && this.submitted) { - if (this.alert) { - if (this.refs.errorRef && this.refs.errorRef.length) { - this.refs.errorRef.forEach((el) => { - this.removeEventListener(el, "click"); - this.removeEventListener(el, "keypress"); - }); - } - this.removeChild(this.alert); - this.alert = null; - } - return; - } - if (this.options.noAlerts) { - if (!message) { - this.emit("error", false); - } - return; - } - if (this.alert) { - try { - if (this.refs.errorRef && this.refs.errorRef.length) { - this.refs.errorRef.forEach((el) => { - this.removeEventListener(el, "click"); - this.removeEventListener(el, "keypress"); - }); - } - this.removeChild(this.alert); - this.alert = null; - } catch (err) { - // ignore - } - } - if (message) { - const attrs = { - class: (options && options.classes) || `alert alert-${type}`, - id: `error-list-${this.id}`, - }; - - const templateOptions = { - message: message instanceof HTMLElement ? message.outerHTML : message, - attrs: attrs, - type, - }; - - this.alert = convertStringToHTMLElement( - this.renderTemplate("alert", templateOptions), - `#${attrs.id}` - ); - } - if (!this.alert) { - return; - } - - this.loadRefs(this.alert, { errorRef: "multiple" }); + // Allow the form to provide component overrides. + if (form && form.settings && form.settings.components) { + this.options.components = form.settings.components; + } - if (this.refs.errorRef && this.refs.errorRef.length) { - this.refs.errorRef.forEach((el) => { - this.addEventListener(el, "click", (e) => { - const key = e.currentTarget.dataset.componentKey; - this.focusOnComponent(key); - }); - this.addEventListener(el, "keydown", (e) => { - if (e.keyCode === 13) { - e.preventDefault(); - const key = e.currentTarget.dataset.componentKey; - this.focusOnComponent(key); - } - }); - }); - } - this.prepend(this.alert); + if (form && form.properties) { + this.options.properties = form.properties; + } + // Use the sanitize config from the form settings or the global sanitize config if it is not provided in the options + if (!this.options.sanitizeConfig && !this.builderMode) { + this.options.sanitizeConfig = _.get(form, 'settings.sanitizeConfig') || _.get(form, 'globalSettings.sanitizeConfig'); } - /** - * Focus on selected component. - * @param {string} key - The key of selected component. - */ - focusOnComponent(key) { - if (key) { - const component = this.getComponent(key); - if (component) { - component.focus(); - } - } + if ('schema' in form && compareVersions(form.schema, '1.x') > 0) { + this.ready.then(() => { + this.setAlert('alert alert-danger', 'Form schema is for a newer version, please upgrade your renderer. Some functionality may not work.'); + }); } - /** - * Show the errors of this form within the alert dialog. - * @param {object} error - An optional additional error to display along with the component errors. - * @returns {*} - */ - /* eslint-disable no-unused-vars */ - /** - * - * @param {Array} errors - An array of errors to display. - * @param {boolean} triggerEvent - Whether or not to trigger the error event. - * @returns {void|Array} - The errors that were set. - */ - showErrors(errors, triggerEvent) { - this.loading = false; - if (!Array.isArray(errors)) { - errors = [errors]; + // See if they pass a module, and evaluate it if so. + if (form && form.module) { + let formModule = null; + if (typeof form.module === 'string') { + try { + formModule = this.evaluate(`return ${form.module}`); } - - errors = errors.concat(this.customErrors).filter((err) => !!err); - - if (!errors.length) { - this.setAlert(false); - return; + catch (err) { + console.warn(err); } + } + else { + formModule = form.module; + } + if (formModule) { + Formio.use(formModule); - // Mark any components as invalid if in a custom message. - errors.forEach((err) => { - const { components = [] } = err; - - if (err.component) { - components.push(err.component); - } - - if (err.path) { - components.push(err.path); - } + // Since we got here after instantiation, we need to manually apply form options. + if (formModule.options && formModule.options.form) { + this.options = Object.assign(this.options, formModule.options.form); + } + } + } - components.forEach((path) => { - const originalPath = getStringFromComponentPath(path); - const component = this.getComponent(path, _.identity, originalPath); + this.initialized = false; + const rebuild = this.rebuild() || Promise.resolve(); + return rebuild.then(() => { + this.emit('formLoad', form); + this.triggerRecaptcha(); + // Make sure to trigger onChange after a render event occurs to speed up form rendering. + setTimeout(() => { + this.onChange(flags); + this.formReadyResolve(); + }, 0); - if (err.fromServer) { - if (component.serverErrors) { - component.serverErrors.push(err); - } else { - component.serverErrors = [err]; - } - } - const components = _.compact(Array.isArray(component) ? component : [component]); + return this.formReady; + }); + } + + /** + * Gets the form object. + * + * @returns {Object} - The form JSON schema. + */ + get form() { + if (!this._form) { + this._form = { + components: [] + }; + } + return this._form; + } + + /** + * Sets the form value. + * + * @alias setForm + * @param {Object} form - The form schema object. + */ + set form(form) { + this.setForm(form); + } + + /** + * Returns the submission object that was set within this form. + * + * @returns {Object} + */ + get submission() { + return this.getValue(); + } + + /** + * Sets the submission of a form. + * + * @example + * import Webform from '@formio/js/Webform'; + * let form = new Webform(document.getElementById('formio')); + * form.src = 'https://examples.form.io/example'; + * form.submission = {data: { + * firstName: 'Joe', + * lastName: 'Smith', + * email: 'joe@example.com' + * }}; + * + * @param {Object} submission - The Form.io submission object. + */ + set submission(submission) { + this.setSubmission(submission); + } + + /** + * Sets a submission and returns the promise when it is ready. + * @param submission + * @param flags + * @return {Promise.} + */ + setSubmission(submission, flags = {}) { + flags = { + ...flags, + fromSubmission: _.has(flags, 'fromSubmission') ? flags.fromSubmission : true, + }; + return this.onSubmission = this.formReady.then( + (resolveFlags) => { + if (resolveFlags) { + flags = { + ...flags, + ...resolveFlags + }; + } + this.submissionSet = true; + this.triggerChange(flags); + this.emit('beforeSetSubmission', submission); + this.setValue(submission, flags); + return this.submissionReadyResolve(submission); + }, + (err) => this.submissionReadyReject(err) + ).catch( + (err) => this.submissionReadyReject(err) + ); + } + + handleDraftError(errName, errDetails, restoreDraft) { + const errorMessage = _.trim(`${this.t(errName)} ${errDetails || ''}`); + console.warn(errorMessage); + this.emit(restoreDraft ? 'restoreDraftError' : 'saveDraftError', errDetails || errorMessage); + } + + /** + * Saves a submission draft. + */ + saveDraft() { + if (!this.draftEnabled) { + return; + } + if (!this.formio) { + this.handleDraftError('saveDraftInstanceError'); + return; + } + if (!Formio.getUser()) { + this.handleDraftError('saveDraftAuthError'); + return; + } + const draft = fastCloneDeep(this.submission); + draft.state = 'draft'; + + if (!this.savingDraft && !this.submitting) { + this.emit('saveDraftBegin'); + this.savingDraft = true; + this.formio.saveSubmission(draft).then((sub) => { + // Set id to submission to avoid creating new draft submission + this.submission._id = sub._id; + this.savingDraft = false; + this.emit('saveDraft', sub); + }) + .catch(err => { + this.savingDraft = false; + this.handleDraftError('saveDraftError', err); + }); + } + } + + /** + * Restores a draft submission based on the user who is authenticated. + * + * @param {userId} - The user id where we need to restore the draft from. + */ + restoreDraft(userId) { + const formio = this.formio || this.options.formio; + if (!formio) { + this.handleDraftError('restoreDraftInstanceError', null, true); + return; + } + this.savingDraft = true; + formio.loadSubmissions({ + params: { + state: 'draft', + owner: userId + } + }).then(submissions => { + if (submissions.length > 0 && !this.options.skipDraftRestore) { + const draft = fastCloneDeep(submissions[0]); + return this.setSubmission(draft).then(() => { + this.draftEnabled = true; + this.savingDraft = false; + this.emit('restoreDraft', draft); + }); + } + // Enable drafts so that we can keep track of changes. + this.draftEnabled = true; + this.savingDraft = false; + this.emit('restoreDraft', null); + }) + .catch(err => { + this.draftEnabled = true; + this.savingDraft = false; + this.handleDraftError('restoreDraftError', err, true); + }); + } + + get schema() { + const schema = fastCloneDeep(_.omit(this._form, ['components'])); + schema.components = []; + this.eachComponent((component) => schema.components.push(component.schema)); + return schema; + } + + mergeData(_this, _that) { + _.mergeWith(_this, _that, (thisValue, thatValue) => { + if (Array.isArray(thisValue) && Array.isArray(thatValue) && thisValue.length !== thatValue.length) { + return thatValue; + } + }); + } - components.forEach((component) => component.setCustomValidity(err.message, true)); - }); + setValue(submission, flags = {}) { + if (!submission || !submission.data) { + submission = { + data: {}, + metadata: submission.metadata, + }; + } + // Metadata needs to be available before setValue + this._submission.metadata = submission.metadata || {}; + this.editing = !!submission._id; + + // Set the timezone in the options if available. + if ( + !this.options.submissionTimezone && + submission.metadata && + submission.metadata.timezone + ) { + this.options.submissionTimezone = submission.metadata.timezone; + } + + const changed = super.setValue(submission.data, flags); + if (!flags.sanitize) { + this.mergeData(this.data, submission.data); + } + + submission.data = this.data; + this._submission = submission; + return changed; + } + + getValue() { + if (!this._submission.data) { + this._submission.data = {}; + } + if (this.viewOnly) { + return this._submission; + } + const submission = this._submission; + submission.data = this.data; + return this._submission; + } + + /** + * Build the form. + */ + init() { + if (this.options.submission) { + const submission = _.extend({}, this.options.submission); + this._submission = submission; + this._data = submission.data; + } + else { + this._submission = this._submission || { data: {} }; + } + + // Remove any existing components. + if (this.components && this.components.length) { + this.destroyComponents(); + this.components = []; + } + + if (this.component) { + this.component.components = this.form ? this.form.components : []; + } + else { + this.component = this.form; + } + this.component.type = 'form'; + this.component.input = false; + + this.addComponents(); + this.on('submitButton', options => { + this.submit(false, options).catch(e => { + options.instance.loading = false; + return e !== false && e !== undefined && console.log(e); + }); + }, true); + + this.on('checkValidity', (data) => this.validate(data, { dirty: true, process: 'change' }), true); + this.on('requestUrl', (args) => (this.submitUrl(args.url,args.headers)), true); + this.on('resetForm', () => this.resetValue(), true); + this.on('deleteSubmission', () => this.deleteSubmission(), true); + this.on('refreshData', () => this.updateValue(), true); + + this.executeFormController(); + + return this.formReady; + } + + executeFormController() { + // If no controller value or + // hidden and set to clearOnHide (Don't calculate a value for a hidden field set to clear when hidden) + if ( + !this.form || !this.form.controller + || ((!this.visible || this.component.hidden) && this.component.clearOnHide && !this.rootPristine) + ) { + return false; + } + + this.formReady.then(() => { + this.evaluate(this.form.controller, { + components: this.components, + instance: this, }); + }); + } + + teardown() { + this.emit('formDelete', this.id); + delete Formio.forms[this.id]; + delete this.executeShortcuts; + delete this.triggerSaveDraft; + super.teardown(); + } + + destroy(all = false) { + this.off('submitButton'); + this.off('checkValidity'); + this.off('requestUrl'); + this.off('resetForm'); + this.off('deleteSubmission'); + this.off('refreshData'); + + return super.destroy(all); + } + + build(element) { + if (element || this.element) { + return this.ready.then(() => { + element = element || this.element; + super.build(element); + }); + } + return this.ready; + } + + getClassName() { + let classes = 'formio-form'; + if (this.options.readOnly) { + classes += ' formio-read-only'; + } + return classes; + } + + render() { + return super.render(this.renderTemplate('webform', { + classes: this.getClassName(), + children: this.renderComponents(), + }), this.builderMode ? 'builder' : 'form', true); + } + + redraw() { + // Don't bother if we have not built yet. + if (!this.element) { + return Promise.resolve(); + } + this.clear(); + this.setContent(this.element, this.render()); + return this.attach(this.element); + } + + attach(element) { + this.setElement(element); + this.loadRefs(element, { webform: 'single' }); + const childPromise = this.attachComponents(this.refs.webform); + this.addEventListener(document, 'keydown', this.executeShortcuts); + this.currentForm = this; + this.hook('attachWebform', element, this); + return childPromise.then(() => { + this.emit('render', this.element); + + return this.setValue(this._submission, { + noUpdateEvent: true, + }); + }); + } - const displayedErrors = []; - if (errors.length) { - errors = _.uniqBy(errors, (error) => error.message); - const createListItem = (message, index) => { - const err = errors[index]; - const messageFromIndex = !_.isUndefined(index) && errors && errors[index]; - const keyOrPath = - messageFromIndex?.formattedKeyOrPath || - messageFromIndex?.path || - messageFromIndex?.context?.path || - (err.context?.component && err.context?.component.key) || - (err.component && err.component.key) || - (err.fromServer && err.path); - - const formattedKeyOrPath = keyOrPath ? getStringFromComponentPath(keyOrPath) : ""; - if (typeof err !== "string" && !err.formattedKeyOrPath) { - err.formattedKeyOrPath = formattedKeyOrPath; - } - - return { - message: unescapeHTML(message), - keyOrPath: formattedKeyOrPath, - }; - }; - - errors.forEach(({ message, context, fromServer, component }, index) => { - const text = - !component?.label || context?.hasLabel || fromServer - ? this.t("alertMessage", { message: this.t(message) }) - : this.t("alertMessageWithLabel", { - label: this.t(component?.label), - message: this.t(message), - }); - displayedErrors.push(createListItem(text, index)); - }); - } + hasRequiredFields() { + let result = false; - const errorsList = this.renderTemplate("errorsList", { errors: displayedErrors }); - this.root.setAlert("danger", errorsList); - if (triggerEvent) { - this.emit("error", errors); + eachComponent(this.form.components, (component) => { + if (component.validate.required) { + result = true; + return true; + } + }, true); + + return result; + } + + resetValue() { + _.each(this.getComponents(), (comp) => (comp.resetValue())); + this.setPristine(true); + this.onChange({ resetValue: true }); + } + + /** + * Sets a new alert to display in the error dialog of the form. + * + * @param {string} type - The type of alert to display. "danger", "success", "warning", etc. + * @param {string} message - The message to show in the alert. + * @param {Object} options + */ + setAlert(type, message, options) { + if (!type && this.submitted) { + if (this.alert) { + if (this.refs.errorRef && this.refs.errorRef.length) { + this.refs.errorRef.forEach(el => { + this.removeEventListener(el, 'click'); + this.removeEventListener(el, 'keypress'); + }); } - - return errors; + this.removeChild(this.alert); + this.alert = null; + } + return; } - /* eslint-enable no-unused-vars */ - - /** - * Called when the submission has completed, or if the submission needs to be sent to an external library. - * @param {object} submission - The submission object. - * @param {boolean} saved - Whether or not this submission was saved to the server. - * @returns {object} - The submission object. - */ - onSubmit(submission, saved) { - this.loading = false; - this.submitting = false; - this.setPristine(true); - // We want to return the submitted submission and setValue will mutate the submission so cloneDeep it here. - this.setValue(fastCloneDeep(submission), { - noValidate: true, - noCheck: true, - }); - this.setAlert("success", `

${this.t("complete")}

`); - // Cancel triggered saveDraft to prevent overriding the submitted state - if (this.draftEnabled && this.triggerSaveDraft?.cancel) { - this.triggerSaveDraft.cancel(); - } - this.emit("submit", submission, saved); - if (saved) { - this.emit("submitDone", submission); + if (this.options.noAlerts) { + if (!message) { + this.emit('error', false); + } + return; + } + if (this.alert) { + try { + if (this.refs.errorRef && this.refs.errorRef.length) { + this.refs.errorRef.forEach(el => { + this.removeEventListener(el, 'click'); + this.removeEventListener(el, 'keypress'); + }); } - return submission; + this.removeChild(this.alert); + this.alert = null; + } + catch (err) { + // ignore + } } + if (message) { + const attrs = { + class: (options && options.classes) || `alert alert-${type}`, + id: `error-list-${this.id}`, + }; - normalizeError(error) { - if (error) { - if (typeof error === "object" && "details" in error) { - error = error.details; - } - - if (typeof error === "string") { - error = { message: error }; - } - } + const templateOptions = { + message: message instanceof HTMLElement ? message.outerHTML : message, + attrs: attrs, + type + }; - return error; + this.alert = convertStringToHTMLElement(this.renderTemplate('alert', templateOptions),`#${attrs.id}`); + } + if (!this.alert) { + return; } - /** - * Called when an error occurs during the submission. - * @param {object} error - The error that occured. - * @returns {Array} errors - All errors. - */ - onSubmissionError(error) { - error = this.normalizeError(error); - - this.submitting = false; - this.setPristine(false); - this.emit("submitError", error || this.errors); + this.loadRefs(this.alert, { errorRef: 'multiple' }); - // Allow for silent cancellations (no error message, no submit button error state) - if (error && error.silent) { - this.emit("change", { isValid: true }, { silent: true }); - return false; - } + if (this.refs.errorRef && this.refs.errorRef.length) { + this.refs.errorRef.forEach(el => { + this.addEventListener(el, 'click', (e) => { + const key = e.currentTarget.dataset.componentKey; + this.focusOnComponent(key); + }); + this.addEventListener(el, 'keydown', (e) => { + if (e.keyCode === 13) { + e.preventDefault(); + const key = e.currentTarget.dataset.componentKey; + this.focusOnComponent(key); + } + }); + }); + } + this.prepend(this.alert); + } + + /** + * Focus on selected component. + * + * @param {string} key - The key of selected component. + * @returns {*} + */ + focusOnComponent(key) { + if (key) { + const component = this.getComponent(key); + if (component) { + component.focus(); + } + } + } + + /** + * Show the errors of this form within the alert dialog. + * + * @param {Object} error - An optional additional error to display along with the component errors. + * @returns {*} + */ + /* eslint-disable no-unused-vars */ + showErrors(errors, triggerEvent) { + this.loading = false; + if (!Array.isArray(errors)) { + errors = [errors]; + } + + errors = errors.concat(this.customErrors).filter((err) => !!err); + + if (!errors.length) { + this.setAlert(false); + return; + } + + // Mark any components as invalid if in a custom message. + errors.forEach((err) => { + const { components = [] } = err; + + if (err.component) { + components.push(err.component); + } + + if (err.path) { + components.push(err.path); + } + + components.forEach((path) => { + const originalPath = getStringFromComponentPath(path); + const component = this.getComponent(path, _.identity, originalPath); + + if (err.fromServer) { + if (component.serverErrors) { + component.serverErrors.push(err); + } + else { + component.serverErrors = [err]; + } + } + const components = _.compact(Array.isArray(component) ? component : [component]); + + components.forEach((component) => component.setCustomValidity(err.message, true)); + }); + }); - const errors = this.showErrors(error, true); + const displayedErrors = []; + if (errors.length) { + errors = _.uniqBy(errors, error => error.message); + const createListItem = (message, index) => { + const err = errors[index]; + const messageFromIndex = !_.isUndefined(index) && errors && errors[index]; + const keyOrPath = (messageFromIndex?.formattedKeyOrPath || messageFromIndex?.path || messageFromIndex?.context?.path) || (err.context?.component && err.context?.component.key) || (err.component && err.component.key) || err.fromServer && err.path; - if (this.root && this.root.alert) { - this.scrollIntoView(this.root.alert); + const formattedKeyOrPath = keyOrPath ? getStringFromComponentPath(keyOrPath) : ''; + if (typeof err !== 'string' && !err.formattedKeyOrPath) { + err.formattedKeyOrPath = formattedKeyOrPath; } - return errors; + return { + message: unescapeHTML(message), + keyOrPath: formattedKeyOrPath + }; + }; + + errors.forEach(({ message, context, fromServer, component }, index) => { + const text = !component?.label || context?.hasLabel || fromServer + ? this.t('alertMessage', { message: this.t(message) }) + : this.t('alertMessageWithLabel', { + label: this.t(component?.label), + message: this.t(message), + }); + displayedErrors.push(createListItem(text, index)); + }); + } + + const errorsList = this.renderTemplate('errorsList', { errors: displayedErrors }); + this.root.setAlert('danger', errorsList); + if (triggerEvent) { + this.emit('error', errors); + } + + return errors; + } + /* eslint-enable no-unused-vars */ + + /** + * Called when the submission has completed, or if the submission needs to be sent to an external library. + * + * @param {Object} submission - The submission object. + * @param {boolean} saved - Whether or not this submission was saved to the server. + * @returns {object} - The submission object. + */ + onSubmit(submission, saved) { + this.loading = false; + this.submitting = false; + this.setPristine(true); + // We want to return the submitted submission and setValue will mutate the submission so cloneDeep it here. + this.setValue(fastCloneDeep(submission), { + noValidate: true, + noCheck: true + }); + this.setAlert('success', `

${this.t('complete')}

`); + // Cancel triggered saveDraft to prevent overriding the submitted state + if (this.draftEnabled && this.triggerSaveDraft?.cancel) { + this.triggerSaveDraft.cancel(); } + this.emit('submit', submission, saved); + if (saved) { + this.emit('submitDone', submission); + } + return submission; + } - /** - * Trigger the change event for this form. - * @param {any} flags - The flags to set on this change event. - * @param {any} changed - The changed object which reflects the changes in the form. - * @param {boolean} modified - Whether or not the form has been modified. - * @param {any} changes - The changes that have occured in the form. - */ - onChange(flags, changed, modified, changes) { - flags = flags || {}; - let isChangeEventEmitted = false; - super.onChange(flags, true); - const value = _.clone(this.submission); - flags.changed = value.changed = changed; - flags.changes = changes; - - if (modified && this.pristine) { - this.pristine = false; - } + normalizeError(error) { + if (error) { + if (typeof error === 'object' && 'details' in error) { + error = error.details; + } + + if (typeof error === 'string') { + error = { message: error }; + } + } + + return error; + } + + /** + * Called when an error occurs during the submission. + * + * @param {Object} error - The error that occured. + */ + onSubmissionError(error) { + error = this.normalizeError(error); + + this.submitting = false; + this.setPristine(false); + this.emit('submitError', error || this.errors); + + // Allow for silent cancellations (no error message, no submit button error state) + if (error && error.silent) { + this.emit('change', { isValid: true }, { silent: true }); + return false; + } + + const errors = this.showErrors(error, true); + + if (this.root && this.root.alert) { + this.scrollIntoView(this.root.alert); + } + + return errors; + } + + /** + * Trigger the change event for this form. + * + * @param changed + * @param flags + */ + onChange(flags, changed, modified, changes) { + flags = flags || {}; + let isChangeEventEmitted = false; + super.onChange(flags, true); + const value = _.clone(this.submission); + flags.changed = value.changed = changed; + flags.changes = changes; + + if (modified && this.pristine) { + this.pristine = false; + } + + this.checkData(value.data, flags); + const shouldValidate = !flags.noValidate || flags.fromIFrame || (flags.fromSubmission && this.rootPristine && this.pristine && flags.changed); + const errors = shouldValidate ? this.validate(value.data, { ...flags, process: 'change' }) : []; + value.isValid = errors.length === 0; + + this.loading = false; + if (this.submitted) { + // show server errors while they are not cleaned/fixed + const nonComponentServerErrors = _.filter(this.serverErrors || [], err => !err.component && !err.path); + this.showErrors(nonComponentServerErrors.length ? nonComponentServerErrors : errors); + } + + // See if we need to save the draft of the form. + if (modified && this.options.saveDraft) { + this.triggerSaveDraft(); + } + + if (!flags || !flags.noEmit) { + this.emit('change', value, flags, modified); + isChangeEventEmitted = true; + } + + // The form is initialized after the first change event occurs. + if (isChangeEventEmitted && !this.initialized) { + this.emit('initialized'); + this.initialized = true; + } + } + + /** + * Send a delete request to the server. + */ + deleteSubmission() { + return this.formio.deleteSubmission() + .then(() => { + this.emit('submissionDeleted', this.submission); + this.resetValue(); + }); + } + + /** + * Cancels the submission. + * + * @alias reset + */ + cancel(noconfirm) { + const shouldReset = this.hook('beforeCancel', true); + if (shouldReset && (noconfirm || confirm(this.t('confirmCancel')))) { + this.resetValue(); + return true; + } + else { + this.emit('cancelSubmit'); + return false; + } + } + + setMetadata(submission) { + // Add in metadata about client submitting the form + submission.metadata = submission.metadata || {}; + _.defaults(submission.metadata, { + timezone: _.get(this, '_submission.metadata.timezone', currentTimezone()), + offset: parseInt(_.get(this, '_submission.metadata.offset', moment().utcOffset()), 10), + origin: document.location.origin, + referrer: document.referrer, + browserName: navigator.appName, + userAgent: navigator.userAgent, + pathName: window.location.pathname, + onLine: navigator.onLine + }); + } - this.checkData(value.data, flags); - const shouldValidate = - !flags.noValidate || - flags.fromIFrame || - (flags.fromSubmission && this.rootPristine && this.pristine && flags.changed); - const errors = shouldValidate - ? this.validate(value.data, { ...flags, process: "change" }) - : []; - value.isValid = errors.length === 0; - - this.loading = false; - if (this.submitted) { - // show server errors while they are not cleaned/fixed - const nonComponentServerErrors = _.filter( - this.serverErrors || [], - (err) => !err.component && !err.path - ); - this.showErrors(nonComponentServerErrors.length ? nonComponentServerErrors : errors); - } + submitForm(options = {}) { + this.clearServerErrors(); - // See if we need to save the draft of the form. - if (modified && this.options.saveDraft) { - this.triggerSaveDraft(); - } + return new Promise((resolve, reject) => { + // Read-only forms should never submit. + if (this.options.readOnly) { + return resolve({ + submission: this.submission, + saved: false + }); + } - if (!flags || !flags.noEmit) { - this.emit("change", value, flags, modified); - isChangeEventEmitted = true; - } + const submission = fastCloneDeep(this.submission || {}); - // The form is initialized after the first change event occurs. - if (isChangeEventEmitted && !this.initialized) { - this.emit("initialized"); - this.initialized = true; - } - } + this.setMetadata(submission); - /** - * Send a delete request to the server. - * @returns {Promise} - The promise that is triggered when the delete is complete. - */ - deleteSubmission() { - return this.formio.deleteSubmission().then(() => { - this.emit("submissionDeleted", this.submission); - this.resetValue(); - }); - } + submission.state = options.state || submission.state || 'submitted'; - /** - * Cancels the submission. - * @param {boolean} noconfirm - Whether or not to confirm the cancellation. - * @alias reset - * @returns {boolean} - TRUE means the submission was cancelled, FALSE otherwise. - */ - cancel(noconfirm) { - const shouldReset = this.hook("beforeCancel", true); - if (shouldReset && (noconfirm || confirm(this.t("confirmCancel")))) { - this.resetValue(); - return true; - } else { - this.emit("cancelSubmit"); - return false; + const isDraft = (submission.state === 'draft'); + this.hook('beforeSubmit', { ...submission, component: options.component }, (err , data) => { + if (err) { + return reject(err); } - } - - setMetadata(submission) { - // Add in metadata about client submitting the form - submission.metadata = submission.metadata || {}; - _.defaults(submission.metadata, { - timezone: _.get(this, "_submission.metadata.timezone", currentTimezone()), - offset: parseInt(_.get(this, "_submission.metadata.offset", moment().utcOffset()), 10), - origin: document.location.origin, - referrer: document.referrer, - browserName: navigator.appName, - userAgent: navigator.userAgent, - pathName: window.location.pathname, - onLine: navigator.onLine, - }); - } - submitForm(options = {}) { - this.clearServerErrors(); + submission._vnote = data && data._vnote ? data._vnote : ''; - return new Promise((resolve, reject) => { - // Read-only forms should never submit. - if (this.options.readOnly) { - return resolve({ - submission: this.submission, - saved: false, - }); + try { + if (!isDraft && !options.noValidate) { + if (!submission.data) { + return reject('Invalid Submission'); } + const errors = this.validate(submission.data, { + dirty: true, + silentCheck: false, + process: 'submit' + }); + if (errors.length || options.beforeSubmitResults?.some((result) => result.status === 'rejected')) { + return reject(errors); + } + } + } + catch (err) { + console.error(err); + } - const submission = fastCloneDeep(this.submission || {}); - - this.setMetadata(submission); - - submission.state = options.state || submission.state || "submitted"; - - const isDraft = submission.state === "draft"; - this.hook( - "beforeSubmit", - { ...submission, component: options.component }, - (err, data) => { - if (err) { - return reject(err); - } - - submission._vnote = data && data._vnote ? data._vnote : ""; - - try { - if (!isDraft && !options.noValidate) { - if (!submission.data) { - return reject("Invalid Submission"); - } - const errors = this.validate(submission.data, { - dirty: true, - silentCheck: false, - process: "submit", - }); - if ( - errors.length || - options.beforeSubmitResults?.some( - (result) => result.status === "rejected" - ) - ) { - return reject(errors); - } - } - } catch (err) { - console.error(err); - } - - this.everyComponent((comp) => { - if (submission._vnote && comp.type === "form" && comp.component.reference) { - _.get(submission.data, comp.path, {})._vnote = submission._vnote; - } - const { persistent } = comp.component; - if (persistent === "client-only") { - _.unset(submission.data, comp.path); - } - }); - - this.hook( - "customValidation", - { ...submission, component: options.component }, - (err) => { - if (err) { - // If string is returned, cast to object. - if (typeof err === "string") { - err = { - message: err, - }; - } - - // Ensure err is an array. - err = Array.isArray(err) ? err : [err]; - return reject(err); - } - - this.loading = true; - - // Use the form action to submit the form if available. - if (this._form && this._form.action) { - const method = - submission.data._id && - this._form.action.includes(submission.data._id) - ? "PUT" - : "POST"; - return Formio.makeStaticRequest( - this._form.action, - method, - submission, - this.formio ? this.formio.options : {} - ) - .then((result) => - resolve({ - submission: result, - saved: true, - }) - ) - .catch((error) => { - this.setServerErrors(error); - - return reject(error); - }); - } - - const submitFormio = this.formio; - if (this.nosubmit || !submitFormio) { - return resolve({ - submission, - saved: false, - }); - } - // If this is an actionUrl, then make sure to save the action and not the submission. - const submitMethod = submitFormio.actionUrl - ? "saveAction" - : "saveSubmission"; - submitFormio[submitMethod](submission) - .then((result) => - resolve({ - submission: result, - saved: true, - }) - ) - .catch((error) => { - this.setServerErrors(error); - - return reject(error); - }); - } - ); - } - ); + this.everyComponent((comp) => { + if (submission._vnote && comp.type === 'form' && comp.component.reference) { + _.get(submission.data, comp.path, {})._vnote = submission._vnote; + } + const { persistent } = comp.component; + if (persistent === 'client-only') { + _.unset(submission.data, comp.path); + } }); - } - setServerErrors(error) { - if (error.details) { - this.serverErrors = error.details - .filter((err) => (err.level ? err.level === "error" : err)) - .map((err) => { - err.fromServer = true; - return err; - }); - } else if (typeof error === "string") { - this.serverErrors = [{ fromServer: true, level: "error", message: error }]; - } - } + this.hook('customValidation', { ...submission, component: options.component }, (err) => { + if (err) { + // If string is returned, cast to object. + if (typeof err === 'string') { + err = { + message: err + }; + } - executeSubmit(options) { - this.submitted = true; - this.submitting = true; - return this.submitForm(options) - .then(({ submission, saved }) => this.onSubmit(submission, saved)) - .then((results) => { - this.submissionInProcess = false; - return results; - }) - .catch((err) => { - this.submissionInProcess = false; - return Promise.reject(this.onSubmissionError(err)); + // Ensure err is an array. + err = Array.isArray(err) ? err : [err]; + return reject(err); + } + + this.loading = true; + + // Use the form action to submit the form if available. + if (this._form && this._form.action) { + const method = (submission.data._id && this._form.action.includes(submission.data._id)) ? 'PUT' : 'POST'; + return Formio.makeStaticRequest(this._form.action, method, submission, this.formio ? this.formio.options : {}) + .then((result) => resolve({ + submission: result, + saved: true, + })) + .catch((error) => { + this.setServerErrors(error); + + return reject(error); + }); + } + + const submitFormio = this.formio; + if (this.nosubmit || !submitFormio) { + return resolve({ + submission, + saved: false, }); - } - - clearServerErrors() { - this.serverErrors?.forEach((error) => { - if (error.path) { - const pathArray = getArrayFromComponentPath(error.path); - const component = this.getComponent( - pathArray, - _.identity, - error.formattedKeyOrPath - ); + } + // If this is an actionUrl, then make sure to save the action and not the submission. + const submitMethod = submitFormio.actionUrl ? 'saveAction' : 'saveSubmission'; + submitFormio[submitMethod](submission) + .then((result) => resolve({ + submission: result, + saved: true, + })) + .catch((error) => { + this.setServerErrors(error); + + return reject(error); + }); + }); + }); + }); + } + + setServerErrors(error) { + if (error.details) { + this.serverErrors = error.details.filter((err) => err.level ? err.level === 'error' : err).map((err) => { + err.fromServer = true; + return err; + }); + } + else if (typeof error === 'string') { + this.serverErrors = [{ fromServer: true, level: 'error', message: error }]; + } + } + + executeSubmit(options) { + this.submitted = true; + this.submitting = true; + return this.submitForm(options) + .then(({ submission, saved }) => this.onSubmit(submission, saved)) + .then((results) => { + this.submissionInProcess = false; + return results; + }) + .catch((err) => { + this.submissionInProcess = false; + return Promise.reject(this.onSubmissionError(err)); + }); + } + + clearServerErrors() { + this.serverErrors?.forEach((error) => { + if (error.path) { + const pathArray = getArrayFromComponentPath(error.path); + const component = this.getComponent(pathArray, _.identity, error.formattedKeyOrPath); + + if (component) { + component.serverErrors = []; + } + } + }); + this.serverErrors = []; + } + + /** + * Submits the form. + * + * @example + * import Webform from '@formio/js/Webform'; + * let form = new Webform(document.getElementById('formio')); + * form.src = 'https://examples.form.io/example'; + * form.submission = {data: { + * firstName: 'Joe', + * lastName: 'Smith', + * email: 'joe@example.com' + * }}; + * form.submit().then((submission) => { + * console.log(submission); + * }); + * + * @param {boolean} before - If this submission occured from the before handlers. + * + * @returns {Promise} - A promise when the form is done submitting. + */ + submit(before, options = {}) { + this.submissionInProcess = true; + if (!before) { + return this.beforeSubmit(options).then(() => this.executeSubmit(options)); + } + else { + return this.executeSubmit(options); + } + } + + submitUrl(URL, headers) { + if (!URL) { + return console.warn('Missing URL argument'); + } + + const submission = this.submission || {}; + const API_URL = URL; + const settings = { + method: 'POST', + headers: {} + }; - if (component) { - component.serverErrors = []; - } - } + if (headers && headers.length > 0) { + headers.map((e) => { + if (e.header !== '' && e.value !== '') { + settings.headers[e.header] = this.interpolate(e.value, submission); + } + }); + } + if (API_URL && settings) { + Formio.makeStaticRequest(API_URL,settings.method,submission, { headers: settings.headers }).then(() => { + this.emit('requestDone'); + this.setAlert('success', '

Success

'); + }).catch((e) => { + const message = `${e.statusText ? e.statusText : ''} ${e.status ? e.status : e}`; + this.emit('error', message); + console.error(message); + this.setAlert('danger', `

${message}

`); + return Promise.reject(this.onSubmissionError(e)); }); - this.serverErrors = []; } - - /** - * Submits the form. - * @example - * import Webform from '@formio/js/Webform'; - * let form = new Webform(document.getElementById('formio')); - * form.src = 'https://examples.form.io/example'; - * form.submission = {data: { - * firstName: 'Joe', - * lastName: 'Smith', - * email: 'joe@example.com' - * }}; - * form.submit().then((submission) => { - * console.log(submission); - * }); - * @param {boolean} before - If this submission occured from the before handlers. - * @param {any} options - The options to use when submitting this form. - * @returns {Promise} - A promise when the form is done submitting. - */ - submit(before, options = {}) { - this.submissionInProcess = true; - if (!before) { - return this.beforeSubmit(options).then(() => this.executeSubmit(options)); - } else { - return this.executeSubmit(options); - } + else { + this.emit('error', 'You should add a URL to this button.'); + this.setAlert('warning', 'You should add a URL to this button.'); + return console.warn('You should add a URL to this button.'); } + } - submitUrl(URL, headers) { - if (!URL) { - return console.warn("Missing URL argument"); - } - - const submission = this.submission || {}; - const API_URL = URL; - const settings = { - method: "POST", - headers: {}, - }; - - if (headers && headers.length > 0) { - headers.map((e) => { - if (e.header !== "" && e.value !== "") { - settings.headers[e.header] = this.interpolate(e.value, submission); - } - }); - } - if (API_URL && settings) { - Formio.makeStaticRequest(API_URL, settings.method, submission, { - headers: settings.headers, - }) - .then(() => { - this.emit("requestDone"); - this.setAlert("success", "

Success

"); - }) - .catch((e) => { - const message = `${e.statusText ? e.statusText : ""} ${e.status ? e.status : e}`; - this.emit("error", message); - console.error(message); - this.setAlert("danger", `

${message}

`); - return Promise.reject(this.onSubmissionError(e)); - }); - } else { - this.emit("error", "You should add a URL to this button."); - this.setAlert("warning", "You should add a URL to this button."); - return console.warn("You should add a URL to this button."); - } + triggerRecaptcha() { + if (!this || !this.components) { + return; } - - triggerRecaptcha() { - if (!this || !this.components) { - return; - } - const recaptchaComponent = searchComponents(this.components, { - "component.type": "recaptcha", - "component.eventType": "formLoad", - }); - if (recaptchaComponent.length > 0) { - recaptchaComponent[0].verify(`${this.form.name ? this.form.name : "form"}Load`); - } + const recaptchaComponent = searchComponents(this.components, { + 'component.type': 'recaptcha', + 'component.eventType': 'formLoad' + }); + if (recaptchaComponent.length > 0) { + recaptchaComponent[0].verify(`${this.form.name ? this.form.name : 'form'}Load`); } + } - set nosubmit(value) { - this._nosubmit = !!value; - this.emit("nosubmit", this._nosubmit); - } + set nosubmit(value) { + this._nosubmit = !!value; + this.emit('nosubmit', this._nosubmit); + } - get nosubmit() { - return this._nosubmit || false; - } + get nosubmit() { + return this._nosubmit || false; + } - get conditions() { - return this.schema.settings?.conditions ?? []; - } + get conditions() { + return this.schema.settings?.conditions ?? []; + } - get variables() { - return this.schema.settings?.variables ?? []; - } + get variables() { + return this.schema.settings?.variables ?? []; + } } Webform.setBaseUrl = Formio.setBaseUrl; diff --git a/src/WebformBuilder.js b/src/WebformBuilder.js index b4104b8883..ea86442243 100644 --- a/src/WebformBuilder.js +++ b/src/WebformBuilder.js @@ -439,6 +439,7 @@ export default class WebformBuilder extends Component { /** * Called when everything is ready. + * * @returns {Promise} - Wait for webform to be ready. */ get ready() { @@ -494,8 +495,7 @@ export default class WebformBuilder extends Component { /** * When a component sets its api key, we need to check if it is unique within its namespace. Find the namespace root * so we can calculate this correctly. - * @param {import('@formio/core').Component} component - The component to find the namespace root for. - * @returns {import('@formio/core').Component[]} - The components root for this namespace. + * @param component */ findNamespaceRoot(component) { const path = getArrayFromComponentPath(component.path); @@ -1300,11 +1300,10 @@ export default class WebformBuilder extends Component { /** * Called when a new component is saved. - * @param {Component} component - The component instance to save. - * @param {Component} parent - The parent component. - * @param {boolean} isNew - If this is a new component. - * @param {Component} original - The original component. - * @returns {boolean} - If the component was saved. + * + * @param parent + * @param component + * @return {boolean} */ saveComponent(component, parent, isNew, original) { this.editForm.detach(); @@ -1777,8 +1776,8 @@ export default class WebformBuilder extends Component { /** * Creates copy of component schema and stores it under sessionStorage. - * @param {Component} component - The component to copy. - * @returns {void} + * @param {Component} component + * @return {*} */ copyComponent(component) { if (!window.sessionStorage) { @@ -1790,8 +1789,8 @@ export default class WebformBuilder extends Component { /** * Paste copied component after the current component. - * @param {Component} component - The component to paste after. - * @returns {void} + * @param {Component} component + * @return {*} */ pasteComponent(component) { if (!window.sessionStorage) { diff --git a/src/Wizard.js b/src/Wizard.js index 7ba379eddc..7b8de1243c 100644 --- a/src/Wizard.js +++ b/src/Wizard.js @@ -8,26 +8,30 @@ import { firstNonNil, uniqueKey, eachComponent, + unescapeHTML } from './utils/utils'; export default class Wizard extends Webform { /** - * Constructor for wizard-based forms. - * @param {HTMLElement | object | import('Form').FormOptions} [elementOrOptions] - The DOM element to render this form within or the options to create this form instance. - * @param {import('Form').FormOptions} [_options] - The options to create a new form instance. - * - breadcrumbSettings.clickable: true (default) - determines if the breadcrumb bar is clickable. - * - buttonSettings.show*(Previous, Next, Cancel): true (default) - determines if the button is shown. - * - allowPrevious: false (default) - determines if the breadcrumb bar is clickable for visited tabs. + * Constructor for wizard based forms + * @param element Dom element to place this wizard. + * @param {Object} options Options object, supported options are: + * - breadcrumbSettings.clickable: true (default) determines if the breadcrumb bar is clickable or not + * - buttonSettings.show*(Previous, Next, Cancel): true (default) determines if the button is shown or not + * - allowPrevious: false (default) determines if the breadcrumb bar is clickable or not for visited tabs */ - constructor(elementOrOptions, _options) { + constructor() { let element, options; - if (elementOrOptions instanceof HTMLElement || options) { - element = elementOrOptions; - options = _options; - } else { - options = elementOrOptions; + if (arguments[0] instanceof HTMLElement || arguments[1]) { + element = arguments[0]; + options = arguments[1] || {}; } + else { + options = arguments[0] || {}; + } + options.display = 'wizard'; + super(element, options); this.pages = []; this.prefixComps = []; @@ -112,7 +116,7 @@ export default class Wizard extends Webform { }); if (!this.isSecondInit) { - this.isClickableDefined = Object.prototype.hasOwnProperty.call(this.options?.breadcrumbSettings, 'clickable'); + this.isClickableDefined = this.options?.breadcrumbSettings?.hasOwnProperty('clickable'); this.isSecondInit = true; } @@ -284,13 +288,6 @@ export default class Wizard extends Webform { } } - /** - * Attaches the wizard to the provided DOM element, initializes component references, sets up navigation, - * and emits a render event. It will initialize the wizard's index if necessary, - * attach event hooks, and make sure that the current page is rendered and displayed correctly. - * @param {HTMLElement} element - The DOM element to which the wizard will be attached. - * @returns {Promise} A promise that resolves when all components have been successfully attached. - */ attach(element) { this.setElement(element); this.loadRefs(element, { @@ -360,10 +357,6 @@ export default class Wizard extends Webform { return _.get(currentPage.component, 'allowPrevious', this.options.allowPrevious); } - /** - * Handles navigate on 'Enter' key event in a wizard form. - * @param {KeyboardEvent} event - The keyboard event object that triggered the handler. - */ handleNaviageteOnEnter(event) { if (event.keyCode === 13) { const clickEvent = new CustomEvent('click'); @@ -374,10 +367,6 @@ export default class Wizard extends Webform { } } - /** - * Handles save on 'Enter' key event in a wizard form. - * @param {KeyboardEvent} event - The keyboard event object that triggered the handler. - */ handleSaveOnEnter(event) { if (event.keyCode === 13) { const clickEvent = new CustomEvent('click'); @@ -416,12 +405,6 @@ export default class Wizard extends Webform { }); } - - /** - * Emits an event indicating that a wizard page has been selected. - * @param {number} index - Index of the selected wizard page in the `pages` array. - * @fires emit - Emits the 'wizardPageSelected' event with the page object and index. - */ emitWizardPageSelected(index) { this.emit('wizardPageSelected', this.pages[index], index); } @@ -882,10 +865,7 @@ export default class Wizard extends Webform { this.options.show = this.options.show || {}; this.options.show[item.key] = true; } - else if ( - Object.prototype.hasOwnProperty.call(this.wizard, 'full') - && !_.isEqual(this.originalOptions.show, this.options.show) - ) { + else if (this.wizard.hasOwnProperty('full') && !_.isEqual(this.originalOptions.show, this.options.show)) { this.options.show = { ...(this.originalOptions.show || {}) }; } } diff --git a/src/addons/PasswordStrength/PasswordStrengthAddon.js b/src/addons/PasswordStrength/PasswordStrengthAddon.js index de9a97c309..977652e7bb 100644 --- a/src/addons/PasswordStrength/PasswordStrengthAddon.js +++ b/src/addons/PasswordStrength/PasswordStrengthAddon.js @@ -226,7 +226,7 @@ export default class PasswordStrengthAddon extends FormioAddon { /** * Determines is a password is secure enough to submit - * @returns {boolean} - returns TRUE if password is valid, FALSE if it is not. + * @return {boolean} */ isValid() { const isValidCheck = this.settings.isValid; @@ -245,9 +245,8 @@ export default class PasswordStrengthAddon extends FormioAddon { * Handles the result of check and constructs a new error object or returns an amount of points to add to the current entropy * @param {boolean|number} valid - Determines if the validation was failed or an amount of points if it was passed * @param {*} validation - Validation configuration + * @param {string} value - Value which was validated * @param {string} message - Message which should be shown if validation was not passed - * @param {any[]} errors - The errors array (will be mutated) - * @returns {number} - Returns an amount of points to add to the current entropy */ handleRuleCheckResult(valid, validation, message, errors) { if (valid !== true) { @@ -293,8 +292,7 @@ export default class PasswordStrengthAddon extends FormioAddon { /** * Performs checks to validate password security - * @param {string} value - The password value to be checked. - * @returns {boolean} - Returns TRUE if password is strong enough, FALSE if it is not. + * @param {string} value - Suggested password */ checkValidity(value) { const passwordLength = value.length; @@ -410,7 +408,6 @@ export default class PasswordStrengthAddon extends FormioAddon { /** * Finds the level which one the passed entropy suits * @param {number} entropy - Points of password's security - * @returns {object} - Returns the level object */ getLevel(entropy = this.entropy) { const lowestLevel = this.levels[0]; diff --git a/src/components/Components.js b/src/components/Components.js index 2b732282d3..0819c682ff 100644 --- a/src/components/Components.js +++ b/src/components/Components.js @@ -58,8 +58,9 @@ export default class Components { /** * Return a path of component's value. - * @param {Component} component - The component instance. - * @returns {string} - The component's value path. + * + * @param {Object} component - The component instance. + * @return {string} - The component's value path. */ static getComponentPath(component) { let path = ''; @@ -78,7 +79,6 @@ export default class Components { path += component.component.key; return _.trim(path, '.'); } - return path; } static create(component, options, data) { diff --git a/src/components/_classes/component/Component.form.js b/src/components/_classes/component/Component.form.js index 29638d3b63..91809511ef 100644 --- a/src/components/_classes/component/Component.form.js +++ b/src/components/_classes/component/Component.form.js @@ -9,11 +9,6 @@ import ComponentEditValidation from './editForm/Component.edit.validation'; import ComponentEditLayout from './editForm/Component.edit.layout'; import EditFormUtils from './editForm/utils'; -/** - * The Edit Form function. - * @param {...any} extend - The components that extend the edit form. - * @returns {import('@formio/core').Component[]} - The edit form components. - */ export default function(...extend) { const components = _.cloneDeep([ { diff --git a/src/components/_classes/component/Component.js b/src/components/_classes/component/Component.js index 3c3606f3c2..9daa721c25 100644 --- a/src/components/_classes/component/Component.js +++ b/src/components/_classes/component/Component.js @@ -194,7 +194,9 @@ export default class Component extends Element { } /** * Return the simple condition settings as part of the component. - * @returns {object} - The simple conditional settings. + * + * @return {Object} + * */ static get conditionOperatorsSettings() { return { @@ -211,8 +213,10 @@ export default class Component extends Element { } /** * Return the array of possible types of component value absed on its schema. + * * @param schema - * @returns {Array} + * @return {Array} + * */ static savedValueTypes(schema) { @@ -223,6 +227,7 @@ export default class Component extends Element { /** * Provides a table view for this component. Override if you wish to do something different than using getView * method of your instance. + * * @param value * @param options */ @@ -232,9 +237,10 @@ export default class Component extends Element { /** * Initialize a new Component. - * @param {object} component - The component JSON you wish to initialize. - * @param {object} options - The options for this component. - * @param {object} data - The global data submission object this component will belong. + * + * @param {Object} component - The component JSON you wish to initialize. + * @param {Object} options - The options for this component. + * @param {Object} data - The global data submission object this component will belong. */ /* eslint-disable max-statements */ constructor(component, options, data) { @@ -272,6 +278,7 @@ export default class Component extends Element { /** * The data path to this specific component instance. + * * @type {string} */ this.path = component?.key || ''; @@ -331,18 +338,21 @@ export default class Component extends Element { /** * Points to a flat map of child components (if applicable). - * @type {object} + * + * @type {Object} */ this.childComponentsMap = {}; /** * Determines if this component is disabled, or not. + * * @type {boolean} */ this._disabled = boolValue(this.component.disabled) ? this.component.disabled : false; /** * Points to the root component, usually the FormComponent. + * * @type {Component} */ this.root = this.options.root || this; @@ -350,12 +360,14 @@ export default class Component extends Element { /** * If this input has been input and provided value. + * * @type {boolean} */ this.pristine = true; /** * Points to the parent component. + * * @type {Component} */ this.parent = this.options.parent; @@ -381,7 +393,7 @@ export default class Component extends Element { /** * Used to trigger a new change in this component. - * @type {Function} - Call to trigger a change in this component. + * @type {function} - Call to trigger a change in this component. */ let changes = []; let lastChanged = null; @@ -423,6 +435,7 @@ export default class Component extends Element { /** * Used to trigger a redraw event within this component. + * * @type {Function} */ this.triggerRedraw = _.debounce(this.redraw.bind(this), 100); @@ -661,8 +674,8 @@ export default class Component extends Element { } /** - * Sets the component visibility. - * @param {boolean} value - Whether the component should be visible or not. + * + * @param value {boolean} */ set visible(value) { if (this._visible !== value) { @@ -681,8 +694,8 @@ export default class Component extends Element { } /** - * Returns the component visibility - * @returns {boolean} - Whether the component is visible or not. + * + * @returns {boolean} */ get visible() { // Show only if visibility changes or if we are in builder mode or if hidden fields should be shown. @@ -789,10 +802,9 @@ export default class Component extends Element { /** * Returns only the schema that is different from the default. - * @param {object} schema - The "full" json schema for the component. - * @param {object} defaultSchema - The "default" json schema for the component. - * @param {boolean} recursion - If we are currently in a recursive loop. - * @returns {object} - The minified json schema for this component. + * + * @param schema + * @param defaultSchema */ getModifiedSchema(schema, defaultSchema, recursion) { const modified = {}; @@ -829,7 +841,6 @@ export default class Component extends Element { /** * Returns the JSON schema for this component. - * @returns {object} - The JSON schema for this component. */ get schema() { return fastCloneDeep(this.getModifiedSchema(_.omit(this.component, 'id'), this.defaultSchema)); @@ -837,7 +848,6 @@ export default class Component extends Element { /** * Returns true if component is inside DataGrid - * @returns {boolean} - True if component is inside DataGrid */ get isInDataGrid() { return this.inDataGrid; @@ -845,10 +855,9 @@ export default class Component extends Element { /** * Translate a text using the i18n system. + * * @param {string} text - The i18n identifier. - * @param {object} params - The i18n parameters to use for translation. - * @param {...any} args - Additional arguments to pass to the translation library. - * @returns {string} - The translated text. + * @param {Object} params - The i18n parameters to use for translation. */ t(text, params = {}, ...args) { if (!text) { @@ -1006,10 +1015,9 @@ export default class Component extends Element { /** * Sanitize an html string. - * @param {string} dirty - The dirty html string to sanitize. - * @param {boolean} forceSanitize - If we should force the sanitize to occur. - * @param {object} options - The options for the sanitize. - * @returns {*} - The sanitized html string. + * + * @param string + * @returns {*} */ sanitize(dirty, forceSanitize, options) { if (!this.shouldSanitizeValue && !forceSanitize) { @@ -1024,9 +1032,12 @@ export default class Component extends Element { /** * Render a template string into html. - * @param {string} template - The template to render. - * @param {object} data - The data to provide to the template. - * @returns {HTMLElement | string} - The created element or an empty string if template is not specified. + * + * @param template + * @param data + * @param actions + * + * @return {HTMLElement|String} - The created element or an empty string if template is not specified. */ renderString(template, data) { if (!template) { @@ -1036,19 +1047,10 @@ export default class Component extends Element { return this.interpolate(template, data); } - /** - * Allows for modification of the component value prior to submission. - * @param {*} input - The input to be modified. - * @returns {*} - The modified input mapping for the extended component. - */ performInputMapping(input) { return input; } - /** - * Returns the component "widget" if one is available. - * @returns {Widget|null} - The widget instance. null if not available. - */ get widget() { const settings = this.component.widget; @@ -1060,10 +1062,6 @@ export default class Component extends Element { return widget; } - /** - * Returns the native supported browser language. - * @returns {string|null} - The native browser language that is supported. - */ getBrowserLanguage() { const nav = window.navigator; const browserLanguagePropertyKeys = ['language', 'browserLanguage', 'systemLanguage', 'userLanguage']; @@ -1091,24 +1089,24 @@ export default class Component extends Element { } /** - * Called before a next and previous page is triggered allowing the components to perform special functions. - * @returns {Promise} - A promise to resolve when the component is no longer blocking the next/previous page navigation. + * Called before a next and previous page is triggered allowing the components + * to perform special functions. + * + * @return {*} */ beforePage() { return Promise.resolve(true); } - /** - * Called before the next page is triggered allowing the components to hook into the page navigation and perform tasks. - * @returns {Promise} - A promise to resolve when the component is no longer blocking the next page navigation. - */ beforeNext() { return this.beforePage(true); } /** - * Called before a submission is triggered allowing the components to perform special async functions. - * @returns {Promise} - A promise to resolve when the component is no longer blocking the submission. + * Called before a submission is triggered allowing the components + * to perform special async functions. + * + * @return {*} */ beforeSubmit() { return Promise.resolve(true); @@ -1116,26 +1114,18 @@ export default class Component extends Element { /** * Return the submission timezone. - * @returns {string} - The submission timezone. + * + * @return {*} */ get submissionTimezone() { this.options.submissionTimezone = this.options.submissionTimezone || _.get(this.root, 'options.submissionTimezone'); return this.options.submissionTimezone; } - /** - * Return the current timezone. - * @returns {string} - The current timezone. - */ get timezone() { return this.getTimezone(this.component); } - /** - * Return the current timezone. - * @param {object} settings - Settings to control how the timezone should be returned. - * @returns {string} - The current timezone. - */ getTimezone(settings) { if (settings.timezone) { return settings.timezone; @@ -1182,18 +1172,10 @@ export default class Component extends Element { } } - /** - * Opens the modal element. - * @param {string} template - The template to use for the modal dialog. - */ - setOpenModalElement(template = null) { + setOpenModalElement(template) { this.componentModal.setOpenModalElement(template || this.getModalPreviewTemplate()); } - /** - * Returns the modal preview template. - * @returns {string} - The modal preview template. - */ getModalPreviewTemplate() { const dataValue = this.component.type === 'password' ? this.dataValue.replace(/./g, '•') : this.dataValue; let modalLabel; @@ -1209,11 +1191,6 @@ export default class Component extends Element { }); } - /** - * Performs a complete build of a component, which empties, renders, sets the content in the DOM, and then finally attaches events. - * @param {HTMLElement} element - The element to attach this component to. - * @returns {Promise} - A promise that resolves when the component has been built. - */ build(element) { element = element || this.element; this.empty(element); @@ -1225,12 +1202,6 @@ export default class Component extends Element { return true; } - /** - * Renders a component as an HTML string. - * @param {string} children - The contents of all the children HTML as a string. - * @param {boolean} topLevel - If this is the topmost component that is being rendered. - * @returns {string} - The rendered HTML string of a component. - */ render(children = `Unknown component: ${this.component.type}`, topLevel = false) { const isVisible = this.visible; this.rendered = true; @@ -1256,11 +1227,6 @@ export default class Component extends Element { } } - /** - * Attaches all the tooltips provided the refs object. - * @param {object} toolTipsRefs - The refs for the tooltips within your template. - * @returns {void} - */ attachTooltips(toolTipsRefs) { toolTipsRefs?.forEach((tooltip, index) => { if (tooltip) { @@ -1281,22 +1247,10 @@ export default class Component extends Element { }); } - /** - * Create a new component modal for this component. - * @param {HTMLElement} element - The element to attach the modal to. - * @param {boolean} modalShouldBeOpened - TRUE if the modal should open immediately. - * @param {any} currentValue - The current value of the component. - * @returns {ComponentModal} - The created component modal. - */ createComponentModal(element, modalShouldBeOpened, currentValue) { return new ComponentModal(this, element, modalShouldBeOpened, currentValue, this._referenceAttributeName); } - /** - * Attaches all event listensers for this component to the DOM elements that were rendered. - * @param {HTMLElement} element - The element to attach the listeners to. - * @returns {Promise} - Resolves when the component is done attaching to the DOM. - */ attach(element) { if (!this.builderMode && !this.previewMode && this.component.modalEdit) { const modalShouldBeOpened = this.componentModal ? this.componentModal.isOpened : false; @@ -1344,9 +1298,6 @@ export default class Component extends Element { return Promise.resolve(); } - /** - * Restors the "focus" on a component after a redraw event has occured. - */ restoreFocus() { const isFocused = this.root?.focusedComponent?.path === this.path; if (isFocused) { @@ -1356,12 +1307,6 @@ export default class Component extends Element { } } - /** - * Adds a keyboard shortcut to this component. - * @param {HTMLElement} element - The element to attach the keyboard shortcut to. - * @param {string} shortcut - The keyboard shortcut to add. - * @returns {void} - */ addShortcut(element, shortcut) { // Avoid infinite recursion. if (!element || !this.root || (this.root === this)) { @@ -1375,12 +1320,6 @@ export default class Component extends Element { this.root.addShortcut(element, shortcut); } - /** - * Removes a keyboard shortcut from this component. - * @param {HTMLElement} element - The element to remove the keyboard shortcut from. - * @param {string} shortcut - The keyboard shortcut to remove. - * @returns {void} - */ removeShortcut(element, shortcut) { // Avoid infinite recursion. if (!element || (this.root === this)) { @@ -1417,13 +1356,6 @@ export default class Component extends Element { } } - /** - * Determines if the component should be refreshed based on the path of another component that changed. - * @param {string} refreshData - The path of the data that needs to trigger a refresh. - * @param {boolean} changed - Flag that is true if the data has been changed. - * @param {any} flags - The flags for the checkData procedure. - * @returns {void} - */ checkRefresh(refreshData, changed, flags) { const changePath = _.get(changed, 'instance.path', false); // Don't let components change themselves. @@ -1443,12 +1375,6 @@ export default class Component extends Element { } } - /** - * Iterates over a list of changes, and determines if the component should be refreshed if it is configured to refresh on any of those components. - * @param {Array} changes - The list of components that have changed. - * @param {any} flags - The checkData flags. - * @returns {void} - */ checkRefreshOn(changes, flags = {}) { changes = changes || []; if (flags.noRefresh) { @@ -1471,8 +1397,8 @@ export default class Component extends Element { /** * Refreshes the component with a new value. - * @param {any} value - The latest value of the component to check if it needs to be refreshed. - * @returns {void} + * + * @param value */ refresh(value) { if (this.hasOwnProperty('refreshOnValue')) { @@ -1496,8 +1422,8 @@ export default class Component extends Element { * with the components data and returns true if they are in the same context. * * Different rows of the same EditGrid, for example, are in different contexts. - * @param {any} component - The component to check if it is in the same context as this component. - * @returns {boolean} - TRUE if the component is in the same context as this component. + * + * @param component */ inContext(component) { if (component.data === this.data) { @@ -1514,19 +1440,10 @@ export default class Component extends Element { return false; } - /** - * Determines if we are in "view" only mode. - * @returns {boolean} - TRUE if we are in "view" only mode. - */ get viewOnly() { return this.options.readOnly && this.options.viewAsHtml; } - /** - * Sets the HTMLElement for this component. - * @param {HTMLElement} element - The element that is attached to this component. - * @returns {void} - */ setElement(element) { if (this.element) { delete this.element.component; @@ -1535,10 +1452,6 @@ export default class Component extends Element { this.element = element; } - /** - * Creates an element to hold the "view only" version of this component. - * @returns {HTMLElement} - The element for this component. - */ createViewOnlyElement() { this.setElement(this.ce('dl', { id: this.id @@ -1552,19 +1465,15 @@ export default class Component extends Element { return this.element; } - /** - * The default value for the "view only" mode of a component if the value is not provided. - * @returns {string} - The default value for this component. - */ get defaultViewOnlyValue() { return '-'; } /** * Uses the widget to determine the output string. - * @param {any} value - The current value of the component. - * @param {any} options - The options for getValueAsString. - * @returns {any|Array} - The value as a string. + * + * @param value + * @return {*} */ getWidgetValueAsString(value, options) { const noInputWidget = !this.refs.input || !this.refs.input[0] || !this.refs.input[0].widget; @@ -1591,12 +1500,6 @@ export default class Component extends Element { return widget.getValueAsString(value, options); } - /** - * Returns the value of the component as a string. - * @param {any} value - The value for this component. - * @param {any} options - The options for this component. - * @returns {string} - The string representation of the value of this component. - */ getValueAsString(value, options) { if (!value) { return ''; @@ -1615,12 +1518,6 @@ export default class Component extends Element { return this.sanitize(stringValue); } - /** - * Returns the string representation "view" of the component value. - * @param {any} value - The value of the component. - * @param {any} options - The options for this component. - * @returns {string} - The string representation of the value of this component. - */ getView(value, options) { if (this.component.protected) { return '--- PROTECTED ---'; @@ -1628,21 +1525,15 @@ export default class Component extends Element { return this.getValueAsString(value, options); } - /** - * Updates the items list for this component. Useful for Select and other List component types. - * @param {...any} args - The arguments to pass to the onChange event. - * @returns {void} - */ updateItems(...args) { this.restoreValue(); this.onChange(...args); } /** - * Returns the value for a specific item in a List type component. - * @param {any} data - The data for this component. - * @param {boolean} [forceUseValue] - if true, return 'value' property of the data - * @returns {any} - The value of the item. + * @param {*} data + * @param {boolean} [forceUseValue=false] - if true, return 'value' property of the data + * @return {*} */ itemValue(data, forceUseValue = false) { if (_.isObject(data) && !_.isArray(data)) { @@ -1658,11 +1549,6 @@ export default class Component extends Element { return data; } - /** - * Returns the item value for html mode. - * @param {any} value - The value for this component. - * @returns {any} - The value of the item for html mode. - */ itemValueForHTMLMode(value) { if (Array.isArray(value)) { const values = value.map(item => Array.isArray(item) ? this.itemValueForHTMLMode(item) : this.itemValue(item)); @@ -1673,13 +1559,6 @@ export default class Component extends Element { return this.itemValue(value); } - /** - * Creates a modal to input the value of this component. - * @param {HTMLElement} element - The element to attach the modal to. - * @param {any} attr - A list of attributes to add to the modal. - * @param {boolean} confirm - If we should add a confirmation to the modal that keeps it from closing unless confirmed. - * @returns {HTMLElement} - The created modal element. - */ createModal(element, attr, confirm) { const dialog = this.ce('div', attr || {}); this.setContent(dialog, this.renderTemplate('dialog')); @@ -1723,10 +1602,6 @@ export default class Component extends Element { return dialog; } - /** - * Uses CSS classes to show or hide an element. - * @returns {boolean} - TRUE if the element has been css removed. - */ get optimizeRedraw() { if (this.options.optimizeRedraw && this.element && !this.visible) { this.addClass(this.element, 'formio-removed'); @@ -1766,7 +1641,7 @@ export default class Component extends Element { /** * Build the custom style from the layout values - * @returns {string} - The custom style + * @return {string} - The custom style */ get customStyle() { let customCSS = ''; @@ -1778,25 +1653,17 @@ export default class Component extends Element { return customCSS; } - /** - * Returns the component condition operator settings if available. - * @returns {object} - The component condition operator settings. - */ static get serverConditionSettings() { return Component.conditionOperatorsSettings; } - /** - * Returns if the application is on a mobile device. - * @returns {boolean} - TRUE if the application is on a mobile device. - */ get isMobile() { return isMobile(); } /** * Returns the outside wrapping element of this component. - * @returns {HTMLElement} - The wrapping element of this component. + * @returns {HTMLElement} */ getElement() { return this.element; @@ -1804,8 +1671,9 @@ export default class Component extends Element { /** * Create an evaluation context for all script executions and interpolations. - * @param {any} additional - Additional context to provide. - * @returns {any} - The evaluation context. + * + * @param additional + * @return {*} */ evalContext(additional) { return super.evalContext(Object.assign({ @@ -1828,32 +1696,21 @@ export default class Component extends Element { /** * Sets the pristine flag for this component. - * @param {boolean} pristine - TRUE to make pristine, FALSE not pristine. + * + * @param pristine {boolean} - TRUE to make pristine, FALSE not pristine. */ setPristine(pristine) { this.pristine = pristine; } - /** - * Returns if the component is pristine. - * @returns {boolean} - TRUE if the component is pristine. - */ get isPristine() { return this.pristine; } - /** - * Sets the dirty flag for this component. - * @param {boolean} dirty - TRUE to make dirty, FALSE not dirty. - */ setDirty(dirty) { this.dirty = dirty; } - /** - * Returns if the component is dirty. - * @returns {boolean} - TRUE if the component is dirty. - */ get isDirty() { return this.dirty; } @@ -1869,12 +1726,6 @@ export default class Component extends Element { this.triggerRootChange(); } - /** - * Returns the icon class for a given icon name. - * @param {string} name - The name of the icon you wish to fetch provided the icon class. This is the "font awesome" version of the name of the icon. - * @param {boolean} spinning - If the component should be spinning. - * @returns {string} - The icon class for the equivalent icon in the iconset we are using. - */ iconClass(name, spinning) { const iconset = this.options.iconset || Templates.current.defaultIconset || 'fa'; return Templates.current.hasOwnProperty('iconClass') @@ -1882,11 +1733,6 @@ export default class Component extends Element { : this.options.iconset === 'fa' ? Templates.defaultTemplates.iconClass(iconset, name, spinning) : name; } - /** - * Returns the size css class names for our current template. - * @param {string} size - The size class name for the default iconset. - * @returns {string} - The size class for our component. - */ size(size) { return Templates.current.hasOwnProperty('size') ? Templates.current.size(size) @@ -1901,25 +1747,17 @@ export default class Component extends Element { return this.t(this.component.label || this.component.placeholder || this.key, { _userInput: true }); } - /** - * Returns the visible errors for this component. - * @returns {Array} - The visible errors for this component. - */ get visibleErrors() { return this._visibleErrors; } - /** - * Returns all the errors for this component, visible or not. - * @returns {Array} - All the errors for this component. - */ get errors() { return this._errors; } /** * Returns the error label for this component. - * @returns {string} - The error label for this component. + * @return {*} */ get errorLabel() { return this.t(this.component.errorLabel @@ -1930,21 +1768,13 @@ export default class Component extends Element { /** * Get the error message provided a certain type of error. - * @param {string} type - The type of error to fetch the message for. - * @returns {string} - The error message configured for this component. + * @param type + * @return {*} */ errorMessage(type) { return (this.component.errors && this.component.errors[type]) ? this.component.errors[type] : type; } - /** - * Sets the content, innerHTML, of an element to the sanitized content. - * @param {HTMLElement} element - The element to set the innerHTML to. - * @param {string} content - The HTML string content that we wish to set. - * @param {boolean} forceSanitize - If we should force the content to be sanitized. - * @param {any} sanitizeOptions - The options for the sanitize function. - * @returns {boolean} - TRUE if the content was sanitized and set. - */ setContent(element, content, forceSanitize, sanitizeOptions) { if (element instanceof HTMLElement) { element.innerHTML = this.sanitize(content, forceSanitize, sanitizeOptions); @@ -1953,9 +1783,6 @@ export default class Component extends Element { return false; } - /** - * Restores the caret position in the input element after a refresh occurs. - */ restoreCaretPosition() { if (this.root?.currentSelection) { if (this.refs.input?.length) { @@ -1978,10 +1805,6 @@ export default class Component extends Element { } } - /** - * Redraw the component. - * @returns {Promise} - A promise that resolves when the component is done redrawing. - */ redraw() { // Don't bother if we have not built yet. if (!this.element || !this.element.parentNode || this.optimizeRedraw) { @@ -1998,10 +1821,6 @@ export default class Component extends Element { return this.attach(this.element); } - /** - * Rebuild and redraw a component. - * @returns {Promise} - A promise that resolves when the component is done rebuilding and redrawing. - */ rebuild() { this.destroy(); this.init(); @@ -2009,21 +1828,12 @@ export default class Component extends Element { return this.redraw(); } - /** - * Removes all event listeners attached to this component. - */ removeEventListeners() { super.removeEventListeners(); this.tooltips.forEach(tooltip => tooltip.destroy()); this.tooltips = []; } - /** - * Returns if the dom node has the classes provided. - * @param {HTMLElement} element - The element to check for the class. - * @param {string} className - The name of the class to check. - * @returns {boolean|void} - TRUE if the element has the class. - */ hasClass(element, className) { if (!element) { return; @@ -2032,12 +1842,6 @@ export default class Component extends Element { return super.hasClass(element, this.transform('class', className)); } - /** - * Adds a class to an HTML element. - * @param {HTMLElement} element - The dom element to add the class to. - * @param {string} className - The class name you wish to add. - * @returns {this|void} - The component instance. - */ addClass(element, className) { if (!element) { return; @@ -2046,12 +1850,6 @@ export default class Component extends Element { return super.addClass(element, this.transform('class', className)); } - /** - * Removes a class from an element. - * @param {HTMLElement} element - The element to remove the class from. - * @param {string} className - The class name to remove. - * @returns {this|void} - The component instance. - */ removeClass(element, className) { if (!element) { return; @@ -2062,7 +1860,8 @@ export default class Component extends Element { /** * Determines if this component has a condition defined. - * @returns {boolean} - TRUE if the component has a condition defined. + * + * @return {null} */ hasCondition() { if (this._hasCondition !== null) { @@ -2075,9 +1874,9 @@ export default class Component extends Element { /** * Check if this component is conditionally visible. - * @param {any} data - The data to check against. - * @param {any} row - The row data to check against. - * @returns {boolean} - TRUE if the component is conditionally visible. + * + * @param data + * @return {boolean} */ conditionallyVisible(data, row) { data = data || this.rootValue; @@ -2093,9 +1892,10 @@ export default class Component extends Element { * Checks the condition of this component. * * TODO: Switch row and data parameters to be consistent with other methods. - * @param {any} row - The row contextual data. - * @param {any} data - The global data object. - * @returns {boolean} - True if the condition applies to this component. + * + * @param row - The row contextual data. + * @param data - The global data object. + * @return {boolean} - True if the condition applies to this component. */ checkCondition(row, data) { return FormioUtils.checkCondition( @@ -2109,10 +1909,6 @@ export default class Component extends Element { /** * Check for conditionals and hide/show the element based on those conditions. - * @param {any} data - The data to check against. - * @param {any} flags - The flags passed to checkData function. - * @param {any} row - The row data to check against. - * @returns {boolean} - TRUE if the component is visible. */ checkComponentConditions(data, flags, row) { data = data || this.rootValue; @@ -2135,10 +1931,8 @@ export default class Component extends Element { /** * Checks conditions for this component and any sub components. - * @param {any} data - The data to check against. - * @param {any} flags - The flags passed to checkData function. - * @param {any} row - The row data to check against. - * @returns {boolean} - TRUE if the component is visible. + * @param args + * @return {boolean} */ checkConditions(data, flags, row) { data = data || this.rootValue; @@ -2147,21 +1941,18 @@ export default class Component extends Element { return this.checkComponentConditions(data, flags, row); } - /** - * Returns the component logic if applicable. - * @returns {Array} - The component logic. - */ get logic() { return this.component.logic || []; } /** * Check all triggers and apply necessary actions. - * @param {any} data - The data to check against. - * @param {any} row - The row data to check against. - * @returns {boolean|void} - TRUE if the component was altered. + * + * @param data */ - fieldLogic(data = this.rootValue, row = this.data) { + fieldLogic(data, row) { + data = data || this.rootValue; + row = row || this.data; const logics = this.logic; // If there aren't logic, don't go further. @@ -2198,10 +1989,6 @@ export default class Component extends Element { return changed; } - /** - * Retuns if the browser is Internet Explorer. - * @returns {boolean} - TRUE if the browser is IE. - */ isIE() { if (typeof window === 'undefined') { return false; @@ -2232,12 +2019,6 @@ export default class Component extends Element { return false; } - /** - * Defines the logic action value through evaluation. - * @param {object} action - The action within the Logic system to perform. - * @param {object} argsObject - The arguments to pass to the evaluation. - * @returns {any} - The result of the evaluation. - */ defineActionValue(action, argsObject) { return this.evaluate( action.value, @@ -2246,15 +2027,6 @@ export default class Component extends Element { ); } - /** - * Apply the actions of Logic for a component once the conditions have been met. - * @param {object} newComponent - The new component to apply the actions to. - * @param {Array} actions - An array of actions - * @param {any} result - The result of the conditional check in order to evaluate the actions. - * @param {any} row - The contextual row data for this component. - * @param {any} data - The global data object for the submission. - * @returns {boolean} - TRUE if the component was altered. - */ applyActions(newComponent, actions, result, row, data) { data = data || this.rootValue; row = row || this.data; @@ -2360,8 +2132,9 @@ export default class Component extends Element { /** * Add a new input error to this element. - * @param {Array|string} messages - An array of messages to add to the element. - * @returns {void} + * + * @param message + * @param dirty */ addMessages(messages) { if (!messages) { @@ -2393,15 +2166,6 @@ export default class Component extends Element { } } - /** - * Sets the form input widget error classes. - * @param {Array} elements - An array of DOM elements to set the error classes on. - * @param {boolean} dirty - If the input is dirty. - * @param {boolean} hasErrors - If the input has errors. - * @param {boolean} hasMessages - If the input has messages. - * @param {HTMLElement} element - The wrapper element for all the other elements passed in first argument. - * @returns {void} - */ setErrorClasses(elements, dirty, hasErrors, hasMessages, element = this.element) { this.clearErrorClasses(); elements.forEach((element) => { @@ -2431,12 +2195,6 @@ export default class Component extends Element { } } - /** - * Adds the classes necessary to mark an element as invalid. - * @param {HTMLElement} element - The element you wish to add the invalid classes to. - * @param {boolean} invalid - TRUE if the component is invalid, FALSE otherwise. - * @returns {void} - */ setElementInvalid(element, invalid) { if (!element) return; @@ -2449,9 +2207,6 @@ export default class Component extends Element { element.setAttribute('aria-invalid', invalid ? 'true' : 'false'); } - /** - * Clears the components data if it is conditionally hidden AND clearOnHide is set to true for this component. - */ clearOnHide() { // clearOnHide defaults to true for old forms (without the value set) so only trigger if the value is false. if ( @@ -2473,10 +2228,6 @@ export default class Component extends Element { } } - /** - * Triggers a debounced onChange event for the root component (usually Webform). - * @param {...any} args - The arguments to pass to the onChange event. - */ triggerRootChange(...args) { if (this.options.onChange) { this.options.onChange(...args); @@ -2486,13 +2237,6 @@ export default class Component extends Element { } } - /** - * Called when the component value has been changed. This will then trigger the root level onChange handler which - * propagates the checkData methods for the full component tree. - * @param {any} flags - The flags for the change event propagation. - * @param {boolean} fromRoot - If the change event is from the root component. - * @returns {boolean} - TRUE if the component has changed. - */ onChange(flags, fromRoot) { flags = flags || {}; if (flags.modified) { @@ -2646,7 +2390,7 @@ export default class Component extends Element { } this.quill = new Quill(element, isIEBrowser ? { ...settings, modules: {} } : settings); - /** This block of code adds the [source] capabilities. See https://codepen.io/anon/pen/ZyEjrQ */ + /** This block of code adds the [source] capabilities. See https://codepen.io/anon/pen/ZyEjrQ **/ const txtArea = document.createElement('textarea'); txtArea.setAttribute('class', 'quill-source-code'); this.quill.addContainer('ql-custom').appendChild(txtArea); @@ -2660,7 +2404,7 @@ export default class Component extends Element { txtArea.style.display = (txtArea.style.display === 'none') ? 'inherit' : 'none'; }); } - /** END CODEBLOCK */ + /** END CODEBLOCK **/ // Make sure to select cursor when they click on the element. this.addEventListener(element, 'click', () => this.quill.focus()); @@ -2714,7 +2458,8 @@ export default class Component extends Element { /** * The empty value for this component. - * @returns {null} - The empty value for this component. + * + * @return {null} */ get emptyValue() { return null; @@ -2722,8 +2467,7 @@ export default class Component extends Element { /** * Returns if this component has a value set. - * @param {any} data - The global data object. - * @returns {boolean} - TRUE if a value is set. + * */ hasValue(data) { return !_.isUndefined(_.get(data || this.data, this.key)); @@ -2731,7 +2475,8 @@ export default class Component extends Element { /** * Get the data value at the root level. - * @returns {*} - The root value for the component, typically the Webform data object. + * + * @return {*} */ get rootValue() { return this.root ? this.root.data : this.data; @@ -2743,7 +2488,7 @@ export default class Component extends Element { /** * Get the static value of this component. - * @returns {*} - The value for this component. + * @return {*} */ get dataValue() { if ( @@ -2764,7 +2509,8 @@ export default class Component extends Element { /** * Sets the static value of this component. - * @param {*} value - The value to set for this component. + * + * @param value */ set dataValue(value) { if ( @@ -2787,8 +2533,8 @@ export default class Component extends Element { /** * Splice a value from the dataValue. - * @param {number} index - The index to splice for an array component values. - * @param {*} flags - The flags to use when splicing the value. + * + * @param index */ splice(index, flags = {}) { if (this.hasValue()) { @@ -2871,7 +2617,8 @@ export default class Component extends Element { /** * Get the input value of this component. - * @returns {*} - The value for the component. + * + * @return {*} */ getValue() { if (!this.hasInput || this.viewOnly || !this.refs.input || !this.refs.input.length) { @@ -2895,8 +2642,9 @@ export default class Component extends Element { /** * Get the value at a specific index. - * @param {number} index - For an array component or multiple values, this returns the value at a specific index. - * @returns {*} - The value at the specified index. + * + * @param index + * @returns {*} */ getValueAt(index) { const input = this.performInputMapping(this.refs.input[index]); @@ -2905,9 +2653,11 @@ export default class Component extends Element { /** * Set the value of this component. - * @param {*} value - The value to set for this component. - * @param {*} flags - The flags to use when setting the value. - * @returns {boolean} - If the value changed. + * + * @param value + * @param flags + * + * @return {boolean} - If the value changed. */ setValue(value, flags = {}) { const changed = this.updateValue(value, flags); @@ -2941,9 +2691,9 @@ export default class Component extends Element { /** * Set the value at a specific index. - * @param {number} index - The index to set the value at. - * @param {*} value - The value to set at the specified index. - * @param {*} flags - The flags to use when setting the value. + * + * @param index + * @param value */ setValueAt(index, value, flags = {}) { if (!flags.noDefault && (value === null || value === undefined) && !this.component.multiple) { @@ -2997,8 +2747,9 @@ export default class Component extends Element { /** * Normalize values coming into updateValue. - * @param {*} value - The value to normalize before setting. - * @returns {*} - The normalized value. + * + * @param value + * @return {*} */ normalizeValue(value) { if (this.component.multiple && !Array.isArray(value)) { @@ -3009,9 +2760,8 @@ export default class Component extends Element { /** * Update a value of this component. - * @param {*} value - The value to update. - * @param {*} flags - The flags to use when updating the value. - * @returns {boolean} - If the value changed. + * + * @param flags */ updateComponentValue(value, flags = {}) { let newValue = (!flags.resetValue && (value === undefined || value === null)) ? this.getValue() : value; @@ -3031,8 +2781,9 @@ export default class Component extends Element { /** * Updates the value of this component plus all sub-components. - * @param {...any} args - The arguments to pass to updateValue. - * @returns {boolean} - If the value changed. + * + * @param args + * @return {boolean} */ updateValue(...args) { return this.updateComponentValue(...args); @@ -3061,9 +2812,10 @@ export default class Component extends Element { /** * Determine if the value of this component has changed. - * @param {*} newValue - The new value to check. - * @param {*} oldValue - The existing value of the component. - * @returns {boolean} - TRUE if the value has changed. + * + * @param newValue + * @param oldValue + * @return {boolean} */ hasChanged(newValue, oldValue) { if ( @@ -3086,9 +2838,8 @@ export default class Component extends Element { /** * Update the value on change. - * @param {*} flags - The flags to use when triggering the on change event. - * @param {boolean} changed - If the value has changed. - * @returns {boolean} - If the value changed. + * + * @param flags */ updateOnChange(flags = {}, changed = false) { if (!flags.noUpdateEvent && changed) { @@ -3102,6 +2853,14 @@ export default class Component extends Element { return false; } + /** + * Perform a calculated value operation. + * + * @param data - The global data object. + * + * @return {boolean} - If the value changed during calculation. + */ + convertNumberOrBoolToString(value) { if (typeof value === 'number' || typeof value === 'boolean' ) { return value.toString(); @@ -3230,10 +2989,9 @@ export default class Component extends Element { /** * Performs calculations in this component plus any child components. - * @param {*} data - The data to perform the calculation with. - * @param {*} flags - The flags to use when calculating the value. - * @param {*} row - The contextual row data to use when performing the calculation. - * @returns {boolean} - TRUE if the value changed. + * + * @param args + * @return {boolean} */ calculateValue(data, flags, row) { data = data || this.rootValue; @@ -3244,7 +3002,7 @@ export default class Component extends Element { /** * Get this component's label text. - * @returns {string} - The label text for this component. + * */ get label() { return this.component.label; @@ -3252,7 +3010,8 @@ export default class Component extends Element { /** * Set this component's label text and render it. - * @param {string} value - The new label text. + * + * @param value - The new label text. */ set label(value) { this.component.label = value; @@ -3263,7 +3022,7 @@ export default class Component extends Element { /** * Get FormioForm element at the root of this component tree. - * @returns {*} root - The root component to search from. + * */ getRoot() { return this.root; @@ -3271,11 +3030,10 @@ export default class Component extends Element { /** * Returns the invalid message, or empty string if the component is valid. - * @param {*} data - The data to check if the component is valid. - * @param {boolean} dirty - If the component is dirty. - * @param {boolean} ignoreCondition - If conditions for the component should be ignored when checking validity. - * @param {*} row - Contextual row data for this component. - * @returns {string} - The message to show when the component is invalid. + * + * @param data + * @param dirty + * @return {*} */ invalidMessage(data, dirty, ignoreCondition, row) { if (!ignoreCondition && !this.checkCondition(row, data)) { @@ -3312,9 +3070,10 @@ export default class Component extends Element { /** * Returns if the component is valid or not. - * @param {*} data - The data to check if the component is valid. - * @param {boolean} dirty - If the component is dirty. - * @returns {boolean} - TRUE if the component is valid. + * + * @param data + * @param dirty + * @return {boolean} */ isValid(data, dirty) { return !this.invalidMessage(data, dirty); @@ -3335,8 +3094,8 @@ export default class Component extends Element { /** * Interpolate errors from the validation methods. - * @param {Array} errors - An array of errors to interpolate. - * @returns {Array} - The interpolated errors. + * @param {*} errors + * @returns */ interpolateErrors(errors) { const interpolatedErrors = FormioUtils.interpolateErrors(this.component, errors, this.t.bind(this)); @@ -3349,7 +3108,7 @@ export default class Component extends Element { * @param {*} data - The root submission data. * @param {*} row - The contextual row data. * @param {*} flags - The flags to perform validation. - * @returns {boolean} - TRUE if the component is valid. + * @returns */ showValidationErrors(errors, data, row, flags) { if (flags.silentCheck) { @@ -3370,7 +3129,7 @@ export default class Component extends Element { * @param {*} data - The root data you wish to use for this component. * @param {*} row - The contextual row data you wish to use for this component. * @param {*} flags - The flags to control the behavior of the validation. - * @returns {Array} - An array of errors if the component is invalid. + * @returns */ validateComponent(data, row, flags = {}) { data = data || this.rootValue; @@ -3405,12 +3164,11 @@ export default class Component extends Element { /** * Checks the validity of this component and sets the error message if it is invalid. - * @param {*} data - The data to check if the component is valid. - * @param {boolean} dirty - If the component is dirty. - * @param {*} row - The contextual row data for this component. - * @param {*} flags - The flags to use when checking the validity. - * @param {Array} allErrors - An array of all errors that have occured so that it can be appended when another one occurs here. - * @returns {boolean} - TRUE if the component is valid. + * + * @param data + * @param dirty + * @param row + * @return {boolean} */ checkComponentValidity(data, dirty, row, flags = {}, allErrors = []) { data = data || this.rootValue; @@ -3449,12 +3207,11 @@ export default class Component extends Element { /** * Checks the validity of the component. - * @param {*} data - The data to check if the component is valid. - * @param {boolean} dirty - If the component is dirty. - * @param {*} row - The contextual row data for this component. - * @param {boolean} silentCheck - If the check should be silent and not set the error messages. - * @param {Array} errors - An array of all errors that have occured so that it can be appended when another one occurs here. - * @returns {boolean} - TRUE if the component is valid. + * @param {*} data + * @param {*} dirty + * @param {*} row + * @param {*} silentCheck + * @returns */ checkValidity(data, dirty, row, silentCheck, errors = []) { data = data || this.rootValue; @@ -3471,10 +3228,11 @@ export default class Component extends Element { /** * Check the conditions, calculations, and validity of a single component and triggers an update if * something changed. - * @param {*} data - The root data of the change event. - * @param {*} flags - The flags from this change event. - * @param {*} row - The contextual row data for this component. - * @returns {void|boolean} - TRUE if no check should be performed on the component. + * + * @param data - The root data of the change event. + * @param flags - The flags from this change event. + * + * @return boolean - If component is valid or not. */ checkData(data, flags, row) { data = data || this.rootValue; @@ -3529,7 +3287,8 @@ export default class Component extends Element { /** * Check if a component is eligible for multiple validation - * @returns {boolean} - TRUE if the component is eligible for multiple validation. + * + * @return {boolean} */ validateMultiple() { return true; @@ -3660,7 +3419,8 @@ export default class Component extends Element { /** * Determines if the value of this component is hidden from the user as if it is coming from the server, but is * protected. - * @returns {boolean|*} - TRUE if the value is hidden. + * + * @return {boolean|*} */ isValueHidden() { if (this.component.protected && this.root.editing) { @@ -3710,8 +3470,6 @@ export default class Component extends Element { /** * Prints out the value of this component as a string value. - * @param {*} value - The value to print out. - * @returns {string} - The string representation of the value. */ asString(value) { value = value || this.getValue(); @@ -3720,7 +3478,7 @@ export default class Component extends Element { /** * Return if the component is disabled. - * @returns {boolean} - TRUE if the component is disabled. + * @return {boolean} */ get disabled() { return this._disabled || this.parentDisabled; @@ -3728,7 +3486,8 @@ export default class Component extends Element { /** * Disable this component. - * @param {boolean} disabled - TRUE to disable the component. + * + * @param {boolean} disabled */ set disabled(disabled) { this._disabled = disabled; @@ -3868,7 +3627,6 @@ export default class Component extends Element { /** * Get the element information. - * @returns {*} - The components "input" DOM element information. */ elementInfo() { const attributes = { @@ -3949,7 +3707,6 @@ export default class Component extends Element { /** * Get `Formio` instance for working with files - * @returns {import('@formio/core').Formio} - The Formio instance file service. */ get fileService() { if (this.options.fileService) { diff --git a/src/components/_classes/component/editForm/Component.edit.display.js b/src/components/_classes/component/editForm/Component.edit.display.js index 3e6e76d865..b6159d9df6 100644 --- a/src/components/_classes/component/editForm/Component.edit.display.js +++ b/src/components/_classes/component/editForm/Component.edit.display.js @@ -187,5 +187,13 @@ export default [ key: 'tableView', input: true }, + { + weight: 1600, + type: 'checkbox', + label: 'Modal Edit', + tooltip: 'Opens up a modal to edit the value of this component.', + key: 'modalEdit', + input: true + }, ]; /* eslint-enable max-len */ diff --git a/src/components/_classes/field/Field.js b/src/components/_classes/field/Field.js index fefa52f60c..5bc4a52ef4 100644 --- a/src/components/_classes/field/Field.js +++ b/src/components/_classes/field/Field.js @@ -1,14 +1,6 @@ import Component from '../component/Component'; -/* - * Field class is a base class for all fields. - * @extends Component - */ export default class Field extends Component { - /** - * @param {object} element - The component to create. - * @returns {Field} - The created field. - */ render(element) { if (this.noField) { return super.render(element); @@ -28,11 +20,7 @@ export default class Field extends Component { } } - /** - /* Saves current caret position to restore it after the component is redrawn - * @param {HTMLElement} element - The element to save the caret position for. - * @param {number} index - The index of the element. - */ + // Saves current caret position to restore it after the component is redrawn saveCaretPosition(element, index) { if (this.root?.focusedComponent?.path === this.path) { try { diff --git a/src/components/_classes/input/Input.js b/src/components/_classes/input/Input.js index da00bf956e..ba3ba94fda 100644 --- a/src/components/_classes/input/Input.js +++ b/src/components/_classes/input/Input.js @@ -276,8 +276,8 @@ export default class Input extends Multivalue { /** * Creates an instance of a widget for this component. - * @param {number} index - The index of the widget. - * @returns {*} - The widget instance. + * + * @return {null} */ createWidget(index) { // Return null if no widget is found. diff --git a/src/components/_classes/list/ListComponent.form.js b/src/components/_classes/list/ListComponent.form.js index e5ac577a6d..e0cca99f24 100644 --- a/src/components/_classes/list/ListComponent.form.js +++ b/src/components/_classes/list/ListComponent.form.js @@ -1,11 +1,6 @@ import Components from '../../Components'; import ListEditData from './editForm/ListComponent.edit.data'; -/** - * The Edit Form function. - * @param {...any} extend - The components that extend the edit form. - * @returns {import('@formio/core').Component[]} - The edit form components. - */ export default function(...extend) { return Components.baseEditForm([ { diff --git a/src/components/_classes/multivalue/Multivalue.js b/src/components/_classes/multivalue/Multivalue.js index 8eb14de301..03e8d971c4 100644 --- a/src/components/_classes/multivalue/Multivalue.js +++ b/src/components/_classes/multivalue/Multivalue.js @@ -38,9 +38,6 @@ export default class Multivalue extends Field { return this.component.hasOwnProperty('multiple') && this.component.multiple; } - /** - * @returns {Field} - The created field. - */ render() { // If single value field. if (!this.useWrapper()) { @@ -71,12 +68,6 @@ export default class Multivalue extends Field { return ''; } - /** - * Renders a single row for multi-value components. - * @param {any} value - The value associated with the row to render. - * @param {number} index - The index of the row in the multi-value list. - * @returns {any} Returns the HTML string representation of the row. - */ renderRow(value, index) { return this.renderTemplate('multiValueRow', { index, @@ -85,10 +76,6 @@ export default class Multivalue extends Field { }); } - /** - * @param {HTMLElement} dom - The DOM element to which the component will attach. - * @returns {Promise} - Promise that resolves when all asynchronous tasks that have finished. - */ attach(dom) { const superAttach = super.attach(dom); this.loadRefs(dom, { @@ -128,10 +115,6 @@ export default class Multivalue extends Field { }); } - - /** - * Remove all event handlers. - */ detach() { if (this.refs.input && this.refs.input.length) { this.refs.input.forEach((input) => { @@ -155,8 +138,9 @@ export default class Multivalue extends Field { /** * Attach inputs to the element. - * @param {HTMLElement} element - The element to attach. - * @param {number} index - The index of the element to attach. + * + * @param element + * @param index */ attachElement(element, index) { this.addEventListener(element, this.inputInfo.changeEvent, () => { @@ -231,19 +215,10 @@ export default class Multivalue extends Field { } } - /** - * Event handler for selecting a mask from a dropdown. - * @param {Event} event - Event triggered by changing the selected option in mask. - */ onSelectMaskHandler(event) { this.updateMask(event.target.maskInput, this.getMaskPattern(event.target.value)); } - /** - * Retrieves the mask pattern for a given mask name - * @param {string} maskName - The name of the mask to retrieve. - * @returns {any} The mask pattern associated with the given mask name. - */ getMaskPattern(maskName) { if (!this.multiMasks) { this.multiMasks = {}; @@ -256,11 +231,6 @@ export default class Multivalue extends Field { return this.multiMasks[maskName]; } - /** - * Attaches a selectable mask to an input field based on its configuration. - * @param {number} index - The index of the select or input in component array. - * @returns {boolean} - Returns true if the mask was successfully attached - */ attachMultiMask(index) { if (!(this.isMultipleMasksField && this.component.inputMasks.length && this.refs.input.length)) { return false; @@ -273,10 +243,6 @@ export default class Multivalue extends Field { return true; } - /** - * @param {any} input - The input element on which the mask is to be applied. - * @param {string} mask - The mask pattern to apply to the input element. Exit early if no mask. - */ updateMask(input, mask) { if (!mask) { return; @@ -287,7 +253,6 @@ export default class Multivalue extends Field { /** * Adds a new empty value to the data array. - * @param {any} value -A value to be added to the data array. */ addNewValue(value) { if (value === undefined) { diff --git a/src/components/_classes/nested/NestedComponent.form.js b/src/components/_classes/nested/NestedComponent.form.js index e0f5da1532..5795262cfb 100644 --- a/src/components/_classes/nested/NestedComponent.form.js +++ b/src/components/_classes/nested/NestedComponent.form.js @@ -1,10 +1,5 @@ import Components from '../../Components'; -/** - * The Edit Form function. - * @param {...any} extend - The components that extend the edit form. - * @returns {import('@formio/core').Component[]} - The edit form components. - */ export default function(...extend) { return Components.baseEditForm([ { diff --git a/src/components/_classes/nested/NestedComponent.js b/src/components/_classes/nested/NestedComponent.js index e95612489d..188d367274 100644 --- a/src/components/_classes/nested/NestedComponent.js +++ b/src/components/_classes/nested/NestedComponent.js @@ -3,12 +3,9 @@ import _ from 'lodash'; import Field from '../field/Field'; import Components from '../../Components'; import { getArrayFromComponentPath, getStringFromComponentPath, getRandomComponentId } from '../../../utils/utils'; +import Component from '../component/Component'; import { process as processAsync, processSync } from '@formio/core/process'; -/** - * NestedComponent class. - * @augments Field - */ export default class NestedComponent extends Field { static schema(...extend) { return Field.schema({ @@ -20,12 +17,6 @@ export default class NestedComponent extends Field { constructor(component, options, data) { super(component, options, data); this.type = 'components'; - /** - * The collapsed state of this NestedComponent. - * @type {boolean} - * @default false - * @private - */ this._collapsed = !!this.component.collapsed; } @@ -33,30 +24,17 @@ export default class NestedComponent extends Field { return NestedComponent.schema(); } - /** - * Get the schema for the NestedComponent. - * @returns {object} The schema for the NestedComponent. - * @override - */ get schema() { const schema = super.schema; const components = _.uniqBy(this.getComponents(), 'component.key'); schema.components = _.map(components, 'schema'); return schema; } - /** - * Get collapsed state. - * @returns {boolean} The collapsed state. - */ + get collapsed() { return this._collapsed; } - /** - * Set collapsed state. - * @param {boolean} value - The collapsed state. - * @returns {void} - */ collapse(value) { const promise = this.redraw(); if (!value) { @@ -65,20 +43,11 @@ export default class NestedComponent extends Field { return promise; } - /** - * Set collapsed state. - * @param {boolean} value - The collapsed state. - * @returns {void} - */ set collapsed(value) { this._collapsed = value; this.collapse(value); } - /** - * Set visible state of parent and each child component. - * @param {boolean} value - The visible state. - * @returns {void} - */ + set visible(value) { // DO NOT CALL super here. There is an issue where clearOnHide was getting triggered with // subcomponents because the "parentVisible" flag was set to false when it should really be @@ -111,54 +80,28 @@ export default class NestedComponent extends Field { } } - /** - * Get visible state. - * @returns {boolean} The visible state. - */ get visible() { return super.visible; } - /** - * Set parent visibility. - * @param {boolean} value - The parent visibility. - * @returns {void} - */ set parentVisible(value) { super.parentVisible = value; this.components.forEach(component => component.parentVisible = this.visible); } - /** - * Get parent visibility. - * @returns {boolean} The parent visibility. - */ get parentVisible() { return super.parentVisible; } - /** - * Get the disabled state. - * @returns {boolean} - The disabled state. - */ get disabled() { return super.disabled; } - /** - * Set the disabled state. - * @param {boolean} disabled - The disabled state. - */ set disabled(disabled) { super.disabled = disabled; this.components.forEach((component) => component.parentDisabled = disabled); } - /** - * Set parent disabled state. - * @param {boolean} value - The parent disabled state. - * @returns {void} - */ set parentDisabled(value) { super.parentDisabled = value; this.components.forEach(component => { @@ -166,35 +109,18 @@ export default class NestedComponent extends Field { }); } - /** - * Get parent disabled state. - * @returns {boolean} The parent disabled state. - */ get parentDisabled() { return super.parentDisabled; } - /** - * Get ready state from all components. - * @returns {Promise} - The promise that resolves when all components are ready. - */ get ready() { return Promise.all(this.getComponents().map(component => component.ready)); } - /** - * Get currentForm object. - * @returns {object} - The current form object. - */ get currentForm() { return super.currentForm; } - /** - * Set currentForm object. - * @param {object} instance - The current form object. - * @returns {void} - */ set currentForm(instance) { super.currentForm = instance; this.getComponents().forEach(component => { @@ -202,19 +128,10 @@ export default class NestedComponent extends Field { }); } - /** - * Get Row Index. - * @returns {number} - The row index. - */ get rowIndex() { return this._rowIndex; } - /** - * Set Row Index to row and update each component. - * @param {number} value - The row index. - * @returns {void} - */ set rowIndex(value) { this._rowIndex = value; this.eachComponent((component) => { @@ -222,29 +139,14 @@ export default class NestedComponent extends Field { }); } - /** - * Get Contextual data of the component. - * @returns {object} - The contextual data of the component. - * @override - */ componentContext() { return this._data; } - /** - * Get the data of the component. - * @returns {object} - The data of the component. - * @override - */ get data() { return this._data; } - /** - * Set the data of the component. - * @param {object} value - The data of the component. - * @returns {void} - */ set data(value) { this._data = value; this.eachComponent((component) => { @@ -252,10 +154,6 @@ export default class NestedComponent extends Field { }); } - /** - * Get components array. - * @returns {Array} - The components array. - */ getComponents() { return this.components || []; } @@ -263,8 +161,8 @@ export default class NestedComponent extends Field { /** * Perform a deep iteration over every component, including those * within other container based components. - * @param {Function} fn - Called for every component. - * @param {any} options - The options to include with this everyComponent call. + * + * @param {function} fn - Called for every component. */ everyComponent(fn, options) { const components = this.getComponents(); @@ -281,11 +179,6 @@ export default class NestedComponent extends Field { }); } - /** - * Check if the component has a component. - * @param {import('@formio/core').Component} component - The component to check. - * @returns {boolean} - TRUE if the component has a component, FALSE otherwise. - */ hasComponent(component) { let result = false; @@ -299,10 +192,6 @@ export default class NestedComponent extends Field { return result; } - /** - * Get the flattened components of this NestedComponent. - * @returns {object} - The flattened components of this NestedComponent. - */ flattenComponents() { const result = {}; @@ -315,7 +204,8 @@ export default class NestedComponent extends Field { /** * Perform an iteration over each component within this container component. - * @param {Function} fn - Called for each component + * + * @param {function} fn - Called for each component */ eachComponent(fn) { _.each(this.getComponents(), (component, index) => { @@ -328,10 +218,11 @@ export default class NestedComponent extends Field { /** * Returns a component provided a key. This performs a deep search within the * component tree. - * @param {string} path - The path to the component. - * @param {Function} [fn] - Called with the component once found. + * + * @param {string} key - The key of the component to retrieve. + * @param {function} [fn] - Called with the component once found. * @param {string} [originalPath] - The original path to the component. - * @returns {any} - The component that is located. + * @return {Component} - The component that is located. */ getComponent(path, fn, originalPath) { originalPath = originalPath || getStringFromComponentPath(path); @@ -386,9 +277,10 @@ export default class NestedComponent extends Field { /** * Return a component provided the Id of the component. + * * @param {string} id - The Id of the component. - * @param {Function} fn - Called with the component once it is retrieved. - * @returns {object} - The component retrieved. + * @param {function} fn - Called with the component once it is retrieved. + * @return {Object} - The component retrieved. */ getComponentById(id, fn) { let comp = null; @@ -406,12 +298,9 @@ export default class NestedComponent extends Field { /** * Create a new component and add it to the components array. - * @param {import('@formio/core').Component} component - The component JSON schema to create. - * @param {object} options - The options to create the component with. - * @param {import('@formio/core').DataObject} data - The submission data object to house the data for this component. - * @param {import('@formio/core').Component} [before] - The component before which to add this component. - * @param {import('@formio/core').Component} [replacedComp] - The component to replace with this component. - * @returns {any} - The created component instance. + * + * @param component + * @param data */ createComponent(component, options, data, before, replacedComp) { if (!component) { @@ -480,9 +369,9 @@ export default class NestedComponent extends Field { } /** - * Add a new component instance to the components array. - * @param {import('@formio/core').DataObject} [data] - The Submission data for this component. - * @param {object} [options] - The options for this component. + * + * @param element + * @param data */ addComponents(data, options) { data = data || this.data; @@ -499,11 +388,11 @@ export default class NestedComponent extends Field { /** * Add a new component to the components array. - * @param {import('@formio/core').Component} component - The component JSON schema to add. - * @param {object} data - The submission data object to house the data for this component. + * + * @param {Object} component - The component JSON schema to add. + * @param {Object} data - The submission data object to house the data for this component. * @param {HTMLElement} before - A DOM element to insert this element before. - * @param {boolean} [noAdd] - A possibly extraneous boolean flag. - * @returns {any} - The created component instance. + * @return {Component} - The created component instance. */ addComponent(component, data, before, noAdd) { data = data || this.data; @@ -576,10 +465,6 @@ export default class NestedComponent extends Field { ]); } - /** - * Attach the logic to the components. - * @param {import('@formio/core').Component[]} components - The components to attach logic to. - */ attachComponentsLogic(components) { components = components || this.components; @@ -615,9 +500,9 @@ export default class NestedComponent extends Field { /** * Remove a component from the components array and from the children object - * @param {import('@formio/core').Component} component - The component to remove from the components. - * @param {import('@formio/core').Component[]} components - An array of components to remove this component from. - * @param {boolean} [all] - If set to TRUE will cascade remove all components. + * + * @param {Component} component - The component to remove from the components. + * @param {Array} components - An array of components to remove this component from. */ removeComponent(component, components, all = false) { components = components || this.components; @@ -630,9 +515,10 @@ export default class NestedComponent extends Field { /** * Removes a component provided the API key of that component. + * * @param {string} key - The API key of the component to remove. - * @param {Function} fn - Called once the component is removed. - * @returns {null|void} - Returns nothing if the component is not found. + * @param {function} fn - Called once the component is removed. + * @return {null} */ removeComponentByKey(key, fn) { const comp = this.getComponent(key, (component, components) => { @@ -651,9 +537,10 @@ export default class NestedComponent extends Field { /** * Removes a component provided the Id of the component. + * * @param {string} id - The Id of the component to remove. - * @param {Function} fn - Called when the component is removed. - * @returns {null|void} - Returns nothing if the component is not found. + * @param {function} fn - Called when the component is removed. + * @return {null} */ removeComponentById(id, fn) { const comp = this.getComponentById(id, (component, components) => { @@ -725,8 +612,8 @@ export default class NestedComponent extends Field { /** * Allow components to hook into the next page trigger to perform their own logic. - * @param {Function} next - The callback to continue to the next page. - * @returns {Promise} - A promise when the page has been processed. + * + * @return {*} */ beforePage(next) { return Promise.all(this.getComponents().map((comp) => comp.beforePage(next))); @@ -734,7 +621,8 @@ export default class NestedComponent extends Field { /** * Allow components to hook into the submission to provide their own async data. - * @returns {Promise} - Returns a promise when the constituent beforeSubmit functions are complete. + * + * @return {*} */ beforeSubmit() { return Promise.allSettled(this.getComponents().map((comp) => comp.beforeSubmit())); @@ -775,10 +663,10 @@ export default class NestedComponent extends Field { /** * Perform a validation on all child components of this nested component. - * @param {import('@formio/core').Component[]} components - The components to validate. - * @param {import('@formio/core').DataObject} data - The data to validate. - * @param {object} flags - The flags to use when validating. - * @returns {Promise|Array} - The errors if any exist. + * @param {*} components + * @param {*} data + * @param {*} flags + * @returns */ validateComponents(components, data, flags = {}) { components = components || this.component.components; @@ -818,9 +706,9 @@ export default class NestedComponent extends Field { /** * Validate a nested component with data, or its own internal data. - * @param {import('@formio/core').DataObject} data - The data to validate. - * @param {object} flags - The flags to use when validating. - * @returns {Array} - The errors if any exist. + * @param {*} data + * @param {*} flags + * @returns */ validate(data, flags = {}) { data = data || this.rootValue; diff --git a/src/components/_classes/nesteddata/NestedDataComponent.js b/src/components/_classes/nesteddata/NestedDataComponent.js index 1ff0ee375a..c6a4271c72 100644 --- a/src/components/_classes/nesteddata/NestedDataComponent.js +++ b/src/components/_classes/nesteddata/NestedDataComponent.js @@ -121,7 +121,8 @@ export default class NestedDataComponent extends NestedComponent { /** * Get the value of this component. - * @returns {any} - Return the value of this component. + * + * @returns {*} */ getValue() { return this.dataValue; diff --git a/src/components/address/Address.form.js b/src/components/address/Address.form.js index aa9a206207..aae69d7cd5 100644 --- a/src/components/address/Address.form.js +++ b/src/components/address/Address.form.js @@ -3,11 +3,6 @@ import AddressEditData from './editForm/Address.edit.data'; import AddressEditDisplay from './editForm/Address.edit.display'; import AddressEditProvider from './editForm/Address.edit.provider'; -/** - * The Edit Form function. - * @param {...any} extend - The components that extend the edit form. - * @returns {import('@formio/core').Component[]} - The edit form components. - */ export default function(...extend) { return Components.baseEditForm([ { diff --git a/src/components/button/Button.form.js b/src/components/button/Button.form.js index 6e15574b9a..1a7d2099ff 100644 --- a/src/components/button/Button.form.js +++ b/src/components/button/Button.form.js @@ -1,11 +1,6 @@ import Components from '../Components'; import ButtonEditDisplay from './editForm/Button.edit.display'; -/** - * The Edit Form function. - * @param {...any} extend - The components that extend the edit form. - * @returns {import('@formio/core').Component[]} - The edit form components. - */ export default function(...extend) { return Components.baseEditForm([ { diff --git a/src/components/button/Button.js b/src/components/button/Button.js index 0505f9fdd1..7194c10e1a 100644 --- a/src/components/button/Button.js +++ b/src/components/button/Button.js @@ -253,11 +253,6 @@ export default class ButtonComponent extends Field { this.disabled = this.shouldDisabled; this.setDisabled(this.refs.button, this.disabled); - /** - * Get url parameter by name - * @param {string} name - The url parameter - * @returns {string} - The url parameter value - */ function getUrlParameter(name) { name = name.replace(/[[]/, '\\[').replace(/[\]]/, '\\]'); const regex = new RegExp(`[\\?&]${name}=([^&#]*)`); diff --git a/src/components/checkbox/Checkbox.form.js b/src/components/checkbox/Checkbox.form.js index 6af6796817..2eca29b217 100644 --- a/src/components/checkbox/Checkbox.form.js +++ b/src/components/checkbox/Checkbox.form.js @@ -3,11 +3,6 @@ import CheckboxEditData from './editForm/Checkbox.edit.data'; import CheckboxEditDisplay from './editForm/Checkbox.edit.display'; import CheckboxEditValidation from './editForm/Checkbox.edit.validation'; -/** - * The Edit Form function. - * @param {...any} extend - The components that extend the edit form. - * @returns {import('@formio/core').Component[]} - The edit form components. - */ export default function(...extend) { return Components.baseEditForm([ { diff --git a/src/components/columns/Columns.form.js b/src/components/columns/Columns.form.js index 5bed40f9b2..76bac20a96 100644 --- a/src/components/columns/Columns.form.js +++ b/src/components/columns/Columns.form.js @@ -2,11 +2,6 @@ import nestedComponentForm from '../_classes/nested/NestedComponent.form'; import ColumnsEditDisplay from './editForm/Columns.edit.display'; -/** - * The Edit Form function. - * @param {...any} extend - The components that extend the edit form. - * @returns {import('@formio/core').Component[]} - The edit form components. - */ export default function(...extend) { return nestedComponentForm([ { diff --git a/src/components/columns/Columns.js b/src/components/columns/Columns.js index 92ccbce8f1..67bddaed06 100644 --- a/src/components/columns/Columns.js +++ b/src/components/columns/Columns.js @@ -134,7 +134,7 @@ export default class ColumnsComponent extends NestedComponent { /** * Group columns in rows. - * @returns {Array.} - The array of columns + * @return {Array.} */ groupByRow() { const initVal = { stack: [], rows: [] }; diff --git a/src/components/container/Container.form.js b/src/components/container/Container.form.js index 6ccefc84fc..75755ed07f 100644 --- a/src/components/container/Container.form.js +++ b/src/components/container/Container.form.js @@ -2,11 +2,6 @@ import Components from '../Components'; import ContainerEditDisplay from './editForm/Container.edit.display'; import ContainerEditData from './editForm/Container.edit.data'; -/** - * The Edit Form function. - * @param {...any} extend - The components that extend the edit form. - * @returns {import('@formio/core').Component[]} - The edit form components. - */ export default function(...extend) { return Components.baseEditForm([ { diff --git a/src/components/content/Content.form.js b/src/components/content/Content.form.js index 3e11a5a4e3..b81c82cd24 100644 --- a/src/components/content/Content.form.js +++ b/src/components/content/Content.form.js @@ -2,11 +2,6 @@ import Components from '../Components'; import ContentEditDisplay from './editForm/Content.edit.display'; import ContentEditLogic from './editForm/Content.edit.logic'; -/** - * The Edit Form function. - * @param {...any} extend - The components that extend the edit form. - * @returns {import('@formio/core').Component[]} - The edit form components. - */ export default function(...extend) { const editForm = Components.baseEditForm([ { diff --git a/src/components/currency/Currency.form.js b/src/components/currency/Currency.form.js index 23d0b9924e..2bfc648ab5 100644 --- a/src/components/currency/Currency.form.js +++ b/src/components/currency/Currency.form.js @@ -1,11 +1,6 @@ import baseEditForm from '../textfield/TextField.form'; import CurrencyEditDisplay from './editForm/Currency.edit.display'; import CurrencyEditData from './editForm/Currency.edit.data'; -/** - * The Edit Form function. - * @param {...any} extend - The components that extend the edit form. - * @returns {import('@formio/core').Component[]} - The edit form components. - */ export default function(...extend) { return baseEditForm([ { diff --git a/src/components/currency/Currency.js b/src/components/currency/Currency.js index dce69bbde5..0356ca2b32 100644 --- a/src/components/currency/Currency.js +++ b/src/components/currency/Currency.js @@ -34,7 +34,8 @@ export default class CurrencyComponent extends NumberComponent { /** * Creates the number mask for currency numbers. - * @returns {*} - The result of the createNumberMask function + * + * @return {*} */ createNumberMask() { const decimalLimit = _.get(this.component, 'decimalLimit', 2); diff --git a/src/components/datagrid/DataGrid.form.js b/src/components/datagrid/DataGrid.form.js index 229c2385f0..6e7218674b 100644 --- a/src/components/datagrid/DataGrid.form.js +++ b/src/components/datagrid/DataGrid.form.js @@ -3,11 +3,6 @@ import DataGridEditData from './editForm/DataGrid.edit.data'; import DataGridEditDisplay from './editForm/DataGrid.edit.display'; import DataGridEditValidation from './editForm/DataGrid.edit.validation'; -/** - * The Edit Form function. - * @param {...any} extend - The components that extend the edit form. - * @returns {import('@formio/core').Component[]} - The edit form components. - */ export default function(...extend) { return Components.baseEditForm([ { diff --git a/src/components/datagrid/DataGrid.js b/src/components/datagrid/DataGrid.js index fef44a671a..fa029029ca 100644 --- a/src/components/datagrid/DataGrid.js +++ b/src/components/datagrid/DataGrid.js @@ -162,9 +162,9 @@ export default class DataGridComponent extends NestedArrayComponent { /** * Split rows into chunks. - * @param {number[]} groups - array of numbers where each item is size of group + * @param {Number[]} groups - array of numbers where each item is size of group * @param {Array} rows - rows collection - * @returns {Array} - The chunked rows + * @return {Array} */ getRowChunks(groups, rows) { const [, chunks] = groups.reduce( @@ -179,7 +179,7 @@ export default class DataGridComponent extends NestedArrayComponent { /** * Create groups object. * Each key in object represents index of first row in group. - * @returns {object} - The groups object. + * @return {Object} */ getGroups() { const groups = _.get(this.component, 'rowGroups', []); @@ -201,8 +201,8 @@ export default class DataGridComponent extends NestedArrayComponent { } /** - * Get group sizes. - * @returns {number[]} - The array of group sizes. + * Retrun group sizes. + * @return {Number[]} */ getGroupSizes() { return _.map(_.get(this.component, 'rowGroups', []), 'numberOfRows'); diff --git a/src/components/datamap/DataMap.form.js b/src/components/datamap/DataMap.form.js index 47e8ec077d..2967af769f 100644 --- a/src/components/datamap/DataMap.form.js +++ b/src/components/datamap/DataMap.form.js @@ -2,11 +2,6 @@ import Components from '../Components'; import DataMapEditData from './editForm/DataMap.edit.data'; import DataMapEditDisplay from './editForm/DataMap.edit.display'; -/** - * The Edit Form function. - * @param {...any} extend - The components that extend the edit form. - * @returns {import('@formio/core').Component[]} - The edit form components. - */ export default function(...extend) { return Components.baseEditForm([ { diff --git a/src/components/datetime/DateTime.form.js b/src/components/datetime/DateTime.form.js index 5536d60913..5a616bd478 100644 --- a/src/components/datetime/DateTime.form.js +++ b/src/components/datetime/DateTime.form.js @@ -5,11 +5,6 @@ import DateTimeEditDisplay from './editForm/DateTime.edit.display'; import DateTimeEditTime from './editForm/DateTime.edit.time'; import DateTimeEditValidation from './editForm/DateTime.edit.validation'; -/** - * The Edit Form function. - * @param {...any} extend - The components that extend the edit form. - * @returns {import('@formio/core').Component[]} - The edit form components. - */ export default function(...extend) { return Components.baseEditForm([ { diff --git a/src/components/day/Day.form.js b/src/components/day/Day.form.js index cb7de71193..928696ad30 100644 --- a/src/components/day/Day.form.js +++ b/src/components/day/Day.form.js @@ -6,11 +6,6 @@ import DayEditDay from './editForm/Day.edit.day'; import DayEditMonth from './editForm/Day.edit.month'; import DayEditYear from './editForm/Day.edit.year'; -/** - * The Edit Form function. - * @param {...any} extend - The components that extend the edit form. - * @returns {import('@formio/core').Component[]} - The edit form components. - */ export default function(...extend) { return Components.baseEditForm([ { diff --git a/src/components/day/Day.js b/src/components/day/Day.js index 9b1bf9a869..397931d3d9 100644 --- a/src/components/day/Day.js +++ b/src/components/day/Day.js @@ -69,7 +69,8 @@ export default class DayComponent extends Field { /** * The empty value for day component. - * @returns {'00/00/0000'} - The empty value of the day component. + * + * @return {'00/00/0000'} */ get emptyValue() { return '00/00/0000'; @@ -405,10 +406,10 @@ export default class DayComponent extends Field { } /** - * Set the value at a specific index and updates the component's refs. - * @param {number} index - The index to set. - * @param {any} value - The value to set. - * @returns {null|void} - Returns null if the value is invalid, otherwise void. + * Set the value at a specific index. + * + * @param index + * @param value */ setValueAt(index, value) { // temporary solution to avoid input reset @@ -468,7 +469,7 @@ export default class DayComponent extends Field { /** * Get the format for the value string. - * @returns {string} - the format for the value string. + * @returns {string} */ get format() { let format = ''; @@ -493,8 +494,9 @@ export default class DayComponent extends Field { /** * Return the date for this component. - * @param {any} value - The value to convert to a date. - * @returns {null|string} - The date string. + * + * @param value + * @return {*} */ getDate(value) { let defaults = [], day, month, year; @@ -548,8 +550,8 @@ export default class DayComponent extends Field { } /** - * Return the date string for this component. - * @returns {string|null} - The date string for this component. + * Return the date object for this component. + * @returns {Date} */ get date() { return this.getDate(); @@ -557,7 +559,8 @@ export default class DayComponent extends Field { /** * Return the raw value. - * @returns {string} - The raw value of the component. + * + * @returns {Date} */ get validationValue() { return this.dataValue; @@ -570,8 +573,9 @@ export default class DayComponent extends Field { /** * Get the value at a specific index. - * @param {number} index - The index to get the value from. - * @returns {*} - The value at index. + * + * @param index + * @returns {*} */ getValueAt(index) { const date = this.date || this.emptyValue; @@ -587,8 +591,9 @@ export default class DayComponent extends Field { /** * Get the input value of the date. - * @param {any} value - The value to convert to a string. - * @returns {string|null} - The string value of the date. + * + * @param value + * @return {null} */ getValueAsString(value) { return this.getDate(value) || ''; diff --git a/src/components/editgrid/EditGrid.form.js b/src/components/editgrid/EditGrid.form.js index b9cd131562..caa0e655ba 100644 --- a/src/components/editgrid/EditGrid.form.js +++ b/src/components/editgrid/EditGrid.form.js @@ -4,11 +4,6 @@ import EditGridEditDisplay from './editForm/EditGrid.edit.display'; import EditGridEditTemplates from './editForm/EditGrid.edit.templates'; import EditGridEditValidation from './editForm/EditGrid.edit.validation'; -/** - * The Edit Form function. - * @param {...any} extend - The components that extend the edit form. - * @returns {import('@formio/core').Component[]} - The edit form components. - */ export default function(...extend) { return Components.baseEditForm([ { diff --git a/src/components/editgrid/EditGrid.js b/src/components/editgrid/EditGrid.js index 1a0bd058ee..500e09fbf6 100644 --- a/src/components/editgrid/EditGrid.js +++ b/src/components/editgrid/EditGrid.js @@ -182,8 +182,8 @@ export default class EditGridComponent extends NestedArrayComponent { } /** - * @returns {boolean} - Returns true if the component has nested components which don't trigger changes on the root level - */ + * Returns true if the component has nested components which don't trigger changes on the root level + */// get hasScopedChildren() { return !this.inlineEditMode; } @@ -1228,7 +1228,7 @@ export default class EditGridComponent extends NestedArrayComponent { } /** - * @returns {boolean} - Return that this component processes its own validation. + * Return that this component processes its own validation. */ get processOwnValidation() { return true; diff --git a/src/components/email/Email.form.js b/src/components/email/Email.form.js index 4f7707d8e0..12258dd955 100644 --- a/src/components/email/Email.form.js +++ b/src/components/email/Email.form.js @@ -2,11 +2,6 @@ import baseEditForm from '../textfield/TextField.form'; import EmailEditFormDisplay from './editForm/Email.edit.display'; import EmailEditFormValidation from './editForm/Email.edit.validation'; -/** - * The Edit Form function. - * @param {...any} extend - The components that extend the edit form. - * @returns {import('@formio/core').Component[]} - The edit form components. - */ export default function(...extend) { return baseEditForm([ { diff --git a/src/components/fieldset/Fieldset.form.js b/src/components/fieldset/Fieldset.form.js index 7bbe8af81a..8ac01aeaf8 100644 --- a/src/components/fieldset/Fieldset.form.js +++ b/src/components/fieldset/Fieldset.form.js @@ -1,10 +1,5 @@ import nestedComponentForm from '../_classes/nested/NestedComponent.form'; import FieldSetEditDisplay from './editForm/Fieldset.edit.display'; -/** - * The Edit Form function. - * @param {...any} extend - The components that extend the edit form. - * @returns {import('@formio/core').Component[]} - The edit form components. - */ export default function(...extend) { return nestedComponentForm([ { diff --git a/src/components/file/File.form.js b/src/components/file/File.form.js index fbdaa6e747..686005eb02 100644 --- a/src/components/file/File.form.js +++ b/src/components/file/File.form.js @@ -4,11 +4,6 @@ import FileEditDisplay from './editForm/File.edit.display'; import FileEditFile from './editForm/File.edit.file'; import FileEditValidation from './editForm/File.edit.validation'; -/** - * The Edit Form function. - * @param {...any} extend - The components that extend the edit form. - * @returns {import('@formio/core').Component[]} - The edit form components. - */ export default function(...extend) { return Components.baseEditForm([ { diff --git a/src/components/form/Form.form.js b/src/components/form/Form.form.js index a9faf554f9..5edcd85f8f 100644 --- a/src/components/form/Form.form.js +++ b/src/components/form/Form.form.js @@ -3,11 +3,6 @@ import FormEditDisplay from './editForm/Form.edit.display'; import FormEditForm from './editForm/Form.edit.form'; import FormEditData from './editForm/Form.edit.data'; -/** - * The Edit Form function. - * @param {...any} extend - The components that extend the edit form. - * @returns {import('@formio/core').Component[]} - The edit form components. - */ export default function(...extend) { return nestedComponentForm([ { diff --git a/src/components/form/Form.js b/src/components/form/Form.js index 6be3099ed3..04cab1613d 100644 --- a/src/components/form/Form.js +++ b/src/components/form/Form.js @@ -397,8 +397,8 @@ export default class FormComponent extends Component { /** * Pass everyComponent to subform. - * @param {any[]} args - Arguments to pass through to the subform's everyComponent method. - * @returns {*} - The result of the subform's everyComponent method. + * @param args + * @returns {*|void} */ everyComponent(...args) { if (this.subForm) { @@ -425,8 +425,8 @@ export default class FormComponent extends Component { /** * Create a subform instance. - * @param {boolean} [fromAttach] - This function is being called from an `attach` method. - * @returns {*} - The subform instance. + * + * @return {*} */ createSubForm(fromAttach) { this.subFormReady = this.loadSubForm(fromAttach).then((form) => { @@ -485,8 +485,6 @@ export default class FormComponent extends Component { /** * Load the subform. - * @param {boolean} fromAttach - This function is being called from an `attach` method. - * @returns {Promise} - The promise that resolves when the subform is loaded. */ loadSubForm(fromAttach) { if (this.builderMode || this.isHidden() || (this.isSubFormLazyLoad() && !fromAttach)) { @@ -583,7 +581,7 @@ export default class FormComponent extends Component { /** * Determine if the subform should be submitted. - * @returns {*|boolean} - TRUE if the subform should be submitted, FALSE if it should not. + * @return {*|boolean} */ get shouldSubmit() { return this.subFormReady && (!this.component.hasOwnProperty('reference') || this.component.reference) && !this.isHidden(); @@ -591,7 +589,8 @@ export default class FormComponent extends Component { /** * Returns the data for the subform. - * @returns {*} - the data for the subform. + * + * @return {*} */ getSubFormData() { if (_.get(this.subForm, 'form.display') === 'pdf') { @@ -604,7 +603,8 @@ export default class FormComponent extends Component { /** * Submit the subform if configured to do so. - * @returns {Promise} - The promise that resolves when the subform is submitted. + * + * @return {*} */ submitSubForm() { // If we wish to submit the form on next page, then do that here. @@ -632,8 +632,6 @@ export default class FormComponent extends Component { /** * Submit the form before the next page is triggered. - * @param {Function} next - The function to trigger the next page. - * @returns {Promise} - The promise that resolves when the subform submission is complete (if necessary) and the next page is triggered. */ beforePage(next) { // Should not submit child forms if we are going to the previous page @@ -645,7 +643,6 @@ export default class FormComponent extends Component { /** * Submit the form before the whole form is triggered. - * @returns {Promise} - The promise that resolves when the subform submission is complete (if necessary) and the form is submitted. */ beforeSubmit() { const submission = this.dataValue; @@ -770,7 +767,7 @@ export default class FormComponent extends Component { /** * Determines if this form is a Nested Wizard * which means it should be a Wizard itself and should be a direct child of a Wizard's page - * @returns {boolean} - TRUE if this form is a Nested Wizard, FALSE otherwise + * @returns {boolean} */ get isNestedWizard() { return this.subForm?._form?.display === 'wizard' && this.parent?.parent?._form?.display === 'wizard'; diff --git a/src/components/hidden/Hidden.form.js b/src/components/hidden/Hidden.form.js index 552f4ba1eb..1e11a9404b 100644 --- a/src/components/hidden/Hidden.form.js +++ b/src/components/hidden/Hidden.form.js @@ -2,11 +2,6 @@ import Components from '../Components'; import HiddenEditDisplay from './editForm/Hidden.edit.display'; import HiddenEditData from './editForm/Hidden.edit.data'; -/** - * The Edit Form function. - * @param {...any} extend - The components that extend the edit form. - * @returns {import('@formio/core').Component[]} - The edit form components. - */ export default function(...extend) { return Components.baseEditForm([ { diff --git a/src/components/hidden/Hidden.js b/src/components/hidden/Hidden.js index 23f954f4e5..0f09c4adf5 100644 --- a/src/components/hidden/Hidden.js +++ b/src/components/hidden/Hidden.js @@ -39,7 +39,8 @@ export default class HiddenComponent extends Input { /** * Check if a component is eligible for multiple validation - * @returns {boolean} - If the component is eligible for multiple validation. + * + * @return {boolean} */ validateMultiple() { // Since "arrays" are able to be stored in hidden components, we need to turn off multiple validation. diff --git a/src/components/html/HTML.form.js b/src/components/html/HTML.form.js index 84e3707323..7f793d24f8 100644 --- a/src/components/html/HTML.form.js +++ b/src/components/html/HTML.form.js @@ -2,11 +2,6 @@ import Components from '../Components'; import HTMLEditDisplay from './editForm/HTML.edit.display'; import HTMLEditLogic from './editForm/HTML.edit.logic'; -/** - * The Edit Form function. - * @param {...any} extend - The components that extend the edit form. - * @returns {import('@formio/core').Component[]} - The edit form components. - */ export default function(...extend) { return Components.baseEditForm([ { diff --git a/src/components/number/Number.form.js b/src/components/number/Number.form.js index 61b80d23d5..0819732999 100644 --- a/src/components/number/Number.form.js +++ b/src/components/number/Number.form.js @@ -4,11 +4,6 @@ import NumberEditDisplay from './editForm/Number.edit.display'; import NumberEditData from './editForm/Number.edit.data'; import NumberEditValidation from './editForm/Number.edit.validation'; -/** - * The Edit Form function. - * @param {...any} extend - The components that extend the edit form. - * @returns {import('@formio/core').Component[]} - The edit form components. - */ export default function(...extend) { return textEditForm([ { diff --git a/src/components/number/Number.js b/src/components/number/Number.js index 3d90c287fd..2b11773a61 100644 --- a/src/components/number/Number.js +++ b/src/components/number/Number.js @@ -83,7 +83,8 @@ export default class NumberComponent extends Input { /** * Creates the number mask for normal numbers. - * @returns {*} - The number mask. + * + * @return {*} */ createNumberMask() { return createNumberMask({ diff --git a/src/components/panel/Panel.form.js b/src/components/panel/Panel.form.js index ed92335bfa..3335332268 100644 --- a/src/components/panel/Panel.form.js +++ b/src/components/panel/Panel.form.js @@ -3,11 +3,6 @@ import nestedComponentForm from '../_classes/nested/NestedComponent.form'; import PanelEditDisplay from './editForm/Panel.edit.display'; import PanelEditConditional from './editForm/Panel.edit.conditional'; -/** - * The Edit Form function. - * @param {...any} extend - The components that extend the edit form. - * @returns {import('@formio/core').Component[]} - The edit form components. - */ export default function(...extend) { return nestedComponentForm([ { diff --git a/src/components/panel/Panel.js b/src/components/panel/Panel.js index f6b1761bd1..264232e9cd 100644 --- a/src/components/panel/Panel.js +++ b/src/components/panel/Panel.js @@ -1,5 +1,6 @@ import NestedComponent from '../_classes/nested/NestedComponent'; import { isChildOf } from '../../utils/utils'; +import FormComponent from '../form/Form'; export default class PanelComponent extends NestedComponent { static schema(...extend) { diff --git a/src/components/password/Password.form.js b/src/components/password/Password.form.js index c57f94aa3f..6c4e9bd123 100644 --- a/src/components/password/Password.form.js +++ b/src/components/password/Password.form.js @@ -4,11 +4,6 @@ import PasswordEditDisplay from './editForm/Password.edit.display'; import PasswordEditData from './editForm/Password.edit.data'; import PasswordEditValidation from './editForm/Password.edit.validation'; -/** - * The Edit Form function. - * @param {...any} extend - The components that extend the edit form. - * @returns {import('@formio/core').Component[]} - The edit form components. - */ export default function(...extend) { return textEditForm([ { diff --git a/src/components/phonenumber/PhoneNumber.form.js b/src/components/phonenumber/PhoneNumber.form.js index a8b0ba6cf1..5a34323540 100644 --- a/src/components/phonenumber/PhoneNumber.form.js +++ b/src/components/phonenumber/PhoneNumber.form.js @@ -2,11 +2,6 @@ import textEditForm from '../textfield/TextField.form'; import PhoneNumberEditValidation from './editForm/PhoneNumber.edit.validation'; -/** - * The Edit Form function. - * @param {...any} extend - The components that extend the edit form. - * @returns {import('@formio/core').Component[]} - The edit form components. - */ export default function(...extend) { return textEditForm([ { diff --git a/src/components/radio/Radio.form.js b/src/components/radio/Radio.form.js index 44d0ec86c6..165a41f278 100644 --- a/src/components/radio/Radio.form.js +++ b/src/components/radio/Radio.form.js @@ -3,11 +3,6 @@ import RadioEditData from './editForm/Radio.edit.data'; import RadioEditDisplay from './editForm/Radio.edit.display'; import RadioEditValidation from './editForm/Radio.edit.validation'; -/** - * The Edit Form function. - * @param {...any} extend - The components that extend the edit form. - * @returns {import('@formio/core').Component[]} - The edit form components. - */ export default function(...extend) { return listComponentForm([ { diff --git a/src/components/radio/Radio.js b/src/components/radio/Radio.js index 73ca8f0912..34228bda79 100644 --- a/src/components/radio/Radio.js +++ b/src/components/radio/Radio.js @@ -413,9 +413,10 @@ export default class RadioComponent extends ListComponent { } /** - * Normalize values coming into updateValue. For example, depending on the configuration, string value `"true"` will be normalized to boolean `true`. - * @param {*} value - The value to normalize - * @returns {*} - Returns the normalized value + * Normalize values coming into updateValue. + * + * @param value + * @return {*} */ normalizeValue(value) { const dataType = this.component.dataType || 'auto'; diff --git a/src/components/recaptcha/ReCaptcha.form.js b/src/components/recaptcha/ReCaptcha.form.js index 116f7afc02..6171a71043 100644 --- a/src/components/recaptcha/ReCaptcha.form.js +++ b/src/components/recaptcha/ReCaptcha.form.js @@ -1,10 +1,6 @@ import Components from '../Components'; import ReCaptchaEditDisplay from './editForm/ReCaptcha.edit.display'; -/** - * The Edit Form function. - * @returns {import('@formio/core').Component[]} - The edit form components. - */ export default function() { return Components.baseEditForm([ { diff --git a/src/components/select/Select.form.js b/src/components/select/Select.form.js index 7a223be7d0..93e6d01cf6 100644 --- a/src/components/select/Select.form.js +++ b/src/components/select/Select.form.js @@ -3,11 +3,6 @@ import SelectEditData from './editForm/Select.edit.data'; import SelectEditDisplay from './editForm/Select.edit.display'; import SelectEditValidation from './editForm/Select.edit.validation'; -/** - * The Edit Form function. - * @param {...any} extend - The components that extend the edit form. - * @returns {import('@formio/core').Component[]} - The edit form components. - */ export default function(...extend) { return listComponentForm([ { diff --git a/src/components/select/Select.js b/src/components/select/Select.js index 051484f585..26641a7edb 100644 --- a/src/components/select/Select.js +++ b/src/components/select/Select.js @@ -331,10 +331,9 @@ export default class SelectComponent extends ListComponent { /** * Adds an option to the select dropdown. - * @param {*} value - The value of the new option. - * @param {string} label - The label of the new option. - * @param {object} [attrs] - Additional value attributes. Defaults to {}. - * @param {string} [id] - An id. Defaults to a random string. + * + * @param value + * @param label */ addOption(value, label, attrs = {}, id = getRandomComponentId()) { if (_.isNil(label)) return; @@ -696,7 +695,6 @@ export default class SelectComponent extends ListComponent { } /** * Get the request headers for this select dropdown. - * @returns {*} - Returns the request headers for this select dropdown. */ get requestHeaders() { // Create the headers object. @@ -1261,6 +1259,10 @@ export default class SelectComponent extends ListComponent { return super.visible; } + /** + * @param {*} value + * @param {Array} items + */ addCurrentChoices(values, items, keyValue) { if (!values) { return false; @@ -1438,9 +1440,10 @@ export default class SelectComponent extends ListComponent { } /** - * Normalize values coming into updateValue. For example, depending on the configuration, string value `"true"` will be normalized to boolean `true`. - * @param {*} value - The value to normalize - * @returns {*} - Returns the normalized value + * Normalize values coming into updateValue. + * + * @param value + * @return {*} */ normalizeValue(value) { if (this.component.multiple && Array.isArray(value)) { @@ -1660,8 +1663,7 @@ export default class SelectComponent extends ListComponent { /** * Performs required transformations on the initial value to use in selectOptions - * @param {*} value - The value to transform. - * @returns {*} - Returns the options value. + * @param {*} value */ getOptionValue(value) { return _.isObject(value) && this.isEntireObjectDisplay() @@ -1677,7 +1679,7 @@ export default class SelectComponent extends ListComponent { /** * If component has static values (values, json) or custom values, returns an array of them - * @returns {Array<*>|undefined} - Returns an array of the static or custom values. + * @returns {Array<*>|undefined} */ getOptionsValues() { let rawItems = []; @@ -1722,7 +1724,8 @@ export default class SelectComponent extends ListComponent { /** * Check if a component is eligible for multiple validation - * @returns {boolean} - Returns FALSE for select components. + * + * @return {boolean} */ validateMultiple() { // Select component will contain one input when flagged as multiple. @@ -1731,7 +1734,7 @@ export default class SelectComponent extends ListComponent { /** * Output this select dropdown as a string value. - * @returns {*} + * @return {*} */ isBooleanOrNumber(value) { diff --git a/src/components/selectboxes/SelectBoxes.form.js b/src/components/selectboxes/SelectBoxes.form.js index 296c0a1e5f..7d7300fc56 100644 --- a/src/components/selectboxes/SelectBoxes.form.js +++ b/src/components/selectboxes/SelectBoxes.form.js @@ -1,11 +1,6 @@ import radioEditForm from '../radio/Radio.form'; import SelectBoxesEditValidation from './editForm/SelectBoxes.edit.validation'; -/** - * The Edit Form function. - * @param {...any} extend - The components that extend the edit form. - * @returns {import('@formio/core').Component[]} - The edit form components. - */ export default function(...extend) { return radioEditForm([ { diff --git a/src/components/selectboxes/SelectBoxes.js b/src/components/selectboxes/SelectBoxes.js index 7aa3b93514..cbb4583db9 100644 --- a/src/components/selectboxes/SelectBoxes.js +++ b/src/components/selectboxes/SelectBoxes.js @@ -97,8 +97,9 @@ export default class SelectBoxesComponent extends RadioComponent { /** * Only empty if the values are all false. - * @param {any} value - The value to check if empty. - * @returns {boolean} - If the value is empty. + * + * @param value + * @return {boolean} */ isEmpty(value = this.dataValue) { let empty = true; @@ -125,8 +126,9 @@ export default class SelectBoxesComponent extends RadioComponent { /** * Normalize values coming into updateValue. - * @param {any} value - The value to normalize. - * @returns {*} - The normalized value + * + * @param value + * @return {*} */ normalizeValue(value) { value = value || {}; @@ -162,9 +164,9 @@ export default class SelectBoxesComponent extends RadioComponent { /** * Set the value of this component. - * @param {any} value - The value to set. - * @param {any} flags - Flags to apply to this update. - * @returns {boolean} - If the value has changed. + * + * @param value + * @param flags */ setValue(value, flags = {}) { const changed = this.updateValue(value, flags); diff --git a/src/components/signature/Signature.form.js b/src/components/signature/Signature.form.js index 4b66dd970b..d7db9e4fb8 100644 --- a/src/components/signature/Signature.form.js +++ b/src/components/signature/Signature.form.js @@ -3,11 +3,6 @@ import SignatureEditData from './editForm/Signature.edit.data'; import SignatureEditDisplay from './editForm/Signature.edit.display'; import SignatureEditValidation from './editForm/Signature.edit.validation'; -/** - * The Edit Form function. - * @param {...any} extend - The components that extend the edit form. - * @returns {import('@formio/core').Component[]} - The edit form components. - */ export default function(...extend) { return Components.baseEditForm([ { diff --git a/src/components/survey/Survey.form.js b/src/components/survey/Survey.form.js index 6724e35739..0db2c40aaf 100644 --- a/src/components/survey/Survey.form.js +++ b/src/components/survey/Survey.form.js @@ -3,11 +3,6 @@ import SurveyEditData from './editForm/Survey.edit.data'; import SurveyEditDisplay from './editForm/Survey.edit.display'; import SurveyEditValidation from './editForm/Survey.edit.validation'; -/** - * The Edit Form function. - * @param {...any} extend - The components that extend the edit form. - * @returns {import('@formio/core').Component[]} - The edit form components. - */ export default function(...extend) { return Components.baseEditForm([ { diff --git a/src/components/table/Table.form.js b/src/components/table/Table.form.js index 08dde4bd11..a0e1155f6a 100644 --- a/src/components/table/Table.form.js +++ b/src/components/table/Table.form.js @@ -2,11 +2,6 @@ import nestedComponentForm from '../_classes/nested/NestedComponent.form'; import TableEditDisplay from './editForm/Table.edit.display'; -/** - * The Edit Form function. - * @param {...any} extend - The components that extend the edit form. - * @returns {import('@formio/core').Component[]} - The edit form components. - */ export default function(...extend) { return nestedComponentForm([ { diff --git a/src/components/tabs/Tabs.form.js b/src/components/tabs/Tabs.form.js index 87e842f4d2..2a02192ac0 100644 --- a/src/components/tabs/Tabs.form.js +++ b/src/components/tabs/Tabs.form.js @@ -2,11 +2,6 @@ import nestedComponentForm from '../_classes/nested/NestedComponent.form'; import TabsEditDisplay from './editForm/Tabs.edit.display'; -/** - * The Edit Form function. - * @param {...any} extend - The components that extend the edit form. - * @returns {import('@formio/core').Component[]} - The edit form components. - */ export default function(...extend) { return nestedComponentForm([ { diff --git a/src/components/tabs/Tabs.js b/src/components/tabs/Tabs.js index 1672e91896..865ae35205 100644 --- a/src/components/tabs/Tabs.js +++ b/src/components/tabs/Tabs.js @@ -131,7 +131,8 @@ export default class TabsComponent extends NestedComponent { /** * Set the current tab. - * @param {number} index - The index of the tab to set. + * + * @param index */ setTab(index) { if (!this.tabs || !this.tabs[index] || !this.refs[this.tabKey] || !this.refs[this.tabKey][index]) { diff --git a/src/components/tags/Tags.form.js b/src/components/tags/Tags.form.js index bf70a95b10..40fb75a39f 100644 --- a/src/components/tags/Tags.form.js +++ b/src/components/tags/Tags.form.js @@ -2,11 +2,6 @@ import Components from '../Components'; import TagsEditData from './editForm/Tags.edit.data'; -/** - * The Edit Form function. - * @param {...any} extend - The components that extend the edit form. - * @returns {import('@formio/core').Component[]} - The edit form components. - */ export default function(...extend) { return Components.baseEditForm([ { diff --git a/src/components/textarea/TextArea.form.js b/src/components/textarea/TextArea.form.js index de42a3eb1e..b8cf874c10 100644 --- a/src/components/textarea/TextArea.form.js +++ b/src/components/textarea/TextArea.form.js @@ -2,11 +2,6 @@ import textEditForm from '../textfield/TextField.form'; import TextAreaEditDisplay from './editForm/TextArea.edit.display'; import TextAreaEditValidation from './editForm/TextArea.edit.validation'; -/** - * The Edit Form function. - * @param {...any} extend - The components that extend the edit form. - * @returns {import('@formio/core').Component[]} - The edit form components. - */ export default function(...extend) { return textEditForm([ { diff --git a/src/components/textarea/TextArea.js b/src/components/textarea/TextArea.js index 596eb2fed5..cb64c9d41b 100644 --- a/src/components/textarea/TextArea.js +++ b/src/components/textarea/TextArea.js @@ -89,8 +89,8 @@ export default class TextAreaComponent extends TextFieldComponent { /** * Updates the editor value. - * @param {number} index - The index of the editor. - * @param {any} newValue - The new editor value. + * + * @param newValue */ updateEditorValue(index, newValue) { newValue = this.getConvertedValue(this.trimBlanks(newValue)); diff --git a/src/components/textfield/TextField.form.js b/src/components/textfield/TextField.form.js index 2c752e7601..50c8c4738e 100644 --- a/src/components/textfield/TextField.form.js +++ b/src/components/textfield/TextField.form.js @@ -4,11 +4,6 @@ import TextFieldEditData from './editForm/TextField.edit.data'; import TextFieldEditDisplay from './editForm/TextField.edit.display'; import TextFieldEditValidation from './editForm/TextField.edit.validation'; -/** - * The Edit Form function. - * @param {...any} extend - The components that extend the edit form. - * @returns {import('@formio/core').Component[]} - The edit form components. - */ export default function(...extend) { return Components.baseEditForm([ { diff --git a/src/components/textfield/TextField.js b/src/components/textfield/TextField.js index 78b782c177..94c22923c6 100644 --- a/src/components/textfield/TextField.js +++ b/src/components/textfield/TextField.js @@ -110,10 +110,11 @@ export default class TextFieldComponent extends Input { } /** - * Returns the mask value object (mutates value!). - * @param {any} [value] - The value to convert to a mask value. - * @param {any} [flags] - The flags to use when converting to a mask value. - * @returns {*} - The value as a mask value. + * Returns the mask value object. + * + * @param value + * @param flags + * @return {*} */ maskValue(value, flags = {}) { // Convert it into the correct format. @@ -135,9 +136,10 @@ export default class TextFieldComponent extends Input { /** * Normalize the value set in the data object. - * @param {any} value - The value to normalize. - * @param {any} flags - The flags to use when normalizing the value. - * @returns {*} - Returns the normalized value. + * + * @param value + * @param flags + * @return {*} */ normalizeValue(value, flags = {}) { if (!this.isMultipleMasksField) { @@ -151,10 +153,10 @@ export default class TextFieldComponent extends Input { /** * Sets the value at this index. - * @param {number} index - The index to set the value at. - * @param {any} value - The value to set. - * @param {any} [flags] - The flags to use when setting the value. - * @returns {void} + * + * @param index + * @param value + * @param flags */ setValueAt(index, value, flags = {}) { if (!this.isMultipleMasksField) { @@ -189,8 +191,9 @@ export default class TextFieldComponent extends Input { /** * Returns the value at this index. - * @param {number} index - The index to get the value from. - * @returns {*} - The value at the index. + * + * @param index + * @return {*} */ getValueAt(index) { if (!this.isMultipleMasksField) { diff --git a/src/components/time/Time.form.js b/src/components/time/Time.form.js index 8de114a35f..b21d70c3b5 100644 --- a/src/components/time/Time.form.js +++ b/src/components/time/Time.form.js @@ -3,11 +3,6 @@ import baseEditForm from '../_classes/component/Component.form'; import TimeEditData from './editForm/Time.edit.data'; import TimeEditDisplay from './editForm/Time.edit.display'; -/** - * The Edit Form function. - * @param {...any} extend - The components that extend the edit form. - * @returns {import('@formio/core').Component[]} - The edit form components. - */ export default function(...extend) { return baseEditForm([ { diff --git a/src/components/unknown/Unknown.form.js b/src/components/unknown/Unknown.form.js index 400082577e..d111ace1c4 100644 --- a/src/components/unknown/Unknown.form.js +++ b/src/components/unknown/Unknown.form.js @@ -1,9 +1,4 @@ import UnknownEditDisplay from './editForm/Unknown.edit.display'; - -/** - * Unknown Component schema. - * @returns {object} - The Unknown Component edit form. - */ export default function() { return { components: [ diff --git a/src/components/url/Url.form.js b/src/components/url/Url.form.js index 451538ebe1..4b772ba6a9 100644 --- a/src/components/url/Url.form.js +++ b/src/components/url/Url.form.js @@ -4,11 +4,6 @@ import UrlEditDisplay from './editForm/Url.edit.display'; import UrlEditData from './editForm/Url.edit.data'; import UrlEditValidation from './editForm/Url.edit.validation'; -/** - * The Edit Form function. - * @param {...any} extend - The components that extend the edit form. - * @returns {import('@formio/core').Component[]} - The edit form components. - */ export default function(...extend) { return textEditForm([ { diff --git a/src/components/well/Well.form.js b/src/components/well/Well.form.js index e5924360ff..1c7f876482 100644 --- a/src/components/well/Well.form.js +++ b/src/components/well/Well.form.js @@ -2,11 +2,6 @@ import nestedComponentForm from '../_classes/nested/NestedComponent.form'; import WellEditDisplay from './editForm/Well.edit.display'; -/** - * The Edit Form function. - * @param {...any} extend - The components that extend the edit form. - * @returns {import('@formio/core').Component[]} - The edit form components. - */ export default function(...extend) { return nestedComponentForm([ { diff --git a/src/formio.form.js b/src/formio.form.js index 787227c51f..b533354653 100644 --- a/src/formio.form.js +++ b/src/formio.form.js @@ -40,10 +40,8 @@ Formio.Components.setComponents(AllComponents); /** * Register a module - * @param {any} mod - The module object to register. This can also be a function which accepts Formio as an argument. - * @param {Function|null} [defaultFn] - The default function to call if the module does not have a known key. - * @param {any} options - Options for the module. - * @returns {void} + * @param {*} plugin + * @returns */ export function registerModule(mod, defaultFn = null, options = {}) { if (typeof mod === 'function') { @@ -105,10 +103,6 @@ export function registerModule(mod, defaultFn = null, options = {}) { } } -/** - * @param {Function|null} defaultFn - The default function to call if the module does not have a known key. - * @returns {void} - */ export function useModule(defaultFn = null) { return (plugins, options = {}) => { plugins = _.isArray(plugins) ? plugins : [plugins]; diff --git a/src/providers/Providers.js b/src/providers/Providers.js index 1fca4aa910..6e7d15c384 100644 --- a/src/providers/Providers.js +++ b/src/providers/Providers.js @@ -4,14 +4,6 @@ import address from './address'; import auth from './auth'; import storage from './storage'; - -/** - * @class Providers - * @classdesc Represents a collection of providers. - */ -/** - * Represents a collection of providers. - */ export default class Providers { static providers = { address, @@ -19,40 +11,21 @@ export default class Providers { storage, }; - /** - * Adds a provider to the collection. - * @param {string} type - The type of the provider. - * @param {string} name - The name of the provider. - * @param {Provider} provider - The provider object. - */ static addProvider(type, name, provider) { Providers.providers[type] = Providers.providers[type] || {}; Providers.providers[type][name] = provider; } - /** - * Adds multiple providers to the collection. - * @param {string} type - The type of the providers. - * @param {{ [key: string]: Provider }} providers - The collection of providers. - */ + static addProviders(type, providers) { Providers.providers[type] = _.merge(Providers.providers[type], providers); } - /** - * Retrives a provider a provider from the collection. - * @param {string} type - The type of the provider. - * @param {string} name - The name of the provider. - * @returns {Provider | void} The provider object. - */ + static getProvider(type, name) { if (Providers.providers[type] && Providers.providers[type][name]) { return Providers.providers[type][name]; } } - /** - * Retrives all providers of a given type. - * @param {string} type - The type of the providers. - * @returns {Provider[] | void} The collection of providers. - */ + static getProviders(type) { if (Providers.providers[type]) { return Providers.providers[type]; diff --git a/src/providers/address/AddressProvider.js b/src/providers/address/AddressProvider.js index 9e6988fa30..442e71a022 100644 --- a/src/providers/address/AddressProvider.js +++ b/src/providers/address/AddressProvider.js @@ -2,162 +2,68 @@ import _ from 'lodash'; import { Formio } from '../../Formio'; -/** - * @typedef {object} RequestOptions - * @property {object} params - The request parameters. - * @property {boolean} noToken - Whether to include a token in the request. - */ - -/** - * @typedef {object} Address - * @property {string} street - The street address. - * @property {string} city - The city. - * @property {string} state - The state. - * @property {string} country - The country. - * @property {string} postalCode - The postal code. - */ - -/** - * @class AddressProvider - * @classdesc Represents an address provider. - */ export class AddressProvider { - /** - * @static - * @type {string} - * @description The name of the address provider. - */ static get name() { - return 'address'; } - /** - * @static - * @type {string} - * @description The display name of the address provider. - */ static get displayName() { - return 'Address'; } - /** - * @class - * @param {object} options - The options for the address provider. - */ constructor(options = {}) { - this.beforeMergeOptions(options); this.options = _.merge({}, this.defaultOptions, options); } - /** - * @private - * @description Executes before merging the options. - */ beforeMergeOptions() { - return; } - /** - * @private - * @type {object} - * @description The default options for the address provider. - */ - get defaultOptions() { return {}; } - /** - * @private - * @type {string} - * @description The query property name. - */ get queryProperty() { return 'query'; } - - /** - * @private - * @type {string|null} - * @description The response property name. - */ get responseProperty() { return null; } - - /** - * @private - * @type {string|null} - * @description The display value property name. - */ get displayValueProperty() { return null; } - /** - * @private - * @param {object} params - The parameters to serialize. - * @returns {string} The serialized parameters. - */ serialize(params) { return _.toPairs(params).map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`).join('&'); } - /** - * @private - * @param {object} options - The request options. - * @returns {RequestOptions} The merged request options. - */ getRequestOptions(options = {}) { return _.merge({}, this.options, options); } - /** - * @private - * @param {object} _options - The request options. - * @throws {Error} Throws an error if the method is not implemented. - */ - getRequestUrl(_options = {}) { + // eslint-disable-next-line no-unused-vars + getRequestUrl(options = {}) { throw new Error('Method AddressProvider#getRequestUrl(options) is abstract.'); } - /** - * @private - * @param {object} options - The request options. - * @returns {Promise} A promise that resolves with the request result. - */ makeRequest(options = {}) { return Formio.makeStaticRequest(this.getRequestUrl(options), 'GET', null, { noToken: true, }); } - /** - * @public - * @description The search parameters for the request. - * @param {string} query - The search query. - * @param {object} options - The search options. - * @returns {Promise} A promise that resolves with the search results. - */ search(query, options = {}) { const requestOptions = this.getRequestOptions(options); const params = requestOptions.params = requestOptions.params || {}; params[this.queryProperty] = query; + return this.makeRequest(requestOptions) .then((result) => this.responseProperty ? _.get(result, this.responseProperty, []) : result); } - /** - * @public - * @param {Address} address - The address object. - * @returns {string} The display value of the address. - */ getDisplayValue(address) { return this.displayValueProperty ? _.get(address, this.displayValueProperty, '') : String(address); } diff --git a/src/providers/address/AzureAddressProvider.js b/src/providers/address/AzureAddressProvider.js index 86d83657c4..a5edb697df 100644 --- a/src/providers/address/AzureAddressProvider.js +++ b/src/providers/address/AzureAddressProvider.js @@ -1,38 +1,14 @@ import { AddressProvider } from './AddressProvider'; - -/** - * @typedef {object} AzureAddressProviderOptionsParams - * @property {string} 'api-version' - The version of the Azure Maps API. - * @property {string} typeahead - Whether to enable typeahead in the search. - * @typedef {object} AzureAddressProviderOptions - * @property {AzureAddressProviderOptionsParams} params - The parameters for the Azure Maps API request. - */ - -/** - * @class - * @augments AddressProvider - * @classdesc Represents an Azure Maps address provider. - */ export class AzureAddressProvider extends AddressProvider { - /** - * Gets the name of the address provider. - * @type {string} - */ static get name() { return 'azure'; } - /** - * Gets the display name of the address provider. - * @type {string} - */ + static get displayName() { return 'Azure Maps'; } - /** - * Gets the default options for the address provider. - * @returns {{ params: { 'api-version': string, typeahead: string } }} The default options. - */ + get defaultOptions() { return { params: { @@ -41,26 +17,15 @@ export class AzureAddressProvider extends AddressProvider { }, }; } - /** - * Gets the response property for the address provider. - * @type {string} - */ + get responseProperty() { return 'results'; } - /** - * Gets the display value property for the address provider. - * @type {string} - */ + get displayValueProperty() { return 'address.freeformAddress'; } - /** - * Gets the request URL for the address provider. - * @param {{params: any}} options - The request options. - * @returns {string} The request URL. - */ getRequestUrl(options = {}) { const { params } = options; diff --git a/src/providers/address/CustomAddressProvider.js b/src/providers/address/CustomAddressProvider.js index da685dc93b..49b3d7d87f 100644 --- a/src/providers/address/CustomAddressProvider.js +++ b/src/providers/address/CustomAddressProvider.js @@ -1,60 +1,26 @@ import { AddressProvider } from './AddressProvider'; -/** - * CustomAddressProvider class extends the AddressProvider class and provides custom functionality for address handling. - * @augments AddressProvider - */ export class CustomAddressProvider extends AddressProvider { - /** - * Returns the name of the custom address provider. - * @type {string} - */ static get name() { return 'custom'; } - /** - * Returns the display name of the custom address provider. - * @type {string} - */ static get displayName() { return 'Custom'; } - /** - * Returns the query property of the custom address provider. - * If not provided, falls back to the query property of the parent class. - * @type {string} - */ get queryProperty() { return this.options.queryProperty || super.queryProperty; } - /** - * Returns the response property of the custom address provider. - * If not provided, falls back to the response property of the parent class. - * @type {string} - */ get responseProperty() { return this.options.responseProperty || super.responseProperty; } - /** - * Returns the display value property of the custom address provider. - * If not provided, falls back to the display value property of the parent class. - * @type {string} - */ get displayValueProperty() { return this.options.displayValueProperty || super.displayValueProperty; } - /** - * Returns the request URL for the custom address provider. - * @param {object} options - The options for the request. - * @param {object} options.params - The parameters for the request. - * @param {string} options.url - The URL for the request. - * @returns {string} The request URL. - */ getRequestUrl(options = {}) { const { params, url } = options; diff --git a/src/providers/address/GoogleAddressProvider.js b/src/providers/address/GoogleAddressProvider.js index 7c34a29e24..38ec86f331 100644 --- a/src/providers/address/GoogleAddressProvider.js +++ b/src/providers/address/GoogleAddressProvider.js @@ -2,172 +2,89 @@ import { Formio } from '../../Formio'; import _ from 'lodash'; import { AddressProvider } from './AddressProvider'; -/** - * @typedef {object} AutocompleteOptions - * @property {string[]} fields - The fields to include in the autocomplete response. - * @property {object} componentRestrictions - The component restrictions for the autocomplete response. - * @property {string[]} componentRestrictions.country - The country codes to restrict the autocomplete response to. - */ - -/** - * @typedef {object} ProviderOptions - * @property {string} region - The region to restrict the autocomplete response to. - * @property {string} key - The API key for Google Maps. - * @property {AutocompleteOptions} autocompleteOptions - The options for the autocomplete functionality. - */ - -/** - * @typedef {object} Place - * @property {object} address_components - The address components of the place. - * @property {string} formatted_address - The formatted address of the place. - * @property {object} geometry - The geometry information of the place. - * @property {string} place_id - The place ID of the place. - * @property {object} plus_code - The plus code of the place. - * @property {string[]} types - The types of the place. - * @property {string} formattedPlace - The formatted place value. - */ - -/** - * @class GoogleAddressProvider - * @augments AddressProvider - */ -export class GoogleAddressProvider extends AddressProvider { - /** - * @returns {string} The name of the provider. - */ +export class GoogleAddressProvider extends AddressProvider { static get name() { return 'google'; } - - /** - * @returns {string} The display name of the provider. - */ - static get displayName() { - return 'Google Maps'; } - /** - - * @param {ProviderOptions} options - The options for the provider. - */ - constructor(options = {}) { super(options); this.setAutocompleteOptions(); + let src = 'https://maps.googleapis.com/maps/api/js?v=quarterly&libraries=places&callback=googleMapsCallback'; + if (options.params?.key) { src += `&key=${options.params.key}`; } + Formio.requireLibrary(this.getLibraryName(), 'google.maps.places', src); } - - /** - * get display value property - * @returns {string} The property to use for display value. - */ - get displayValueProperty() { return 'formattedPlace'; } - - /** - * @returns {string} The alternative property to use for display value. - */ - get alternativeDisplayValueProperty() { return 'formatted_address'; - } - /** - * @param {AutocompleteOptions} options - The autocomplete options. - */ set autocompleteOptions(options) { this._autocompleteOptions = options; } - - /** - * @returns {AutocompleteOptions} The autocomplete options. - */ get autocompleteOptions() { - return this._autocompleteOptions; } - /** - * Sets the autocomplete options based on the provider options. - - */ setAutocompleteOptions() { let options = _.get(this.options, 'params.autocompleteOptions', {}); if (!_.isObject(options)) { options = {}; } - this.addRequiredProviderOptions(options); + this.addRequiredProviderOptions(options); this.autocompleteOptions = options; } - /** - - * Converts the region to autocomplete option if it exists. - * @param {ProviderOptions} options - The provider options. - */ - beforeMergeOptions(options) { // providing support of old Google Provider option this.convertRegionToAutocompleteOption(options); } - - /** - * @returns {string} The name of the library. - */ getLibraryName() { return 'googleMaps'; } - /** - * Converts the region to autocomplete option. - * @param {ProviderOptions} options - The provider options. - */ convertRegionToAutocompleteOption(options) { - const providerOptions = options; let region = _.get(providerOptions, 'params.region', ''); + if (region && !_.has(options, 'params.autocompleteOptions')) { region = region.toUpperCase().trim(); // providing compatibility with ISO 3166-1 Alpha-2 county codes (for checking compatibility https://en.wikipedia.org/wiki/List_of_ISO_3166_country_codes) const countryCodes = { 'UK': 'GB' }; + if (countryCodes[region]) { region = countryCodes[region]; } + _.set(providerOptions, 'params.autocompleteOptions.componentRestrictions.country', [region]); } } - /** - * @returns {string[]} The required address properties. - */ getRequiredAddressProperties() { return ['address_components', 'formatted_address','geometry','place_id', 'plus_code', 'types']; } - /** - * Adds the required provider options to the options. - * @param {AutocompleteOptions} options - The autocomplete options. - */ addRequiredProviderOptions(options) { - const addressProperties = this.getRequiredAddressProperties(); + if (_.isArray(options.fields) && options.fields.length > 0 ) { options.fields.forEach(optionalField => { if (!addressProperties.some(addressProp => optionalField === addressProp)) { diff --git a/src/providers/address/NominatimAddressProvider.js b/src/providers/address/NominatimAddressProvider.js index 13c730b6bf..04a391fd56 100644 --- a/src/providers/address/NominatimAddressProvider.js +++ b/src/providers/address/NominatimAddressProvider.js @@ -1,33 +1,14 @@ import { AddressProvider } from './AddressProvider'; -/** - * @typedef {object} NominatimAddressProviderOptionsParams - * @property {{ addressdetails: string, format: string } } params - The parameters for the Nominatim API request. - */ -/** - * Represents an Nominatim address provider. - * {extends AddressProvider} - */ - export class NominatimAddressProvider extends AddressProvider { - /** - * Gets the name of the address provider. - * @type {string} - */ static get name() { return 'nominatim'; } - /** - * Gets the display name of the address provider. - * @type {string} - */ + static get displayName() { return 'OpenStreetMap Nominatim'; } - /** - * Gets the default options for the address provider. - * @returns {NominatimAddressProviderOptionsParams} The default options. - */ + get defaultOptions() { return { params: { @@ -36,25 +17,15 @@ export class NominatimAddressProvider extends AddressProvider { }, }; } - /** - * Gets the response property for the address provider. - * @type {string} - */ + get queryProperty() { return 'q'; } - /** - * Gets the display value property for the address provider. - * @returns {string} The property to use for display value. - */ + get displayValueProperty() { return 'display_name'; } - /** - * Generates the request URL for the address provider with options. - * @param {NominatimAddressProviderOptionsParams} options - The request options. - * @returns {string} The formatted Url. - */ + getRequestUrl(options = {}) { const { params } = options; diff --git a/src/providers/processor/fileProcessor.js b/src/providers/processor/fileProcessor.js index 23adcc1450..869f73151a 100644 --- a/src/providers/processor/fileProcessor.js +++ b/src/providers/processor/fileProcessor.js @@ -1,9 +1,3 @@ -/** - * Creates a file processor function. - * @param {Formio} formio - The Formio instance. - * @param {object} config - The configuration object. - * @returns {function(File, object): Promise} A function that takes a file and options, and returns a Promise that resolves with the processed file. - */ const fileProcessor = (formio, config) => (file, options) => new Promise((resolve, reject) => { const xhr = new XMLHttpRequest(); diff --git a/src/providers/storage/azure.js b/src/providers/storage/azure.js index 5476fb18a6..46fd5fbfb7 100644 --- a/src/providers/storage/azure.js +++ b/src/providers/storage/azure.js @@ -1,13 +1,5 @@ - import XHR from './xhr'; - -/** - * Azure File Services provider for file storage. - * @param {object} formio formio instance - * @returns {import('./typedefs').FileProvider} The FileProvider interface defined in index.js. - */ function azure(formio) { - return { uploadFile(file, fileName, dir, progressCallback, url, options, fileKey, groupPermissions, groupId, abortCallback) { return XHR.upload(formio, 'azure', (xhr, response) => { @@ -38,7 +30,4 @@ function azure(formio) { } azure.title = 'Azure File Services'; - - - export default azure; diff --git a/src/providers/storage/base64.js b/src/providers/storage/base64.js index 8935173e87..c5fc7ab950 100644 --- a/src/providers/storage/base64.js +++ b/src/providers/storage/base64.js @@ -1,7 +1,3 @@ -/** - * base64 File Services provider for file storage. - * @returns {import('./typedefs').FileProvider} The FileProvider interface defined in index.js. - */ function base64() { return { title: 'Base64', diff --git a/src/providers/storage/dropbox.js b/src/providers/storage/dropbox.js index 2d97cb819d..b1229fd674 100644 --- a/src/providers/storage/dropbox.js +++ b/src/providers/storage/dropbox.js @@ -1,9 +1,4 @@ import { setXhrHeaders } from './xhr'; -/** - * Dropbox provider for file storage. - * @param {object} formio formio instance - * @returns {import('./typedefs').FileProvider} The FileProvider interface defined in index.js. - */ function dropbox(formio) { return { uploadFile(file, fileName, dir, progressCallback, url, options, fileKey, groupPermissions, groupId, abortCallback) { @@ -67,5 +62,6 @@ function dropbox(formio) { } }; } + dropbox.title = 'Dropbox'; export default dropbox; diff --git a/src/providers/storage/googleDrive.js b/src/providers/storage/googleDrive.js index b97a46a8c8..655d01b5cd 100644 --- a/src/providers/storage/googleDrive.js +++ b/src/providers/storage/googleDrive.js @@ -1,11 +1,4 @@ import { setXhrHeaders } from './xhr'; - -/** - * - * Google Drive provider for file storage. - * @param {object} formio - formio instance - * @returns {import('./typedefs').FileProvider} The FileProvider interface defined in index.js. - */ function googledrive(formio) { return { uploadFile(file, fileName, dir, progressCallback, url, options, fileKey, groupPermissions, groupId, abortCallback) { diff --git a/src/providers/storage/index.js b/src/providers/storage/index.js index ace6103ab4..47ce885382 100644 --- a/src/providers/storage/index.js +++ b/src/providers/storage/index.js @@ -5,8 +5,6 @@ import url from './url'; import indexeddb from './indexeddb'; import googledrive from './googleDrive'; - - export default { base64, s3, diff --git a/src/providers/storage/indexeddb.js b/src/providers/storage/indexeddb.js index 21c0fc6aa0..0fbf206799 100644 --- a/src/providers/storage/indexeddb.js +++ b/src/providers/storage/indexeddb.js @@ -1,8 +1,4 @@ import { v4 as uuidv4 } from 'uuid'; -/** - * indexedDb provider for file storage. - * @returns {import('./typedefs').FileProvider} The FileProvider interface defined in index.js. - */ function indexeddb() { return { title: 'indexedDB', diff --git a/src/providers/storage/s3.js b/src/providers/storage/s3.js index c50e62c9a1..5afc8cc7da 100644 --- a/src/providers/storage/s3.js +++ b/src/providers/storage/s3.js @@ -7,11 +7,6 @@ const loadAbortControllerPolyfill = async() => { } }; -/** - * S3 File Services provider for file storage. - * @param {object} formio formio instance - * @returns {import('./typedefs').FileProvider} The FileProvider interface defined in index.js. - */ function s3(formio) { return { async uploadFile(file, fileName, dir, progressCallback, url, options, fileKey, groupPermissions, groupId, abortCallback, multipartOptions) { diff --git a/src/providers/storage/url.js b/src/providers/storage/url.js index c65803e90c..7722e21b66 100644 --- a/src/providers/storage/url.js +++ b/src/providers/storage/url.js @@ -1,14 +1,4 @@ -/** - * - * @param {object} formio - formio instance - * @returns {import('./typedefs').FileProvider} The FileProvider interface defined in index.js. - */ function url(formio) { - /** - * - * @param {object} options - options to set on the xhr - * @param {object} xhr - the xhr object - */ function setOptions(options, xhr) { const parsedOptions = typeof options === 'string' ? JSON.parse(options) : options; for (const prop in parsedOptions) { diff --git a/src/providers/storage/util.js b/src/providers/storage/util.js index 53665773b7..f84101648f 100644 --- a/src/providers/storage/util.js +++ b/src/providers/storage/util.js @@ -1,23 +1,3 @@ -/** - * @typedef {any[]} Args - */ - -/** - * Function to be retried - * @callback RetryFunction - * @param {...Args} args - * @returns {Promise} - */ - -/** - * Executes a function with retries in case of failure. - * @param {RetryFunction} fn - The function to be executed. - * @param {Args} args - The arguments to be passed to the function. - * @param {number} [retries] - The number of retries in case of failure. - * @param {string} [err] - The error message to be thrown after all retries have failed. - * @returns {Promise} The result of the function execution. - * @throws {Error} When all retries have failed. - */ export async function withRetries(fn, args, retries = 3, err = null) { if (!retries) { throw new Error(err); diff --git a/src/utils/builder.js b/src/utils/builder.js index e983777414..0412628032 100644 --- a/src/utils/builder.js +++ b/src/utils/builder.js @@ -3,9 +3,11 @@ import { eachComponent, uniqueKey } from './utils'; export default { /** * Appends a number to a component.key to keep it unique - * @param {import('@formio/core').Component[]} container - The container of components to uniquify against - * @param {import('@formio/core').Component} component - The Component to uniqify. - * @returns {boolean} - If the component was changed. + * + * @param {Object} form + * The components parent form. + * @param {Object} component + * The component to uniquify */ uniquify(container, component) { let changed = false; @@ -40,9 +42,6 @@ export default { return changed; }, - /** - * Additional shortcuts for the builder. - */ additionalShortcuts: { button: [ 'Enter', @@ -50,10 +49,6 @@ export default { ] }, - /** - * Returns the alpha character shortcuts. - * @returns {string[]} - An array of shortcuts of alpha characters. - */ getAlphaShortcuts() { return _.range('A'.charCodeAt(), 'Z'.charCodeAt() + 1).map((charCode) => String.fromCharCode(charCode)); }, diff --git a/src/utils/calendarUtils.js b/src/utils/calendarUtils.js index ff33374646..e3969a3e67 100644 --- a/src/utils/calendarUtils.js +++ b/src/utils/calendarUtils.js @@ -14,11 +14,12 @@ export const CALENDAR_ERROR_MESSAGES = { /** * Builds the response for checkInvalidDate. - * @param {string} message + * + * @param {String} message * The message for response. - * @param {boolean} result + * @param {Boolean} result * The boolean flag for response. - * @returns {{message: string, result: boolean}} - The response object. + * * @return {{message: string, result: boolean}} */ function buildResponse(message, result) { return { @@ -29,15 +30,16 @@ function buildResponse(message, result) { /** * Checks the value for a min date and max date. + * * @param {moment} value * The value to check. - * @param {[string]} format + * @param {[String]} format * A moment formats. * @param {Date} maxDate * The max date. * @param {Date} minDate * The min date. - * @returns {{message: string, result: boolean}} - The response object. + * * @return {{message: string, result: boolean}} */ export function lessOrGreater(value, format, maxDate, minDate) { let message = ''; @@ -69,11 +71,16 @@ export function lessOrGreater(value, format, maxDate, minDate) { /** * Checks the entered date for validity. - * @param {string} value - The value to check. - * @param {[string]} format - A moment formats. - * @param {Date} minDate - The minimum date. - * @param {Date} maxDate - The maximum date. - * @returns {{message: string, result: boolean}} - The response object. + * + * @param {String} value + * The value to check. + * @param {[String]} format + * A moment formats. + * @param {Date} maxDate + * The max date. + * @param {Date} minDate + * The min date. + * * @return {{message: string, result: boolean}} */ export function checkInvalidDate(value, format, minDate, maxDate) { const date = moment(value, format, true); diff --git a/src/utils/formUtils.js b/src/utils/formUtils.js index 30d6d1ba41..05db606af2 100644 --- a/src/utils/formUtils.js +++ b/src/utils/formUtils.js @@ -1,91 +1,621 @@ -import { Utils } from '@formio/core'; -const { - flattenComponents, - guid, - uniqueName, - MODEL_TYPES, - getModelType, - getComponentAbsolutePath, - getComponentPath, - isComponentModelType, - isComponentNestedDataType, - componentPath, - componentChildPath, - eachComponentDataAsync, - eachComponentData, - getComponentKey, - getContextualRowPath, - getContextualRowData, - componentInfo, - eachComponent, - eachComponentAsync, - getComponentData, - getComponentActualValue, - isLayoutComponent, - matchComponent, - getComponent, - searchComponents, - removeComponent, - hasCondition, - parseFloatExt, - formatAsCurrency, - escapeRegExCharacters, - getValue, - getStrings, - generateFormChange, - applyFormChanges, - findComponent, - getEmptyValue, - isComponentDataEmpty -} = Utils; +import get from 'lodash/get'; +import set from 'lodash/set'; +import has from 'lodash/has'; +import clone from 'lodash/clone'; +import forOwn from 'lodash/forOwn'; +import isString from 'lodash/isString'; +import isNaN from 'lodash/isNaN'; +import isNil from 'lodash/isNil'; +import isPlainObject from 'lodash/isPlainObject'; +import round from 'lodash/round'; +import chunk from 'lodash/chunk'; +import pad from 'lodash/pad'; +import { compare, applyPatch } from 'fast-json-patch'; +import _ from 'lodash'; +import { fastCloneDeep } from './utils'; + +/** + * Determine if a component is a layout component or not. + * + * @param {Object} component + * The component to check. + * + * @returns {Boolean} + * Whether or not the component is a layout component. + */ +export function isLayoutComponent(component) { + return Boolean( + (component.columns && Array.isArray(component.columns)) || + (component.rows && Array.isArray(component.rows)) || + (component.components && Array.isArray(component.components)) + ); +} + +/** + * Iterate through each component within a form. + * + * @param {Object} components + * The components to iterate. + * @param {Function} fn + * The iteration function to invoke for each component. + * @param {Boolean} includeAll + * Whether or not to include layout components. + * @param {String} path + * The current data path of the element. Example: data.user.firstName + * @param {Object} parent + * The parent object. + */ +export function eachComponent(components, fn, includeAll, path, parent, inRecursion) { + if (!components) return; + path = path || ''; + if (inRecursion) { + if (components.noRecurse) { + delete components.noRecurse; + return; + } + components.noRecurse = true; + } + components.forEach((component) => { + if (!component) { + return; + } + const hasColumns = component.columns && Array.isArray(component.columns); + const hasRows = component.rows && Array.isArray(component.rows); + const hasComps = component.components && Array.isArray(component.components); + let noRecurse = false; + const newPath = component.key ? (path ? (`${path}.${component.key}`) : component.key) : ''; + + // Keep track of parent references. + if (parent) { + // Ensure we don't create infinite JSON structures. + component.parent = clone(parent); + delete component.parent.components; + delete component.parent.componentMap; + delete component.parent.columns; + delete component.parent.rows; + } + + // there's no need to add other layout components here because we expect that those would either have columns, rows or components + const layoutTypes = ['htmlelement', 'content']; + const isLayoutComponent = hasColumns || hasRows || (hasComps && !component.input) || layoutTypes.indexOf(component.type) > -1; + if (includeAll || component.tree || !isLayoutComponent) { + noRecurse = fn(component, newPath, components); + } + + const subPath = () => { + if ( + component.key && + !['panel', 'table', 'well', 'columns', 'fieldset', 'tabs', 'form'].includes(component.type) && + ( + ['datagrid', 'container', 'editgrid', 'address', 'dynamicWizard', 'datatable', 'tagpad'].includes(component.type) || + component.tree + ) + ) { + return newPath; + } + else if ( + component.key && + component.type === 'form' + ) { + return `${newPath}.data`; + } + return path; + }; + + if (!noRecurse) { + if (hasColumns) { + component.columns.forEach((column) => + eachComponent(column.components, fn, includeAll, subPath(), parent ? component : null), true); + } + + else if (hasRows) { + component.rows.forEach((row) => { + if (Array.isArray(row)) { + row.forEach((column) => + eachComponent(column.components, fn, includeAll, subPath(), parent ? component : null), true); + } + }); + } + + else if (hasComps) { + eachComponent(component.components, fn, includeAll, subPath(), parent ? component : null, true); + } + } + }); + if (components.noRecurse) { + delete components.noRecurse; + } +} + +/** + * Matches if a component matches the query. + * + * @param component + * @param query + * @return {boolean} + */ +export function matchComponent(component, query) { + if (isString(query)) { + return (component.key === query) || (component.path === query); + } + else { + let matches = false; + forOwn(query, (value, key) => { + matches = (get(component, key) === value); + if (!matches) { + return false; + } + }); + return matches; + } +} + +/** + * Get a component by its key + * + * @param {Object} components + * The components to iterate. + * @param {String|Object} key + * The key of the component to get, or a query of the component to search. + * + * @returns {Object} + * The component that matches the given key, or undefined if not found. + */ +export function getComponent(components, key, includeAll) { + let result; + eachComponent(components, (component, path) => { + if ((path === key) || (component.path === key)) { + result = component; + return true; + } + }, includeAll); + return result; +} + +/** + * Finds a component provided a query of properties of that component. + * + * @param components + * @param query + * @return {*} + */ +export function searchComponents(components, query) { + const results = []; + eachComponent(components, (component) => { + if (matchComponent(component, query)) { + results.push(component); + } + }, true); + return results; +} /** * Deprecated version of findComponents. Renamed to searchComponents. - * @param {import('@formio/core').Component[]} components - The components to find components within. - * @param {object} query - The query to use when searching for the components. - * @returns {import('@formio/core').Component[]} - The result of the component that is found. + * + * @param components + * @param query + * @returns {*} */ export function findComponents(components, query) { console.warn('formio.js/utils findComponents is deprecated. Use searchComponents instead.'); return searchComponents(components, query); } -export { - flattenComponents, - guid, - uniqueName, - MODEL_TYPES, - getModelType, - getComponentAbsolutePath, - getComponentPath, - isComponentModelType, - isComponentNestedDataType, - componentPath, - componentChildPath, - eachComponentDataAsync, - eachComponentData, - getComponentKey, - getContextualRowPath, - getContextualRowData, - componentInfo, - eachComponent, - eachComponentAsync, - getComponentData, - getComponentActualValue, - isLayoutComponent, - matchComponent, - getComponent, - searchComponents, - removeComponent, - hasCondition, - parseFloatExt, - formatAsCurrency, - escapeRegExCharacters, - getValue, - getStrings, - generateFormChange, - applyFormChanges, - findComponent, - getEmptyValue, - isComponentDataEmpty -}; +/** + * This function will find a component in a form and return the component AND THE PATH to the component in the form. + * Path to the component is stored as an array of nested components and their indexes.The Path is being filled recursively + * when you iterating through the nested structure. + * If the component is not found the callback won't be called and function won't return anything. + * + * @param components + * @param key + * @param fn + * @param path + * @returns {*} + */ +export function findComponent(components, key, path, fn) { + if (!components) return; + path = path || []; + + if (!key) { + return fn(components); + } + + components.forEach(function(component, index) { + var newPath = path.slice(); + // Add an index of the component it iterates through in nested structure + newPath.push(index); + if (!component) return; + + if (component.hasOwnProperty('columns') && Array.isArray(component.columns)) { + newPath.push('columns'); + component.columns.forEach(function(column, index) { + var colPath = newPath.slice(); + colPath.push(index); + colPath.push('components'); + findComponent(column.components, key, colPath, fn); + }); + } + + if (component.hasOwnProperty('rows') && Array.isArray(component.rows)) { + newPath.push('rows'); + component.rows.forEach(function(row, index) { + var rowPath = newPath.slice(); + rowPath.push(index); + row.forEach(function(column, index) { + var colPath = rowPath.slice(); + colPath.push(index); + colPath.push('components'); + findComponent(column.components, key, colPath, fn); + }); + }); + } + + if (component.hasOwnProperty('components') && Array.isArray(component.components)) { + newPath.push('components'); + findComponent(component.components, key, newPath, fn); + } + + if (component.key === key) { + //Final callback if the component is found + fn(component, newPath, components); + } + }); +} + +/** + * Remove a component by path. + * + * @param components + * @param path + */ +export function removeComponent(components, path) { + // Using _.unset() leave a null value. Use Array splice instead. + var index = path.pop(); + if (path.length !== 0) { + components = get(components, path); + } + components.splice(index, 1); +} + +export function generateFormChange(type, data) { + let change; + switch (type) { + case 'add': + change = { + op: 'add', + key: data.component.key, + container: data.parent.key, // Parent component + path: data.path, // Path to container within parent component. + index: data.index, // Index of component in parent container. + component: data.component + }; + break; + case 'edit': + change = { + op: 'edit', + key: data.originalComponent.key, + patches: compare(data.originalComponent, data.component) + }; + + // Don't save if nothing changed. + if (!change.patches.length) { + change = null; + } + break; + case 'remove': + change = { + op: 'remove', + key: data.component.key, + }; + break; + } + + return change; +} + +export function applyFormChanges(form, changes) { + const failed = []; + changes.forEach(function(change) { + var found = false; + switch (change.op) { + case 'add': + var newComponent = change.component; + + // Find the container to set the component in. + findComponent(form.components, change.container, null, function(parent) { + if (!change.container) { + parent = form; + } + + // A move will first run an add so remove any existing components with matching key before inserting. + findComponent(form.components, change.key, null, function(component, path) { + // If found, use the existing component. (If someone else edited it, the changes would be here) + newComponent = component; + removeComponent(form.components, path); + }); + + found = true; + var container = get(parent, change.path); + container.splice(change.index, 0, newComponent); + }); + break; + case 'remove': + findComponent(form.components, change.key, null, function(component, path) { + found = true; + const oldComponent = get(form.components, path); + if (oldComponent.key !== component.key) { + path.pop(); + } + removeComponent(form.components, path); + }); + break; + case 'edit': + findComponent(form.components, change.key, null, function(component, path) { + found = true; + try { + const oldComponent = get(form.components, path); + const newComponent = applyPatch(component, change.patches).newDocument; + + if (oldComponent.key !== newComponent.key) { + path.pop(); + } + + set(form.components, path, newComponent); + } + catch (err) { + failed.push(change); + } + }); + break; + case 'move': + break; + } + if (!found) { + failed.push(change); + } + }); + + return { + form, + failed + }; +} + +/** + * Flatten the form components for data manipulation. + * + * @param {Object} components + * The components to iterate. + * @param {Boolean} includeAll + * Whether or not to include layout components. + * + * @returns {Object} + * The flattened components map. + */ +export function flattenComponents(components, includeAll = false) { + const flattened = {}; + eachComponent(components, (component, path) => { + flattened[path] = component; + }, includeAll); + return flattened; +} + +/** + * Returns if this component has a conditional statement. + * + * @param component - The component JSON schema. + * + * @returns {boolean} - TRUE - This component has a conditional, FALSE - No conditional provided. + */ +export function hasCondition(component) { + return Boolean( + (component.customConditional) || + (component.conditional && (component.conditional.when || + (_.some(component.conditional.conditions || [], (condition => condition.component && condition.operator))) || + component.conditional.json || + component.conditional.condition + )) + ); +} + +/** + * Extension of standard #parseFloat(value) function, that also clears input string. + * + * @param {any} value + * The value to parse. + * + * @returns {Number} + * Parsed value. + */ +export function parseFloatExt(value) { + return parseFloat(isString(value) + ? value.replace(/[^\de.+-]/gi, '') + : value); +} + +/** + * Formats provided value in way how Currency component uses it. + * + * @param {any} value + * The value to format. + * + * @returns {String} + * Value formatted for Currency component. + */ +export function formatAsCurrency(value) { + const parsedValue = parseFloatExt(value); + + if (isNaN(parsedValue)) { + return ''; + } + + const parts = round(parsedValue, 2) + .toString() + .split('.'); + parts[0] = chunk(Array.from(parts[0]).reverse(), 3) + .reverse() + .map((part) => part + .reverse() + .join('')) + .join(','); + parts[1] = pad(parts[1], 2, '0'); + return parts.join('.'); +} + +/** + * Escapes RegEx characters in provided String value. + * + * @param {String} value + * String for escaping RegEx characters. + * @returns {string} + * String with escaped RegEx characters. + */ +export function escapeRegExCharacters(value) { + return value.replace(/[-[\]/{}()*+?.\\^$|]/g, '\\$&'); +} + +/** + * Get the value for a component key, in the given submission. + * + * @param {Object} submission + * A submission object to search. + * @param {String} key + * A for components API key to search for. + */ +export function getValue(submission, key) { + const search = (data) => { + if (isPlainObject(data)) { + if (has(data, key)) { + return _.get(data, key); + } + + let value = null; + + forOwn(data, (prop) => { + const result = search(prop); + if (!isNil(result)) { + value = result; + return false; + } + }); + + return value; + } + else { + return null; + } + }; + + return search(submission.data); +} + +/** + * Iterate over all components in a form and get string values for translation. + * @param form + */ +export function getStrings(form) { + const properties = ['label', 'title', 'legend', 'tooltip', 'description', 'placeholder', 'prefix', 'suffix', 'errorLabel', 'content', 'html']; + const strings = []; + eachComponent(form.components, component => { + properties.forEach(property => { + if (component.hasOwnProperty(property) && component[property]) { + strings.push({ + key: component.key, + type: component.type, + property, + string: component[property] + }); + } + }); + if ((!component.dataSrc || component.dataSrc === 'values') && component.hasOwnProperty('values') && Array.isArray(component.values) && component.values.length) { + component.values.forEach((value, index) => { + strings.push({ + key: component.key, + property: `value[${index}].label`, + string: component.values[index].label + }); + }); + } + + // Hard coded values from Day component + if (component.type === 'day') { + [ + 'day', + 'month', + 'year', + 'Day', + 'Month', + 'Year', + 'january', + 'february', + 'march', + 'april', + 'may', + 'june', + 'july', + 'august', + 'september', + 'october', + 'november', + 'december' + ].forEach(string => { + strings.push({ + key: component.key, + property: 'day', + string, + }); + }); + + if (component.fields.day.placeholder) { + strings.push({ + key: component.key, + property: 'fields.day.placeholder', + string: component.fields.day.placeholder, + }); + } + + if (component.fields.month.placeholder) { + strings.push({ + key: component.key, + property: 'fields.month.placeholder', + string: component.fields.month.placeholder, + }); + } + + if (component.fields.year.placeholder) { + strings.push({ + key: component.key, + property: 'fields.year.placeholder', + string: component.fields.year.placeholder, + }); + } + } + + if (component.type === 'editgrid') { + const string = component.addAnother || 'Add Another'; + if (component.addAnother) { + strings.push({ + key: component.key, + property: 'addAnother', + string, + }); + } + } + + if (component.type === 'select') { + [ + 'loading...', + 'Type to search' + ].forEach(string => { + strings.push({ + key: component.key, + property: 'select', + string, + }); + }); + } + }, true); + + return strings; +} diff --git a/src/utils/utils.js b/src/utils/utils.js index 414c6c3b67..c06750eb3f 100644 --- a/src/utils/utils.js +++ b/src/utils/utils.js @@ -38,10 +38,6 @@ jsonLogic.add_operation('relativeMaxDate', (relativeMaxDate) => { export { jsonLogic, ConditionOperators }; export * as moment from 'moment-timezone/moment-timezone'; -/** - * Sets the path to the component and parent schema. - * @param {import('@formio/core').Component} component - The component to set the path for. - */ function setPathToComponentAndPerentSchema(component) { component.path = getComponentPath(component); const dataParent = getDataParentComponent(component); @@ -52,11 +48,10 @@ function setPathToComponentAndPerentSchema(component) { /** * Evaluate a method. - * @param {Function|string|object} func - The function to evaluate. - * @param {*} args - A map of arguments to pass to the function. - * @param {string} ret - The name of the "return" variable in the script. - * @param {boolean} tokenize - True if the script should be interpolated before being executed. - * @returns {*} - The result of the evaluation. + * + * @param func + * @param args + * @return {*} */ export function evaluate(func, args, ret, tokenize) { let returnVal = null; @@ -122,19 +117,16 @@ export function evaluate(func, args, ret, tokenize) { return returnVal; } -/** - * Returns a random compoennt ID. - * @returns {string} - A random component ID. - */ export function getRandomComponentId() { return `e${Math.random().toString(36).substring(7)}`; } /** * Get a property value of an element. - * @param {CSSStyleDeclaration} style - The style element to get the property value from. - * @param {string} prop - The property to get the value for. - * @returns {number} - The value of the property. + * + * @param style + * @param prop + * @return {number} */ export function getPropertyValue(style, prop) { let value = style.getPropertyValue(prop); @@ -144,8 +136,9 @@ export function getPropertyValue(style, prop) { /** * Get an elements bounding rectagle. - * @param {HTMLElement} element - A DOM element to get the bounding rectangle for. - * @returns {{x: number, y: number, width: number, height: number}} - The bounding rectangle. + * + * @param element + * @return {{x: string, y: string, width: string, height: string}} */ export function getElementRect(element) { const style = window.getComputedStyle(element, null); @@ -159,8 +152,9 @@ export function getElementRect(element) { /** * Determines the boolean value of a setting. - * @param {string|boolean} value - A string or boolean value to convert to boolean. - * @returns {boolean} - The boolean value of the setting. + * + * @param value + * @return {boolean} */ export function boolValue(value) { if (_.isBoolean(value)) { @@ -176,18 +170,22 @@ export function boolValue(value) { /** * Check to see if an ID is a mongoID. - * @param {string} text - The text to check if it is a mongoID. - * @returns {boolean} - TRUE if the text is a mongoID; FALSE otherwise. + * @param text + * @return {Array|{index: number, input: string}|Boolean|*} */ export function isMongoId(text) { - return !!text.toString().match(/^[0-9a-fA-F]{24}$/); + return text.toString().match(/^[0-9a-fA-F]{24}$/); } /** * Checks the calculated value for a provided component and data. - * @param {import('@formio/core').Component} component - The component to check for the calculated value. - * @param {import('@formio/core').Submission} submission - A submission object. - * @param {*} rowData - The contextual row data for the component. + * + * @param {Object} component + * The component to check for the calculated value. + * @param {Object} submission + * A submission object. + * @param data + * The full submission data. */ export function checkCalculated(component, submission, rowData) { // Process calculated value stuff if present. @@ -203,13 +201,14 @@ export function checkCalculated(component, submission, rowData) { } /** - * Check if a simple conditional evaluates to true. - * @param {import('@formio/core').Component} component - The component to check for the conditional. - * @param {import('@formio/core').SimpleConditional} condition - The condition to check. - * @param {*} row - The row data for the component. - * @param {*} data - The full submission data. - * @param {import('../../src/components/_classes/component/Component').Component} instance - The instance of the component. - * @returns {boolean} - TRUE if the condition is true; FALSE otherwise. + * Check if a simple conditional evaluates to true. + * + * @param condition + * @param condition + * @param row + * @param data + * @param instance + * @returns {boolean} */ export function checkSimpleConditional(component, condition, row, data, instance) { if (condition.when) { @@ -263,13 +262,6 @@ export function checkCalculated(component, submission, rowData) { } } -/** - * Returns a components normalized value. - * @param {string} compPath - The full path to the component. - * @param {*} data - The data object to get the value from. - * @param {*} row - The contextual row data for the component. - * @returns {*} - The normalized value of the component. - */ export function getComponentActualValue(compPath, data, row) { let value = null; @@ -288,15 +280,12 @@ export function getComponentActualValue(compPath, data, row) { /** * Check custom javascript conditional. - * @param {import('@formio/core').Component} component - The component to check for the conditional. - * @param {string} custom - The custom conditional string to evaluate. - * @param {*} row - The row data for the component. - * @param {*} data - The full submission data. - * @param {import('@formio/core').Form} form - The form object. - * @param {string} variable - The variable name for the result of the custom conditional. - * @param {*} onError - A custom return if there is an error or the value is null from the evaluation. - * @param {import('../../src/components/_classes/component/Component').Component} instance - The component instance. - * @returns {*} - The result of the evaulation. + * + * @param component + * @param custom + * @param row + * @param data + * @returns {*} */ export function checkCustomConditional(component, custom, row, data, form, variable, onError, instance) { if (typeof custom === 'string') { @@ -311,16 +300,6 @@ export function checkCustomConditional(component, custom, row, data, form, varia return value; } -/** - * Check a component for JSON conditionals. - * @param {import('@formio/core').Component} component - The component - * @param {import('@formio/core').JSONConditional} json - The json conditional to check. - * @param {*} row - The contextual row data for the component. - * @param {*} data - The full submission data. - * @param {import('@formio/core').Form} form - The Form JSON of the form. - * @param {*} onError - Custom return value if there is an error. - * @returns {boolean} - TRUE if the condition is true; FALSE otherwise. - */ export function checkJsonConditional(component, json, row, data, form, onError) { try { return jsonLogic.apply(json, { @@ -336,14 +315,6 @@ export function checkJsonConditional(component, json, row, data, form, onError) } } -/** - * Returns the contextual row data for a component. - * @param {import('@formio/core').Component} component - The component to get the row data for. - * @param {*} row - The row data for the component. - * @param {import('../../src/components/_classes/component/Component').Component} instance - The component instance. - * @param {*} conditional - The component conditional. - * @returns {*} - The contextual row data for the component. - */ function getRow(component, row, instance, conditional) { const condition = conditional || component.conditional; // If no component's instance passed (happens only in 6.x server), calculate its path based on the schema @@ -368,12 +339,15 @@ function getRow(component, row, instance, conditional) { /** * Checks the conditions for a provided component and data. - * @param {import('@formio/core').Component} component - The component to check for the condition. - * @param {*} row - The data within a row - * @param {*} data - The full submission data. - * @param {import('@formio/core').Form} form - The form object. - * @param {import('../../src/components/_classes/component/Component').Component} instance - The component instance. - * @returns {boolean} - TRUE if the condition is true; FALSE otherwise. + * + * @param component + * The component to check for the condition. + * @param row + * The data within a row + * @param data + * The full submission data. + * + * @returns {boolean} */ export function checkCondition(component, row, data, form, instance) { const { customConditional, conditional } = component; @@ -394,13 +368,12 @@ export function checkCondition(component, row, data, form, instance) { /** * Test a trigger on a component. - * @param {import('@formio/core').Component} component - The component to test the trigger against. - * @param {import('@formio/core').LogicTrigger} trigger - The trigger configuration. - * @param {import('@formio/core').DataObject} row - The contextual row data. - * @param {import('@formio/core').DataObject} data - The root data object. - * @param {import('@formio/core').Form} form - The form object. - * @param {any} instance - The component that is performing the trigger. - * @returns {boolean} - TRUE if the trigger should fire; FALSE otherwise. + * + * @param component + * @param action + * @param data + * @param row + * @returns {mixed} */ export function checkTrigger(component, trigger, row, data, form, instance) { // If trigger is empty, don't fire it @@ -421,16 +394,6 @@ export function checkTrigger(component, trigger, row, data, form, instance) { return false; } -/** - * Sets a property on a component via an executed Logic action. - * @param {import('@formio/core').Component} component - The component to set the property on. - * @param {import('@formio/core').LogicAction} action - The action to perform on the component. - * @param {string} result - The name of the variable in the evaulation to use as the result. - * @param {import('@formio/core').DataObject} row - The contextual row data. - * @param {import('@formio/core').DataObject} data - The full submission data. - * @param {any} instance - The component instance. - * @returns {import('@formio/core').Component} - The modified component. - */ export function setActionProperty(component, action, result, row, data, instance) { const property = action.property.value; @@ -471,8 +434,8 @@ export function setActionProperty(component, action, result, row, data, instance /** * Unescape HTML characters like <, >, & and etc. - * @param {string} str - The string to unescape. - * @returns {string} - The unescaped string. + * @param str + * @returns {string} */ export function unescapeHTML(str) { if (typeof window === 'undefined' || !('DOMParser' in window)) { @@ -485,10 +448,11 @@ export function unescapeHTML(str) { /** * Make HTML element from string - * @param {string} str - The string to convert to an HTML element. - * @param {string} selector - The selector to use to get the element once it is created. - * @returns {HTMLElement} - The HTML element that was created. + * @param str + * @param selector + * @returns {HTMLElement} */ + export function convertStringToHTMLElement(str, selector) { const doc = new window.DOMParser().parseFromString(str, 'text/html'); return doc.body.querySelector(selector); @@ -496,10 +460,10 @@ export function convertStringToHTMLElement(str, selector) { /** * Make a filename guaranteed to be unique. - * @param {string} name - The original name of the file. - * @param {string} template - The template to use for the unique name. - * @param {object} evalContext - The context to use for the evaluation. - * @returns {string} - A unique filename. + * @param name + * @param template + * @param evalContext + * @returns {string} */ export function uniqueName(name, template, evalContext) { template = template || '{{fileName}}-{{guid}}'; @@ -523,10 +487,6 @@ export function uniqueName(name, template, evalContext) { return uniqueName; } -/** - * Returns a GUID - * @returns {string} - A GUID. - */ export function guid() { return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => { const r = Math.random()*16|0; @@ -539,8 +499,9 @@ export function guid() { /** * Return a translated date setting. - * @param {string|Date} date - The date to translate. - * @returns {(null|Date)} - The translated date. + * + * @param date + * @return {(null|Date)} */ export function getDateSetting(date) { if (_.isNil(date) || _.isNaN(date) || date === '') { @@ -588,18 +549,14 @@ export function getDateSetting(date) { return dateSetting.toDate(); } -/** - * Returns true if the date is a valid date. False otherwise. - * @param {Date|string} date - The date to check for validity. - * @returns {boolean} - TRUE if the date is valid; FALSE otherwise. - */ export function isValidDate(date) { return _.isDate(date) && !_.isNaN(date.getDate()); } /** * Get the current timezone string. - * @returns {string} - The current timezone. + * + * @return {string} */ export function currentTimezone() { if (moment.currentTimezone) { @@ -611,9 +568,10 @@ export function currentTimezone() { /** * Get an offset date provided a date object and timezone object. - * @param {Date} date - The date to offset. - * @param {string} timezone - The timezone to offset the date to. - * @returns {Date} - The offset date. + * + * @param date + * @param timezone + * @return {Date} */ export function offsetDate(date, timezone) { if (timezone === 'UTC') { @@ -631,7 +589,8 @@ export function offsetDate(date, timezone) { /** * Returns if the zones are loaded. - * @returns {boolean} - TRUE if the zones are loaded; FALSE otherwise. + * + * @return {boolean} */ export function zonesLoaded() { return moment.zonesLoaded; @@ -639,8 +598,9 @@ export function zonesLoaded() { /** * Returns if we should load the zones. - * @param {string} timezone - The timezone to check if we should load the zones. - * @returns {boolean} - TRUE if we should load the zones; FALSE otherwise. + * + * @param timezone + * @return {boolean} */ export function shouldLoadZones(timezone) { if (timezone === currentTimezone() || timezone === 'UTC') { @@ -651,9 +611,8 @@ export function shouldLoadZones(timezone) { /** * Externally load the timezone data. - * @param {string} url - The URL to load the timezone data from. - * @param {string} timezone - The timezone to load. - * @returns {Promise | *} - Resolves when the zones for this timezone are loaded. + * + * @return {Promise | *} */ export function loadZones(url, timezone) { if (timezone && !shouldLoadZones(timezone)) { @@ -680,10 +639,11 @@ export function loadZones(url, timezone) { /** * Get the moment date object for translating dates with timezones. - * @param {string|Date} value - The value to convert into a moment date. - * @param {string} format - The format to convert the date to. - * @param {string} timezone - The timezone to convert the date to. - * @returns {Date} - The moment date object. + * + * @param value + * @param format + * @param timezone + * @return {*} */ export function momentDate(value, format, timezone) { const momentDate = moment(value); @@ -701,12 +661,11 @@ export function momentDate(value, format, timezone) { /** * Format a date provided a value, format, and timezone object. - * @param {string} timezonesUrl - The URL to load the timezone data from. - * @param {string|Date} value - The value to format. - * @param {string} format - The format to format the date to. - * @param {string} timezone - The timezone to format the date to. - * @param {string} flatPickrInputFormat - The format to use for flatpickr input. - * @returns {string} - The formatted date. + * + * @param value + * @param format + * @param timezone + * @return {string} */ export function formatDate(timezonesUrl, value, format, timezone, flatPickrInputFormat) { const momentDate = moment(value, flatPickrInputFormat || undefined); @@ -742,12 +701,12 @@ export function formatDate(timezonesUrl, value, format, timezone, flatPickrInput /** * Pass a format function to format within a timezone. - * @param {string} timezonesUrl - The URL to load the timezone data from. - * @param {Function} formatFn - The format function to use. - * @param {Date|string} date - The date to format. - * @param {string} format - The format to format the date to. - * @param {string} timezone - The timezone to format the date to. - * @returns {string} - The formatted date. + * + * @param formatFn + * @param date + * @param format + * @param timezone + * @return {string} */ export function formatOffset(timezonesUrl, formatFn, date, format, timezone) { if (timezone === currentTimezone()) { @@ -768,11 +727,6 @@ export function formatOffset(timezonesUrl, formatFn, date, format, timezone) { } } -/** - * Returns the local date format information. - * @param {Intl.LocalesArgument} locale - The locale to get the date format for. - * @returns {object} - The local date format information. - */ export function getLocaleDateFormatInfo(locale) { const formatInfo = {}; @@ -787,8 +741,8 @@ export function getLocaleDateFormatInfo(locale) { /** * Convert the format from the angular-datepicker module to flatpickr format. - * @param {string} format - The format to convert. - * @returns {string} - The converted format. + * @param format + * @return {string} */ export function convertFormatToFlatpickr(format) { return format @@ -824,8 +778,8 @@ export function convertFormatToFlatpickr(format) { /** * Convert the format from the angular-datepicker module to moment format. - * @param {string} format - The format to convert. - * @returns {string} - The converted format. + * @param format + * @return {string} */ export function convertFormatToMoment(format) { return format @@ -841,11 +795,6 @@ export function convertFormatToMoment(format) { .replace(/U/g, 'X'); } -/** - * Convert the format from the angular-datepicker module to mask format. - * @param {string} format - The format to convert. - * @returns {string} - The converted format. - */ export function convertFormatToMask(format) { return format // Long month replacement. @@ -905,13 +854,6 @@ export function getInputMask(mask, placeholderChar) { return maskArray; } -/** - * Unmasks a value using the provided mask and placeholder characters. - * @param {string} value - The value to unmask. - * @param {string} mask - The mask to use for unmasking. - * @param {string} placeholderChar - The placeholder character to use for unmasking. - * @returns {string} - The unmasked value. - */ export function unmaskValue(value, mask, placeholderChar) { if (!mask || !value || value.length > mask.length) { return value; @@ -933,12 +875,6 @@ export function unmaskValue(value, mask, placeholderChar) { return unmaskedValue; } -/** - * Returns true if the value matches the input mask format. - * @param {string} value - The value to check. - * @param {string} inputMask - The input mask to check against. - * @returns {boolean} - TRUE if the value matches the input mask; FALSE otherwise. - */ export function matchInputMask(value, inputMask) { if (!inputMask) { return true; @@ -961,11 +897,6 @@ export function matchInputMask(value, inputMask) { return true; } -/** - * Returns the number separators (i.e. 1,000) for the provided language. - * @param {string} lang - The language code to get the number separators for. - * @returns {{delimiter: string, decimalSeparator: string}} - The number separators. - */ export function getNumberSeparators(lang = 'en') { const formattedNumberString = (12345.6789).toLocaleString(lang); const delimeters = formattedNumberString.match(/..(.)...(.)../); @@ -981,12 +912,6 @@ export function getNumberSeparators(lang = 'en') { }; } -/** - * Returns the number for the maximum amount of decimal places for a number. - * @param {import('@formio/core').Component} component - The component to check for decimal limits. - * @param {number} defaultLimit - The default limit to use if none is provided in the component. - * @returns {number} - The number of decimal places allowed. - */ export function getNumberDecimalLimit(component, defaultLimit) { if (_.has(component, 'decimalLimit')) { return _.get(component, 'decimalLimit'); @@ -1005,15 +930,6 @@ export function getNumberDecimalLimit(component, defaultLimit) { return decimalLimit; } -/** - * Returns the currency affixes for a specific language. - * @param {object} arg0 - The arguments object. - * @param {string} arg0.currency - The currency code to get the affixes for. - * @param {number} arg0.decimalLimit - The number of decimal places to use. - * @param {string} arg0.decimalSeparator - The decimal separator to use. - * @param {string} arg0.lang - The language code to use. - * @returns {{prefix: string, suffix: string}} - The currency affixes. - */ export function getCurrencyAffixes({ currency, decimalLimit, @@ -1041,9 +957,10 @@ export function getCurrencyAffixes({ /** * Fetch the field data provided a component. - * @param {import('@formio/core').DataObject} data - The data object to fetch the field data from. - * @param {import('@formio/core').Component} component - The component to fetch the field data for. - * @returns {*} - The field data. + * + * @param data + * @param component + * @return {*} */ export function fieldData(data, component) { if (!data) { @@ -1096,25 +1013,18 @@ export function fieldData(data, component) { /** * Delays function execution with possibility to execute function synchronously or cancel it. - * @param {Function} fn - Function to delay - * @param {number} delay - Delay time - * @param {...any} args - Arguments to pass to the function - * @returns {*} - Function to cancel the delay + * + * @param fn Function to delay + * @param delay Delay time + * @return {*} */ export function delay(fn, delay = 0, ...args) { const timer = setTimeout(fn, delay, ...args); - /** - * - */ function cancel() { clearTimeout(timer); } - /** - * Execute the function early. - * @returns {*} - The result of the function. - */ function earlyCall() { cancel(); return fn(...args); @@ -1128,9 +1038,11 @@ export function delay(fn, delay = 0, ...args) { /** * Iterate the given key to make it unique. - * @param {string} key + * + * @param {String} key * Modify the component key to be unique. - * @returns {string} + * + * @returns {String} * The new component key. */ export function iterateKey(key) { @@ -1145,9 +1057,10 @@ export function iterateKey(key) { /** * Determines a unique key within a map provided the base key. - * @param {Record} map - The map to check for uniqueness. - * @param {string} base - The base path of the key. - * @returns {string} - The unique key. + * + * @param map + * @param base + * @return {*} */ export function uniqueKey(map, base) { let newKey = base; @@ -1159,9 +1072,8 @@ export function uniqueKey(map, base) { /** * Determines the major version number of bootstrap. - * @param {object} options - The options to check for bootstrap version. - * @param {string} options.bootstrap - The bootstrap version to use. - * @returns {number} - The bootstrap version. + * + * @return {number} */ export function bootstrapVersion(options) { if (options.bootstrap) { @@ -1179,8 +1091,9 @@ export function bootstrapVersion(options) { /** * Retrun provided argument. * If argument is a function, returns the result of a function call. - * @param {Function|any} e - The argument to check if a function and call if so. - * @returns {any} - Either the result of the function call (e) or e if it is not a function. + * @param {*} e; + * + * @return {*} */ export function unfold(e) { if (typeof e === 'function') { @@ -1192,35 +1105,30 @@ export function unfold(e) { /** * Map values through unfold and return first non-nil value. - * @param {Array} collection - The collection to map through unfold.; - * @returns {T} - The first non-nil value. + * @param {Array} collection; + * + * @return {T} */ export const firstNonNil = _.flow([ _.partialRight(_.map, unfold), _.partialRight(_.find, v => !_.isUndefined(v)) ]); -/** - * Create enclosed state. Returns functions to getting and cycling between states. +/* + * Create enclosed state. + * Returns functions to getting and cycling between states. * @param {*} a - initial state. * @param {*} b - next state. - * @returns {Functions[]} -- [get, toggle]; + * @return {Functions[]} -- [get, toggle]; */ export function withSwitch(a, b) { let state = a; let next = b; - /** - * Returns the state of the switch. - * @returns {*} - The current state. - */ function get() { return state; } - /** - * Toggles the state of the switch. - */ function toggle() { const prev = state; state = next; @@ -1230,14 +1138,6 @@ export function withSwitch(a, b) { return [get, toggle]; } -/** - * Create a function that will call the provided function only the provided limit. - * @param {Function} callback - The callback to call. - * @param {object} options - The options to use. - * @param {number} options.limit - The limit to call the callback. - * @param {number} options.delay - The delay to wait before resetting the call count. - * @returns {Function} - The function that will call the callback only the provided limit. - */ export function observeOverload(callback, options = {}) { const { limit = 50, delay = 500 } = options; let callCount = 0; @@ -1263,13 +1163,6 @@ export function observeOverload(callback, options = {}) { }; } -/** - * Returns the components that are provided within an evaluation context. - * @param {any} context - The evaluation context to get the components from. - * @param {boolean} excludeNested - Exclude nested components. - * @param {Array} excludedTypes - The types of components to exclude. - * @returns {Array} - The components within the evaluation context. - */ export function getContextComponents(context, excludeNested, excludedTypes = []) { const values = []; @@ -1286,11 +1179,6 @@ export function getContextComponents(context, excludeNested, excludedTypes = []) return values; } -/** - * Returns the button components that are within an evaluation context. - * @param {any} context - The evaluation context to get the components from. - * @returns {Array} - The button components within the evaluation context. - */ export function getContextButtons(context) { const values = []; @@ -1311,9 +1199,12 @@ const inTextTags = ['#text', 'A', 'B', 'EM', 'I', 'SMALL', 'STRONG', 'SUB', 'SUP /** * Helper function for 'translateHTMLTemplate'. Translates text value of the passed html element. - * @param {HTMLElement} elem - The element to translate. - * @param {Function} translate - The translation function. - * @returns {string} - Translated element template. + * + * @param {HTMLElement} elem + * @param {Function} translate + * + * @returns {String} + * Translated element template. */ function translateElemValue(elem, translate) { if (!elem.innerText) { @@ -1350,8 +1241,10 @@ function translateElemValue(elem, translate) { /** * Helper function for 'translateHTMLTemplate'. Goes deep through html tag children and calls function to translate their text values. - * @param {HTMLElement} tag - The tag to translate. - * @param {Function} translate - The translation function. + * + * @param {HTMLElement} tag + * @param {Function} translate + * * @returns {void} */ function translateDeepTag(tag, translate) { @@ -1371,9 +1264,12 @@ function translateDeepTag(tag, translate) { /** * Translates text values in html template. - * @param {string} template - The template to translate. - * @param {Function} translate - The translation function. - * @returns {string} - Html template with translated values. + * + * @param {String} template + * @param {Function} translate + * + * @returns {String} + * Html template with translated values. */ export function translateHTMLTemplate(template, translate) { const isHTML = /<[^>]*>/.test(template); @@ -1395,9 +1291,9 @@ export function translateHTMLTemplate(template, translate) { /** * Sanitize an html string. - * @param {string} string - The string to sanitize. - * @param {any} options - The options to use for sanitization. - * @returns {string} - The sanitized html string. + * + * @param string + * @returns {*} */ export function sanitize(string, options) { if (typeof dompurify.sanitize !== 'function') { @@ -1446,8 +1342,6 @@ export function sanitize(string, options) { /** * Fast cloneDeep for JSON objects only. - * @param {any} obj - The object to perform a fast clone deep against. - * @returns {any} - The cloned object. */ export function fastCloneDeep(obj) { return obj ? JSON.parse(JSON.stringify(obj)) : obj; @@ -1455,11 +1349,6 @@ export function fastCloneDeep(obj) { export { Evaluator, interpolate }; -/** - * Returns if the component is an input component. - * @param {import('@formio/core').Component} componentJson - The JSON of a component. - * @returns {bool} - TRUE if the component is an input component; FALSE otherwise. - */ export function isInputComponent(componentJson) { if (componentJson.input === false || componentJson.input === true) { return componentJson.input; @@ -1480,11 +1369,6 @@ export function isInputComponent(componentJson) { } } -/** - * Takes a component path, and returns a component path array. - * @param {string} pathStr - The path string to convert to an array. - * @returns {Arryay} - The array of paths. - */ export function getArrayFromComponentPath(pathStr) { if (!pathStr || !_.isString(pathStr)) { if (!_.isArray(pathStr)) { @@ -1499,12 +1383,6 @@ export function getArrayFromComponentPath(pathStr) { .map(part => _.defaultTo(_.toNumber(part), part)); } -/** - * Returns true if the component is a child of the parent. - * @param {any} child - The child component to check. - * @param {any} parent - The parent component to check. - * @returns {boolean} - TRUE if the child is a child of the parent; FALSE otherwise. - */ export function isChildOf(child, parent) { while (child && child.parent) { if (child.parent === parent) { @@ -1515,11 +1393,6 @@ export function isChildOf(child, parent) { return false; } -/** - * Takes an array of component path indexes, and returns a string version of that array. - * @param {Array} path - The path array to convert to a string. - * @returns {string} - The string version of the path. - */ export function getStringFromComponentPath(path) { if (!_.isArray(path)) { return path; @@ -1536,22 +1409,17 @@ export function getStringFromComponentPath(path) { return strPath; } -/** - * Takes a number and rounds it to the provided precision amount. - * @param {number} number - The number to round. - * @param {number} precision - The precision to round the number to. - * @returns {string} - The rounded number. - */ export function round(number, precision) { if (_.isNumber(number)) { return number.toFixed(precision); } - return number.toString(); + return number; } /** * Check for Internet Explorer browser version - * @returns {(number|null)} - The IE browser version or null if not IE + * + * @return {(number|null)} */ export function getIEBrowserVersion() { const { ie, version } = getBrowserInfo(); @@ -1561,7 +1429,8 @@ export function getIEBrowserVersion() { /** * Get browser name and version (modified from 'jquery-browser-plugin') - * @returns {object} -- {{browser name, version, isWebkit?}} + * + * @return {Object} -- {{browser name, version, isWebkit?}} * Possible browser names: chrome, safari, ie, edge, opera, mozilla, yabrowser */ export function getBrowserInfo() { @@ -1614,20 +1483,13 @@ export function getBrowserInfo() { return browser; } -/** - * Takes a component path, which may include array indicies (i.e. [0][1]), and returns the compoennt path without the indicies. - * @param {string} path - The path to remove the indicies from. - * @returns {string} - The path without the indicies. - */ export function getComponentPathWithoutIndicies(path = '') { return path.replace(/\[\d+\]/, ''); } /** * Returns a path to the component which based on its schema - * @param {import('@formio/core').Component} component - Component containing link to its parent's schema in the 'parent' property - * @param {string} path - Path to the component - * @returns {string} - Path to the component + * @param {*} component is a component's schema containing link to its parent's schema in the 'parent' property */ export function getComponentPath(component, path = '') { if (!component || !component.key || component?._form?.display === 'wizard') { // unlike the Webform, the Wizard has the key and it is a duplicate of the panel key @@ -1639,8 +1501,8 @@ export function getComponentPath(component, path = '') { /** * Returns a parent component of the passed component instance skipping all the Layout components - * @param {Component} componentInstance - The component to check for the parent. - * @returns {Component|undefined} - The parent data component. + * @param {*} componentInstance + * @return {(Component|undefined)} */ export function getDataParentComponent(componentInstance) { if (!componentInstance) { @@ -1657,8 +1519,8 @@ export function getDataParentComponent(componentInstance) { /** * Returns whether the value is a promise - * @param {any} value - The value to check - * @returns {boolean} - TRUE if the value is a promise; FALSE otherwise + * @param value + * @return {boolean} */ export function isPromise(value) { return value @@ -1670,9 +1532,9 @@ export function getDataParentComponent(componentInstance) { /** * Determines if the component has a scoping parent in tree (a component which scopes its children and manages its * changes by itself, e.g. EditGrid) - * @param {Component} componentInstance - The component to check for the scoping parent. - * @param {boolean} firstPass - Whether it is the first pass of the function - * @returns {boolean|*} - TRUE if the component has a scoping parent; FALSE otherwise + * @param componentInstance + * @param firstPass + * @returns {boolean|boolean|*} */ export function isInsideScopingComponent(componentInstance, firstPass = true) { if (!firstPass && componentInstance?.hasScopedChildren) { @@ -1688,11 +1550,6 @@ export function isInsideScopingComponent(componentInstance, firstPass = true) { return false; } -/** - * Returns all the focusable elements within the provided dom element. - * @param {HTMLElement} element - The element to get the focusable elements from. - * @returns {NodeList} - The focusable elements within the provided element. - */ export function getFocusableElements(element) { const focusableSelector = `button:not([disabled]), input:not([disabled]), select:not([disabled]), @@ -1713,11 +1570,6 @@ export const componentValueTypes = { any: 'any', }; -/** - * Returns the saved types for the component - * @param {import('@formio/core').Component} fullSchema - The component schema - * @returns {Array|null} - The saved types for the component - */ export function getComponentSavedTypes(fullSchema) { const schema = fullSchema || {}; @@ -1734,10 +1586,9 @@ export function getComponentSavedTypes(fullSchema) { /** * Interpolates @formio/core errors so that they are compatible with the renderer - * @param {Component} component - The component to interpolate the errors for - * @param {FieldError[]} errors - The errors to interpolate - * @param {Function} interpolateFn - The interpolation function - * @returns {[]} - The interpolated errors + * @param {FieldError[]} errors + * @param firstPass + * @returns {[]} */ export const interpolateErrors = (component, errors, interpolateFn) => { return errors.map((error) => { @@ -1748,11 +1599,6 @@ export const interpolateErrors = (component, errors, interpolateFn) => { }); }; -/** - * Returns the template keys inside the template code. - * @param {string} template - The template to get the keys from. - * @returns {Array} - The keys inside the template. - */ export function getItemTemplateKeys(template) { const templateKeys = []; if (!template) { @@ -1772,11 +1618,6 @@ export function getItemTemplateKeys(template) { return templateKeys; } -/** - * Returns if the component is a select resource with an object for its value. - * @param {import('@formio/core').Component} comp - The component to check. - * @returns {boolean} - TRUE if the component is a select resource with an object for its value; FALSE otherwise. - */ export function isSelectResourceWithObjectValue(comp = {}) { const { reference, dataSrc, valueProperty } = comp; return reference || (dataSrc === 'resource' && (!valueProperty || valueProperty === 'data')); diff --git a/src/widgets/CalendarWidget.js b/src/widgets/CalendarWidget.js index 2479711dff..9113387b3c 100644 --- a/src/widgets/CalendarWidget.js +++ b/src/widgets/CalendarWidget.js @@ -69,7 +69,8 @@ export default class CalendarWidget extends InputWidget { /** * Load the timezones. - * @returns {boolean} TRUE if the zones are loading, FALSE otherwise. + * + * @return {boolean} TRUE if the zones are loading, FALSE otherwise. */ loadZones() { const timezone = this.timezone; @@ -307,11 +308,11 @@ export default class CalendarWidget extends InputWidget { } /** - * Return the date value as a string. - * @param {string|Date} date - The date object or a date string that is momentjs compatible. - * @param {string} format - The DateParser code format. - * @param {boolean} [useTimezone] - If the timezone should be used. - * @returns {string} - Returns the formatted date string. + * Return the date value. + * + * @param date + * @param format + * @return {string} */ getDateValue(date, format, useTimezone) { if (useTimezone) { @@ -322,7 +323,8 @@ export default class CalendarWidget extends InputWidget { /** * Return the value of the selected date. - * @returns {*} - The value of the selected date. + * + * @return {*} */ getValue() { // Standard output format. @@ -349,8 +351,8 @@ export default class CalendarWidget extends InputWidget { /** * Set the selected date value. - * @param {*} value - The value to set. - * @returns {void} + * + * @param value */ setValue(value) { const saveAsText = (this.settings.saveAs === 'text'); diff --git a/yarn.lock b/yarn.lock index 5071131e3a..d34ee45783 100644 --- a/yarn.lock +++ b/yarn.lock @@ -15,7 +15,7 @@ "@jridgewell/gen-mapping" "^0.3.5" "@jridgewell/trace-mapping" "^0.3.24" -"@babel/code-frame@^7.23.5", "@babel/code-frame@^7.24.1", "@babel/code-frame@^7.24.2": +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.23.5", "@babel/code-frame@^7.24.1", "@babel/code-frame@^7.24.2": version "7.24.2" resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.2.tgz#718b4b19841809a58b29b68cde80bc5e1aa6d9ae" integrity sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ== @@ -219,15 +219,6 @@ resolved "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70" integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw== -"@es-joy/jsdoccomment@~0.42.0": - version "0.42.0" - resolved "https://registry.yarnpkg.com/@es-joy/jsdoccomment/-/jsdoccomment-0.42.0.tgz#59e878708336aaee88c2b34c894f73dbf77ae2b0" - integrity sha512-R1w57YlVA6+YE01wch3GPYn6bCsrOV3YW/5oGGE2tmX6JcL9Nr+b5IikrjMPF+v9CV3ay+obImEdsDhovhJrzw== - dependencies: - comment-parser "1.4.1" - esquery "^1.5.0" - jsdoc-type-pratt-parser "~4.0.0" - "@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0": version "4.4.0" resolved "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" @@ -802,6 +793,11 @@ resolved "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== +abab@^1.0.0: + version "1.0.4" + resolved "https://registry.npmjs.org/abab/-/abab-1.0.4.tgz#5faad9c2c07f60dd76770f71cf025b62a63cfd4e" + integrity sha512-I+Wi+qiE2kUXyrRhNsWv6XsjUTBJjSoVSctKNBfLG5zG/Xe7Rjbxf13+vqYHNTwHaFU+FtSlVxOCTiMEVtPv0A== + abab@^2.0.0, abab@^2.0.6: version "2.0.6" resolved "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz#41b80f2c871d19686216b82309231cfd3cb3d291" @@ -835,6 +831,13 @@ acorn-es7-plugin@^1.0.12: resolved "https://registry.npmjs.org/acorn-es7-plugin/-/acorn-es7-plugin-1.1.7.tgz#f2ee1f3228a90eead1245f9ab1922eb2e71d336b" integrity sha512-7D+8kscFMf6F2t+8ZRYmv82CncDZETsaZ4dEl5lh3qQez7FVABk2Vz616SAbnIq1PbNsLVaZjl2oSkk5BWAKng== +acorn-globals@^1.0.4: + version "1.0.9" + resolved "https://registry.npmjs.org/acorn-globals/-/acorn-globals-1.0.9.tgz#55bb5e98691507b74579d0513413217c380c54cf" + integrity sha512-j3/4pkfih8W4NK22gxVSXcEonTpAHOHh0hu5BoZrKcOsW/4oBPxTi4Yk3SAj+FhC1f3+bRTkXdm4019gw1vg9g== + dependencies: + acorn "^2.1.0" + acorn-globals@^4.3.0: version "4.3.4" resolved "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.3.4.tgz#9fa1926addc11c97308c4e66d7add0d40c3272e7" @@ -848,7 +851,7 @@ acorn-import-assertions@^1.9.0: resolved "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz#507276249d684797c84e0734ef84860334cfb1ac" integrity sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA== -acorn-jsx@^5.3.2: +acorn-jsx@^5.2.0, acorn-jsx@^5.3.2: version "5.3.2" resolved "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== @@ -863,6 +866,11 @@ acorn-walk@^8.0.0, acorn-walk@^8.1.1: resolved "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz#7703af9415f1b6db9315d6895503862e231d34aa" integrity sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A== +acorn@^2.1.0, acorn@^2.4.0: + version "2.7.0" + resolved "https://registry.npmjs.org/acorn/-/acorn-2.7.0.tgz#ab6e7d9d886aaca8b085bc3312b79a198433f0e7" + integrity sha512-pXK8ez/pVjqFdAgBkF1YPVRacuLQ9EXBKaKWaeh58WNfMkCmZhOZzu+NtKSPD5PHmCCHheQ5cD29qM1K4QTxIg== + acorn@^5.0.0: version "5.7.4" resolved "https://registry.npmjs.org/acorn/-/acorn-5.7.4.tgz#3e8d8a9947d0599a1796d10225d7432f4a4acf5e" @@ -873,6 +881,11 @@ acorn@^6.0.1, acorn@^6.0.4: resolved "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz#35866fd710528e92de10cf06016498e47e39e1e6" integrity sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ== +acorn@^7.1.1: + version "7.4.1" + resolved "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" + integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== + acorn@^8.0.4, acorn@^8.4.1, acorn@^8.7.1, acorn@^8.8.2, acorn@^8.9.0: version "8.11.3" resolved "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz#71e0b14e13a4ec160724b38fb7b0f233b1b81d7a" @@ -890,7 +903,7 @@ ajv-keywords@^3.5.2: resolved "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== -ajv@^6.12.3, ajv@^6.12.4, ajv@^6.12.5: +ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.3, ajv@^6.12.4, ajv@^6.12.5: version "6.12.6" resolved "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== @@ -924,6 +937,13 @@ ansi-cyan@^0.1.1: dependencies: ansi-wrap "0.1.0" +ansi-escapes@^4.2.1: + version "4.3.2" + resolved "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" + integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== + dependencies: + type-fest "^0.21.3" + ansi-gray@^0.1.1: version "0.1.1" resolved "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz#2962cf54ec9792c48510a3deb524436861ef7251" @@ -948,6 +968,11 @@ ansi-regex@^3.0.0: resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz#123d6479e92ad45ad897d4054e3c7ca7db4944e1" integrity sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw== +ansi-regex@^4.1.0: + version "4.1.1" + resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz#164daac87ab2d6f6db3a29875e2d1766582dabed" + integrity sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g== + ansi-regex@^5.0.1: version "5.0.1" resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" @@ -958,12 +983,12 @@ ansi-regex@^6.0.1: resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz#3183e38fae9a65d7cb5e53945cd5897d0260a06a" integrity sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA== -ansi-sequence-parser@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/ansi-sequence-parser/-/ansi-sequence-parser-1.1.1.tgz#e0aa1cdcbc8f8bb0b5bca625aac41f5f056973cf" - integrity sha512-vJXt3yiaUL4UU546s3rPXlsry/RnM730G1+HkpKE012AN0sx1eOrxSu95oKDIonskeLTijMgqWZ3uDEe3NFvyg== +ansi-styles@^2.2.1: + version "2.2.1" + resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" + integrity sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA== -ansi-styles@^3.2.1: +ansi-styles@^3.2.0, ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== @@ -1023,16 +1048,18 @@ archy@^1.0.0: resolved "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40" integrity sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw== -are-docs-informative@^0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/are-docs-informative/-/are-docs-informative-0.0.2.tgz#387f0e93f5d45280373d387a59d34c96db321963" - integrity sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig== - arg@^4.1.0: version "4.1.3" resolved "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== +argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== + dependencies: + sprintf-js "~1.0.2" + argparse@^2.0.1: version "2.0.1" resolved "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" @@ -1210,6 +1237,11 @@ assign-symbols@^1.0.0: resolved "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" integrity sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw== +astral-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" + integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== + async-done@^1.2.0, async-done@^1.2.2: version "1.3.2" resolved "https://registry.npmjs.org/async-done/-/async-done-1.3.2.tgz#5e15aa729962a4b07414f528a88cdf18e0b290a2" @@ -1279,6 +1311,86 @@ aws4@^1.8.0: resolved "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz#ce1c9d143389679e253b314241ea9aa5cec980d3" integrity sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg== +babel-code-frame@^6.26.0: + version "6.26.0" + resolved "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" + integrity sha512-XqYMR2dfdGMW+hd0IUZ2PwK+fGeFkOxZJ0wY+JaQAHzt1Zx8LcvpiZD2NiGkEG8qx0CfkAOr5xt76d1e8vG90g== + dependencies: + chalk "^1.1.3" + esutils "^2.0.2" + js-tokens "^3.0.2" + +babel-generator@6.11.4: + version "6.11.4" + resolved "https://registry.npmjs.org/babel-generator/-/babel-generator-6.11.4.tgz#14f6933abb20c62666d27e3b7b9f5b9dc0712a9a" + integrity sha512-JFBWXdE89s4V3E8kZroEEsnQF2A4/+55IzciGjnAATXj7HTMSum3SrW7QRYGSDLWTTQF+hhD3BmC2UFGgtM0Yw== + dependencies: + babel-messages "^6.8.0" + babel-runtime "^6.9.0" + babel-types "^6.10.2" + detect-indent "^3.0.1" + lodash "^4.2.0" + source-map "^0.5.0" + +babel-generator@6.26.1: + version "6.26.1" + resolved "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz#1844408d3b8f0d35a404ea7ac180f087a601bd90" + integrity sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA== + dependencies: + babel-messages "^6.23.0" + babel-runtime "^6.26.0" + babel-types "^6.26.0" + detect-indent "^4.0.0" + jsesc "^1.3.0" + lodash "^4.17.4" + source-map "^0.5.7" + trim-right "^1.0.1" + +babel-messages@^6.23.0, babel-messages@^6.8.0: + version "6.23.0" + resolved "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e" + integrity sha512-Bl3ZiA+LjqaMtNYopA9TYE9HP1tQ+E5dLxE0XrAzcIJeK2UqF0/EaqXwBn9esd4UmTfEab+P+UYQ1GnioFIb/w== + dependencies: + babel-runtime "^6.22.0" + +babel-runtime@^6.22.0, babel-runtime@^6.26.0, babel-runtime@^6.9.0: + version "6.26.0" + resolved "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" + integrity sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g== + dependencies: + core-js "^2.4.0" + regenerator-runtime "^0.11.0" + +babel-traverse@6.26.0: + version "6.26.0" + resolved "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee" + integrity sha512-iSxeXx7apsjCHe9c7n8VtRXGzI2Bk1rBSOJgCCjfyXb6v1aCqE1KSEpq/8SXuVN8Ka/Rh1WDTF0MDzkvTA4MIA== + dependencies: + babel-code-frame "^6.26.0" + babel-messages "^6.23.0" + babel-runtime "^6.26.0" + babel-types "^6.26.0" + babylon "^6.18.0" + debug "^2.6.8" + globals "^9.18.0" + invariant "^2.2.2" + lodash "^4.17.4" + +babel-types@^6.10.2, babel-types@^6.26.0: + version "6.26.0" + resolved "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497" + integrity sha512-zhe3V/26rCWsEZK8kZN+HaQj5yQ1CilTObixFzKW1UWjqG7618Twz6YEsCnjfg5gBcJh02DrpCkS9h98ZqDY+g== + dependencies: + babel-runtime "^6.26.0" + esutils "^2.0.2" + lodash "^4.17.4" + to-fast-properties "^1.0.3" + +babylon@6.18.0, babylon@^6.18.0: + version "6.18.0" + resolved "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" + integrity sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ== + bach@^1.0.0: version "1.2.0" resolved "https://registry.npmjs.org/bach/-/bach-1.2.0.tgz#4b3ce96bf27134f79a1b414a51c14e34c3bd9880" @@ -1369,6 +1481,11 @@ body-parser@^1.19.0: type-is "~1.6.18" unpipe "1.0.0" +boolbase@~1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" + integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww== + bootstrap-icons@^1.10.5: version "1.11.3" resolved "https://registry.npmjs.org/bootstrap-icons/-/bootstrap-icons-1.11.3.tgz#03f9cb754ec005c52f9ee616e2e84a82cab3084b" @@ -1485,11 +1602,6 @@ buffer-from@^1.0.0: resolved "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== -builtin-modules@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.3.0.tgz#cae62812b89801e9656336e46223e030386be7b6" - integrity sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw== - bytes@3.1.2: version "3.1.2" resolved "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" @@ -1564,6 +1676,17 @@ chai@^4.3.7: pathval "^1.1.1" type-detect "^4.0.8" +chalk@^1.1.3: + version "1.1.3" + resolved "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" + integrity sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A== + dependencies: + ansi-styles "^2.2.1" + escape-string-regexp "^1.0.2" + has-ansi "^2.0.0" + strip-ansi "^3.0.0" + supports-color "^2.0.0" + chalk@^2.0.1, chalk@^2.1.0, chalk@^2.4.2: version "2.4.2" resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" @@ -1586,6 +1709,11 @@ chance@^1.1.9: resolved "https://registry.npmjs.org/chance/-/chance-1.1.11.tgz#78e10e1f9220a5bbc60a83e3f28a5d8558d84d1b" integrity sha512-kqTg3WWywappJPqtgrdvbA380VoXO2eu9VCV895JgbyHsaErXdyHK9LOZ911OvAk6L0obK7kDk9CGs8+oBawVA== +chardet@^0.7.0: + version "0.7.0" + resolved "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" + integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== + check-error@^1.0.3: version "1.0.3" resolved "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz#a6502e4312a7ee969f646e83bb3ddd56281bd694" @@ -1593,6 +1721,53 @@ check-error@^1.0.3: dependencies: get-func-name "^2.0.2" +cheerio@0.20.0: + version "0.20.0" + resolved "https://registry.npmjs.org/cheerio/-/cheerio-0.20.0.tgz#5c710f2bab95653272842ba01c6ea61b3545ec35" + integrity sha512-e5jCTzJc28MWkrLLjB1mu3ks7rDQJLC5y/JMdQkOAEX/dmJk62rC6Xae1yvOO4xyCxLpzcth3jIZ7nypmjQ/0w== + dependencies: + css-select "~1.2.0" + dom-serializer "~0.1.0" + entities "~1.1.1" + htmlparser2 "~3.8.1" + lodash "^4.1.0" + optionalDependencies: + jsdom "^7.0.2" + +cheerio@0.22.0: + version "0.22.0" + resolved "https://registry.npmjs.org/cheerio/-/cheerio-0.22.0.tgz#a9baa860a3f9b595a6b81b1a86873121ed3a269e" + integrity sha512-8/MzidM6G/TgRelkzDG13y3Y9LxBjCb+8yOEZ9+wwq5gVF2w2pV0wmHvjfT0RvuxGyR7UEuK36r+yYMbT4uKgA== + dependencies: + css-select "~1.2.0" + dom-serializer "~0.1.0" + entities "~1.1.1" + htmlparser2 "^3.9.1" + lodash.assignin "^4.0.9" + lodash.bind "^4.1.4" + lodash.defaults "^4.0.1" + lodash.filter "^4.4.0" + lodash.flatten "^4.2.0" + lodash.foreach "^4.3.0" + lodash.map "^4.4.0" + lodash.merge "^4.4.0" + lodash.pick "^4.2.1" + lodash.reduce "^4.4.0" + lodash.reject "^4.4.0" + lodash.some "^4.4.0" + +cheerio@1.0.0-rc.2: + version "1.0.0-rc.2" + resolved "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.2.tgz#4b9f53a81b27e4d5dac31c0ffd0cfa03cc6830db" + integrity sha512-9LDHQy1jHc/eXMzPN6/oah9Qba4CjdKECC7YYEE/2zge/tsGwt19NQp5NFdfd5Lx6TZlyC5SXNQkG41P9r6XDg== + dependencies: + css-select "~1.2.0" + dom-serializer "~0.1.0" + entities "~1.1.1" + htmlparser2 "^3.9.1" + lodash "^4.15.0" + parse5 "^3.0.1" + chokidar@3.5.3: version "3.5.3" resolved "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" @@ -1664,6 +1839,18 @@ clean-css@4.2.3: dependencies: source-map "~0.6.0" +cli-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" + integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== + dependencies: + restore-cursor "^3.1.0" + +cli-width@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz#a2f48437a2caa9a22436e794bf071ec9e61cedf6" + integrity sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw== + cliui@^3.2.0: version "3.2.0" resolved "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d" @@ -1761,6 +1948,16 @@ color-convert@^2.0.1: dependencies: color-name "~1.1.4" +color-logger@0.0.3: + version "0.0.3" + resolved "https://registry.npmjs.org/color-logger/-/color-logger-0.0.3.tgz#d9b22dd1d973e166b18bf313f9f481bba4df2018" + integrity sha512-s4oriek7VTdSmDbS5chJhNui3uUzlk/mU39V4HnOUv0KphRXpIj73lq4wY5f8l/x+WtHUhiV+FCzsrNO1w6REA== + +color-logger@0.0.6: + version "0.0.6" + resolved "https://registry.npmjs.org/color-logger/-/color-logger-0.0.6.tgz#e56245ef29822657110c7cb75a9cd786cb69ed1b" + integrity sha512-0iBj3eHRYnor8EJi3oQ1kixbr7B2Sbw1InxjsYZxS+q2H+Ii69m3ARYSJeYIqmf/QRtFhWnR1v97wp8N7ABubw== + color-name@1.1.3: version "1.1.3" resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" @@ -1803,11 +2000,6 @@ commander@^7.2.0: resolved "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== -comment-parser@1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/comment-parser/-/comment-parser-1.4.1.tgz#bdafead37961ac079be11eb7ec65c4d021eaf9cc" - integrity sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg== - compare-versions@^6.0.0-rc.2: version "6.1.0" resolved "https://registry.npmjs.org/compare-versions/-/compare-versions-6.1.0.tgz#3f2131e3ae93577df111dba133e6db876ffe127a" @@ -1908,7 +2100,7 @@ copy-props@^2.0.1: each-props "^1.3.2" is-plain-object "^5.0.0" -core-js@^2.0.0: +core-js@^2.0.0, core-js@^2.4.0: version "2.6.12" resolved "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz#d9333dfa7b065e347cc5682219d6f690859cc2ec" integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ== @@ -1962,6 +2154,17 @@ cross-spawn@^5.0.1: shebang-command "^1.2.0" which "^1.2.9" +cross-spawn@^6.0.5: + version "6.0.5" + resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" + integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== + dependencies: + nice-try "^1.0.4" + path-key "^2.0.1" + semver "^5.5.0" + shebang-command "^1.2.0" + which "^1.2.9" + cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" @@ -1978,11 +2181,33 @@ crossvent@1.5.5: dependencies: custom-event "^1.0.0" -cssom@0.3.x, cssom@^0.3.4: +css-select@~1.2.0: + version "1.2.0" + resolved "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz#2b3a110539c5355f1cd8d314623e870b121ec858" + integrity sha512-dUQOBoqdR7QwV90WysXPLXG5LO7nhYBgiWVfxF80DKPF8zx1t/pUd2FYy73emg3zrjtM6dzmYgbHKfV2rxiHQA== + dependencies: + boolbase "~1.0.0" + css-what "2.1" + domutils "1.5.1" + nth-check "~1.0.1" + +css-what@2.1: + version "2.1.3" + resolved "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz#a6d7604573365fe74686c3f311c56513d88285f2" + integrity sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg== + +cssom@0.3.x, "cssom@>= 0.3.0 < 0.4.0", cssom@^0.3.4: version "0.3.8" resolved "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz#9f1276f5b2b463f2114d3f2c75250af8c1a36f4a" integrity sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg== +"cssstyle@>= 0.2.29 < 0.3.0": + version "0.2.37" + resolved "https://registry.npmjs.org/cssstyle/-/cssstyle-0.2.37.tgz#541097234cb2513c83ceed3acddc27ff27987d54" + integrity sha512-FUpKc+1FNBsHUr9IsfSGCovr8VuGOiiuzlgCyppKBjJi2jYTOFLN3oiiNRMIvYqbFzF38mqKj4BgcevzU5/kIA== + dependencies: + cssom "0.3.x" + cssstyle@^1.1.1: version "1.4.0" resolved "https://registry.npmjs.org/cssstyle/-/cssstyle-1.4.0.tgz#9d31328229d3c565c61e586b02041a28fccdccf1" @@ -2077,14 +2302,14 @@ debounce@^1.2.1: resolved "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz#38881d8f4166a5c5848020c11827b834bcb3e0a5" integrity sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug== -debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.9: +debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9: version "2.6.9" resolved "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== dependencies: ms "2.0.0" -debug@4, debug@4.3.4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@~4.3.1, debug@~4.3.2, debug@~4.3.4: +debug@4, debug@4.3.4, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@~4.3.1, debug@~4.3.2, debug@~4.3.4: version "4.3.4" resolved "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== @@ -2200,6 +2425,22 @@ detect-file@^1.0.0: resolved "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz#f0d66d03672a825cb1b73bdb3fe62310c8e552b7" integrity sha512-DtCOLG98P007x7wiiOmfI0fi3eIKyWiLTGJ2MDnVi/E04lWGbf+JzrRHMm0rgIIZJGtHpKpbVgLWHrv8xXpc3Q== +detect-indent@^3.0.1: + version "3.0.1" + resolved "https://registry.npmjs.org/detect-indent/-/detect-indent-3.0.1.tgz#9dc5e5ddbceef8325764b9451b02bc6d54084f75" + integrity sha512-xo3WP66SNbr1Eim85s/qyH0ZL8PQUwp86HWm0S1l8WnJ/zjT6T3w1nwNA0yOZeuvOemupEYvpvF6BIdYRuERJQ== + dependencies: + get-stdin "^4.0.1" + minimist "^1.1.0" + repeating "^1.1.0" + +detect-indent@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208" + integrity sha512-BDKtmHlOzwI7iRuEkhzsnPoi5ypEhWAJB5RvHWe1kMr06js3uK5B3734i3ui5Yd+wOJV1cpE4JnivPD283GU/A== + dependencies: + repeating "^2.0.0" + di@^0.0.1: version "0.0.1" resolved "https://registry.npmjs.org/di/-/di-0.0.1.tgz#806649326ceaa7caa3306d75d985ea2748ba913c" @@ -2278,6 +2519,22 @@ dom-serialize@^2.2.1: extend "^3.0.0" void-elements "^2.0.0" +dom-serializer@0: + version "0.2.2" + resolved "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz#1afb81f533717175d478655debc5e332d9f9bb51" + integrity sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g== + dependencies: + domelementtype "^2.0.1" + entities "^2.0.0" + +dom-serializer@~0.1.0: + version "0.1.1" + resolved "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz#1ec4059e284babed36eec2941d4a970a189ce7c0" + integrity sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA== + dependencies: + domelementtype "^1.3.0" + entities "^1.1.1" + dom-set@^1.0.1: version "1.1.1" resolved "https://registry.npmjs.org/dom-set/-/dom-set-1.1.1.tgz#5c2c610ee4839b520ed5f98ddbcbe314c0fa954a" @@ -2292,6 +2549,16 @@ dom-walk@^0.1.0: resolved "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz#0c548bef048f4d1f2a97249002236060daa3fd84" integrity sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w== +domelementtype@1, domelementtype@^1.3.0, domelementtype@^1.3.1: + version "1.3.1" + resolved "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f" + integrity sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w== + +domelementtype@^2.0.1: + version "2.3.0" + resolved "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz#5c45e8e869952626331d7aab326d01daf65d589d" + integrity sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw== + domexception@^1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/domexception/-/domexception-1.0.1.tgz#937442644ca6a31261ef36e3ec677fe805582c90" @@ -2306,11 +2573,41 @@ domexception@^4.0.0: dependencies: webidl-conversions "^7.0.0" +domhandler@2.3: + version "2.3.0" + resolved "https://registry.npmjs.org/domhandler/-/domhandler-2.3.0.tgz#2de59a0822d5027fabff6f032c2b25a2a8abe738" + integrity sha512-q9bUwjfp7Eif8jWxxxPSykdRZAb6GkguBGSgvvCrhI9wB71W2K/Kvv4E61CF/mcCfnVJDeDWx/Vb/uAqbDj6UQ== + dependencies: + domelementtype "1" + +domhandler@^2.3.0: + version "2.4.2" + resolved "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz#8805097e933d65e85546f726d60f5eb88b44f803" + integrity sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA== + dependencies: + domelementtype "1" + dompurify@^3.0.6, dompurify@^3.1.0: version "3.1.0" resolved "https://registry.npmjs.org/dompurify/-/dompurify-3.1.0.tgz#8c6b9fe986969a33aa4686bd829cbe8e14dd9445" integrity sha512-yoU4rhgPKCo+p5UrWWWNKiIq+ToGqmVVhk0PmMYBK4kRsR3/qhemNFL8f6CFmBd4gMwm3F4T7HBoydP5uY07fA== +domutils@1.5, domutils@1.5.1: + version "1.5.1" + resolved "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz#dcd8488a26f563d61079e48c9f7b7e32373682cf" + integrity sha512-gSu5Oi/I+3wDENBsOWBiRK1eoGxcywYSqg3rR960/+EfY0CF4EX1VPkgHOZ3WiS/Jg2DtliF6BhWcHlfpYUcGw== + dependencies: + dom-serializer "0" + domelementtype "1" + +domutils@^1.5.1: + version "1.7.0" + resolved "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a" + integrity sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg== + dependencies: + dom-serializer "0" + domelementtype "1" + downloadjs@^1.4.7: version "1.4.7" resolved "https://registry.npmjs.org/downloadjs/-/downloadjs-1.4.7.tgz#f69f96f940e0d0553dac291139865a3cd0101e3c" @@ -2388,6 +2685,11 @@ electron-to-chromium@^1.4.668: resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.736.tgz#ecb4348f4d5c70fb1e31c347e5bad6b751066416" integrity sha512-Rer6wc3ynLelKNM4lOCg7/zPQj8tPOCB2hzD32PX9wd3hgRRi9MxEbmkFCokzcEhRVMiOVLjnL9ig9cefJ+6+Q== +emoji-regex@^7.0.1: + version "7.0.3" + resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" + integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== + emoji-regex@^8.0.0: version "8.0.0" resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" @@ -2465,6 +2767,21 @@ ent@~2.2.0: resolved "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz#e964219325a21d05f44466a2f686ed6ce5f5dd1d" integrity sha512-GHrMyVZQWvTIdDtpiEXdHZnFQKzeO09apj8Cbl4pKWy4i0Oprcq17usfDt5aO63swf0JOeMWjWQE/LzgSRuWpA== +entities@1.0: + version "1.0.0" + resolved "https://registry.npmjs.org/entities/-/entities-1.0.0.tgz#b2987aa3821347fcde642b24fdfc9e4fb712bf26" + integrity sha512-LbLqfXgJMmy81t+7c14mnulFHJ170cM6E+0vMXR9k/ZiZwgX8i5pNgjTCX3SO4VeUsFLV+8InixoretwU+MjBQ== + +entities@^1.1.1, entities@~1.1.1: + version "1.1.2" + resolved "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56" + integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w== + +entities@^2.0.0: + version "2.2.0" + resolved "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" + integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A== + entities@^4.4.0: version "4.5.0" resolved "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48" @@ -2630,7 +2947,7 @@ escalade@^3.1.1: resolved "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz#54076e9ab29ea5bf3d8f1ed62acffbb88272df27" integrity sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA== -escape-html@~1.0.3: +escape-html@1.0.3, escape-html@~1.0.3: version "1.0.3" resolved "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== @@ -2640,7 +2957,7 @@ escape-string-regexp@4.0.0, escape-string-regexp@^4.0.0: resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== -escape-string-regexp@^1.0.3, escape-string-regexp@^1.0.5: +escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.3, escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== @@ -2650,7 +2967,7 @@ escape-string-regexp@^5.0.0: resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz#4683126b500b61762f2dbebace1806e8be31b1c8" integrity sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw== -escodegen@^1.11.0: +escodegen@^1.11.0, escodegen@^1.6.1: version "1.14.3" resolved "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz#4e7b81fba61581dc97582ed78cab7f0e8d63f503" integrity sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw== @@ -2662,22 +2979,118 @@ escodegen@^1.11.0: optionalDependencies: source-map "~0.6.1" -eslint-plugin-jsdoc@^48.2.3: - version "48.2.3" - resolved "https://registry.yarnpkg.com/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-48.2.3.tgz#0188d17c7a4aa7185416556589e71a954b343ecd" - integrity sha512-r9DMAmFs66VNvNqRLLjHejdnJtILrt3xGi+Qx0op0oRfFGVpOR1Hb3BC++MacseHx93d8SKYPhyrC9BS7Os2QA== +esdoc-accessor-plugin@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/esdoc-accessor-plugin/-/esdoc-accessor-plugin-1.0.0.tgz#791ba4872e6c403515ce749b1348d6f0293ad9eb" + integrity sha512-s9mNmdHGOyQOaOUXNHPz38Y8clm6dR8/fa9DPGzuRYmIN+Lv0NVnpPAcHb5XrfC23/Mz3IUwD8h798f5Ai4rbA== + +esdoc-brand-plugin@^1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/esdoc-brand-plugin/-/esdoc-brand-plugin-1.0.1.tgz#7c0e1ae90e84c30b2d3369d3a6449f9dc9f8d511" + integrity sha512-Yv9j3M7qk5PSLmSeD6MbPsfIsEf8K43EdH8qZpE/GZwnJCRVmDPrZJ1cLDj/fPu6P35YqgcEaJK4E2NL/CKA7g== dependencies: - "@es-joy/jsdoccomment" "~0.42.0" - are-docs-informative "^0.0.2" - comment-parser "1.4.1" - debug "^4.3.4" - escape-string-regexp "^4.0.0" - esquery "^1.5.0" - is-builtin-module "^3.2.1" - semver "^7.6.0" - spdx-expression-parse "^4.0.0" + cheerio "0.22.0" + +esdoc-coverage-plugin@^1.0.0: + version "1.1.0" + resolved "https://registry.npmjs.org/esdoc-coverage-plugin/-/esdoc-coverage-plugin-1.1.0.tgz#3869869cd7f87891f972625787695a299aece45c" + integrity sha512-M+94/Y+eoM08V3teiJIYpJ5HF13jH4cC9LQZrjmA91mlAqCHtNzelHF9ZdWofoOFYFRNpllFsXTFsJgwVa000A== + +esdoc-ecmascript-proposal-plugin@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/esdoc-ecmascript-proposal-plugin/-/esdoc-ecmascript-proposal-plugin-1.0.0.tgz#390dc5656ba8a2830e39dba3570d79138df2ffd9" + integrity sha512-PuaU/O8d+Sb0J6qQdyhmy74h/2cp/2kqsvPuoCiK+50Rw54nlGqXxvWNaaNikS5qntE0FfssnwZtUPa6q4RiXg== + +esdoc-external-ecmascript-plugin@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/esdoc-external-ecmascript-plugin/-/esdoc-external-ecmascript-plugin-1.0.0.tgz#78f565d4a0c5185ac63152614dce1fe1a86688db" + integrity sha512-ASj7lhfZpzI01xd4XqB4HN+zNKwnhdaN/OIp/CTnUiLIErMOeUqzV9z/dcnUUeDY3NSwPCH1pUNATVwznspmHw== + dependencies: + fs-extra "1.0.0" + +esdoc-integrate-manual-plugin@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/esdoc-integrate-manual-plugin/-/esdoc-integrate-manual-plugin-1.0.0.tgz#1854a6aa1c081035d7c8c51e3bdd4fb65aa4711c" + integrity sha512-+XcW8xRtuFVFadoVLIOj6kzX4uqtAEB5UoR7AA5g46StxLghZZ6RLrRQSERUTIc3VX9v47lOMKEaQvQfanv3+A== + +esdoc-integrate-test-plugin@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/esdoc-integrate-test-plugin/-/esdoc-integrate-test-plugin-1.0.0.tgz#e2d0d00090f7f0c35e5d2f2c033327a79e53e409" + integrity sha512-WRbkbnbWnzF4RdmcoJLYZvhod7jLVUYWU2ZAojYjK+GiqSgy2yjGi7PxckeGF0LtpCuqqKat3PRdUNEMo6Nf3A== -eslint-scope@5.1.1: +esdoc-lint-plugin@^1.0.0: + version "1.0.2" + resolved "https://registry.npmjs.org/esdoc-lint-plugin/-/esdoc-lint-plugin-1.0.2.tgz#4962930c6dc5b25d80cf6eff1b0f3c24609077f7" + integrity sha512-24AYqD2WbZI9We02I7/6dzAa7yUliRTFUaJCZAcYJMQicJT5gUrNFVaI8XmWEN/mhF3szIn1uZBNWeLul4CmNw== + +esdoc-publish-html-plugin@^1.0.0: + version "1.1.2" + resolved "https://registry.npmjs.org/esdoc-publish-html-plugin/-/esdoc-publish-html-plugin-1.1.2.tgz#bdece7bc7a0a3e419933503252db7a6772879dab" + integrity sha512-hG1fZmTcEp3P/Hv/qKiMdG1qSp8MjnVZMMkxL5P5ry7I2sX0HQ4P9lt2lms+90Lt0r340HHhSuVx107UL7dphg== + dependencies: + babel-generator "6.11.4" + cheerio "0.22.0" + escape-html "1.0.3" + fs-extra "1.0.0" + ice-cap "0.0.4" + marked "0.3.19" + taffydb "2.7.2" + +esdoc-standard-plugin@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/esdoc-standard-plugin/-/esdoc-standard-plugin-1.0.0.tgz#661201cac7ef868924902446fdac1527253c5d4d" + integrity sha512-IDEG9NV/MF5Bi2TdKPqQ3GHfDkgqYhk2iyvBNX+XcNKYmXm9zxtXVS459WAmiTZuYpDLtDGbulQdJ1t4ud57mw== + dependencies: + esdoc-accessor-plugin "^1.0.0" + esdoc-brand-plugin "^1.0.0" + esdoc-coverage-plugin "^1.0.0" + esdoc-external-ecmascript-plugin "^1.0.0" + esdoc-integrate-manual-plugin "^1.0.0" + esdoc-integrate-test-plugin "^1.0.0" + esdoc-lint-plugin "^1.0.0" + esdoc-publish-html-plugin "^1.0.0" + esdoc-type-inference-plugin "^1.0.0" + esdoc-undocumented-identifier-plugin "^1.0.0" + esdoc-unexported-identifier-plugin "^1.0.0" + +esdoc-type-inference-plugin@^1.0.0: + version "1.0.2" + resolved "https://registry.npmjs.org/esdoc-type-inference-plugin/-/esdoc-type-inference-plugin-1.0.2.tgz#916e3f756de1d81d9c0dbe1c008e8dafd322cfaf" + integrity sha512-tMIcEHNe1uhUGA7lT1UTWc9hs2dzthnTgmqXpmeUhurk7fL2tinvoH+IVvG/sLROzwOGZQS9zW/F9KWnpMzLIQ== + +esdoc-undocumented-identifier-plugin@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/esdoc-undocumented-identifier-plugin/-/esdoc-undocumented-identifier-plugin-1.0.0.tgz#82e05d371c32d12871140f1d5c81ec99fd9cc2c8" + integrity sha512-T0hQc0ec1+pUJPDBoJ2SxEv7uX9VD7Q9+7UAGnDZ5R2l2JYa3WY7cawyqfbMHVtLgvqH0eMBpxdfRsQvAWzj4Q== + +esdoc-unexported-identifier-plugin@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/esdoc-unexported-identifier-plugin/-/esdoc-unexported-identifier-plugin-1.0.0.tgz#1f9874c6a7c2bebf9ad397c3ceb75c9c69dabab1" + integrity sha512-PRdMLWHWdy9PwxzYDG2clhta9H7yHDpGCBIHxSw9R7TFK6ZYuPK1fUbURIzIxcdQhzt1PX9Cn6Cak2824K0+Ng== + +esdoc@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/esdoc/-/esdoc-1.1.0.tgz#07d40ebf791764cd537929c29111e20a857624f3" + integrity sha512-vsUcp52XJkOWg9m1vDYplGZN2iDzvmjDL5M/Mp8qkoDG3p2s0yIQCIjKR5wfPBaM3eV14a6zhQNYiNTCVzPnxA== + dependencies: + babel-generator "6.26.1" + babel-traverse "6.26.0" + babylon "6.18.0" + cheerio "1.0.0-rc.2" + color-logger "0.0.6" + escape-html "1.0.3" + fs-extra "5.0.0" + ice-cap "0.0.4" + marked "0.3.19" + minimist "1.2.0" + taffydb "2.7.3" + +eslint-config-formio@^1.1.4: + version "1.1.4" + resolved "https://registry.npmjs.org/eslint-config-formio/-/eslint-config-formio-1.1.4.tgz#64082979bdc8166445a463884998c7e1ee3b7de5" + integrity sha512-8V3cbflYi53i9QyWpl1MffkrSM/uz3tRQ86N+5K4WAa7qGtUeo9hDB5+ZrsfxT0nfnwqVf/1d5CgzUKH2EuKqw== + +eslint-scope@5.1.1, eslint-scope@^5.0.0: version "5.1.1" resolved "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== @@ -2693,11 +3106,66 @@ eslint-scope@^7.2.2: esrecurse "^4.3.0" estraverse "^5.2.0" +eslint-utils@^1.4.3: + version "1.4.3" + resolved "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz#74fec7c54d0776b6f67e0251040b5806564e981f" + integrity sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q== + dependencies: + eslint-visitor-keys "^1.1.0" + +eslint-visitor-keys@^1.1.0: + version "1.3.0" + resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" + integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== + eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4.3: version "3.4.3" resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== +eslint@^6.0.0: + version "6.8.0" + resolved "https://registry.npmjs.org/eslint/-/eslint-6.8.0.tgz#62262d6729739f9275723824302fb227c8c93ffb" + integrity sha512-K+Iayyo2LtyYhDSYwz5D5QdWw0hCacNzyq1Y821Xna2xSJj7cijoLLYmLxTQgcgZ9mC61nryMy9S7GRbYpI5Ig== + dependencies: + "@babel/code-frame" "^7.0.0" + ajv "^6.10.0" + chalk "^2.1.0" + cross-spawn "^6.0.5" + debug "^4.0.1" + doctrine "^3.0.0" + eslint-scope "^5.0.0" + eslint-utils "^1.4.3" + eslint-visitor-keys "^1.1.0" + espree "^6.1.2" + esquery "^1.0.1" + esutils "^2.0.2" + file-entry-cache "^5.0.1" + functional-red-black-tree "^1.0.1" + glob-parent "^5.0.0" + globals "^12.1.0" + ignore "^4.0.6" + import-fresh "^3.0.0" + imurmurhash "^0.1.4" + inquirer "^7.0.0" + is-glob "^4.0.0" + js-yaml "^3.13.1" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.3.0" + lodash "^4.17.14" + minimatch "^3.0.4" + mkdirp "^0.5.1" + natural-compare "^1.4.0" + optionator "^0.8.3" + progress "^2.0.0" + regexpp "^2.0.1" + semver "^6.1.2" + strip-ansi "^5.2.0" + strip-json-comments "^3.0.1" + table "^5.2.3" + text-table "^0.2.0" + v8-compile-cache "^2.0.3" + eslint@^8.57.0: version "8.57.0" resolved "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz#c786a6fd0e0b68941aaf624596fb987089195668" @@ -2752,6 +3220,15 @@ esniff@^2.0.1: event-emitter "^0.3.5" type "^2.7.2" +espree@^6.1.2: + version "6.2.1" + resolved "https://registry.npmjs.org/espree/-/espree-6.2.1.tgz#77fc72e1fd744a2052c20f38a5b575832e82734a" + integrity sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw== + dependencies: + acorn "^7.1.1" + acorn-jsx "^5.2.0" + eslint-visitor-keys "^1.1.0" + espree@^9.6.0, espree@^9.6.1: version "9.6.1" resolved "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz#a2a17b8e434690a5432f2f8018ce71d331a48c6f" @@ -2761,7 +3238,7 @@ espree@^9.6.0, espree@^9.6.1: acorn-jsx "^5.3.2" eslint-visitor-keys "^3.4.1" -esprima@^4.0.1: +esprima@^4.0.0, esprima@^4.0.1: version "4.0.1" resolved "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== @@ -2773,7 +3250,7 @@ espurify@^1.6.0: dependencies: core-js "^2.0.0" -esquery@^1.4.2, esquery@^1.5.0: +esquery@^1.0.1, esquery@^1.4.2: version "1.5.0" resolved "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz#6ce17738de8577694edd7361c57182ac8cb0db0b" integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg== @@ -2893,6 +3370,15 @@ extend@^3.0.0, extend@~3.0.2: resolved "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== +external-editor@^3.0.3: + version "3.1.0" + resolved "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495" + integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew== + dependencies: + chardet "^0.7.0" + iconv-lite "^0.4.24" + tmp "^0.0.33" + extglob@^0.3.1: version "0.3.2" resolved "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1" @@ -3036,6 +3522,20 @@ fetch-ponyfill@^7.1.0: dependencies: node-fetch "~2.6.1" +figures@^3.0.0: + version "3.2.0" + resolved "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af" + integrity sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg== + dependencies: + escape-string-regexp "^1.0.5" + +file-entry-cache@^5.0.1: + version "5.0.1" + resolved "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz#ca0f6efa6dd3d561333fb14515065c2fafdf439c" + integrity sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g== + dependencies: + flat-cache "^2.0.1" + file-entry-cache@^6.0.1: version "6.0.1" resolved "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" @@ -3169,6 +3669,15 @@ flagged-respawn@^1.0.0: resolved "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz#e7de6f1279ddd9ca9aac8a5971d618606b3aab41" integrity sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q== +flat-cache@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0" + integrity sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA== + dependencies: + flatted "^2.0.0" + rimraf "2.6.3" + write "1.0.3" + flat-cache@^3.0.4: version "3.2.0" resolved "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz#2c0c2d5040c99b1632771a9d105725c0115363ee" @@ -3188,6 +3697,11 @@ flatpickr@^4.6.13: resolved "https://registry.npmjs.org/flatpickr/-/flatpickr-4.6.13.tgz#8a029548187fd6e0d670908471e43abe9ad18d94" integrity sha512-97PMG/aywoYpB4IvbvUJi0RQi8vearvU0oov1WW3k0WZPBMrTQVqekSX5CjSG/M4Q3i6A/0FKXC7RyAoAUUSPw== +flatted@^2.0.0: + version "2.0.2" + resolved "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz#4575b21e2bcee7434aa9be662f4b7b5f9c2b5138" + integrity sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA== + flatted@^3.2.7, flatted@^3.2.9: version "3.3.1" resolved "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz#21db470729a6734d4997002f439cb308987f567a" @@ -3275,7 +3789,7 @@ fragment-cache@^0.2.1: dependencies: map-cache "^0.2.2" -fs-extra@^1.0.0: +fs-extra@1.0.0, fs-extra@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-1.0.0.tgz#cd3ce5f7e7cb6145883fcae3191e9877f8587950" integrity sha512-VerQV6vEKuhDWD2HGOybV6v5I73syoc/cXAbKlgTC7M/oFVEtklWlp9QH2Ijw3IaWDOQcMkldSPa7zXy79Z/UQ== @@ -3284,6 +3798,15 @@ fs-extra@^1.0.0: jsonfile "^2.1.0" klaw "^1.0.0" +fs-extra@5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-5.0.0.tgz#414d0110cdd06705734d055652c5411260c31abd" + integrity sha512-66Pm4RYbjzdyeuqudYqhFiNBbCIuI9kgRqLPSHIlXHidW8NIQtVdkM1yeZ4lXwuhbTETv3EUGMNHAAw6hiundQ== + dependencies: + graceful-fs "^4.1.2" + jsonfile "^4.0.0" + universalify "^0.1.0" + fs-extra@^8.1.0: version "8.1.0" resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0" @@ -3334,6 +3857,11 @@ function.prototype.name@^1.1.6: es-abstract "^1.22.1" functions-have-names "^1.2.3" +functional-red-black-tree@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" + integrity sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g== + functions-have-names@^1.2.3: version "1.2.3" resolved "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" @@ -3375,6 +3903,11 @@ get-intrinsic@^1.1.3, get-intrinsic@^1.2.1, get-intrinsic@^1.2.3, get-intrinsic@ has-symbols "^1.0.3" hasown "^2.0.0" +get-stdin@^4.0.1: + version "4.0.1" + resolved "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe" + integrity sha512-F5aQMywwJ2n85s4hJPTT9RPxGmubonuB10MNYo17/xph174n2MIR33HRguhzVag10O/npM7SPk73LMZNP+FaWw== + get-symbol-description@^1.0.2: version "1.0.2" resolved "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz#533744d5aa20aca4e079c8e5daf7fd44202821f5" @@ -3419,7 +3952,7 @@ glob-parent@^3.0.1, glob-parent@^3.1.0: is-glob "^3.1.0" path-dirname "^1.0.0" -glob-parent@^5.1.2, glob-parent@~5.1.2: +glob-parent@^5.0.0, glob-parent@^5.1.2, glob-parent@~5.1.2: version "5.1.2" resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== @@ -3534,6 +4067,13 @@ globals@^11.1.0: resolved "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== +globals@^12.1.0: + version "12.4.0" + resolved "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz#a18813576a41b00a24a97e7f815918c2e19925f8" + integrity sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg== + dependencies: + type-fest "^0.8.1" + globals@^13.19.0: version "13.24.0" resolved "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz#8432a19d78ce0c1e833949c36adb345400bb1171" @@ -3541,6 +4081,11 @@ globals@^13.19.0: dependencies: type-fest "^0.20.2" +globals@^9.18.0: + version "9.18.0" + resolved "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" + integrity sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ== + globalthis@^1.0.3: version "1.0.3" resolved "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz#5852882a52b80dc301b0660273e1ed082f0b6ccf" @@ -3638,6 +4183,15 @@ gulp-concat@^2.6.1: through2 "^2.0.0" vinyl "^2.0.0" +gulp-eslint@^6.0.0: + version "6.0.0" + resolved "https://registry.npmjs.org/gulp-eslint/-/gulp-eslint-6.0.0.tgz#7d402bb45f8a67652b868277011812057370a832" + integrity sha512-dCVPSh1sA+UVhn7JSQt7KEb4An2sQNbOdB3PA8UCfxsoPlAKjJHxYHGXdXC7eb+V1FAnilSFFqslPrq037l1ig== + dependencies: + eslint "^6.0.0" + fancy-log "^1.3.2" + plugin-error "^1.0.1" + gulp-filter@^7.0.0: version "7.0.0" resolved "https://registry.npmjs.org/gulp-filter/-/gulp-filter-7.0.0.tgz#e0712f3e57b5d647f802a1880255cafb54abf158" @@ -3736,6 +4290,13 @@ har-validator@~5.1.3: ajv "^6.12.3" har-schema "^2.0.0" +has-ansi@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" + integrity sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg== + dependencies: + ansi-regex "^2.0.0" + has-bigints@^1.0.1, has-bigints@^1.0.2: version "1.0.2" resolved "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" @@ -3862,6 +4423,29 @@ html-escaper@^2.0.2: resolved "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== +htmlparser2@^3.9.1: + version "3.10.1" + resolved "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz#bd679dc3f59897b6a34bb10749c855bb53a9392f" + integrity sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ== + dependencies: + domelementtype "^1.3.1" + domhandler "^2.3.0" + domutils "^1.5.1" + entities "^1.1.1" + inherits "^2.0.1" + readable-stream "^3.1.1" + +htmlparser2@~3.8.1: + version "3.8.3" + resolved "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.3.tgz#996c28b191516a8be86501a7d79757e5c70c1068" + integrity sha512-hBxEg3CYXe+rPIua8ETe7tmG3XDn9B0edOE/e9wH2nLczxzgdu0m0aNHY+5wFZiviLWLdANPJTssa92dMcXQ5Q== + dependencies: + domelementtype "1" + domhandler "2.3" + domutils "1.5" + entities "1.0" + readable-stream "1.1" + http-errors@2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" @@ -3908,7 +4492,15 @@ https-proxy-agent@^5.0.1: agent-base "6" debug "4" -iconv-lite@0.4.24: +ice-cap@0.0.4: + version "0.0.4" + resolved "https://registry.npmjs.org/ice-cap/-/ice-cap-0.0.4.tgz#8a6d31ab4cac8d4b56de4fa946df3352561b6e18" + integrity sha512-39ZblYEKlqj7LHgLkUcVk7zcJp772lOVQAUhN6QyY88w8/4bn5SgDeU2020yzHosf+uKPuCFK1UQ36gyBNiraw== + dependencies: + cheerio "0.20.0" + color-logger "0.0.3" + +iconv-lite@0.4.24, iconv-lite@^0.4.24: version "0.4.24" resolved "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== @@ -3927,6 +4519,11 @@ idb@^7.1.1: resolved "https://registry.npmjs.org/idb/-/idb-7.1.1.tgz#d910ded866d32c7ced9befc5bfdf36f572ced72b" integrity sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ== +ignore@^4.0.6: + version "4.0.6" + resolved "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" + integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== + ignore@^5.2.0, ignore@^5.3.1: version "5.3.1" resolved "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz#5073e554cd42c5b33b394375f538b8593e34d4ef" @@ -3937,7 +4534,7 @@ immutable@^4.0.0: resolved "https://registry.npmjs.org/immutable/-/immutable-4.3.5.tgz#f8b436e66d59f99760dc577f5c99a4fd2a5cc5a0" integrity sha512-8eabxkth9gZatlwl5TBuJnCsoTADlL6ftEr7A4qgdaTsPyreilDSnUk57SO+jfKcNtxPa22U5KK6DSeAYhpBJw== -import-fresh@^3.2.1: +import-fresh@^3.0.0, import-fresh@^3.2.1: version "3.3.0" resolved "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== @@ -3971,7 +4568,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.3: +inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.1, inherits@~2.0.3: version "2.0.4" resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== @@ -3991,6 +4588,25 @@ inputmask@^5.0.9-beta.45: resolved "https://registry.npmjs.org/inputmask/-/inputmask-5.0.9-beta.62.tgz#e882904404e6038155492f939170820da89f3157" integrity sha512-8r2R5YEk6xEWgV6Sd8PwmMkFBF/9uGJipPYE01BAvZLFnK7oUKI9yaB74fHEc4525Y3lM69qk48oMq6jTN8cZQ== +inquirer@^7.0.0: + version "7.3.3" + resolved "https://registry.npmjs.org/inquirer/-/inquirer-7.3.3.tgz#04d176b2af04afc157a83fd7c100e98ee0aad003" + integrity sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA== + dependencies: + ansi-escapes "^4.2.1" + chalk "^4.1.0" + cli-cursor "^3.1.0" + cli-width "^3.0.0" + external-editor "^3.0.3" + figures "^3.0.0" + lodash "^4.17.19" + mute-stream "0.0.8" + run-async "^2.4.0" + rxjs "^6.6.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + through "^2.3.6" + internal-slot@^1.0.7: version "1.0.7" resolved "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz#c06dcca3ed874249881007b0a5523b172a190802" @@ -4010,6 +4626,13 @@ interpret@^3.1.1: resolved "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz#5be0ceed67ca79c6c4bc5cf0d7ee843dcea110c4" integrity sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ== +invariant@^2.2.2: + version "2.2.4" + resolved "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" + integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== + dependencies: + loose-envify "^1.0.0" + invert-kv@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" @@ -4082,13 +4705,6 @@ is-buffer@^1.1.5: resolved "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== -is-builtin-module@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-3.2.1.tgz#f03271717d8654cfcaf07ab0463faa3571581169" - integrity sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A== - dependencies: - builtin-modules "^3.3.0" - is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.7: version "1.2.7" resolved "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" @@ -4172,6 +4788,11 @@ is-extglob@^2.1.0, is-extglob@^2.1.1: resolved "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== +is-finite@^1.0.0: + version "1.1.0" + resolved "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz#904135c77fb42c0641d6aa1bcdbc4daa8da082f3" + integrity sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w== + is-fullwidth-code-point@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" @@ -4179,6 +4800,11 @@ is-fullwidth-code-point@^1.0.0: dependencies: number-is-nan "^1.0.0" +is-fullwidth-code-point@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + integrity sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w== + is-fullwidth-code-point@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" @@ -4380,6 +5006,11 @@ is-windows@^1.0.1, is-windows@^1.0.2: resolved "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== +isarray@0.0.1: + version "0.0.1" + resolved "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" + integrity sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ== + isarray@1.0.0, isarray@~1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" @@ -4469,11 +5100,16 @@ js-cookie@^3.0.5: resolved "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz#0b7e2fd0c01552c58ba86e0841f94dc2557dcdbc" integrity sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw== -js-tokens@^4.0.0: +"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== +js-tokens@^3.0.2: + version "3.0.2" + resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" + integrity sha512-RjTcuD4xjtthQkaWH7dFlH85L+QaVtSoOyGdZ3g6HFhS9dFNDfLyqgm2NFe2X6cQpeFmt0452FJjFG5UameExg== + js-yaml@4.1.0, js-yaml@^4.1.0: version "4.1.0" resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" @@ -4481,16 +5117,19 @@ js-yaml@4.1.0, js-yaml@^4.1.0: dependencies: argparse "^2.0.1" +js-yaml@^3.13.1: + version "3.14.1" + resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" + integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + jsbn@~0.1.0: version "0.1.1" resolved "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" integrity sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg== -jsdoc-type-pratt-parser@~4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-4.0.0.tgz#136f0571a99c184d84ec84662c45c29ceff71114" - integrity sha512-YtOli5Cmzy3q4dP26GraSOeAhqecewG04hoO8DY56CH4KJ9Fvv5qKWUCCo3HZob7esJQHCv6/+bnTy72xZZaVQ== - jsdom-global@^3.0.2: version "3.0.2" resolved "https://registry.npmjs.org/jsdom-global/-/jsdom-global-3.0.2.tgz#6bd299c13b0c4626b2da2c0393cd4385d606acb9" @@ -4557,6 +5196,32 @@ jsdom@22.1.0: ws "^8.13.0" xml-name-validator "^4.0.0" +jsdom@^7.0.2: + version "7.2.2" + resolved "https://registry.npmjs.org/jsdom/-/jsdom-7.2.2.tgz#40b402770c2bda23469096bee91ab675e3b1fc6e" + integrity sha512-kYeYuos/pYp0V/V8VAoGnUc0va0UZjTjwCsldBFZNBrOi9Q5kUXrvsw6W5/lQllB7hKXBARC4HRk1Sfk4dPFtA== + dependencies: + abab "^1.0.0" + acorn "^2.4.0" + acorn-globals "^1.0.4" + cssom ">= 0.3.0 < 0.4.0" + cssstyle ">= 0.2.29 < 0.3.0" + escodegen "^1.6.1" + nwmatcher ">= 1.3.7 < 2.0.0" + parse5 "^1.5.1" + request "^2.55.0" + sax "^1.1.4" + symbol-tree ">= 3.1.0 < 4.0.0" + tough-cookie "^2.2.0" + webidl-conversions "^2.0.0" + whatwg-url-compat "~0.6.5" + xml-name-validator ">= 2.0.1 < 3.0.0" + +jsesc@^1.3.0: + version "1.3.0" + resolved "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" + integrity sha512-Mke0DA0QjUWuJlhsE0ZPPhYiJkRap642SmI/4ztCFaUs6V2AiH1sfecc+57NgaryfAA2VR3v6O+CSjC1jZJKOA== + jsesc@^2.5.1: version "2.5.2" resolved "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" @@ -4602,11 +5267,6 @@ json5@^2.1.2, json5@^2.2.3: resolved "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== -jsonc-parser@^3.2.0: - version "3.2.1" - resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-3.2.1.tgz#031904571ccf929d7670ee8c547545081cb37f1a" - integrity sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA== - jsonfile@^2.1.0: version "2.4.0" resolved "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz#3736a2b428b87bbda0cc83b53fa3d633a35c2ae8" @@ -4798,6 +5458,14 @@ lead@^1.0.0: dependencies: flush-write-stream "^1.0.2" +levn@^0.3.0, levn@~0.3.0: + version "0.3.0" + resolved "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" + integrity sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA== + dependencies: + prelude-ls "~1.1.2" + type-check "~0.3.2" + levn@^0.4.1: version "0.4.1" resolved "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" @@ -4806,14 +5474,6 @@ levn@^0.4.1: prelude-ls "^1.2.1" type-check "~0.4.0" -levn@~0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" - integrity sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA== - dependencies: - prelude-ls "~1.1.2" - type-check "~0.3.2" - liftoff@^3.1.0: version "3.1.0" resolved "https://registry.npmjs.org/liftoff/-/liftoff-3.1.0.tgz#c9ba6081f908670607ee79062d700df062c52ed3" @@ -4872,6 +5532,16 @@ lodash-es@^4.17.21: resolved "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee" integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw== +lodash.assignin@^4.0.9: + version "4.2.0" + resolved "https://registry.npmjs.org/lodash.assignin/-/lodash.assignin-4.2.0.tgz#ba8df5fb841eb0a3e8044232b0e263a8dc6a28a2" + integrity sha512-yX/rx6d/UTVh7sSVWVSIMjfnz95evAgDFdb1ZozC35I9mSFCkmzptOzevxjgbQUsc78NR44LVHWjsoMQXy9FDg== + +lodash.bind@^4.1.4: + version "4.2.1" + resolved "https://registry.npmjs.org/lodash.bind/-/lodash.bind-4.2.1.tgz#7ae3017e939622ac31b7d7d7dcb1b34db1690d35" + integrity sha512-lxdsn7xxlCymgLYo1gGvVrfHmkjDiyqVv62FAeF2i5ta72BipE1SLxw8hPEPLhD4/247Ijw07UQH7Hq/chT5LA== + lodash.clone@^4.3.2: version "4.5.0" resolved "https://registry.npmjs.org/lodash.clone/-/lodash.clone-4.5.0.tgz#195870450f5a13192478df4bc3d23d2dea1907b6" @@ -4882,6 +5552,26 @@ lodash.clonedeep@^4.5.0: resolved "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" integrity sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ== +lodash.defaults@^4.0.1: + version "4.2.0" + resolved "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c" + integrity sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ== + +lodash.filter@^4.4.0: + version "4.6.0" + resolved "https://registry.npmjs.org/lodash.filter/-/lodash.filter-4.6.0.tgz#668b1d4981603ae1cc5a6fa760143e480b4c4ace" + integrity sha512-pXYUy7PR8BCLwX5mgJ/aNtyOvuJTdZAo9EQFUvMIYugqmJxnrYaANvTbgndOzHSCSR0wnlBBfRXJL5SbWxo3FQ== + +lodash.flatten@^4.2.0: + version "4.4.0" + resolved "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz#f31c22225a9632d2bbf8e4addbef240aa765a61f" + integrity sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g== + +lodash.foreach@^4.3.0: + version "4.5.0" + resolved "https://registry.npmjs.org/lodash.foreach/-/lodash.foreach-4.5.0.tgz#1a6a35eace401280c7f06dddec35165ab27e3e53" + integrity sha512-aEXTF4d+m05rVOAUG3z4vZZ4xVexLKZGF0lIxuHZ1Hplpk/3B6Z1+/ICICYRLm7c41Z2xiejbkCkJoTlypoXhQ== + lodash.get@^4.4.2: version "4.4.2" resolved "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" @@ -4892,12 +5582,32 @@ lodash.isequal@^4.5.0: resolved "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" integrity sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ== -lodash.merge@^4.6.2: +lodash.map@^4.4.0: + version "4.6.0" + resolved "https://registry.npmjs.org/lodash.map/-/lodash.map-4.6.0.tgz#771ec7839e3473d9c4cde28b19394c3562f4f6d3" + integrity sha512-worNHGKLDetmcEYDvh2stPCrrQRkP20E4l0iIS7F8EvzMqBBi7ltvFN5m1HvTf1P7Jk1txKhvFcmYsCr8O2F1Q== + +lodash.merge@^4.4.0, lodash.merge@^4.6.2: version "4.6.2" resolved "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== -lodash.some@^4.2.2: +lodash.pick@^4.2.1: + version "4.4.0" + resolved "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz#52f05610fff9ded422611441ed1fc123a03001b3" + integrity sha512-hXt6Ul/5yWjfklSGvLQl8vM//l3FtyHZeuelpzK6mm99pNvN9yTDruNZPEJZD1oWrqo+izBmB7oUfWgcCX7s4Q== + +lodash.reduce@^4.4.0: + version "4.6.0" + resolved "https://registry.npmjs.org/lodash.reduce/-/lodash.reduce-4.6.0.tgz#f1ab6b839299ad48f784abbf476596f03b914d3b" + integrity sha512-6raRe2vxCYBhpBu+B+TtNGUzah+hQjVdu3E17wfusjyrXBka2nBS8OH/gjVZ5PvHOhWmIZTYri09Z6n/QfnNMw== + +lodash.reject@^4.4.0: + version "4.6.0" + resolved "https://registry.npmjs.org/lodash.reject/-/lodash.reject-4.6.0.tgz#80d6492dc1470864bbf583533b651f42a9f52415" + integrity sha512-qkTuvgEzYdyhiJBx42YPzPo71R1aEr0z79kAv7Ixg8wPFEjgRgJdUsGMG3Hf3OYSF/kHI79XhNlt+5Ar6OzwxQ== + +lodash.some@^4.2.2, lodash.some@^4.4.0: version "4.6.0" resolved "https://registry.npmjs.org/lodash.some/-/lodash.some-4.6.0.tgz#1bb9f314ef6b8baded13b549169b2a945eb68e4d" integrity sha512-j7MJE+TuT51q9ggt4fSgVqro163BEFjAt3u97IqU+JA2DkWl80nFTrowzLpZ/BnpN7rrl0JA/593NAdd8p/scQ== @@ -4907,7 +5617,7 @@ lodash.sortby@^4.7.0: resolved "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" integrity sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA== -lodash@^4.0.1, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.21: +lodash@^4.0.1, lodash@^4.1.0, lodash@^4.15.0, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.21, lodash@^4.17.4, lodash@^4.2.0: version "4.17.21" resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -4938,6 +5648,13 @@ log4js@^6.4.1: rfdc "^1.3.0" streamroller "^3.1.5" +loose-envify@^1.0.0: + version "1.4.0" + resolved "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" + integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== + dependencies: + js-tokens "^3.0.0 || ^4.0.0" + loupe@^2.3.6: version "2.3.7" resolved "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz#6e69b7d4db7d3ab436328013d37d1c8c3540c697" @@ -4972,11 +5689,6 @@ lru-cache@^6.0.0: dependencies: yallist "^4.0.0" -lunr@^2.3.9: - version "2.3.9" - resolved "https://registry.yarnpkg.com/lunr/-/lunr-2.3.9.tgz#18b123142832337dd6e964df1a5a7707b25d35e1" - integrity sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow== - make-error@^1.1.1: version "1.3.6" resolved "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" @@ -5001,10 +5713,10 @@ map-visit@^1.0.0: dependencies: object-visit "^1.0.0" -marked@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/marked/-/marked-4.3.0.tgz#796362821b019f734054582038b116481b456cf3" - integrity sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A== +marked@0.3.19: + version "0.3.19" + resolved "https://registry.npmjs.org/marked/-/marked-0.3.19.tgz#5d47f709c4c9fc3c216b6d46127280f40b39d790" + integrity sha512-ea2eGWOqNxPcXv8dyERdSr/6FmzvWwzjMxpfGB/sbMccXoct+xY+YukPD+QTUZwyvK7BZwcr4m21WBOW41pAkg== matchdep@^2.0.0: version "2.0.0" @@ -5107,6 +5819,11 @@ mime@^2.5.2: resolved "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz#a2a682a95cd4d0cb1d6257e28f83da7e35800367" integrity sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg== +mimic-fn@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" + integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== + min-document@^2.19.0: version "2.19.0" resolved "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz#7bd282e3f5842ed295bb748cdd9f1ffa2c824685" @@ -5149,7 +5866,12 @@ minimatch@^9.0.1, minimatch@^9.0.3, minimatch@^9.0.4: dependencies: brace-expansion "^2.0.1" -minimist@^1.2.3, minimist@^1.2.6: +minimist@1.2.0: + version "1.2.0" + resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" + integrity sha512-7Wl+Jz+IGWuSdgsQEJ4JunV0si/iMhg42MnQQG6h1R6TNeVenp4U9x5CC5v/gYqz/fENLQITAWXidNtVL0NNbw== + +minimist@^1.1.0, minimist@^1.2.3, minimist@^1.2.6: version "1.2.8" resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== @@ -5167,7 +5889,7 @@ mixin-deep@^1.2.0: for-in "^1.0.2" is-extendable "^1.0.1" -mkdirp@^0.5.4, mkdirp@^0.5.5: +mkdirp@^0.5.1, mkdirp@^0.5.4, mkdirp@^0.5.5: version "0.5.6" resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== @@ -5256,6 +5978,11 @@ mute-stdout@^1.0.0: resolved "https://registry.npmjs.org/mute-stdout/-/mute-stdout-1.0.1.tgz#acb0300eb4de23a7ddeec014e3e96044b3472331" integrity sha512-kDcwXR4PS7caBpuRYYBUz9iVixUk3anO3f5OYFiIPwK/20vCzKCHyKoulbiDY1S53zD2bxUpxN/IJ+TnXjfvxg== +mute-stream@0.0.8: + version "0.0.8" + resolved "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" + integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== + nan@^2.12.1: version "2.19.0" resolved "https://registry.npmjs.org/nan/-/nan-2.19.0.tgz#bb58122ad55a6c5bc973303908d5b16cfdd5a8c0" @@ -5303,6 +6030,11 @@ next-tick@^1.1.0: resolved "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz#1836ee30ad56d67ef281b22bd199f709449b35eb" integrity sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ== +nice-try@^1.0.4: + version "1.0.5" + resolved "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" + integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== + nise@^5.1.5: version "5.1.9" resolved "https://registry.npmjs.org/nise/-/nise-5.1.9.tgz#0cb73b5e4499d738231a473cd89bd8afbb618139" @@ -5362,11 +6094,23 @@ now-and-later@^2.0.0: dependencies: once "^1.3.2" +nth-check@~1.0.1: + version "1.0.2" + resolved "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz#b2bd295c37e3dd58a3bf0700376663ba4d9cf05c" + integrity sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg== + dependencies: + boolbase "~1.0.0" + number-is-nan@^1.0.0: version "1.0.1" resolved "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" integrity sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ== +"nwmatcher@>= 1.3.7 < 2.0.0": + version "1.4.4" + resolved "https://registry.npmjs.org/nwmatcher/-/nwmatcher-1.4.4.tgz#2285631f34a95f0d0395cd900c96ed39b58f346e" + integrity sha512-3iuY4N5dhgMpCUrOVnuAdGrgxVqV2cJpM+XNccjR2DKOB1RUP0aA+wGXEiNziG/UKboFyGBIoKOaNlJxx8bciQ== + nwsapi@^2.0.9, nwsapi@^2.2.4: version "2.2.7" resolved "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.7.tgz#738e0707d3128cb750dddcfe90e4610482df0f30" @@ -5480,12 +6224,19 @@ once@^1.3.0, once@^1.3.1, once@^1.3.2, once@^1.4.0: dependencies: wrappy "1" +onetime@^5.1.0: + version "5.1.2" + resolved "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" + integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== + dependencies: + mimic-fn "^2.1.0" + opener@^1.5.2: version "1.5.2" resolved "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz#5d37e1f35077b9dcac4301372271afdeb2a13598" integrity sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A== -optionator@^0.8.1: +optionator@^0.8.1, optionator@^0.8.3: version "0.8.3" resolved "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== @@ -5528,6 +6279,11 @@ os-shim@^0.1.2: resolved "https://registry.npmjs.org/os-shim/-/os-shim-0.1.3.tgz#6b62c3791cf7909ea35ed46e17658bb417cb3917" integrity sha512-jd0cvB8qQ5uVt0lvCIexBaROw1KyKm5sbulg2fWOHjETisuCzWyt+eTZKEMs8v6HwzoGs8xik26jg7eCM6pS+A== +os-tmpdir@~1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g== + p-limit@^2.2.0: version "2.3.0" resolved "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" @@ -5614,6 +6370,18 @@ parse5@5.1.0: resolved "https://registry.npmjs.org/parse5/-/parse5-5.1.0.tgz#c59341c9723f414c452975564c7c00a68d58acd2" integrity sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ== +parse5@^1.5.1: + version "1.5.1" + resolved "https://registry.npmjs.org/parse5/-/parse5-1.5.1.tgz#9b7f3b0de32be78dc2401b17573ccaf0f6f59d94" + integrity sha512-w2jx/0tJzvgKwZa58sj2vAYq/S/K1QJfIB3cWYea/Iu1scFPDQQ3IQiVZTHWtRBwAjv2Yd7S/xeZf3XqLDb3bA== + +parse5@^3.0.1: + version "3.0.3" + resolved "https://registry.npmjs.org/parse5/-/parse5-3.0.3.tgz#042f792ffdd36851551cf4e9e066b3874ab45b5c" + integrity sha512-rgO9Zg5LLLkfJF9E6CCmXlSE4UVceloys8JrFqCcHloC3usd/kJCyPDwH2SOlzix2j3xaP9sUX3e8+kvkuleAA== + dependencies: + "@types/node" "*" + parse5@^7.1.2: version "7.1.2" resolved "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz#0736bebbfd77793823240a23b7fc5e010b7f8e32" @@ -5653,6 +6421,11 @@ path-is-absolute@^1.0.0, path-is-absolute@^1.0.1: resolved "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== +path-key@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" + integrity sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw== + path-key@^3.1.0: version "3.1.1" resolved "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" @@ -5959,6 +6732,11 @@ progress@^1.1.8: resolved "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz#e260c78f6161cdd9b0e56cc3e0a85de17c7a57be" integrity sha512-UdA8mJ4weIkUBO224tIarHzuHs4HuYiJvsuGT7j/SPQiUJVjYvNDBIPa0hAorduOfjGohB/qHWRa/lrrWX/mXw== +progress@^2.0.0: + version "2.0.3" + resolved "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" + integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== + proto-list@~1.2.1: version "1.2.4" resolved "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849" @@ -6113,7 +6891,17 @@ read-pkg@^1.0.0: normalize-package-data "^2.3.2" path-type "^1.0.0" -"readable-stream@2 || 3", readable-stream@3, readable-stream@^3.0.6: +readable-stream@1.1: + version "1.1.13" + resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.13.tgz#f6eef764f514c89e2b9e23146a75ba106756d23e" + integrity sha512-E98tWzqShvKDGpR2MbjsDkDQWLW2TfWUC15H4tNQhIJ5Lsta84l8nUGL9/ybltGwe+wZzWPpc1Kmd2wQP4bdCA== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + +"readable-stream@2 || 3", readable-stream@3, readable-stream@^3.0.6, readable-stream@^3.1.1: version "3.6.2" resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== @@ -6172,6 +6960,11 @@ redux@^4.2.0: dependencies: "@babel/runtime" "^7.9.2" +regenerator-runtime@^0.11.0: + version "0.11.1" + resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" + integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== + regenerator-runtime@^0.14.0: version "0.14.1" resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f" @@ -6202,6 +6995,11 @@ regexp.prototype.flags@^1.5.2: es-errors "^1.3.0" set-function-name "^2.0.1" +regexpp@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f" + integrity sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw== + remove-bom-buffer@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz#c2bf1e377520d324f623892e33c10cac2c252b53" @@ -6234,6 +7032,20 @@ repeat-string@^1.5.2, repeat-string@^1.6.1: resolved "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" integrity sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w== +repeating@^1.1.0: + version "1.1.3" + resolved "https://registry.npmjs.org/repeating/-/repeating-1.1.3.tgz#3d4114218877537494f97f77f9785fab810fa4ac" + integrity sha512-Nh30JLeMHdoI+AsQ5eblhZ7YlTsM9wiJQe/AHIunlK3KWzvXhXb36IJ7K1IOeRjIOtzMjdUHjwXUFxKJoPTSOg== + dependencies: + is-finite "^1.0.0" + +repeating@^2.0.0: + version "2.0.1" + resolved "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" + integrity sha512-ZqtSMuVybkISo2OWvqvm7iHSWngvdaW3IpsT9/uP8v4gMi591LY6h35wdOfvQdWCKFWZWm2Y1Opp4kV7vQKT6A== + dependencies: + is-finite "^1.0.0" + replace-ext@0.0.1: version "0.0.1" resolved "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz#29bbd92078a739f0bcce2b4ee41e837953522924" @@ -6290,7 +7102,7 @@ request-promise-native@^1.0.5: stealthy-require "^1.1.1" tough-cookie "^2.3.3" -request@^2.81.0, request@^2.88.0: +request@^2.55.0, request@^2.81.0, request@^2.88.0: version "2.88.2" resolved "https://registry.npmjs.org/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== @@ -6377,6 +7189,14 @@ resolve@^1.1.6, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.20.0, resolve@^1.4.0 path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" +restore-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" + integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== + dependencies: + onetime "^5.1.0" + signal-exit "^3.0.2" + ret@~0.1.10: version "0.1.15" resolved "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" @@ -6392,6 +7212,13 @@ rfdc@^1.3.0: resolved "https://registry.npmjs.org/rfdc/-/rfdc-1.3.1.tgz#2b6d4df52dffe8bb346992a10ea9451f24373a8f" integrity sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg== +rimraf@2.6.3: + version "2.6.3" + resolved "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" + integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== + dependencies: + glob "^7.1.3" + rimraf@^2.6.2: version "2.7.1" resolved "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" @@ -6411,6 +7238,11 @@ rrweb-cssom@^0.6.0: resolved "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.6.0.tgz#ed298055b97cbddcdeb278f904857629dec5e0e1" integrity sha512-APM0Gt1KoXBz0iIkkdB/kfvGOwC4UuJFeG/c+yV7wSc7q96cG/kJ0HiYCnzivD9SB53cLV1MlHFNfOuPaadYSw== +run-async@^2.4.0: + version "2.4.1" + resolved "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455" + integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ== + run-parallel@^1.1.9: version "1.2.0" resolved "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" @@ -6418,6 +7250,13 @@ run-parallel@^1.1.9: dependencies: queue-microtask "^1.2.2" +rxjs@^6.6.0: + version "6.6.7" + resolved "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz#90ac018acabf491bf65044235d5863c4dab804c9" + integrity sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ== + dependencies: + tslib "^1.9.0" + safe-array-concat@^1.1.2: version "1.1.2" resolved "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz#81d77ee0c4e8b863635227c721278dd524c20edb" @@ -6468,6 +7307,11 @@ sass@^1.74.1: immutable "^4.0.0" source-map-js ">=0.6.2 <2.0.0" +sax@^1.1.4: + version "1.3.0" + resolved "https://registry.npmjs.org/sax/-/sax-1.3.0.tgz#a5dbe77db3be05c9d1ee7785dbd3ea9de51593d0" + integrity sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA== + saxes@^3.1.5: version "3.1.11" resolved "https://registry.npmjs.org/saxes/-/saxes-3.1.11.tgz#d59d1fd332ec92ad98a2e0b2ee644702384b1c5b" @@ -6498,12 +7342,12 @@ semver-greatest-satisfied-range@^1.1.0: dependencies: sver-compat "^1.5.0" -"semver@2 || 3 || 4 || 5": +"semver@2 || 3 || 4 || 5", semver@^5.5.0: version "5.7.2" resolved "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== -semver@^6.3.1: +semver@^6.1.2, semver@^6.3.1: version "6.3.1" resolved "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== @@ -6602,16 +7446,6 @@ shebang-regex@^3.0.0: resolved "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== -shiki@^0.14.7: - version "0.14.7" - resolved "https://registry.yarnpkg.com/shiki/-/shiki-0.14.7.tgz#c3c9e1853e9737845f1d2ef81b31bcfb07056d4e" - integrity sha512-dNPAPrxSc87ua2sKJ3H5dQ/6ZaY8RNnaAqK+t0eG7p0Soi2ydiqbGOTaZCqaYvA/uZYfS1LJnemt3Q+mSfcPCg== - dependencies: - ansi-sequence-parser "^1.1.0" - jsonc-parser "^3.2.0" - vscode-oniguruma "^1.7.0" - vscode-textmate "^8.0.0" - shortcut-buttons-flatpickr@^0.4.0: version "0.4.0" resolved "https://registry.npmjs.org/shortcut-buttons-flatpickr/-/shortcut-buttons-flatpickr-0.4.0.tgz#a36e0a88a670ed2637b7b1adb5bee0914c29a7e7" @@ -6627,6 +7461,11 @@ side-channel@^1.0.4: get-intrinsic "^1.2.4" object-inspect "^1.13.1" +signal-exit@^3.0.2: + version "3.0.7" + resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== + signal-exit@^4.0.1: version "4.1.0" resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" @@ -6668,6 +7507,15 @@ slash@^3.0.0: resolved "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== +slice-ansi@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636" + integrity sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ== + dependencies: + ansi-styles "^3.2.0" + astral-regex "^1.0.0" + is-fullwidth-code-point "^2.0.0" + snapdragon-node@^2.0.1: version "2.1.1" resolved "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" @@ -6756,7 +7604,7 @@ source-map-url@^0.4.0: resolved "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz#0af66605a745a5a2f91cf1bbf8a7afbc283dec56" integrity sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw== -source-map@^0.5.1, source-map@^0.5.6: +source-map@^0.5.0, source-map@^0.5.1, source-map@^0.5.6, source-map@^0.5.7: version "0.5.7" resolved "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ== @@ -6810,14 +7658,6 @@ spdx-expression-parse@^3.0.0: spdx-exceptions "^2.1.0" spdx-license-ids "^3.0.0" -spdx-expression-parse@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-4.0.0.tgz#a23af9f3132115465dac215c099303e4ceac5794" - integrity sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ== - dependencies: - spdx-exceptions "^2.1.0" - spdx-license-ids "^3.0.0" - spdx-license-ids@^3.0.0: version "3.0.17" resolved "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.17.tgz#887da8aa73218e51a1d917502d79863161a93f9c" @@ -6830,6 +7670,11 @@ split-string@^3.0.1, split-string@^3.0.2: dependencies: extend-shallow "^3.0.0" +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== + sshpk@^1.7.0: version "1.18.0" resolved "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz#1663e55cddf4d688b86a46b77f0d5fe363aba028" @@ -6930,6 +7775,15 @@ string-width@^1.0.1, string-width@^1.0.2: is-fullwidth-code-point "^1.0.0" strip-ansi "^3.0.0" +string-width@^3.0.0: + version "3.1.0" + resolved "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" + integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== + dependencies: + emoji-regex "^7.0.1" + is-fullwidth-code-point "^2.0.0" + strip-ansi "^5.1.0" + string-width@^5.0.1, string-width@^5.1.2: version "5.1.2" resolved "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" @@ -6974,6 +7828,11 @@ string_decoder@^1.1.1: dependencies: safe-buffer "~5.2.0" +string_decoder@~0.10.x: + version "0.10.31" + resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" + integrity sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ== + string_decoder@~1.1.1: version "1.1.1" resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" @@ -7011,6 +7870,13 @@ strip-ansi@^4.0.0: dependencies: ansi-regex "^3.0.0" +strip-ansi@^5.1.0, strip-ansi@^5.2.0: + version "5.2.0" + resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" + integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== + dependencies: + ansi-regex "^4.1.0" + strip-ansi@^7.0.1: version "7.1.0" resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" @@ -7033,7 +7899,7 @@ strip-bom@^2.0.0: dependencies: is-utf8 "^0.2.0" -strip-json-comments@3.1.1, strip-json-comments@^3.1.1: +strip-json-comments@3.1.1, strip-json-comments@^3.0.1, strip-json-comments@^3.1.1: version "3.1.1" resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== @@ -7045,6 +7911,11 @@ supports-color@8.1.1, supports-color@^8.0.0, supports-color@^8.1.1: dependencies: has-flag "^4.0.0" +supports-color@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" + integrity sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g== + supports-color@^5.3.0: version "5.5.0" resolved "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" @@ -7072,11 +7943,31 @@ sver-compat@^1.5.0: es6-iterator "^2.0.1" es6-symbol "^3.1.1" -symbol-tree@^3.2.2, symbol-tree@^3.2.4: +"symbol-tree@>= 3.1.0 < 4.0.0", symbol-tree@^3.2.2, symbol-tree@^3.2.4: version "3.2.4" resolved "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== +table@^5.2.3: + version "5.4.6" + resolved "https://registry.npmjs.org/table/-/table-5.4.6.tgz#1292d19500ce3f86053b05f0e8e7e4a3bb21079e" + integrity sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug== + dependencies: + ajv "^6.10.2" + lodash "^4.17.14" + slice-ansi "^2.1.0" + string-width "^3.0.0" + +taffydb@2.7.2: + version "2.7.2" + resolved "https://registry.npmjs.org/taffydb/-/taffydb-2.7.2.tgz#7bf8106a5c1a48251b3e3bc0a0e1732489fd0dc8" + integrity sha512-R6es6/C/m1xXZckrSam4j07YKbd74437mRJ/R944S1hLG7mIl2/EQW7tQPI4XiX7jTduFzz31g7466a2BcsglQ== + +taffydb@2.7.3: + version "2.7.3" + resolved "https://registry.npmjs.org/taffydb/-/taffydb-2.7.3.tgz#2ad37169629498fca5bc84243096d3cde0ec3a34" + integrity sha512-GQ3gtYFSOAxSMN/apGtDKKkbJf+8izz5YfbGqIsUc7AMiQOapARZ76dhilRY2h39cynYxBFdafQo5HUL5vgkrg== + tapable@^2.1.1, tapable@^2.2.0: version "2.2.1" resolved "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" @@ -7147,7 +8038,7 @@ through2@^4.0.2: dependencies: readable-stream "3" -through@^2.3.8: +through@^2.3.6, through@^2.3.8: version "2.3.8" resolved "https://registry.npmjs.org/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== @@ -7169,6 +8060,13 @@ tippy.js@^6.3.7: dependencies: "@popperjs/core" "^2.9.0" +tmp@^0.0.33: + version "0.0.33" + resolved "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" + integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== + dependencies: + os-tmpdir "~1.0.2" + tmp@^0.2.1: version "0.2.3" resolved "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz#eb783cc22bc1e8bebd0671476d46ea4eb32a79ae" @@ -7182,6 +8080,11 @@ to-absolute-glob@^2.0.0, to-absolute-glob@^2.0.2: is-absolute "^1.0.0" is-negated-glob "^1.0.0" +to-fast-properties@^1.0.3: + version "1.0.3" + resolved "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" + integrity sha512-lxrWP8ejsq+7E3nNjwYmUBMAgjMTZoTI+sdBOpvNyijeDLa29LUn9QaoXAHv4+Z578hbmHHJKZknzxVtvo77og== + to-fast-properties@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" @@ -7236,7 +8139,7 @@ totalist@^3.0.0: resolved "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz#ba3a3d600c915b1a97872348f79c127475f6acf8" integrity sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ== -tough-cookie@^2.3.3, tough-cookie@^2.5.0, tough-cookie@~2.5.0: +tough-cookie@^2.2.0, tough-cookie@^2.3.3, tough-cookie@^2.5.0, tough-cookie@~2.5.0: version "2.5.0" resolved "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== @@ -7268,7 +8171,7 @@ tr46@^4.1.1: dependencies: punycode "^2.3.0" -tr46@~0.0.3: +tr46@~0.0.1, tr46@~0.0.3: version "0.0.3" resolved "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== @@ -7282,6 +8185,11 @@ traverse@^0.6.6: typedarray.prototype.slice "^1.0.3" which-typed-array "^1.1.15" +trim-right@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" + integrity sha512-WZGXGstmCWgeevgTL54hrCuw1dyMQIzWy7ZfqRJfSmJZBwklI15egmQytFP6bPidmw3M8d5yEowl1niq4vmqZw== + ts-api-utils@^1.3.0: version "1.3.0" resolved "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz#4b490e27129f1e8e686b45cc4ab63714dc60eea1" @@ -7322,6 +8230,11 @@ tsc@^2.0.4: resolved "https://registry.yarnpkg.com/tsc/-/tsc-2.0.4.tgz#5f6499146abea5dca4420b451fa4f2f9345238f5" integrity sha512-fzoSieZI5KKJVBYGvwbVZs/J5za84f2lSTLPYf6AGiIf43tZ3GNrI1QzTLcjtyDDP4aLxd46RTZq1nQxe7+k5Q== +tslib@^1.9.0: + version "1.14.1" + resolved "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" + integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== + tunnel-agent@^0.6.0: version "0.6.0" resolved "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" @@ -7358,6 +8271,16 @@ type-fest@^0.20.2: resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== +type-fest@^0.21.3: + version "0.21.3" + resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" + integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== + +type-fest@^0.8.1: + version "0.8.1" + resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" + integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== + type-func@^1.0.1: version "1.0.3" resolved "https://registry.npmjs.org/type-func/-/type-func-1.0.3.tgz#ab184234ae80d8d50057cefeff3b2d97d08ae9b0" @@ -7442,16 +8365,6 @@ typedarray@^0.0.6: resolved "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA== -typedoc@^0.25.13: - version "0.25.13" - resolved "https://registry.yarnpkg.com/typedoc/-/typedoc-0.25.13.tgz#9a98819e3b2d155a6d78589b46fa4c03768f0922" - integrity sha512-pQqiwiJ+Z4pigfOnnysObszLiU3mVLWAExSPf+Mu06G/qsc3wzbuM56SZQvONhHLncLUhYzOVkjFFpFfL5AzhQ== - dependencies: - lunr "^2.3.9" - marked "^4.3.0" - minimatch "^9.0.3" - shiki "^0.14.7" - typescript@5.3.2: version "5.3.2" resolved "https://registry.npmjs.org/typescript/-/typescript-5.3.2.tgz#00d1c7c1c46928c5845c1ee8d0cc2791031d4c43" @@ -7616,6 +8529,11 @@ v8-compile-cache-lib@^3.0.1: resolved "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== +v8-compile-cache@^2.0.3: + version "2.4.0" + resolved "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.4.0.tgz#cdada8bec61e15865f05d097c5f4fd30e94dc128" + integrity sha512-ocyWc3bAHBB/guyqJQVI5o4BZkPhznPYUG2ea80Gond/BgNWpap8TOmLSeeQG7bnh2KMISxskdADG59j7zruhw== + v8flags@^3.2.0: version "3.2.0" resolved "https://registry.npmjs.org/v8flags/-/v8flags-3.2.0.tgz#b243e3b4dfd731fa774e7492128109a0fe66d656" @@ -7738,16 +8656,6 @@ void-elements@^2.0.0: resolved "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec" integrity sha512-qZKX4RnBzH2ugr8Lxa7x+0V6XD9Sb/ouARtiasEQCHB1EVU4NXtmHsDDrx1dO4ne5fc3J6EW05BP1Dl0z0iung== -vscode-oniguruma@^1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz#439bfad8fe71abd7798338d1cd3dc53a8beea94b" - integrity sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA== - -vscode-textmate@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/vscode-textmate/-/vscode-textmate-8.0.0.tgz#2c7a3b1163ef0441097e0b5d6389cd5504b59e5d" - integrity sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg== - w3c-hr-time@^1.0.1: version "1.0.2" resolved "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz#0a89cdf5cc15822df9c360543676963e0cc308cd" @@ -7779,6 +8687,11 @@ watchpack@^2.4.1: glob-to-regexp "^0.4.1" graceful-fs "^4.1.2" +webidl-conversions@^2.0.0: + version "2.0.1" + resolved "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-2.0.1.tgz#3bf8258f7d318c7443c36f2e169402a1a6703506" + integrity sha512-OZ7I/f0sM+T28T2/OXinNGfmvjm3KKptdyQy8NPRZyLfYBn+9vt72Bfr+uQaE9OvWyxJjQ5kHFygH2wOTUb76g== + webidl-conversions@^3.0.0: version "3.0.1" resolved "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" @@ -7925,6 +8838,13 @@ whatwg-mimetype@^3.0.0: resolved "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz#5fa1a7623867ff1af6ca3dc72ad6b8a4208beba7" integrity sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q== +whatwg-url-compat@~0.6.5: + version "0.6.5" + resolved "https://registry.npmjs.org/whatwg-url-compat/-/whatwg-url-compat-0.6.5.tgz#00898111af689bb097541cd5a45ca6c8798445bf" + integrity sha512-vbg5+JVNwGtHRI3GheZGWrcUlxF9BXHbA80dLa+2XqJjlV/BK6upoi2j8dIRW9FGPUUyaMm7Hf1pTexHnsk85g== + dependencies: + tr46 "~0.0.1" + whatwg-url@^12.0.0, whatwg-url@^12.0.1: version "12.0.1" resolved "https://registry.npmjs.org/whatwg-url/-/whatwg-url-12.0.1.tgz#fd7bcc71192e7c3a2a97b9a8d6b094853ed8773c" @@ -8060,6 +8980,13 @@ wrappy@1: resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== +write@1.0.3: + version "1.0.3" + resolved "https://registry.npmjs.org/write/-/write-1.0.3.tgz#0800e14523b923a387e415123c865616aae0f5c3" + integrity sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig== + dependencies: + mkdirp "^0.5.1" + written-number@^0.11.1: version "0.11.1" resolved "https://registry.npmjs.org/written-number/-/written-number-0.11.1.tgz#ef060a7b5ad5ff8fbf4ff88daa8fb2260726ecc9" @@ -8087,6 +9014,11 @@ ws@~8.11.0: resolved "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz#6a0d36b8edfd9f96d8b25683db2f8d7de6e8e143" integrity sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg== +"xml-name-validator@>= 2.0.1 < 3.0.0": + version "2.0.1" + resolved "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-2.0.1.tgz#4d8b8f1eccd3419aa362061becef515e1e559635" + integrity sha512-jRKe/iQYMyVJpzPH+3HL97Lgu5HrCfii+qSo+TfjKHtOnvbnvdVfMYrn9Q34YV81M2e5sviJlI6Ko9y+nByzvA== + xml-name-validator@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a"