@hraness/sponge 0.6.10 → 0.6.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -72,6 +72,10 @@ never reads cookies, passwords or the browser's profile.
72
72
  Once the extension is connected, a page that comes back thin from the public web
73
73
  is tried again through the browser: first a plain fetch with your cookies, then a
74
74
  muted background tab that runs the page's scripts and closes afterwards.
75
+ When a site shows a security check (Cloudflare's "Just a moment…"), the tab waits
76
+ up to 20 seconds for your browser to clear it on its own, as it usually does for
77
+ a browser the site already knows. Sponge never clicks or answers a check; one that
78
+ stays is reported as blocked.
75
79
  `refresh ITEM --browser` (or `add URL --browser`) skips the public web and reads
76
80
  only through the browser. Its popup and right-click menu save the current page or
77
81
  a link. If no browser is connected, a `--browser` job fails as `browser-offline`
@@ -89,6 +89,7 @@ async function renderPage(url, timeoutMs) {
89
89
  try {
90
90
  await chrome.tabs.update(tab.id, { muted: true });
91
91
  if (!(await loaded(tab.id, deadline))) return { ok: false, code: 'timeout' };
92
+ await passedCheck(tab.id, Math.min(deadline, Date.now() + checkWaitMs));
92
93
  const [result] = await chrome.scripting.executeScript({ target: { tabId: tab.id }, func: snapshot });
93
94
  const page = result?.result;
94
95
  if (!page || typeof page.html !== 'string') return { ok: false, code: 'failed' };
@@ -101,6 +102,34 @@ async function renderPage(url, timeoutMs) {
101
102
  }
102
103
  }
103
104
 
105
+ /** How long a site's security check gets to let this browser through on its own. */
106
+ const checkWaitMs = 20_000;
107
+
108
+ /**
109
+ * Waits while the tab shows a security check (Cloudflare's "Just a moment…" and the like), which a real browser often
110
+ * clears by itself within seconds. Nothing is clicked or answered; a check that stays is captured as what it is.
111
+ */
112
+ async function passedCheck(tabId, until) {
113
+ while (Date.now() < until) {
114
+ const [result] = await chrome.scripting.executeScript({ target: { tabId }, func: checking }).catch(() => [null]);
115
+ if (result?.result === false) return;
116
+ await new Promise((resolve) => setTimeout(resolve, 500));
117
+ await loaded(tabId, until);
118
+ }
119
+ }
120
+
121
+ /** Runs in the page: whether it is a security check rather than the page itself. */
122
+ function checking() {
123
+ return (
124
+ /^(?:just a moment|one more step|attention required|security check|checking your browser)/i.test(
125
+ document.title.trim(),
126
+ ) ||
127
+ document.querySelector(
128
+ '#challenge-running, #challenge-form, #challenge-stage, script[src*="/cdn-cgi/challenge-platform/"]',
129
+ ) !== null
130
+ );
131
+ }
132
+
104
133
  /** A new tab first reports its blank start page as complete; only the requested page counts. */
105
134
  const navigated = (tab) => tab.status === 'complete' && !tab.pendingUrl && /^https?:/.test(tab.url ?? '');
106
135
 
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "manifest_version": 3,
3
3
  "name": "Sponge",
4
- "version": "0.6.10",
4
+ "version": "0.6.11",
5
5
  "description": "Save pages to your local Sponge library with the sign-ins you already have. Cookies never leave the browser.",
6
6
  "key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoSbZrBglr0h0193XOgavySnrG0DQif+WgYJ37CFSrbBwWP43rUz2ZzGRPvNveHgFZvFZlhGITJD0VC4NMQa2kxGAPP66RWEulIZDvGauxKonwcrlSneD+srPY8oMNX5sivTqw819uMwDA70oxBxKyTX4t4vwpwXuFX3Zf+5jwUOD3nz8XZFGT9uDh86MHyYYlURzsZQYBJSf2qAN17+OfhV7NHCWM5FdQodnOau6N/PcH/MstVGnbOaWeaTGged0PS2QGA5NDoOu5WZv1sUTHFqzM/Wsb/h1l8Kt5IfOZAXvhokhBBW7HTyYqgvX4wFHuj5fNioYshBUfMrKeZZFlQIDAQAB",
7
7
  "minimum_chrome_version": "116",
@@ -33,16 +33,16 @@
33
33
  }
34
34
  ],
35
35
  "build": {
36
- "asrSourceSha256": "1eb8d6a6c0df90cfdadfb26232d402a5f616b41340678927361fdcaa5acf2ab7",
36
+ "asrSourceSha256": "535c4265d279168ae6f971b875974669f6096dacefdfe217eeeb983eb300e9ab",
37
37
  "clangVersion": "Apple clang version 21.0.0 (clang-2100.1.1.101)",
38
- "embeddingSourceSha256": "0bba0ee3cebc6dd6196e41114d7e61ca74b68440af751656fcd1c282cad3bdee",
39
- "mediaSourceSha256": "6ef49c79b8ce06d73c8f53ffb892dfd8d8c6dc96adff90c224cf4803c032313b",
38
+ "embeddingSourceSha256": "c0588228be185b42f031243e10de15aae6c0dd5d865dda63457083a37f478bf4",
39
+ "mediaSourceSha256": "b8af23eb8c2298235dde54f900ac523d6614c9b92afd5db36f2d21aaecdd9d07",
40
40
  "rustcVersion": "rustc 1.97.1 (8bab26f4f 2026-07-14)",
41
41
  "swiftVersion": "Apple Swift version 6.3.3 (swiftlang-6.3.3.1.3 clang-2100.1.1.101)"
42
42
  },
43
43
  "minimumMacOS": "26.0",
44
- "packageVersion": "0.6.10",
44
+ "packageVersion": "0.6.11",
45
45
  "platform": "darwin",
46
46
  "schemaVersion": 1,
47
- "sourceCommit": "05a98d475948f8de577dd51178dbfd34c1a7c872"
47
+ "sourceCommit": "2b29176548506e04efd9f0a304de7c573b392e1d"
48
48
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hraness/sponge",
3
- "version": "0.6.10",
3
+ "version": "0.6.11",
4
4
  "description": "A local library for captured articles and verified offline assets.",
5
5
  "repository": {
6
6
  "type": "git",