From 1fad5bb5e0f3264386bc8e40beeb4cdae2a832cb Mon Sep 17 00:00:00 2001 From: David Guilherme Date: Wed, 7 Apr 2021 14:32:16 +0100 Subject: [PATCH] feat(rules): add url validator (#3253) --- docs/content/guide/global-validators.md | 17 +++++++++++++++++ packages/i18n/src/locale/en.json | 3 ++- packages/i18n/src/locale/pt_BR.json | 3 ++- packages/i18n/src/locale/pt_PT.json | 3 ++- packages/rules/src/url.ts | 23 +++++++++++++++++++++++ packages/rules/tests/url.spec.ts | 16 ++++++++++++++++ 6 files changed, 62 insertions(+), 3 deletions(-) create mode 100644 packages/rules/src/url.ts create mode 100644 packages/rules/tests/url.spec.ts diff --git a/docs/content/guide/global-validators.md b/docs/content/guide/global-validators.md index 9996c1276..d3daa8df3 100644 --- a/docs/content/guide/global-validators.md +++ b/docs/content/guide/global-validators.md @@ -315,6 +315,7 @@ Object.keys(rules).forEach(rule => {
  • regex
  • required
  • size
  • +
  • url
  • ### Playground @@ -727,3 +728,19 @@ The file size added to the field under validation must not exceed the specified | Param Name | Required? | Default | Description | | ---------- | --------- | ------- | ----------------------------------- | | `size` | **yes** | | The maximum file size in kilobytes. | + +#### url + +The field under validation must be a valid url. You can pass a `pattern` if you need the url to be more restricted. + +```vue + + + + + +``` + +| Param Name | Required? | Default | Description | +| ---------- | --------- | ------- | --------------------------------------------------------- | +| `pattern` | **no** | | A regular expression instance or string representing one. | diff --git a/packages/i18n/src/locale/en.json b/packages/i18n/src/locale/en.json index 65713b60c..459c0ca5a 100644 --- a/packages/i18n/src/locale/en.json +++ b/packages/i18n/src/locale/en.json @@ -25,6 +25,7 @@ "regex": "The {field} field format is invalid", "required_if": "The {field} field is required", "required": "The {field} field is required", - "size": "The {field} field size must be less than 0:{size}KB" + "size": "The {field} field size must be less than 0:{size}KB", + "url": "The {field} field is not a valid URL" } } diff --git a/packages/i18n/src/locale/pt_BR.json b/packages/i18n/src/locale/pt_BR.json index 68f42f85b..9568e0610 100644 --- a/packages/i18n/src/locale/pt_BR.json +++ b/packages/i18n/src/locale/pt_BR.json @@ -26,6 +26,7 @@ "regex": "O campo {field} possui um formato inválido", "required": "O campo {field} é obrigatório", "required_if": "O campo {field} é obrigatório", - "size": "O campo {field} deve ser menor que 0:{size}KB" + "size": "O campo {field} deve ser menor que 0:{size}KB", + "url": "O campo {field} deve ser uma URL válida" } } diff --git a/packages/i18n/src/locale/pt_PT.json b/packages/i18n/src/locale/pt_PT.json index 5afb29054..ae05aae98 100644 --- a/packages/i18n/src/locale/pt_PT.json +++ b/packages/i18n/src/locale/pt_PT.json @@ -24,6 +24,7 @@ "regex": "O campo {field} possui um formato inválido", "required": "O campo {field} é obrigatório", "required_if": "O campo {field} é obrigatório", - "size": "O campo {field} deve ser menor que 0:{size}KB" + "size": "O campo {field} deve ser menor que 0:{size}KB", + "url": "O campo {field} deve ser uma URL válida" } } diff --git a/packages/rules/src/url.ts b/packages/rules/src/url.ts new file mode 100644 index 000000000..12e12177b --- /dev/null +++ b/packages/rules/src/url.ts @@ -0,0 +1,23 @@ +import { getSingleParam, isEmpty } from './utils'; + +const urlValidator = (value: unknown, params: [string | RegExp | undefined] | { pattern?: string | RegExp }) => { + if (isEmpty(value)) { + return true; + } + + let pattern = getSingleParam(params, 'pattern'); + if (typeof pattern === 'string') { + pattern = new RegExp(pattern); + } + + try { + // eslint-disable-next-line no-new + new URL(value as string); + } catch { + return false; + } + + return pattern?.test(value as string) ?? true; +}; + +export default urlValidator; diff --git a/packages/rules/tests/url.spec.ts b/packages/rules/tests/url.spec.ts new file mode 100644 index 000000000..da07b8027 --- /dev/null +++ b/packages/rules/tests/url.spec.ts @@ -0,0 +1,16 @@ +import validate from '../src/url'; + +test('validates url', () => { + const validUrl = 'https://test.com:8080/en/whatever/?q=test#wow'; + + // no pattern + expect(validate(validUrl, {})).toBe(true); + expect(validate('/only/path', {})).toBe(false); + expect(validate('invalid', {})).toBe(false); + + // with pattern + expect(validate(validUrl, { pattern: 'https://.*' })).toBe(true); + expect(validate(validUrl, { pattern: /http:\/\/.*/ })).toBe(false); + expect(validate(validUrl, ['/en/whatever/'])).toBe(true); + expect(validate(validUrl, ['/fr/whatever/'])).toBe(false); +});