Skip to content

Commit fb69512

Browse files
committed
Add Chrome Side Panel support and update manifest to v1.2.0
1 parent 66b1128 commit fb69512

4 files changed

Lines changed: 130 additions & 8 deletions

File tree

README.md

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,17 +44,14 @@ typographic giveaways out of AI text.
4444

4545
## Browser extension
4646

47-
Popup only. Click the toolbar icon, paste, clean, copy. It declares no
48-
permissions and no host access, so it can't read any page you visit, and it
49-
works with no connection.
47+
Opens directly as a Chrome Side Panel. Click the toolbar icon, and it docks cleanly on the side of your browser without floating in front of your page content. Paste, clean, copy. It declares no remote permissions and no host access, so it can't read any page you visit, and it works completely offline.
5048

51-
Not on the Chrome Web Store yet, so load it unpacked in Chrome, Edge, Brave or
52-
Opera:
49+
Load it unpacked in Chrome, Edge, Brave or Opera:
5350

5451
1. Download the latest zip from [Releases](https://github.com/cig13zs/invisibles/releases) and unzip it.
5552
2. Open `chrome://extensions` and turn on Developer mode.
5653
3. Click Load unpacked and pick the `extension` folder.
57-
4. Click the Invisibles icon and paste your text.
54+
4. Click the Invisibles icon to open the sidebar and paste your text.
5855

5956
## Use it as a library
6057

extension/background.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// Opens the side panel when the toolbar icon is clicked
2+
chrome.sidePanel
3+
.setPanelBehavior({ openPanelOnActionClick: true })
4+
.catch((error) => console.error(error));

extension/manifest.json

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,28 @@
11
{
22
"manifest_version": 3,
33
"name": "Invisibles — hidden character cleaner",
4-
"version": "1.1.1",
4+
"version": "1.2.0",
55
"description": "See the invisible characters hiding in your text, then strip them. Runs in your browser, no permissions, nothing uploaded.",
66
"icons": {
77
"16": "icons/icon16.png",
88
"48": "icons/icon48.png",
99
"128": "icons/icon128.png"
1010
},
11+
"permissions": [
12+
"sidePanel"
13+
],
14+
"side_panel": {
15+
"default_path": "sidepanel.html"
16+
},
1117
"action": {
12-
"default_popup": "popup.html",
1318
"default_title": "Invisibles — clean hidden characters",
1419
"default_icon": {
1520
"16": "icons/icon16.png",
1621
"48": "icons/icon48.png",
1722
"128": "icons/icon128.png"
1823
}
24+
},
25+
"background": {
26+
"service_worker": "background.js"
1927
}
2028
}

extension/sidepanel.html

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
<!doctype html>
2+
<html lang=" en\>
3+
<head>
4+
<meta charset=\utf-8\>
5+
<meta name=\viewport\ content=\width=device-width,initial-scale=1\>
6+
<title>Invisibles Sidebar</title>
7+
<style>
8+
:root{
9+
--bg:#faf9f6; --panel:#fff; --raised:#f3f1ec;
10+
--ink:#1c1a17; --muted:#6b665d; --line:#e4e0d8;
11+
--clay:#b4522f; --clay-soft:#f7ece7; --clay-ink:#fdfcfa;
12+
--ok:#1f7a4d; --hit:#b3372c; --hit-soft:#f9eae8;
13+
--r-sm:8px; --r-md:11px; --r-lg:14px; --r-pill:999px;
14+
--s1:6px; --s2:10px; --s3:14px; --s4:20px; --s5:28px;
15+
}
16+
@media (prefers-color-scheme:dark){:root{
17+
--bg:#14130f; --panel:#1c1a16; --raised:#221f1a;
18+
--ink:#f0ede5; --muted:#a09a8d; --line:#2e2a24;
19+
--clay:#e0865e; --clay-soft:#2a1c15; --clay-ink:#14130f;
20+
--ok:#54c489; --hit:#ef7f70; --hit-soft:#2c1815;
21+
}}
22+
*{box-sizing:border-box}
23+
html,body{height:100%;margin:0;padding:0}
24+
body{display:flex;flex-direction:column;padding:var(--s4);
25+
background:var(--bg);color:var(--ink);
26+
font:14px/1.55 ui-sans-serif,system-ui,-apple-system,\Segoe UI\,Roboto,sans-serif;
27+
-webkit-font-smoothing:antialiased;-webkit-text-size-adjust:100%}
28+
29+
.header{flex:none;margin-bottom:var(--s3)}
30+
h1{font-size:18px;margin:0;font-weight:660;letter-spacing:-.01em;display:flex;align-items:center;gap:6px}
31+
h1 .badge{font-size:11px;font-weight:600;padding:2px 7px;border-radius:var(--r-pill);background:var(--clay-soft);color:var(--clay)}
32+
.sub{color:var(--muted);font-size:12.5px;margin:4px 0 0;line-height:1.4}
33+
34+
.content{flex:1;display:flex;flex-direction:column;gap:var(--s2);overflow-y:auto}
35+
textarea{width:100%;min-height:120px;flex:1;resize:vertical;border:1px solid var(--line);
36+
border-radius:var(--r-md);background:var(--panel);color:var(--ink);padding:12px;
37+
font:13px/1.6 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}
38+
textarea::placeholder{color:var(--muted);opacity:.75}
39+
textarea:focus{outline:2px solid var(--clay);outline-offset:1px;border-color:var(--clay)}
40+
a:focus-visible,button:focus-visible,input:focus-visible{outline:2px solid var(--clay);outline-offset:2px}
41+
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
42+
43+
.row{display:flex;gap:var(--s2);align-items:center;flex-wrap:wrap;flex:none}
44+
button{min-height:38px;padding:9px 16px;border-radius:var(--r-sm);font-weight:620;font-size:13px;
45+
border:1px solid var(--line);background:var(--panel);color:var(--ink);cursor:pointer;
46+
transition:background .15s ease,border-color .15s ease}
47+
button:hover{border-color:var(--muted)}
48+
button.primary{background:var(--clay);color:var(--clay-ink);border-color:var(--clay)}
49+
button.primary:hover{background:var(--ink);border-color:var(--ink)}
50+
button:disabled{opacity:.42;cursor:default}
51+
button:disabled:hover{border-color:var(--line);background:var(--panel)}
52+
53+
label.opt{display:flex;align-items:center;gap:8px;font-size:12.5px;color:var(--muted);
54+
cursor:pointer;flex:none}
55+
label.opt input{accent-color:var(--clay);width:15px;height:15px;flex:none}
56+
57+
#summary{font-size:13px;flex:none}
58+
.verdict{font-weight:680}
59+
.verdict.clean{color:var(--ok)}.verdict.dirty{color:var(--clay)}
60+
#chips{display:flex;gap:var(--s1);flex-wrap:wrap;flex:none}
61+
.chip{font-size:11.5px;border:1px solid var(--line);border-radius:var(--r-pill);
62+
padding:3px 10px;color:var(--muted);background:var(--panel)}
63+
.chip b{color:var(--ink);font-weight:640}
64+
#out{background:var(--raised);flex:1;min-height:100px}
65+
.hint{font-size:12px;color:var(--muted);flex:none}
66+
67+
.footer{flex:none;margin-top:var(--s3);border-top:1px solid var(--line);padding-top:var(--s3)}
68+
.links{display:flex;gap:var(--s2)}
69+
.links a{flex:1;text-align:center;text-decoration:none;font-weight:620;font-size:12px;
70+
padding:8px;border-radius:var(--r-sm);min-height:36px;display:flex;align-items:center;justify-content:center}
71+
.kofi{background:var(--clay-soft);color:var(--clay);border:1px solid var(--clay)}
72+
.kofi:hover{background:var(--clay);color:var(--clay-ink)}
73+
.gh{background:var(--raised);color:var(--ink);border:1px solid var(--line)}
74+
.gh:hover{border-color:var(--muted)}
75+
@media (prefers-reduced-motion:reduce){*{transition-duration:.01ms!important}}
76+
</style>
77+
</head>
78+
<body>
79+
<div class=\header\>
80+
<h1>Invisibles <span class=\badge\>Sidebar</span></h1>
81+
<p class=\sub\>Reveal &amp; strip hidden characters offline. Zero tracking.</p>
82+
</div>
83+
84+
<div class=\content\>
85+
<label class=\sr-only\ for=\in\>Text to inspect</label>
86+
<textarea id=\in\ placeholder=\Paste text here to inspect…\ spellcheck=\false\ autocomplete=\off\></textarea>
87+
88+
<div class=\row\>
89+
<button id=\clean\ class=\primary\ type=\button\ disabled>Clean it</button>
90+
<button id=\copy\ type=\button\ hidden>Copy clean text</button>
91+
</div>
92+
93+
<label class=\opt\><input type=\checkbox\ id=\norm\> normalize smart quotes / em-dashes</label>
94+
95+
<div id=\summary\ role=\status\ aria-live=\polite\></div>
96+
<div id=\chips\></div>
97+
98+
<label class=\sr-only\ for=\out\>Clean text</label>
99+
<textarea id=\out\ readonly spellcheck=\false\ hidden></textarea>
100+
<div class=\hint\ id=\delta\ aria-live=\polite\></div>
101+
</div>
102+
103+
<div class=\footer\>
104+
<div class=\links\>
105+
<a class=\kofi\ href=\https://ko-fi.com/jju1s\ target=\_blank\ rel=\noopener\>☕ Ko-fi</a>
106+
<a class=\gh\ href=\https://github.com/cig13zs/invisibles\ target=\_blank\ rel=\noopener\>GitHub</a>
107+
</div>
108+
</div>
109+
110+
<script src=\core.js\></script>
111+
<script src=\popup.js\></script>
112+
</body>
113+
</html>

0 commit comments

Comments
 (0)