Skip to content

Commit

Permalink
fix: some invalid URLs (#168)
Browse files Browse the repository at this point in the history
closes #159
  • Loading branch information
e-krebs authored Aug 31, 2024
1 parent cc2c1f9 commit 4dea88f
Show file tree
Hide file tree
Showing 12 changed files with 55 additions and 22 deletions.
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,6 @@ jobs:
- run: bun run setup-ci
- run: bun run type-check
- run: bun run lint
- run: bun test
- run: bun run build
- run: bun run zip
Binary file modified bun.lockb
Binary file not shown.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
"@crxjs/vite-plugin": "^1.0.14",
"@e-krebs/react-library": "^0.0.23",
"@tailwindcss/typography": "^0.5.9",
"@types/bun": "^1.1.8",
"@types/chrome": "^0.0.236",
"@types/express": "^4.17.17",
"@types/node": "^20.16.1",
Expand Down
3 changes: 2 additions & 1 deletion src/components/List/Item/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { FC, useEffect, useRef, useState } from 'react';

import { getUrl } from 'utils/getURL';
import { getIcon, IconAndPalette } from 'utils/icon';
import { ListItem } from 'utils/typings';

Expand Down Expand Up @@ -27,7 +28,7 @@ export const Item: FC<ItemProps> = ({

useEffect(() => {
const effect = async () => {
const iconAndPalette = await getIcon(new URL(url).hostname, logo);
const iconAndPalette = await getIcon(getUrl(url).hostname, logo);
setIcon(iconAndPalette);
};
effect();
Expand Down
5 changes: 3 additions & 2 deletions src/components/List/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { filterTag, get, search } from 'utils/get';
import { getAllTags } from 'utils/getAllTags';
import { getLastTag, setLastTag } from 'utils/lastTag';
import { getActiveTab } from 'utils/getActiveTab';
import { getUrl } from 'utils/getURL';
import { urlsAreMatching } from 'utils/currentUrlIsMatching';

import { SearchFilter } from './SearchFilter';
Expand Down Expand Up @@ -43,13 +44,13 @@ export const List: FC = () => {
useEffect(() => {
const initActiveTab = async () => {
const url = await getActiveTab();
setActiveTab(url ? new URL(url) : undefined);
setActiveTab(url ? getUrl(url) : undefined);
};
initActiveTab();
}, []);

const isMatching = useCallback(
(url: string) => activeTab !== undefined && urlsAreMatching(new URL(url), activeTab),
(url: string) => activeTab !== undefined && urlsAreMatching(url, activeTab),
[activeTab]
);

Expand Down
2 changes: 1 addition & 1 deletion src/pages/contentScript/Page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export const Page = () => {
setUrl(message.url);
setAllTags(message.tags ?? []);
setTags([]);
const listItem = await getMatchingListItem(new URL(message.url), [msgService]);
const listItem = await getMatchingListItem(message.url, [msgService]);
setMatching(listItem ? { service: msgService, listItem } : undefined);
setIsLoading(false);
modalRef.current?.openModal();
Expand Down
6 changes: 3 additions & 3 deletions src/pages/serviceWorker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ const refreshBadge = async () => {
);
};

const refreshBadgeIfMatching = async (currentUrl: URL) => {
const refreshBadgeIfMatching = async (currentUrl: string) => {
const services = getServices();
const isMatching = await currentUrlIsMatching(currentUrl, services);
setBadgeColor(isMatching);
Expand All @@ -47,14 +47,14 @@ const tabsUpdatedListener = async (
{ active, url }: chrome.tabs.Tab
) => {
if (active && url) {
await refreshBadgeIfMatching(new URL(url));
await refreshBadgeIfMatching(url);
}
};

const tabsActivatedListener = async ({ tabId }: chrome.tabs.TabActiveInfo) => {
const { url } = await chrome.tabs.get(tabId);
if (url) {
await refreshBadgeIfMatching(new URL(url));
await refreshBadgeIfMatching(url);
}
};

Expand Down
16 changes: 16 additions & 0 deletions src/utils/__tests__/getUrl.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { describe, it, expect } from 'bun:test';

import { getUrl } from 'utils/getURL';

describe('getUrl', () => {
it('should work with simple urls', () => {
expect(getUrl('https://www.google.fr')).toEqual(new URL('https://www.google.fr'));
expect(getUrl('https://github.com/e-krebs/pile')).toEqual(
new URL('https://github.com/e-krebs/pile')
);
});

it('should work with known edge cases', () => {
expect(getUrl('svg.wtf')).toEqual(new URL('https://svg.wtf'));
});
});
2 changes: 1 addition & 1 deletion src/utils/badge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ const updateBadgeInner = async (services: Service[], badgeValues: BadgeValues) =
.reduce((a, b) => a + b);

const url = await getActiveTab();
const isMatching = url ? await currentUrlIsMatching(new URL(url), services) : false;
const isMatching = url ? await currentUrlIsMatching(url, services) : false;

if (total > 0) {
setBadgeColor(isMatching);
Expand Down
31 changes: 18 additions & 13 deletions src/utils/currentUrlIsMatching.ts
Original file line number Diff line number Diff line change
@@ -1,45 +1,50 @@
import { get } from './get';
import { getUrl } from './getURL';
import type { Service } from './services';
import { ListItem } from './typings';
import { beautifyUrl } from './url';

export const getMatchingListItem = async (
currentUrl: URL,
currentUrl: URL | string,
services: Service[]
): Promise<ListItem | undefined> => {
const currentURL = typeof currentUrl === 'string' ? getUrl(currentUrl) : currentUrl;
const matching = await Promise.all(
services
.map(async (service) => {
const isConnected = await service.isConnected();
if (!isConnected) return;
const { data } = await get(service);
return data.find((item) => {
const url = new URL(item.url);
return urlsAreMatching(url, currentUrl);
});
return data.find((item) => urlsAreMatching(item.url, currentURL));
})
.flat()
);
return matching.find((item) => item !== undefined);
};

export const currentUrlIsMatching = async (currentUrl: URL, services: Service[]): Promise<boolean> => {
export const currentUrlIsMatching = async (
currentUrl: URL | string,
services: Service[]
): Promise<boolean> => {
const currentURL = typeof currentUrl === 'string' ? getUrl(currentUrl) : currentUrl;
const matches = await Promise.all(
services.map(async (service) => {
const isConnected = await service.isConnected();
if (!isConnected) return false;
const { data } = await get(service);
const matchingUrls = data
.map((i) => new URL(i.url))
.filter((iUrl) => urlsAreMatching(iUrl, currentUrl));
const matchingUrls = data.filter(({ url }) => urlsAreMatching(url, currentURL));
return matchingUrls.length > 0;
})
);
const isMatching = matches.reduce((a, b) => a || b);
return isMatching;
};

export const urlsAreMatching = (url1: URL, url2: URL): boolean =>
beautifyUrl(url1.origin) === beautifyUrl(url2.origin) &&
beautifyUrl(url1.pathname) === beautifyUrl(url2.pathname) &&
url1.search === url2.search;
export const urlsAreMatching = (url1: URL | string, url2: URL): boolean => {
const URL1 = typeof url1 === 'string' ? getUrl(url1) : url1;
return (
beautifyUrl(URL1.origin) === beautifyUrl(url2.origin) &&
beautifyUrl(URL1.pathname) === beautifyUrl(url2.pathname) &&
url1.search === url2.search
);
};
8 changes: 8 additions & 0 deletions src/utils/getURL.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export const getUrl = (url: string): URL => {
try {
return new URL(url);
} catch {
// very basic, should probably be improved
return new URL(`https://${url}`);
}
};
2 changes: 1 addition & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"skipLibCheck": true,
"jsx": "react-jsx",
"resolveJsonModule": true,
"types": ["chrome", "node"],
"types": ["chrome", "bun"],
"baseUrl": "src",
}
}

0 comments on commit 4dea88f

Please sign in to comment.