diff --git a/package.json b/package.json index 538d4fc..e92dfd7 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "@holllo/preact-components": "^0.2.3", "htm": "^3.1.1", "modern-normalize": "^1.1.0", + "nanoid": "^4.0.0", "preact": "^10.11.0", "webextension-polyfill": "^0.10.0" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7d2f259..dd2d70e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -10,6 +10,7 @@ specifiers: c8: ^7.12.0 htm: ^3.1.1 modern-normalize: ^1.1.0 + nanoid: ^4.0.0 postcss: ^8.4.16 preact: ^10.11.0 sass: ^1.55.0 @@ -29,6 +30,7 @@ dependencies: '@holllo/preact-components': 0.2.3_htm@3.1.1+preact@10.11.0 htm: 3.1.1 modern-normalize: 1.1.0 + nanoid: 4.0.0 preact: 10.11.0 webextension-polyfill: 0.10.0 @@ -5197,6 +5199,12 @@ packages: hasBin: true dev: true + /nanoid/4.0.0: + resolution: {integrity: sha512-IgBP8piMxe/gf73RTQx7hmnhwz0aaEXYakvqZyE302IXW3HyVNhdNGC+O2MwMAVhLEnvXlvKtGbtJf6wvHihCg==} + engines: {node: ^14 || ^16 || >=18} + hasBin: true + dev: false + /natural-compare/1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} dev: true @@ -7637,6 +7645,11 @@ packages: resolution: {integrity: sha512-liCEteZ5z+QRyh3XzsYWQyxedBHBvx8CDlNvvi+BJz74L0E5/ID2v7JtoX3bD541AlMuOy4e/iWif6hhNGBFNw==} engines: {node: '>=12.20'} hasBin: true + peerDependencies: + webpack: '>=1.11.0' + peerDependenciesMeta: + webpack: + optional: true dependencies: '@eslint/eslintrc': 1.3.2 '@typescript-eslint/eslint-plugin': 5.36.2_q7mrctxvxoqtj4jpjqmbsyg2qy @@ -7677,7 +7690,6 @@ packages: transitivePeerDependencies: - eslint-import-resolver-typescript - supports-color - - webpack dev: true bundledDependencies: - '@typescript-eslint/eslint-plugin' diff --git a/source/background-scripts/initialize.ts b/source/background-scripts/initialize.ts index 4985ed1..3722c61 100644 --- a/source/background-scripts/initialize.ts +++ b/source/background-scripts/initialize.ts @@ -21,8 +21,10 @@ browser.runtime.onInstalled.addListener(async () => { browser.webNavigation.onBeforeNavigate.addListener(async (details) => { const url = new URL(details.url); - for (const parameters of Object.values(await browser.storage.local.get())) { - const redirect = parseRedirect(parameters); + for (const [id, parameters] of Object.entries( + await browser.storage.local.get(), + )) { + const redirect = parseRedirect(parameters, id); if (redirect === undefined) { continue; } diff --git a/source/redirect/base.ts b/source/redirect/base.ts index 75f99bd..bc5fa3c 100644 --- a/source/redirect/base.ts +++ b/source/redirect/base.ts @@ -1,3 +1,5 @@ +import {customAlphabet} from 'nanoid'; + export const matcherTypes = ['hostname'] as const; export const redirectTypes = ['hostname', 'simple'] as const; @@ -22,7 +24,17 @@ export type RedirectParameters = { }; export abstract class Redirect

{ - constructor(public parameters: P & Matcher) {} + public static generateId(): string { + const alphabet = 'abcdefghijklmnopqrstuvwxyz'; + const nanoid = customAlphabet(`${alphabet}${alphabet.toUpperCase()}`, 20); + return nanoid(); + } + + public id: string; + + constructor(public parameters: P & Matcher, id?: string) { + this.id = id ?? Redirect.generateId(); + } public isMatch(url: URL): boolean { if (this.parameters.matcherType === 'hostname') { diff --git a/source/redirect/exports.ts b/source/redirect/exports.ts index 57a7d8a..5a09d65 100644 --- a/source/redirect/exports.ts +++ b/source/redirect/exports.ts @@ -9,14 +9,15 @@ export type Redirects = HostnameRedirect | SimpleRedirect; export function parseRedirect

( parameters: P, + id: string, ): Redirects | undefined { const redirectType = parameters?.redirectType; if (redirectType === 'hostname') { - return new HostnameRedirect(parameters); + return new HostnameRedirect(parameters, id); } if (redirectType === 'simple') { - return new SimpleRedirect(parameters); + return new SimpleRedirect(parameters, id); } } diff --git a/tests/redirect.test.ts b/tests/redirect.test.ts index 3135947..d387f6f 100644 --- a/tests/redirect.test.ts +++ b/tests/redirect.test.ts @@ -40,11 +40,13 @@ test('parseRedirect', (t) => { ]; for (const sample of samples) { - const redirect = parseRedirect(sample); + const redirect = parseRedirect(sample, Redirect.generateId()); if (redirect === undefined) { t.pass('parseRedirect returned undefined'); } else { + t.regex(redirect.id, /^[a-z]{20}$/i); + redirect.id = 'id'; t.snapshot(redirect, `Class ${redirect.constructor.name}`); } } diff --git a/tests/snapshots/tests/redirect.test.ts.md b/tests/snapshots/tests/redirect.test.ts.md index 692af26..a58fc1c 100644 --- a/tests/snapshots/tests/redirect.test.ts.md +++ b/tests/snapshots/tests/redirect.test.ts.md @@ -9,6 +9,7 @@ Generated by [AVA](https://avajs.dev). > Class HostnameRedirect HostnameRedirect { + id: 'id', parameters: { hostname: 'example.org', matcherType: 'hostname', @@ -20,6 +21,7 @@ Generated by [AVA](https://avajs.dev). > Class SimpleRedirect SimpleRedirect { + id: 'id', parameters: { matcherType: 'hostname', redirectType: 'simple', diff --git a/tests/snapshots/tests/redirect.test.ts.snap b/tests/snapshots/tests/redirect.test.ts.snap index 904e77a..b8e6b6b 100644 Binary files a/tests/snapshots/tests/redirect.test.ts.snap and b/tests/snapshots/tests/redirect.test.ts.snap differ