Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12,393 changes: 7,350 additions & 5,043 deletions package-lock.json

Large diffs are not rendered by default.

18 changes: 9 additions & 9 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,25 +15,25 @@
"Firefox 67"
],
"dependencies": {
"delay": "^4.3.0",
"webext-base-css": "^1.1.0",
"webext-options-sync": "^1.2.4",
"webextension-polyfill": "^0.4.0"
"delay": "^5.0.0",
"webext-base-css": "^1.3.1",
"webext-options-sync": "^2.0.1",
"webextension-polyfill": "^0.7.0"
},
"devDependencies": {
"@parcel/config-webextension": "^2.0.0-nightly.2258",
"@types/chrome": "0.0.86",
"@types/chrome": "0.0.134",
"ava": "^2.2.0",
"esm": "^3.2.25",
"lodash.merge": "^4.6.2",
"moment": "^2.24.0",
"moment": "^2.29.1",
"npm-run-all": "^4.1.5",
"parcel": "^2.0.0-nightly.634",
"sinon": "^7.3.2",
"sinon": "^10.0.0",
"sinon-chrome": "^3.0.1",
"stylelint": "^13.12.0",
"stylelint-config-xo": "^0.15.0",
"xo": "^0.24.0"
"stylelint-config-xo": "^0.20.0",
"xo": "^0.38.2"
},
"ava": {
"files": [
Expand Down
16 changes: 8 additions & 8 deletions source/background.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import browser from 'webextension-polyfill';
import delay from 'delay';
import optionsStorage from './options-storage';
import localStore from './lib/local-store';
import {openTab} from './lib/tabs-service';
import {queryPermission} from './lib/permissions-service';
import {getNotificationCount, getTabUrl} from './lib/api';
import {renderCount, renderError, renderWarning} from './lib/badge';
import {checkNotifications, openNotification} from './lib/notifications-service';
import {isChrome, isNotificationTargetPage} from './util';
import optionsStorage from './options-storage.js';
import localStore from './lib/local-store.js';
import {openTab} from './lib/tabs-service.js';
import {queryPermission} from './lib/permissions-service.js';
import {getNotificationCount, getTabUrl} from './lib/api.js';
import {renderCount, renderError, renderWarning} from './lib/badge.js';
import {checkNotifications, openNotification} from './lib/notifications-service.js';
import {isChrome, isNotificationTargetPage} from './util.js';

async function scheduleNextAlarm(interval) {
const intervalSetting = await localStore.get('interval') || 60;
Expand Down
22 changes: 11 additions & 11 deletions source/lib/api.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import optionsStorage from '../options-storage';
import {parseLinkHeader} from '../util';
import optionsStorage from '../options-storage.js';
import {parseLinkHeader} from '../util.js';

export async function getGitHubOrigin() {
const {rootUrl} = await optionsStorage.getAll();
Expand Down Expand Up @@ -32,9 +32,9 @@ export async function getApiUrl() {
return `${origin}/api/v3`;
}

export async function getParsedUrl(endpoint, params) {
export async function getParsedUrl(endpoint, parameters) {
const api = await getApiUrl();
const query = params ? '?' + (new URLSearchParams(params)).toString() : '';
const query = parameters ? '?' + (new URLSearchParams(parameters)).toString() : '';
return `${api}${endpoint}${query}`;
}

Expand All @@ -53,8 +53,8 @@ export async function getHeaders() {
};
}

export async function makeApiRequest(endpoint, params) {
const url = await getParsedUrl(endpoint, params);
export async function makeApiRequest(endpoint, parameters) {
const url = await getParsedUrl(endpoint, parameters);
let response;
try {
response = await fetch(url, {
Expand All @@ -81,27 +81,27 @@ export async function makeApiRequest(endpoint, params) {
headers,
json
};
} catch (error) {
} catch {
return Promise.reject(new Error('parse error'));
}
}

export async function getNotificationResponse({page = 1, maxItems = 100, lastModified = ''}) {
const {onlyParticipating} = await optionsStorage.getAll();
const params = {
const parameters = {
page,
per_page: maxItems // eslint-disable-line camelcase
};

if (onlyParticipating) {
params.participating = onlyParticipating;
parameters.participating = onlyParticipating;
}

if (lastModified) {
params.since = lastModified;
parameters.since = lastModified;
}

return makeApiRequest('/notifications', params);
return makeApiRequest('/notifications', parameters);
}

export async function getNotifications({page, maxItems, lastModified, notifications = []}) {
Expand Down
2 changes: 1 addition & 1 deletion source/lib/badge.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import browser from 'webextension-polyfill';
import * as defaults from './defaults';
import * as defaults from './defaults.js';

function render(text, color, title) {
browser.browserAction.setBadgeText({text});
Expand Down
4 changes: 3 additions & 1 deletion source/lib/local-store.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import browser from 'webextension-polyfill';

export default {
const localStore = {
async get(key) {
const result = await browser.storage.local.get(key);
return result[key];
Expand All @@ -18,3 +18,5 @@ export default {
return browser.storage.local.clear();
}
};

export default localStore;
18 changes: 9 additions & 9 deletions source/lib/notifications-service.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import delay from 'delay';
import browser from 'webextension-polyfill';
import optionsStorage from '../options-storage';
import repositoriesStorage from '../repositories-storage';
import {parseFullName} from '../util';
import {makeApiRequest, getNotifications, getTabUrl, getGitHubOrigin} from './api';
import {getNotificationReasonText} from './defaults';
import {openTab} from './tabs-service';
import localStore from './local-store';
import optionsStorage from '../options-storage.js';
import repositoriesStorage from '../repositories-storage.js';
import {parseFullName} from '../util.js';
import {makeApiRequest, getNotifications, getTabUrl, getGitHubOrigin} from './api.js';
import {getNotificationReasonText} from './defaults.js';
import {openTab} from './tabs-service.js';
import localStore from './local-store.js';

function getLastReadForNotification(notification) {
// Extract the specific fragment URL for a notification
Expand Down Expand Up @@ -46,7 +46,7 @@ async function issueOrPRHandler(notification) {
const {json: response} = await makeApiRequest(url.pathname);
const targetUrl = response.message === 'Not Found' ? await getTabUrl() : response.html_url;
return targetUrl;
} catch (error) {
} catch {
// If anything related to querying the API fails, extract the URL to issue/PR from the API url
const alterateURL = new URL(await getGitHubOrigin() + url.pathname);

Expand Down Expand Up @@ -87,7 +87,7 @@ export async function openNotification(notificationId) {
try {
const urlToOpen = await notificationHandlers[notification.subject.type](notification);
return openTab(urlToOpen);
} catch (error) {
} catch {
return openTab(await getTabUrl());
}
}
Expand Down
32 changes: 16 additions & 16 deletions source/lib/repositories-service.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import {parseLinkHeader, parseFullName} from '../util';
import repositoriesStorage from '../repositories-storage';
import {makeApiRequest} from './api';
import {parseLinkHeader, parseFullName} from '../util.js';
import repositoriesStorage from '../repositories-storage.js';
import {makeApiRequest} from './api.js';

export async function getRepositories(
repos = [],
params = {
page: '1',
per_page: '100' // eslint-disable-line camelcase
}
parameters = {}
) {
const {headers, json} = await makeApiRequest('/user/subscriptions', params);
parameters = {
page: '1',
per_page: '100', // eslint-disable-line camelcase
...parameters
};
const {headers, json} = await makeApiRequest('/user/subscriptions', parameters);
repos = [...repos, ...json];

const {next} = parseLinkHeader(headers.get('Link'));
Expand All @@ -27,18 +29,16 @@ export async function getRepositories(
export async function listRepositories(update) {
const stored = await repositoriesStorage.getAll();

let tree = stored;
const tree = stored;
if (update || !tree || Object.keys(tree).length <= 0) {
const fetched = await getRepositories();
/* eslint-disable camelcase */
tree = fetched.reduce((tree, {full_name}) => {
for (const {full_name} of fetched) {
const {owner, repository} = parseFullName(full_name);
return Object.assign({}, tree, {
[owner]: Object.assign(tree[owner] || {}, {
[repository]: Boolean(stored && stored[owner] && stored[owner][repository])
})
});
}, {});
tree[owner] = tree[owner] || {};
tree[owner][repository] = Boolean(stored && stored[owner] && stored[owner][repository]);
}

/* eslint-enable camelcase */
await repositoriesStorage.set(tree);
}
Expand Down
4 changes: 2 additions & 2 deletions source/lib/tabs-service.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import browser from 'webextension-polyfill';
import optionsStorage from '../options-storage';
import {isChrome} from '../util';
import optionsStorage from '../options-storage.js';
import {isChrome} from '../util.js';

export const emptyTabUrls = isChrome() ? [
'chrome://newtab/',
Expand Down
4 changes: 2 additions & 2 deletions source/lib/user-service.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {makeApiRequest} from './api';
import localStore from './local-store';
import {makeApiRequest} from './api.js';
import localStore from './local-store.js';

export async function getUser(update) {
let user = await localStore.get('user');
Expand Down
5 changes: 0 additions & 5 deletions source/options.css
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,6 @@ input:not([type='checkbox']) {
font-size: 11px;
}

input:not([type='checkbox']):not(:placeholder-shown):valid {
color: var(--github-green);
border: 1px solid !important;
}

input:not([type='checkbox']):invalid {
color: var(--github-red);
border: 1px solid !important;
Expand Down
8 changes: 4 additions & 4 deletions source/options.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import browser from 'webextension-polyfill';
import optionsStorage from './options-storage';
import initRepositoriesForm from './repositories';
import {requestPermission} from './lib/permissions-service';
import {background} from './util';
import optionsStorage from './options-storage.js';
import initRepositoriesForm from './repositories.js';
import {requestPermission} from './lib/permissions-service.js';
import {background} from './util.js';

document.addEventListener('DOMContentLoaded', async () => {
try {
Expand Down
10 changes: 5 additions & 5 deletions source/repositories.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import repositoriesStorage from './repositories-storage';
import optionsStorage from './options-storage';
import {listRepositories} from './lib/repositories-service';
import {getUser} from './lib/user-service';
import {background} from './util';
import repositoriesStorage from './repositories-storage.js';
import optionsStorage from './options-storage.js';
import {listRepositories} from './lib/repositories-service.js';
import {getUser} from './lib/user-service.js';
import {background} from './util.js';

const form = document.querySelector('#repositories-form');
const button = document.querySelector('#reload-repositories');
Expand Down
15 changes: 8 additions & 7 deletions source/util.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import browser from 'webextension-polyfill';
import {getGitHubOrigin} from './lib/api';
import {getGitHubOrigin} from './lib/api.js';

export function isChrome() {
return navigator.userAgent.includes('Chrome');
Expand All @@ -17,7 +17,7 @@ export async function isNotificationTargetPage(url) {
return false;
}

const pathname = urlObject.pathname.replace(/^[/]|[/]$/g, ''); // Remove trailing and leading slashes
const pathname = urlObject.pathname.replace(/^\/|\/$/g, ''); // Remove trailing and leading slashes

// For https://github.com/notifications and the beta https://github.com/notifications/beta
if (pathname === 'notifications' || pathname === 'notifications/beta') {
Expand All @@ -31,16 +31,17 @@ export async function isNotificationTargetPage(url) {
}

export function parseLinkHeader(header) {
return (header || '').split(',').reduce((links, part) => {
const links = {};
for (const part of (header || '').split(',')) {
const [sectionUrl = '', sectionName = ''] = part.split(';');
const url = sectionUrl.replace(/<(.+)>/, '$1').trim();
const name = sectionName.replace(/rel="(.+)"/, '$1').trim();
if (!name || !url) {
return links;
if (name && url) {
links[name] = url;
}
}

return Object.assign({}, links, {[name]: url});
}, {});
return links;
}

const backgroundPage = browser.extension.getBackgroundPage() || window;
Expand Down
4 changes: 2 additions & 2 deletions test/api-test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import test from 'ava';
import * as api from '../source/lib/api';
import {fakeFetch} from './util';
import * as api from '../source/lib/api.js';
import {fakeFetch} from './util.js';

test.beforeEach(t => {
t.context.service = Object.assign({}, api);
Expand Down
4 changes: 2 additions & 2 deletions test/badge-test.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import test from 'ava';

import * as defaults from '../source/lib/defaults';
import {renderCount, renderError} from '../source/lib/badge';
import * as defaults from '../source/lib/defaults.js';
import {renderCount, renderError} from '../source/lib/badge.js';

test.beforeEach(() => {
browser.flush();
Expand Down
6 changes: 3 additions & 3 deletions test/defaults-test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import test from 'ava';
import * as defaults from '../source/lib/defaults';
import * as defaults from '../source/lib/defaults.js';

test.serial('#getBadgeDefaultColor return array of 4 numbers between 0 and 255 inclusive', t => {
const color = defaults.getBadgeDefaultColor();
Expand Down Expand Up @@ -40,7 +40,7 @@ test.serial('#getNotificationReasonText returns notification reasons', t => {
const invalidReasons = [
'no such reason',
undefined,
NaN,
Number.NaN,
{foo: 42}
];

Expand All @@ -59,7 +59,7 @@ test.serial('#getErrorSymbol returns either "X" or "?" strings', t => {
const invalidMessages = [
'no such thing',
undefined,
NaN,
Number.NaN,
{foo: 312}
];

Expand Down
2 changes: 1 addition & 1 deletion test/local-store-test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import test from 'ava';
import localStore from '../source/lib/local-store';
import localStore from '../source/lib/local-store.js';

test.beforeEach(t => {
browser.flush();
Expand Down
8 changes: 4 additions & 4 deletions test/notifications-service-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ import test from 'ava';
import sinon from 'sinon';
import moment from 'moment';

import * as notifications from '../source/lib/notifications-service';
import {getNotificationReasonText} from '../source/lib/defaults';
import {fakeFetch} from './util';
import * as notifications from '../source/lib/notifications-service.js';
import {getNotificationReasonText} from '../source/lib/defaults.js';
import {fakeFetch} from './util.js';

test.beforeEach(t => {
t.context.service = Object.assign({}, notifications);
t.context.notificationId = (Math.random() * 1000 | 0).toString();
t.context.notificationId = Math.trunc(Math.random() * 1000).toString();
t.context.notificationUrl = `https://api.github.com/notifications/${t.context.notificationId}`;
t.context.notificationsUrl = 'https://github.com/user/notifications';
t.context.notificationHtmlUrl = `https://github.com/user/repo/issues/${t.context.notificationId}`;
Expand Down
Loading