Skip to content

Commit

Permalink
Add basic functionality to alter URL
Browse files Browse the repository at this point in the history
  • Loading branch information
xuhdev committed Dec 10, 2024
1 parent c2c8412 commit 395e13b
Show file tree
Hide file tree
Showing 6 changed files with 198 additions and 4 deletions.
3 changes: 2 additions & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ root = true
[*.{js,ts,tsx,mjs}]
indent_size = 2
indent_style = space
max_line_length = 80

[*.scss]
indent_size = 2
Expand All @@ -13,4 +14,4 @@ indent_size = 2
indent_style = space

[*.md]
max_line_length = 100
max_line_length = 100
49 changes: 47 additions & 2 deletions src/main.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,51 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
test("Placeholder", () => {
// Placeholder

import { SiteData, amazonComParam, builtinSiteData } from "./site_data";
import { generateActivatingUrl, generateDisablingUrl } from "./main";

describe("generate Url", () => {
const activatingResult = "https://example.com/?result=activated" as const;
const disablingResult = "https://example.com/?notactivated" as const;
const matchingUrl = "https://example.com";
const unmatchingUrl = "https://example.org";
const siteData = [
{
name: "Test Example",
urlRegex: /https:\/\/example\.com/,
activatingFunc: (): string => activatingResult,
disablingFunc: (): string => disablingResult,
},
] as const satisfies SiteData;

test("Returns activating function result if URL matches", () => {
expect(generateActivatingUrl(matchingUrl, siteData)).toBe(activatingResult);
});

test("Returns disabling function result if URL matches", () => {
expect(generateDisablingUrl(matchingUrl, siteData)).toBe(disablingResult);
});

for (const func of [generateActivatingUrl, generateDisablingUrl] as const) {
test("Returns null if no URL matches", () => {
expect(func(unmatchingUrl, siteData)).toBeNull();
});
}

describe("builtin sitedata", () => {
test("Amazon.com activating matched", () => {
expect(
generateActivatingUrl("https://www.amazon.com/s?", builtinSiteData),
).toBe(
`https://www.amazon.com/s?${amazonComParam.key}=${encodeURIComponent(amazonComParam.value)}`,
);
});

test("Amazon.com disabling matched", () => {
expect(
generateDisablingUrl("https://www.amazon.com/s?rh=", builtinSiteData),
).toBe("https://www.amazon.com/s");
});
});
});
46 changes: 46 additions & 0 deletions src/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/** @license GPL-3.0-or-later
*
* Copyright (C) 2024 8 Hobbies, LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

import type { SiteData, SiteDataEntry } from "./site_data";

function getMatchedSite(url: string, siteData: SiteData): SiteDataEntry | null {
const matchedSite = siteData.find((siteDataEntry) =>
siteDataEntry.urlRegex.exec(url),
);

return matchedSite ?? null;
}

/** Returns the updated URL of the functionality of this extension on a given current URL. */
export function generateActivatingUrl(
url: string,
siteData: SiteData,
): string | null {
const matchedSite = getMatchedSite(url, siteData);

return matchedSite?.activatingFunc(url) ?? null;
}

export function generateDisablingUrl(
url: string,
siteData: SiteData,
): string | null {
const matchedSite = getMatchedSite(url, siteData);

return matchedSite?.disablingFunc(url) ?? null;
}
2 changes: 1 addition & 1 deletion src/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
},
"minimum_chrome_version": "128",
"permissions": ["storage"],
"host_permissions": ["*://www.amazon.com/*"],
"host_permissions": ["https://www.amazon.com/s?*"],
"action": {},
"browser_specific_settings": {
"gecko": {
Expand Down
47 changes: 47 additions & 0 deletions src/site_data.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/** @license GPL-3.0-or-later
*
* Copyright (C) 2024 8 Hobbies, LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

import { addUrlParam, removeUrlParam } from "./utils";

export interface SiteDataEntry {
name: string;
// Regular expression to match the website.
urlRegex: RegExp;
// Function being called when the user visits a website of interest.
activatingFunc: (url: string) => string | null;
// Function being called when the user clicks on the extension icon to disable.
disablingFunc: (url: string) => string | null;
}

export type SiteData = SiteDataEntry[];

export const amazonComParam = {
key: "rh",
value: "n:16310101,p_6:ATVPDKIKX0DER",
};

export const builtinSiteData = [
{
name: "Amazon.com",
urlRegex: /https:\/\/www\.amazon\.com\/s.*/,
disablingFunc: (url: string): string | null =>
removeUrlParam(url, amazonComParam.key),
activatingFunc: (url: string): string | null =>
addUrlParam(url, amazonComParam.key, amazonComParam.value),
},
] as const satisfies SiteData;
55 changes: 55 additions & 0 deletions src/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/** @license GPL-3.0-or-later
*
* Copyright (C) 2024 8 Hobbies, LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

/** Add a param to a URL. */
export function addUrlParam(
url: string,
paramKey: string,
paramValue: string,
): string | null {
const parsedUrl = URL.parse(url);

// TODO: Impossible to create a case to trigger this part for now. Remove the coverage exception once we can.
/* c8 ignore start */
if (parsedUrl === null) {
// Not a URL.
console.error(`${url} is not a URL.`);
return null;
}
/* c8 ignore stop */

parsedUrl.searchParams.set(paramKey, paramValue);
return parsedUrl.toString();
}

/** Remove a param from a URL. */
export function removeUrlParam(url: string, paramKey: string): string | null {
const parsedUrl = URL.parse(url);

// TODO: Impossible to create a case to trigger this part for now. Remove the coverage exception once we can.
/* c8 ignore start */
if (parsedUrl === null) {
// Not a URL.
console.error(`${url} is not a URL.`);
return null;
}
/* c8 ignore stop */

parsedUrl.searchParams.delete(paramKey);
return parsedUrl.toString();
}

0 comments on commit 395e13b

Please sign in to comment.