1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
|
browser.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
if (changeInfo.url) {
groupTabs(tabId);
}
});
const colors = [
"blue",
"cyan",
"grey",
"green",
"orange",
"pink",
"purple",
"red",
"yellow",
];
async function groupTabs(tabId) {
const tabs = await browser.tabs.query({ currentWindow: true });
const domainGroups = {};
const groupIds = [];
for (let tab of tabs) {
if (!groupIds.includes(tab.groupId)) {
groupIds.push(tab.groupId);
}
const hostname = new URL(tab.url).hostname;
const parts = hostname.split(".");
let domain = parts[0];
if (parts.length > 1) {
parts.pop();
if (parts[0] == "www") {
parts.shift();
}
domain = toTitleCase(parts.join(" "));
}
if (domain == "") {
domain = "Browser";
}
if (tab.groupId == -1 || tab.id == tabId || tab.active) {
if (!domainGroups[domain]) {
domainGroups[domain] = [];
}
domainGroups[domain].push(tab.id);
}
}
for (const groupId in groupIds) {
if (groupIds[groupId] != -1) {
let tabGroup = await browser.tabGroups.get(groupIds[groupId]);
if (tabGroup.title in domainGroups) {
const updatedGroup = await browser.tabs.group({
tabIds: domainGroups[tabGroup.title],
groupId: tabGroup.id,
});
delete domainGroups[tabGroup.title];
}
}
}
for (const domain in domainGroups) {
const groupId = await browser.tabs.group({
tabIds: domainGroups[domain],
});
await browser.tabGroups.update(groupId, {
title: domain,
color: colors[groupId % colors.length],
});
}
}
function toTitleCase(str) {
str = str.replace(/[-_]/g, " ");
return str.replace(
/\w(\S)*/g,
(text) =>
text.charAt(0).toUpperCase() + text.substring(1).toLowerCase(),
);
}
|