@jalik/form-parser
Advanced tools
Comparing version 2.0.12 to 3.0.0
{ | ||
"name": "@jalik/form-parser", | ||
"version": "2.0.12", | ||
"version": "3.0.0", | ||
"description": "A utility to parse complex forms with minimum effort.", | ||
@@ -26,37 +26,41 @@ "license": "MIT", | ||
}, | ||
"main": "dist/index.js", | ||
"esnext": "src/index.js", | ||
"sideEffects": false, | ||
"esnext": "./esm/index.js", | ||
"main": "./cjs/index.js", | ||
"module": "./esm/index.js", | ||
"files": [ | ||
"/cjs", | ||
"/esm" | ||
], | ||
"scripts": { | ||
"build": "babel src -d dist", | ||
"clean": "rimraf dist", | ||
"dev": "babel --watch src -d dist", | ||
"lint": "eslint .", | ||
"lint-fix": "eslint --fix .", | ||
"prepare": "npm run clean && npm run build && npm run lint", | ||
"prepublishOnly": "npm test", | ||
"build": "npm run build-cjs && npm run build-esm", | ||
"build-cjs": "tsc -p tsconfig.cjs.json", | ||
"build-esm": "tsc", | ||
"clean": "rimraf ./cjs ./esm", | ||
"dev-cjs": "tsc --watch -p tsconfig.cjs.json", | ||
"dev-esm": "tsc --watch", | ||
"dev": "concurrently 'npm:dev-*'", | ||
"lint": "eslint --ext .ts .", | ||
"lint-fix": "eslint --ext .ts --fix .", | ||
"prepare": "npm run clean && npm run build", | ||
"prepublishOnly": "npm run lint && npm test", | ||
"test": "jest --passWithNoTests --coverage=true" | ||
}, | ||
"files": [ | ||
"/dist", | ||
"/src" | ||
], | ||
"dependencies": { | ||
"@babel/runtime": "^7.19.4" | ||
}, | ||
"devDependencies": { | ||
"@babel/cli": "^7.19.3", | ||
"@babel/core": "^7.19.3", | ||
"@babel/plugin-transform-runtime": "^7.19.1", | ||
"@babel/preset-env": "^7.19.4", | ||
"@jest/globals": "^29.2.1", | ||
"acorn": "^8.8.0", | ||
"eslint": "^8.25.0", | ||
"eslint-config-airbnb-base": "^15.0.0", | ||
"eslint-plugin-import": "^2.26.0", | ||
"eslint-plugin-jest": "^27.1.3", | ||
"jest": "^29.2.1", | ||
"@babel/cli": "^7.22.5", | ||
"@babel/preset-env": "^7.21.5", | ||
"@babel/preset-typescript": "^7.21.5", | ||
"@jest/globals": "^29.5.0", | ||
"@typescript-eslint/eslint-plugin": "^5.59.2", | ||
"@typescript-eslint/parser": "^5.59.2", | ||
"concurrently": "^8.2.0", | ||
"eslint": "^8.43.0", | ||
"eslint-config-standard": "^17.1.0", | ||
"eslint-plugin-import": "^2.27.5", | ||
"eslint-plugin-jest": "^27.2.2", | ||
"jest": "^29.5.0", | ||
"jest-environment-jsdom": "^29.2.1", | ||
"typescript": "^4.8.4" | ||
"rimraf": "^5.0.1", | ||
"typescript": "^5.0.4" | ||
} | ||
} |
300
README.md
# @jalik/form-parser | ||
![GitHub package.json version](https://img.shields.io/github/package-json/v/jalik/js-form-parser.svg) | ||
[![Build Status](https://travis-ci.com/jalik/js-form-parser.svg?branch=master)](https://travis-ci.com/jalik/js-form-parser) | ||
![Build Status](https://github.com/jalik/js-form-parser/actions/workflows/node.js.yml/badge.svg) | ||
![Last commit](https://img.shields.io/github/last-commit/jalik/js-form-parser.svg) | ||
[![GitHub issues](https://img.shields.io/github/issues/jalik/js-form-parser.svg)](https://github.com/jalik/js-form-parser/issues) | ||
![GitHub](https://img.shields.io/github/license/jalik/js-form-parser.svg) | ||
![GitHub last commit](https://img.shields.io/github/last-commit/jalik/js-form-parser.svg) | ||
[![GitHub issues](https://img.shields.io/github/issues/jalik/js-form-parser.svg)](https://github.com/jalik/js-form-parser/issues) | ||
![npm](https://img.shields.io/npm/dt/@jalik/form-parser.svg) | ||
@@ -13,3 +14,6 @@ | ||
Parsing forms can be painful, but with this great library you can get all fields from a form, automatically parse values (boolean, number, string, array, object), remove unnecessary spaces from strings and replace empty strings with null, plus you can decide which fields are collected or ignored and even use your own cleaning function. | ||
Parsing forms can be painful, but with this great library you can get all fields from a form, | ||
automatically parse values (boolean, number, string, array, object), remove unnecessary spaces from | ||
strings and replace empty strings with null, plus you can decide which fields are collected or | ||
ignored and even use your own cleaning function. | ||
@@ -32,14 +36,12 @@ ## Getting started | ||
You can get fields from this form in a single object with minimum effort by using the `parseForm()` method. | ||
You can collect and parse all fields in a single object with `parseForm()`. | ||
**Note:** The form object must be an `HTMLFormElement`. | ||
```js | ||
import { parseForm } from "@jalik/form-parser"; | ||
import { parseForm } from '@jalik/form-parser' | ||
// Get an existing HTML form element | ||
const form = document.getElementById("my-form"); | ||
const form = document.getElementById('my-form') | ||
// Parse form values with default options | ||
const fields = parseForm(form); | ||
const fields = parseForm(form) | ||
``` | ||
@@ -60,21 +62,38 @@ | ||
Below is a more complete form example, with a lot of different cases to help you understand the behavior of the parsing function (pay attention to comments, values and attributes). | ||
Below is a more complete form example, with a lot of different cases to help you understand the | ||
behavior of the parsing function (pay attention to comments, values and attributes). | ||
```html | ||
<form id="my-form"> | ||
<!-- Fields with no name will be ignored --> | ||
<!-- Fields without name are ignored --> | ||
<input type="text" value="aaa"> | ||
<!-- Disabled fields are always ignored --> | ||
<input name="disabled_field" value="hello" disabled> | ||
<!-- Buttons are always ignored --> | ||
<input name="input_button" type="button" value="Click me"> | ||
<input name="input_reset" type="reset" value="Reset"> | ||
<input name="input_submit" type="submit" value="Submit"> | ||
<button name="button" type="button" value="Click me"></button> | ||
<button name="reset" type="reset" value="Reset"></button> | ||
<button name="submit" type="submit" value="Submit"></button> | ||
<!-- These fields will be parsed to booleans --> | ||
<!-- These fields will be parsed to booleans --> | ||
<!-- boolean = false --> | ||
<input name="boolean" type="radio" data-type="boolean" value="true"> | ||
<input name="boolean" type="radio" data-type="boolean" value="false" checked> | ||
<!-- hidden_boolean = true --> | ||
<input name="hidden_boolean" type="hidden" data-type="auto" value="true"> | ||
<!-- These fields will be parsed to numbers --> | ||
<!-- These fields will be parsed to numbers --> | ||
<input name="float" type="number" value="09.99"> | ||
<!-- hidden_float = 9.99 --> | ||
<input name="hidden_float" type="hidden" data-type="number" value="09.99"> | ||
<!-- text_integer = 1 --> | ||
<input name="text_integer" type="text" data-type="number" value="01"> | ||
<input name="integer" type="number" value="01"> | ||
<input name="range" type="range" value="0118"> | ||
<select name="select_number" data-type="auto"> | ||
<!-- select_number = 30 --> | ||
<select name="select_number" data-type="number"> | ||
<option value="10"></option> | ||
@@ -84,20 +103,38 @@ <option value="20"></option> | ||
</select> | ||
<!-- float = 9.99 --> | ||
<input name="float" type="number" value="09.99"> | ||
<!-- integer = 1 --> | ||
<input name="integer" type="number" value="01"> | ||
<!-- range = 0118 --> | ||
<input name="range" type="range" value="0118"> | ||
<!-- These fields will be parsed to strings --> | ||
<!-- These fields will be parsed to strings --> | ||
<!-- number_text = '0123' --> | ||
<input name="number_text" type="number" data-type="string" value="0123"> | ||
<!-- date = '2017-11-14' --> | ||
<input name="date" type="date" value="2017-11-14"> | ||
<!-- file = 'file://path/to/file.txt' --> | ||
<input name="file" type="file" value="file://path/to/file.txt"> | ||
<!-- hidden_text = 'shadowed' --> | ||
<input name="hidden_text" type="hidden" value="shadowed"> | ||
<!-- month = '2017-11' --> | ||
<input name="month" type="month" value="2017-11"> | ||
<input name="number_text" type="number" data-type="string" value="0123"> | ||
<!-- text = 'Hello' --> | ||
<input name="text" type="text" value="Hello"> | ||
<!-- url = 'http://www.github.com/' --> | ||
<input name="url" type="url" value="http://www.github.com/"> | ||
<!-- week = '2017-W16' --> | ||
<input name="week" type="week" value="2017-W16"> | ||
<!-- textarea = 'Hello' --> | ||
<textarea name="textarea">Hello</textarea> | ||
<!-- Passwords are never altered or parsed ("data-type" is ignored) --> | ||
<!-- Password fields are never altered (trimmed), even by cleanFunction --> | ||
<input name="password" type="password" value=" s3crEt "> | ||
<!-- password = ' 1337 ' --> | ||
<input name="password" type="password" data-type="number" value=" 1337 "> | ||
<!-- These fields will be parsed as array --> | ||
<!-- These fields will be parsed as array --> | ||
<input name="array[]" type="checkbox" value="A" checked> | ||
<input name="array[]" type="checkbox" value="B" checked> | ||
<!-- select_multiple = [20, 30] --> | ||
<select name="select_multiple" data-type="number" multiple> | ||
@@ -108,13 +145,5 @@ <option value="10"></option> | ||
</select> | ||
<!-- Disabled fields are ignored by default --> | ||
<input name="disabled_field" value="" disabled> | ||
<!-- Buttons are ignored by default --> | ||
<input name="input_button" type="button" value="Click me"> | ||
<input name="input_reset" type="reset" value="Reset"> | ||
<input name="input_submit" type="submit" value="Submit"> | ||
<button name="button" type="button" value="Click me"></button> | ||
<button name="reset" type="reset" value="Reset"></button> | ||
<button name="submit" type="submit" value="Submit"></button> | ||
<!-- array = ['A', 'B'] --> | ||
<input name="array[]" type="checkbox" value="A" checked> | ||
<input name="array[]" type="checkbox" value="B" checked> | ||
</form> | ||
@@ -126,9 +155,9 @@ ``` | ||
```js | ||
import { parseForm } from "@jalik/form-parser"; | ||
import { parseForm } from '@jalik/form-parser' | ||
// Get an existing HTML form element | ||
const form = document.getElementById("my-form"); | ||
const form = document.getElementById('my-form') | ||
// Parse form values using default options | ||
const fields = parseForm(form); | ||
const fields = parseForm(form) | ||
``` | ||
@@ -156,5 +185,11 @@ | ||
"textarea": "Hello", | ||
"password": " s3crEt ", | ||
"array": ["A", "B"], | ||
"select_multiple": [20, 30] | ||
"password": " 1337 ", | ||
"array": [ | ||
"A", | ||
"B" | ||
], | ||
"select_multiple": [ | ||
20, | ||
30 | ||
] | ||
} | ||
@@ -165,3 +200,3 @@ ``` | ||
To get an array of values from a form, use this syntax : | ||
To get an array of values, append `[]` to a field name: | ||
@@ -174,4 +209,4 @@ ```html | ||
<input name="array[]" type="checkbox" value="C" checked> | ||
<!-- This will create an array with checked values, but it will keep indexes --> | ||
<!-- This will create an array with checked values (indexed) --> | ||
<input name="colors[2]" type="checkbox" value="red" checked> | ||
@@ -186,9 +221,9 @@ <input name="colors[1]" type="checkbox" value="blue"> | ||
```js | ||
import { parseForm } from "@jalik/form-parser"; | ||
import { parseForm } from '@jalik/form-parser' | ||
// Get an existing HTML form element | ||
const form = document.getElementById("my-form"); | ||
const form = document.getElementById('my-form') | ||
// Parse form values using default options | ||
const fields = parseForm(form); | ||
const fields = parseForm(form) | ||
``` | ||
@@ -198,6 +233,13 @@ | ||
``` | ||
```json | ||
{ | ||
"array": ["B", "C"], | ||
"colors": ["white", undefined, "red"] | ||
"array": [ | ||
"B", | ||
"C" | ||
], | ||
"colors": [ | ||
"white", | ||
undefined, | ||
"red" | ||
] | ||
} | ||
@@ -208,3 +250,3 @@ ``` | ||
To get an object from a form, use this syntax : | ||
To get an object, write attributes like `[attribute]`: | ||
@@ -222,9 +264,9 @@ ```html | ||
```js | ||
import { parseForm } from "@jalik/form-parser"; | ||
import { parseForm } from '@jalik/form-parser' | ||
// Get an existing HTML form element | ||
const form = document.getElementById("my-form"); | ||
const form = document.getElementById('my-form') | ||
// Parse form values using default options | ||
const fields = parseForm(form); | ||
const fields = parseForm(form) | ||
``` | ||
@@ -243,5 +285,6 @@ | ||
### Using numbers as object attribute (since v2.0.6) | ||
### Using numbers as keys in objects (since v2.0.6) | ||
If you need to create an object with numbers as attributes, use single or double quotes to force the parser to interpret it as a string and then creating an object instead of an array. | ||
If you need to create an object with numbers as attributes, use single or double quotes to force the | ||
parser to interpret it as a string and then creating an object instead of an array. | ||
@@ -272,16 +315,23 @@ ```html | ||
```json | ||
{"elements": ["Zero", "One", "Two"]} | ||
{ | ||
"elements": [ | ||
"Zero", | ||
"One", | ||
"Two" | ||
] | ||
} | ||
``` | ||
## Forcing fields types | ||
## Fields parsing | ||
Sometimes you may want to force a number to be parsed as a string for example. | ||
In this case, use the `data-type` attribute on the input. When the parser will get fields values, it will automatically convert them to the given `data-type`. | ||
To define the type of field, you can use the attribute `data-type` or `type`. | ||
The attribute `data-type` takes precedence over `type` if both of are defined. | ||
The `data-type` attribute can have one of the following values : `auto`, `boolean`, `number` or `string`. | ||
When using `data-type` attribute, the value can be: | ||
* `auto` to convert the value to the best guess type (ex: `123` => `number`, `true` => `boolean`) | ||
* `boolean` to convert the value to a boolean (ex: `true`, `1`, `yes`, `on`, `false`, `0`, `no`, `off`) | ||
* `number` to convert the value to a number | ||
**Note:** The `auto` data-type will convert value to the best guess type (ex: `123` => `number`). | ||
When using `type` attribute on `<input>`, only `number` and `range` are parsed to numbers. | ||
**Note:** The `boolean` data-type will convert `"1"` and `"true"` to `true`, all other values are `false`. | ||
```html | ||
@@ -305,7 +355,6 @@ <!-- This will parse "true" as a boolean --> | ||
If no `data-type` attribute is set, the `type` attribute will be used (for `input` elements at least), this behavior is active by default with the combination of this options `{dynamicTyping: true, smartTyping: true}` in the `parseForm()` function. | ||
## Parsing complex forms with nested fields | ||
This purpose of this lib is to reconstruct an object corresponding to the form structure, so it can parse complex forms containing "unlimited" nested arrays and objects. | ||
It is possible to reconstruct an object corresponding to the form structure, so it can | ||
parse complex forms containing nested arrays and objects. | ||
@@ -319,3 +368,3 @@ ```html | ||
<!-- A very deep field value --> | ||
<!-- A useless deep nested field value --> | ||
<input name="deep_1[][deep_2][0][][deep_3]" value="DEEP"> | ||
@@ -328,9 +377,9 @@ </form> | ||
```js | ||
import { parseForm } from "@jalik/form-parser"; | ||
import { parseForm } from '@jalik/form-parser' | ||
// Get an existing HTML form element | ||
const form = document.getElementById("my-form"); | ||
const form = document.getElementById('my-form') | ||
// Parse form values using default options | ||
const fields = parseForm(form); | ||
const fields = parseForm(form) | ||
``` | ||
@@ -356,3 +405,5 @@ | ||
[ | ||
{"deep_3": "DEEP"} | ||
{ | ||
"deep_3": "DEEP" | ||
} | ||
] | ||
@@ -365,28 +416,29 @@ ] | ||
## Filtering fields | ||
## Filtering | ||
You can get only the fields you want with `filterFunction(field)` option in the `parseForm()` method. The filter function will be called with all fields and must return `true` to return the field. | ||
When parsing a form, you can filter values with `filterFunction(field, parsedValue)` option in the `parseForm(form, options)`. | ||
The filter function must return `true` to return the field. | ||
```js | ||
import { parseForm } from "@jalik/form-parser"; | ||
import { parseForm } from '@jalik/form-parser' | ||
// Get an existing HTML form element | ||
const form = document.getElementById("my-form"); | ||
const form = document.getElementById('my-form') | ||
// Parse form values using default options | ||
const fields = parseForm(form, { | ||
// returns only text fields | ||
filterFunction: (field) => field.type === "text", | ||
filterFunction: (field, parsedValue) => field.type === 'text' | ||
}); | ||
``` | ||
## Cleaning parsed values | ||
## Cleaning | ||
All string values can be cleaned using the `cleanFunction(value, field)` option in the `parseForm()` method. The clean function will be called with any value that is a string of length > 0. | ||
Values can be cleaned by passing `cleanFunction(value, field)` to `parseForm(form, options)`. | ||
Note that only strings are passed to this function and that password fields are ignored. | ||
```js | ||
import { parseForm } from "@jalik/form-parser"; | ||
import { parseForm } from '@jalik/form-parser' | ||
// Get an existing HTML form element | ||
const form = document.getElementById("my-form"); | ||
const form = document.getElementById('my-form') | ||
@@ -397,9 +449,9 @@ // Parse form values using default options | ||
// Apply uppercase to lastName field | ||
if (field.name === "lastName" || /name/gi.test(field.name)) { | ||
value = value.toUpperCase(); | ||
if (field.name === 'lastName' || /name/gi.test(field.name)) { | ||
value = value.toUpperCase() | ||
} | ||
// Remove HTML code from all fields | ||
return value.replace(/<\/?[^>]+>/gm, ""); | ||
return value.replace(/<\/?[^>]+>/gm, '') | ||
} | ||
}); | ||
}) | ||
``` | ||
@@ -411,17 +463,20 @@ | ||
You can parse a single field with options, it works the same way as `parseForm(form, options)` but with a field. | ||
To parse a single field. | ||
```html | ||
<form> | ||
<select data-type="number" name="values" multiple> | ||
<option>1</option> | ||
<option selected>2</option> | ||
<option selected>3</option> | ||
</select> | ||
</form> | ||
``` | ||
```js | ||
import { parseField } from "@jalik/form-parser"; | ||
import { parseField } from '@jalik/form-parser' | ||
// Colors is a select allowing multiple values to be selected | ||
const colorsSelect = document.getElementById("colors-field"); | ||
// Get the colors array (ex: colors = ['blue', 'green']) | ||
const colors = parseField(colorsSelect, { | ||
dynamicTyping: true, | ||
nullify: true, | ||
smartTyping: true, | ||
trim: true, | ||
}); | ||
const field = document.getElementById('values') | ||
const values = parseField(field) | ||
// values = [2, 3] | ||
``` | ||
@@ -431,38 +486,41 @@ | ||
You can parse a form with options to customize the behavior. | ||
To parse a form with all fields. | ||
```html | ||
<form id="my-form"> | ||
<input type="number" name="age" value="35" /> | ||
<select data-type="number" name="values" multiple> | ||
<option>1</option> | ||
<option selected>2</option> | ||
<option selected>3</option> | ||
</select> | ||
</form> | ||
``` | ||
```js | ||
import { parseForm } from "@jalik/form-parser"; | ||
import { parseForm } from '@jalik/form-parser' | ||
// Get an existing HTML form element | ||
const form = document.getElementById("my-form"); | ||
const form = document.getElementById('my-form') | ||
// Parse form values with custom options | ||
const fields = parseForm(form, { | ||
// Cleans parsed values | ||
cleanFunction(value, field) { | ||
return typeof value === 'string' ? stripTags(value) : value; | ||
return typeof value === 'string' ? stripTags(value) : value | ||
}, | ||
// Only returns fields that matches the condition | ||
filterFunction(field) { | ||
return field.type === 'text'; | ||
return field.type === 'text' | ||
}, | ||
// Don't get buttons | ||
ignoreButtons: true, | ||
// Don't get disabled fields | ||
ignoreDisabled: true, | ||
// Don't get fields with empty string | ||
ignoreEmpty: false, | ||
// Don't get radios or checkboxes that are not checked | ||
// useful to get a false value instead of undefined | ||
ignoreUnchecked: false, | ||
// Replace empty strings with null | ||
nullify: true, | ||
// Parse values to the best guess type (ex: "001" => 1) | ||
dynamicTyping: true, | ||
// Parse values based on field type (ex: type="number" will parse to number) | ||
smartTyping: true, | ||
// Set parsing mode. | ||
// - none: disable parsing | ||
// - type: enable parsing based on "type" attribute (ex: type="number") | ||
// - data-type: enable parsing based on "data-type" attribute (ex: data-type="number") | ||
// - auto: enable parsing based on data-type and type (in this order) | ||
parsing: 'none' | 'type' | 'data-type' | 'auto', | ||
// Remove extra spaces | ||
trim: true | ||
}); | ||
}) | ||
``` | ||
@@ -477,5 +535,1 @@ | ||
The code is released under the [MIT License](http://www.opensource.org/licenses/MIT). | ||
If you find this lib useful and would like to support my work, donations are welcome :) | ||
[![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=6UA5YELH55WLC) |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
80113
0
11
1068
512
15
1
- Removed@babel/runtime@^7.19.4
- Removed@babel/runtime@7.26.7(transitive)
- Removedregenerator-runtime@0.14.1(transitive)