From 2665ee32989b6f262a676a18e64110f817e2c385 Mon Sep 17 00:00:00 2001 From: Bauke Date: Wed, 2 Nov 2022 11:10:29 +0100 Subject: [PATCH] Add a regex redirect. --- source/redirect/base.ts | 2 +- source/redirect/exports.ts | 7 +++++ source/redirect/regex.ts | 9 +++++++ tests/redirect.test.ts | 18 +++++++++++-- tests/snapshots/tests/redirect.test.ts.md | 27 ++++++++++++++++++++ tests/snapshots/tests/redirect.test.ts.snap | Bin 539 -> 652 bytes 6 files changed, 60 insertions(+), 3 deletions(-) create mode 100644 source/redirect/regex.ts diff --git a/source/redirect/base.ts b/source/redirect/base.ts index 4ac15cf..8c4facc 100644 --- a/source/redirect/base.ts +++ b/source/redirect/base.ts @@ -1,5 +1,5 @@ export const matcherTypes = ['hostname', 'regex'] as const; -export const redirectTypes = ['hostname', 'simple'] as const; +export const redirectTypes = ['hostname', 'regex', 'simple'] as const; export type MatcherType = typeof matcherTypes[number]; export type RedirectType = typeof redirectTypes[number]; diff --git a/source/redirect/exports.ts b/source/redirect/exports.ts index e9a4137..351e9fe 100644 --- a/source/redirect/exports.ts +++ b/source/redirect/exports.ts @@ -1,9 +1,11 @@ import {RedirectParameters} from './base.js'; import {HostnameRedirect} from './hostname.js'; +import {RegexRedirect} from './regex.js'; import {SimpleRedirect} from './simple.js'; export * from './base.js'; export * from './hostname.js'; +export * from './regex.js'; export * from './simple.js'; export type Redirects = HostnameRedirect | SimpleRedirect; @@ -11,6 +13,7 @@ export type Redirects = HostnameRedirect | SimpleRedirect; export function parseRedirect( parameters: RedirectParameters, ): Redirects | undefined { + const matcherType = parameters?.matcherType; const redirectType = parameters?.redirectType; if (redirectType === 'hostname') { @@ -20,4 +23,8 @@ export function parseRedirect( if (redirectType === 'simple') { return new SimpleRedirect(parameters); } + + if (matcherType === 'regex' && redirectType === 'regex') { + return new RegexRedirect(parameters); + } } diff --git a/source/redirect/regex.ts b/source/redirect/regex.ts new file mode 100644 index 0000000..afee6fa --- /dev/null +++ b/source/redirect/regex.ts @@ -0,0 +1,9 @@ +import {Redirect} from './base.js'; + +export class RegexRedirect extends Redirect { + public redirect(redirect: URL | string): URL { + const url = redirect instanceof URL ? redirect.href : redirect; + const regex = new RegExp(this.parameters.matcherValue, 'gi'); + return new URL(url.replace(regex, this.parameters.redirectValue)); + } +} diff --git a/tests/redirect.test.ts b/tests/redirect.test.ts index dd32ecf..73bc6e1 100644 --- a/tests/redirect.test.ts +++ b/tests/redirect.test.ts @@ -12,6 +12,7 @@ import { Redirect, Redirects, RedirectParameters, + RegexRedirect, SimpleRedirect, } from '../source/redirect/exports.js'; @@ -33,6 +34,15 @@ const simpleParameters: RedirectParameters = { redirectValue: 'https://example.org/simple', }; +const regexParameters: RedirectParameters = { + enabled: true, + id: 3, + matcherType: 'regex', + matcherValue: '(.+)\\.com', + redirectType: 'regex', + redirectValue: '$1.org', +}; + test('parseRedirect', (t) => { const samples: RedirectParameters[] = [ { @@ -41,6 +51,7 @@ test('parseRedirect', (t) => { undefined as unknown as RedirectParameters, hostnameParameters, simpleParameters, + regexParameters, ]; for (const sample of samples) { @@ -58,18 +69,21 @@ test('parseRedirect', (t) => { test('Redirect.redirect', (t) => { const hostnameRedirect = new HostnameRedirect(hostnameParameters); const simpleRedirect = new SimpleRedirect(simpleParameters); + const regexRedirect = new RegexRedirect(regexParameters); - const samples: Array<[string, Redirect]> = [ + const samples: Array<[string | URL, Redirect]> = [ ['https://example.com', hostnameRedirect], ['https://example.com/path#hash?query=test', hostnameRedirect], ['https://example.com', simpleRedirect], ['https://example.com/path', simpleRedirect], + ['https://example.com', regexRedirect], + [new URL('https://example.com'), regexRedirect], ]; for (const [index, [url, redirect]] of samples.entries()) { t.snapshot( { - original: url, + original: url instanceof URL ? url.href : url, redirected: redirect.redirect(url).href, }, `${index} ${redirect.constructor.name}`, diff --git a/tests/snapshots/tests/redirect.test.ts.md b/tests/snapshots/tests/redirect.test.ts.md index 87d8eeb..4982a87 100644 --- a/tests/snapshots/tests/redirect.test.ts.md +++ b/tests/snapshots/tests/redirect.test.ts.md @@ -32,6 +32,19 @@ Generated by [AVA](https://avajs.dev). }, } +> Class RegexRedirect + + RegexRedirect { + parameters: { + enabled: true, + id: 3, + matcherType: 'regex', + matcherValue: '(.+)\\.com', + redirectType: 'regex', + redirectValue: '$1.org', + }, + } + ## Redirect.redirect > 0 HostnameRedirect @@ -61,3 +74,17 @@ Generated by [AVA](https://avajs.dev). original: 'https://example.com/path', redirected: 'https://example.org/simple', } + +> 4 RegexRedirect + + { + original: 'https://example.com', + redirected: 'https://example.org/', + } + +> 5 RegexRedirect + + { + original: 'https://example.com/', + redirected: 'https://example.org/', + } diff --git a/tests/snapshots/tests/redirect.test.ts.snap b/tests/snapshots/tests/redirect.test.ts.snap index faafc6acf2894801ab232b7ee2e023573d0bbd67..156fb160f43deb5a1cf5d3f365edc2ba5978d95a 100644 GIT binary patch literal 652 zcmV;70(1RARzVrVnPCmB1GI4iV!~s7B)md5Kxy( za>Op@*txr+c3=P`HWm<45fg=lg%QO6zyRW}VLKp1O>LkLd?;SAfZv(UCR^4*pI^-%9%5#p> zgUyNe$MjT8uOEeG_pq1UB97-ZyYdoiv$dhKBB&&exQyaw(EO`u8;%W zn24O^;kJLacH;PQUTVg?W@z@&`9GhRi~;r4J873){ah27miaVhSby7tu&{t*)HOLt zl{m{UealOM@Y-I7ay>DfzFFBijO$}1WN>Q6bRT1*Vs1bWsedtfcr*eJvjz`NNR@lU zrP96JU1ehZqGD1FH( m|K}?TPN!N$Y~Y>AfIk8QnWIEBcIRNR-@$Kyw)&hU3IG7c(>1~X literal 539 zcmV+$0_6QcRzVxg3E`0zjY(U;~%*LW)3Z9@_ASxJEG{eaXx@=B_XvFjsosUfh! zH^9y?cZul(YGJr>bI2gj-!7oInlZwN2_-+>k50@u23FL^yoW}cc(4dRtOEJdXxMHPQ_@Q zGg^2`@^I7y4?_taOphvS(4x|sukJB%IIEacjg7^md}B#cq1mx|X7BzNu!aZJ8`lqK d;Nw2YN3{t)`szVzhM5V?%sY)rwu}M?003kQ2{-@%