Skip to content

Commit 4eb4c44

Browse files
highdaclaude
andcommitted
Add Font Ripper bookmarklet install page
Builds the draggable bookmark from minified.js on vibecode-snippets main, so pushes to the source repo go live without a sync step. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent a3cab6b commit 4eb4c44

3 files changed

Lines changed: 127 additions & 0 deletions

File tree

‎README.md‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,7 @@
1515
### Guitar learning helpers (added/updated as I learn)
1616

1717
[Chord transition trainer](/vibecode-snippets/chords-trainer/)
18+
19+
### Bookmarklets
20+
21+
[Font Ripper](/vibecode-snippets/font-ripper.html)

‎index.html‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,22 @@ <h3 class="c-title">Chord Transition Trainer</h3>
264264
</a>
265265
</div>
266266
</section>
267+
268+
<!-- BOOKMARKLETS -->
269+
<section>
270+
<div class="sec-head">
271+
<h2><span class="num">04</span>Bookmarklets</h2>
272+
<div class="rule"></div>
273+
</div>
274+
<div class="grid">
275+
<a class="card" href="/vibecode-snippets/font-ripper.html">
276+
<div class="c-top"><span class="c-icon">🔤</span><span class="c-tag">Bookmarklet</span></div>
277+
<h3 class="c-title">Font Ripper</h3>
278+
<p class="c-desc">Finds every font on a page — CSS, JS FontFace, type testers, even unloaded styles — with previews and ZIP download.</p>
279+
<span class="c-go">Install <span class="arrow">→</span></span>
280+
</a>
281+
</div>
282+
</section>
267283
</main>
268284

269285
<footer>

‎vibecode-snippets/font-ripper.html‎

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
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>Font Ripper — highda archives</title>
7+
<meta name="description" content="Bookmarklet that finds every font on a page — CSS, JS FontFace, type testers, not-yet-loaded styles — with previews and ZIP download.">
8+
<meta name="color-scheme" content="dark">
9+
<link rel="preconnect" href="https://fonts.googleapis.com">
10+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
11+
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;700&family=VT323&display=swap" rel="stylesheet">
12+
<style>
13+
:root{
14+
--bg:#08080f;--bg-2:#0e0e1c;--ink:#d7d7e6;--muted:#7a7a96;
15+
--cyan:#55ffff;--magenta:#ff55ff;--line:rgba(85,255,255,.16);--card:rgba(255,255,255,.025);
16+
--radius:14px;--mono:'JetBrains Mono',ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
17+
}
18+
*{box-sizing:border-box}
19+
body{margin:0;min-height:100vh;background:linear-gradient(180deg,var(--bg),var(--bg-2));color:var(--ink);
20+
font-family:var(--mono);line-height:1.6;-webkit-font-smoothing:antialiased}
21+
.wrap{max-width:760px;margin:0 auto;padding:clamp(40px,9vw,90px) 16px 60px}
22+
.back{color:var(--muted);text-decoration:none;font-size:13px}
23+
.back:hover{color:var(--cyan)}
24+
h1{font-family:'VT323',var(--mono);font-weight:400;font-size:clamp(48px,11vw,96px);line-height:.95;margin:18px 0 8px;color:#fff}
25+
.tagline{margin:0 0 30px;max-width:56ch}
26+
.tagline em{color:var(--magenta);font-style:normal}
27+
.panel{border:1px solid var(--line);border-radius:var(--radius);background:var(--card);padding:22px}
28+
.install{display:flex;flex-wrap:wrap;gap:12px;align-items:center}
29+
.bookmarklet{display:inline-flex;align-items:center;gap:10px;padding:14px 22px;border:1px solid var(--cyan);border-radius:10px;
30+
color:var(--cyan);background:rgba(85,255,255,.06);text-decoration:none;font-weight:700;cursor:grab;
31+
box-shadow:0 10px 40px -14px rgba(85,255,255,.5)}
32+
.bookmarklet:hover{background:rgba(85,255,255,.12)}
33+
.bookmarklet[aria-disabled="true"]{opacity:.35;pointer-events:none}
34+
button{padding:14px 18px;border:1px solid var(--line);border-radius:10px;background:none;color:var(--ink);font:inherit;cursor:pointer}
35+
button:hover:not(:disabled){border-color:var(--magenta);color:var(--magenta)}
36+
button:disabled{opacity:.35;cursor:default}
37+
.status{display:block;margin-top:14px;font-size:12.5px;color:var(--muted)}
38+
h2{font-size:13px;letter-spacing:.22em;text-transform:uppercase;color:var(--cyan);margin:40px 0 12px}
39+
ol,ul{padding-left:20px;margin:0}
40+
li{margin-bottom:6px}
41+
li::marker{color:var(--magenta)}
42+
kbd,code{font-family:var(--mono);font-size:.9em;color:#fff}
43+
.muted{color:var(--muted);font-size:13.5px}
44+
a{color:var(--cyan)}
45+
</style>
46+
</head>
47+
<body>
48+
<div class="wrap">
49+
<a class="back" href="/">← highda archives</a>
50+
<h1>Font Ripper</h1>
51+
<p class="tagline">A bookmarklet that finds <em>every</em> font on a page — CSS, JS <code>FontFace</code>, type testers, even styles the tester hasn't loaded yet — with live previews and one-click ZIP download.</p>
52+
53+
<div class="panel">
54+
<div class="install">
55+
<a class="bookmarklet" id="bookmarklet" href="#" aria-disabled="true">🔤 Font Ripper</a>
56+
<button id="copy" disabled>Copy code</button>
57+
</div>
58+
<span class="status" id="status">Loading latest build…</span>
59+
</div>
60+
61+
<h2>Install</h2>
62+
<ol>
63+
<li>Show the bookmarks bar (<kbd>Ctrl/⌘ + Shift + B</kbd>).</li>
64+
<li>Drag the <strong>Font Ripper</strong> button onto it.</li>
65+
<li>Open any page and click the bookmark.</li>
66+
</ol>
67+
<p class="muted">Can't drag (mobile, some browsers)? Hit “Copy code”, create a new bookmark and paste it as the URL.</p>
68+
69+
<h2>What it catches</h2>
70+
<ul class="muted">
71+
<li>CSS <code>@font-face</code> incl. <code>@import</code>, shadow DOM, same-origin iframes and CORS-blocked sheets</li>
72+
<li>Fonts registered from JS via <code>FontFace</code>, matched to their files by glyph metrics + internal names</li>
73+
<li>Any font file the page downloaded, even from extension-less URLs</li>
74+
<li>Font files referenced in the page source that haven't been loaded yet</li>
75+
</ul>
76+
<p class="muted">Out of reach: cross-origin iframes (listed so you can run it there), fonts decrypted in JS, text rendered into images.</p>
77+
<p class="muted">Source &amp; details: <a href="https://github.com/highda/vibecode-snippets/tree/main/bookmarklets/font-ripper">github.com/highda/vibecode-snippets</a></p>
78+
</div>
79+
<script>
80+
// Always the latest build from the source repo (raw.githubusercontent.com allows CORS).
81+
// Percent-encoded because browsers URL-decode javascript: bookmarks before running them.
82+
(async () => {
83+
const SRC = "https://raw.githubusercontent.com/highda/vibecode-snippets/main/bookmarklets/font-ripper/minified.js";
84+
const link = document.getElementById("bookmarklet");
85+
const copy = document.getElementById("copy");
86+
const status = document.getElementById("status");
87+
try {
88+
const res = await fetch(SRC, { cache: "no-cache" });
89+
if (!res.ok) throw new Error("HTTP " + res.status);
90+
const code = (await res.text()).trim().replace(/^javascript:/, "");
91+
const href = "javascript:" + encodeURIComponent(code);
92+
link.href = href;
93+
link.removeAttribute("aria-disabled");
94+
link.onclick = e => { e.preventDefault(); status.textContent = "Drag the button to your bookmarks bar instead of clicking it."; };
95+
copy.disabled = false;
96+
copy.onclick = async () => {
97+
try { await navigator.clipboard.writeText(href); status.textContent = "Copied — paste it as a bookmark URL."; }
98+
catch { status.textContent = "Clipboard blocked — drag the button instead."; }
99+
};
100+
status.textContent = `Ready — latest build (${Math.round(code.length / 1024)} kB).`;
101+
} catch (e) {
102+
status.textContent = "Couldn't load the latest build: " + e.message;
103+
}
104+
})();
105+
</script>
106+
</body>
107+
</html>

0 commit comments

Comments
 (0)