Skip to content

Commit 19daf42

Browse files
committed
Updated theme colors for accessibility, more options in popup, db auto refresh
1 parent 0563e85 commit 19daf42

9 files changed

Lines changed: 284 additions & 116 deletions

File tree

README.md

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,16 @@ and [Microsoft Edge](https://microsoftedge.microsoft.com/addons/detail/licensedb
1616
## Using the extension
1717

1818
To run the diff, select text on a web page and click on the extension icon. You will have the option
19-
to compare against licenses, exceptions or both. Once the comparisons have
20-
completed, it will return the top 20 results (this can be changed in the extension options). You can
21-
select each result from the dropdown to see the differences and copy the license identifier by clicking
19+
to compare against licenses, exceptions or both. You can also select which source you want results from (SPDX, ScanCode or both) and to include/exclude deprecated licenses and exceptions. Once the comparisons have
20+
completed, it will return the top 10 results (this can be changed in the extension options). You can
21+
select each result from the dropdown to see the differences, click the link to go to the license text source and copy the license identifier by clicking
2222
on the copy button.
2323

24-
Licenses and exceptions that are marked as deprecated are currently excluded from comparison
25-
but I would like to add the ability to include/exclude as an option in the future.
24+
When using both sources, the results will be sorted by highest to lowest match score or you can select "Group by source" in the "Results grouping" dropdown to group results by SPDX and ScanCode.
25+
26+
This has only been tested on web pages and may not work correctly for documents being viewed in a browser.
27+
28+
## Options
29+
30+
In the extension options, you can set the maximum number of results to return, set the minimum match threshold, manually refresh the license database, reset the database for a complete rebuild and choose the theme (light or dark).
2631

27-
This has only been tested to diff text on web pages and may not work correctly for documents being
28-
viewed in a browser.

manifest.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
{
22
"manifest_version": 3,
33
"name": "LicenseDB License Diff",
4-
"version": "0.0.6.1",
4+
"version": "0.0.7.0",
55
"description": "Compares and diffs selected text using AboutCode's ScanCode LicenseDB license list and SPDX License List.",
66
"permissions": [
77
"activeTab",
88
"scripting",
99
"tabs",
10-
"storage"
10+
"storage",
11+
"alarms"
1112
],
1213
"host_permissions": [
1314
"https://scancode-licensedb.aboutcode.org/*",

src/background/background.js

Lines changed: 135 additions & 89 deletions
Large diffs are not rendered by default.

src/content/content.css

Lines changed: 44 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -216,16 +216,16 @@
216216
}
217217

218218
#license-diff-url a {
219-
color: #439843;
219+
color: #2d682d;
220220
text-decoration: none;
221221
font-weight: 500;
222222
transition: all 0.2s ease;
223223
border-bottom: 1px dotted transparent;
224224
}
225225

226226
#license-diff-url a:hover {
227-
color: #2d682d;
228-
border-bottom: 1px dotted #2d682d;
227+
color: #1a3d1a;
228+
border-bottom: 1px dotted #1a3d1a;
229229
}
230230

231231
#license-diff-display {
@@ -252,6 +252,13 @@
252252
overflow-wrap: break-word;
253253
}
254254

255+
#license-diff-display .ldiff-pending {
256+
padding: 12px;
257+
color: #6b7280;
258+
font-style: italic;
259+
text-align: center;
260+
}
261+
255262
/* Custom scrollbar for the diff display */
256263
#license-diff-display::-webkit-scrollbar {
257264
width: 8px;
@@ -397,6 +404,20 @@
397404
border: 1px solid rgba(33, 150, 243, 0.35);
398405
}
399406

407+
.deprecated-badge {
408+
display: inline-flex;
409+
align-items: center;
410+
margin-left: 8px;
411+
padding: 2px 8px;
412+
border-radius: 999px;
413+
font-size: 11px;
414+
font-weight: 700;
415+
letter-spacing: 0.2px;
416+
background-color: rgba(245, 158, 11, 0.15);
417+
color: #92400e;
418+
border: 1px solid rgba(245, 158, 11, 0.35);
419+
}
420+
400421
/* Theme control row */
401422
#license-diff-theme {
402423
display: flex;
@@ -454,12 +475,12 @@
454475
}
455476

456477
#license-diff-ui.ld-theme-light #license-diff-url a {
457-
color: #439843 !important;
478+
color: #2d682d !important;
458479
}
459480

460481
#license-diff-ui.ld-theme-light #license-diff-url a:hover {
461-
color: #2d682d !important;
462-
border-bottom: 1px dotted #2d682d !important;
482+
color: #1a3d1a !important;
483+
border-bottom: 1px dotted #1a3d1a !important;
463484
}
464485

465486
#license-diff-ui.ld-theme-light .source-badge.source-licensedb {
@@ -474,6 +495,12 @@
474495
border-color: rgba(33, 150, 243, 0.35) !important;
475496
}
476497

498+
#license-diff-ui.ld-theme-light .deprecated-badge {
499+
background-color: rgba(245, 158, 11, 0.15) !important;
500+
color: #92400e !important;
501+
border-color: rgba(245, 158, 11, 0.35) !important;
502+
}
503+
477504
#license-diff-ui.ld-theme-light .license-diff-notification.info {
478505
background-color: #e7f3fe !important;
479506
color: #0c5460 !important;
@@ -570,6 +597,12 @@
570597
border-color: rgba(68, 147, 248, 0.45) !important;
571598
}
572599

600+
#license-diff-ui.ld-theme-dark .deprecated-badge {
601+
background-color: rgba(245, 158, 11, 0.18) !important;
602+
color: #fcd34d !important;
603+
border-color: rgba(245, 158, 11, 0.4) !important;
604+
}
605+
573606
#license-diff-ui.ld-theme-dark #license-diff-progress-container {
574607
background-color: #212830 !important;
575608
}
@@ -598,7 +631,7 @@
598631

599632
#license-diff-ui.ld-theme-dark .license-diff-notification.success {
600633
background-color: #238636 !important;
601-
color: #3fb950 !important;
634+
color: #ffffff !important;
602635
border-left: 4px solid #34d399 !important;
603636
}
604637

@@ -625,4 +658,8 @@
625658

626659
#license-diff-ui.ld-theme-dark #license-diff-display::-webkit-scrollbar-thumb:hover {
627660
background-color: #64748b !important;
661+
}
662+
663+
#license-diff-ui.ld-theme-dark #license-diff-display .ldiff-pending {
664+
color: #9ca3af !important;
628665
}

src/content/content.js

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -192,11 +192,12 @@ if (__LD_STATE__.initialized || __LD_STATE__.initializing) {
192192

193193
const appendOption = (m, targetParent = dropdown) => {
194194
const pct = prettyPercent(m.charSimilarity);
195+
const deprecatedSuffix = m.deprecated ? ' [deprecated]' : '';
195196
const opt = createEl('option');
196197
opt.value = m.matchKey;
197198
opt.textContent = pct
198-
? `${m.license}${pct}${m.sourceLabel || getSourceLabel(m.source)}`
199-
: `${m.license}${m.sourceLabel || getSourceLabel(m.source)}`;
199+
? `${m.license}${pct}${m.sourceLabel || getSourceLabel(m.source)}${deprecatedSuffix}`
200+
: `${m.license}${m.sourceLabel || getSourceLabel(m.source)}${deprecatedSuffix}`;
200201
targetParent.appendChild(opt);
201202
};
202203

@@ -213,7 +214,8 @@ if (__LD_STATE__.initialized || __LD_STATE__.initializing) {
213214
matches.forEach(m => appendOption(m, dropdown));
214215
}
215216

216-
setDisplay(groupingRow, matches.length ? 'flex' : 'none');
217+
const uniqueSources = new Set(matches.map(m => m.source || 'licensedb'));
218+
setDisplay(groupingRow, (matches.length && uniqueSources.size > 1) ? 'flex' : 'none');
217219

218220
if (matches.length) {
219221
if (selectedMatchKey && matches.some(m => m.matchKey === selectedMatchKey)) {
@@ -351,6 +353,8 @@ if (__LD_STATE__.initialized || __LD_STATE__.initializing) {
351353
removeClass(progressEl, 'no-transition');
352354
}
353355

356+
setDisplay(status, 'block');
357+
setDisplay(progressBar, 'block');
354358
status.textContent = 'Starting license comparison...';
355359
matches = [];
356360

@@ -385,6 +389,7 @@ if (__LD_STATE__.initialized || __LD_STATE__.initializing) {
385389

386390
m.link = `<a href="${targetUrl}" target="_blank">${m.name}</a>
387391
<span class="source-badge ${getSourceClass(m.source)}">${sourceLabel}</span>
392+
${m.deprecated ? '<span class="deprecated-badge">deprecated</span>' : ''}
388393
<span class="spdx-container">
389394
<span class="spdx-id">(${m.spdx})</span>
390395
<button class="copy-spdx-button" data-spdx="${m.spdx}" title="Copy ID">
@@ -411,7 +416,9 @@ if (__LD_STATE__.initialized || __LD_STATE__.initializing) {
411416
}, { passive: false });
412417
}
413418

414-
safeSetHTML(diffContainer, sel.diff);
419+
safeSetHTML(diffContainer, sel.diff !== null
420+
? sel.diff
421+
: '<div class="ldiff-pending">Generating diff\u2026</div>');
415422
updateDiffSizing();
416423
setupCopyButtons();
417424
};
@@ -424,9 +431,33 @@ if (__LD_STATE__.initialized || __LD_STATE__.initializing) {
424431
dropdown.onchange();
425432
}
426433

427-
status.textContent = 'Comparison complete!';
434+
const hasPendingDiffs = matches.some(m => m.diff === null);
435+
if (hasPendingDiffs) {
436+
status.textContent = 'Results ready. Generating diffs...';
437+
} else {
438+
setDisplay(status, 'none');
439+
setDisplay(progressBar, 'none');
440+
}
428441
updateDiffSizing();
429442
sendResponse({ success: true });
443+
} else if (message.action === 'updateMatchDiff') {
444+
const match = matches.find(m => m.matchKey === message.matchKey);
445+
if (match) {
446+
match.diff = message.diff;
447+
// If this match is currently selected in the dropdown, refresh its diff view
448+
if (dropdown.value === message.matchKey) {
449+
safeSetHTML(diffContainer, match.diff !== null
450+
? match.diff
451+
: '<div class="ldiff-pending">Generating diff\u2026</div>');
452+
updateDiffSizing();
453+
}
454+
// Hide status and progress bar when all diffs have arrived
455+
if (matches.every(m => m.diff !== null)) {
456+
setDisplay(status, 'none');
457+
setDisplay(progressBar, 'none');
458+
}
459+
}
460+
sendResponse({ success: true });
430461
} else if (message.action === 'showError') {
431462
removeClass(progressEl, 'animating');
432463
status.textContent = `Error: ${message.error}`;

src/shared/ui-defaults.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
export const UI_DEFAULTS = Object.freeze({
22
theme: 'light',
3-
scanFilter: 'both'
3+
scanFilter: 'both',
4+
includeDeprecated: false,
5+
scanSource: 'both'
46
});
57

68
export const BADGE_STYLES = Object.freeze({

src/ui/options/options.html

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838

3939
button {
4040
background-color: #4CAF50;
41-
color: white;
41+
color: #000000;
4242
border: none;
4343
border-radius: 4px;
4444
padding: 10px 16px;
@@ -67,6 +67,7 @@
6767

6868
.button-danger {
6969
background-color: #dc3545;
70+
color: white;
7071
}
7172

7273
.button-danger:hover {

src/ui/popup/popup.html

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,36 @@
55
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
66
<title>License Diff</title>
77
<style>
8-
body { font-family: system-ui, sans-serif; margin: 12px; width: 220px; }
8+
body { font-family: system-ui, sans-serif; margin: 12px; width: 220px; background-color: #ffffff; color: #333333; }
99
fieldset { border: none; padding: 0; margin: 0 0 8px 0; }
10+
legend { font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; color: #888; margin-bottom: 4px; padding: 0; }
1011
label { display: flex; align-items: center; gap: 6px; margin-bottom: 4px; }
11-
button { width: 100%; padding: 6px; margin-top: 8px; }
12+
button { width: 100%; padding: 6px; margin-top: 8px; background-color: #4CAF50; color: #000000; border: none; border-radius: 4px; cursor: pointer; font-size: 13px; }
13+
button:hover { background-color: #3d8b3d; }
14+
15+
body.theme-dark { background-color: #0d1117; color: #f0f6fc; }
16+
body.theme-dark legend { color: #8b949e; }
17+
body.theme-dark button { background-color: #238636; color: #ffffff; }
18+
body.theme-dark button:hover { background-color: #2ea043; }
1219
</style>
1320
</head>
1421
<body>
1522
<fieldset id="filter-form">
23+
<legend>Compare</legend>
1624
<label><input type="radio" name="scanFilter" value="licenses" />Licenses only</label>
1725
<label><input type="radio" name="scanFilter" value="exceptions" />Exceptions only</label>
1826
<label><input type="radio" name="scanFilter" value="both" />Licenses + Exceptions</label>
1927
</fieldset>
28+
<fieldset id="deprecated-form">
29+
<legend>Filters</legend>
30+
<label><input type="checkbox" id="include-deprecated" />Include deprecated</label>
31+
</fieldset>
32+
<fieldset id="source-form">
33+
<legend>Sources</legend>
34+
<label><input type="radio" name="scanSource" value="licensedb" />ScanCode only</label>
35+
<label><input type="radio" name="scanSource" value="spdx" />SPDX only</label>
36+
<label><input type="radio" name="scanSource" value="both" />Both sources</label>
37+
</fieldset>
2038
<button id="run-scan" type="button">Run comparison</button>
2139
<script type="module" src="popup.js"></script>
2240
</body>

src/ui/popup/popup.js

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
import { UI_DEFAULTS } from "../../shared/ui-defaults.js";
22

33
const FILTER_DEFAULT = UI_DEFAULTS.scanFilter;
4+
const DEPRECATED_DEFAULT = UI_DEFAULTS.includeDeprecated;
5+
const SCAN_SOURCE_DEFAULT = UI_DEFAULTS.scanSource;
6+
const THEME_DEFAULT = UI_DEFAULTS.theme;
47

58
function storageGet(defaults) {
69
return new Promise((resolve) => {
@@ -26,18 +29,44 @@ function storageSet(obj) {
2629
}
2730

2831
async function init() {
29-
const { scanFilter } = await storageGet({ scanFilter: FILTER_DEFAULT });
32+
const { scanFilter, includeDeprecated, scanSource, theme } = await storageGet({
33+
scanFilter: FILTER_DEFAULT,
34+
includeDeprecated: DEPRECATED_DEFAULT,
35+
scanSource: SCAN_SOURCE_DEFAULT,
36+
theme: THEME_DEFAULT
37+
});
38+
39+
document.body.classList.toggle('theme-dark', theme === 'dark');
3040
document.querySelectorAll('input[name="scanFilter"]').forEach((input) => {
3141
input.checked = input.value === scanFilter;
3242
input.addEventListener('change', async () => {
3343
if (input.checked) await storageSet({ scanFilter: input.value });
3444
});
3545
});
3646

47+
const deprecatedCheckbox = document.getElementById('include-deprecated');
48+
deprecatedCheckbox.checked = !!includeDeprecated;
49+
deprecatedCheckbox.addEventListener('change', async () => {
50+
await storageSet({ includeDeprecated: deprecatedCheckbox.checked });
51+
});
52+
53+
document.querySelectorAll('input[name="scanSource"]').forEach((input) => {
54+
input.checked = input.value === scanSource;
55+
input.addEventListener('change', async () => {
56+
if (input.checked) await storageSet({ scanSource: input.value });
57+
});
58+
});
59+
3760
document.getElementById('run-scan').addEventListener('click', async () => {
3861
const selected = document.querySelector('input[name="scanFilter"]:checked')?.value || FILTER_DEFAULT;
62+
const selectedSource = document.querySelector('input[name="scanSource"]:checked')?.value || SCAN_SOURCE_DEFAULT;
3963
try {
40-
await chrome.runtime.sendMessage({ action: 'startScanWithFilter', filter: selected });
64+
await chrome.runtime.sendMessage({
65+
action: 'startScanWithFilter',
66+
filter: selected,
67+
includeDeprecated: deprecatedCheckbox.checked,
68+
scanSource: selectedSource
69+
});
4170
} catch (err) {
4271
console.error('Failed to start scan:', err);
4372
} finally {

0 commit comments

Comments
 (0)