Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

NewsInverter — news rewriter (Chrome extension MV3)

NewsInverter flips the meaning of headlines, sub-headlines, and article text without ever flashing the original text.

It achieves this with an ultra-early prehide CSS (runs at document_start) + headline overlays rendered via ::before.

FOOC = Flash Of Original Content — this project drives FOOC to zero.


Table of contents


Features

  • No original text visible, ever — prehide targets only not-yet-inverted nodes.
  • Headline overlay — original headline is transparent; visible text is drawn via ::before.
  • Paragraph replacement — body text replaced in DOM with the inverted version.
  • SPA/lazy content ready — re-inverts on DOM mutations and when elements enter viewport.
  • Fingerprint memory — repeated original snippets are auto-replaced from cache.
  • LLM + local fallback — calls your backend/LLM; if it times out, uses a quick antonymizer.
  • Defensive CSS — never hides containers or pseudo-elements, so overlays stay visible.

How it works

  1. content_start.js (runs at document_start)

    • Immediately sets html[data-ni-prehide="1"] and injects prehide CSS to hide only non-inverted nodes.
    • Injects page_inject.js into the page.
    • Bridges window.postMessage ⇄ Service Worker (action: "invert").
  2. page_inject.js (in-page logic)

    • Finds the article root, collects H1/H2/H3, P, LI, BLOCKQUOTE, FIGCAPTION, etc.
    • Headlines: apply overlay (::before) + mark with data-news-inverted="1".
    • Paragraphs: replace textContent + mark with data-news-inverted="1".
    • Guards: MutationObserver + IntersectionObserver keep everything inverted on SPA updates.
    • Fingerprinting: normalized original → inverted cache for instant re-apply.
  3. Service Worker

    • Responds to { action: "invert", text } with { ok: true, text: "<inverted>" }.
    • (Optional) handles inject_page_script fallback.

Why zero FOOC?
Nodes are transparent until inverted (prehide selectors). As soon as inversion is applied, we set data-news-inverted="1" and (for headlines) show overlay text via ::before while the original node stays transparent.


Project structure

/extension ├─ manifest.json ├─ content_start.js # prehide + SW bridge + injects page_inject.js (document_start) ├─ page_inject.js # selectors, inversion logic, overlays, guards, fingerprinting └─ service_worker.js # responds to 'invert', optional 'inject_page_script'


Installation (Load Unpacked)

  1. Go to chrome://extensions and enable Developer mode.
  2. Click Load unpacked and select the /extension folder.
  3. Open a news article page — you should see only inverted text (no original flash).

Manifest (MV3) example

{
  "name": "NewsInverter",
  "version": "0.1.0",
  "manifest_version": 3,
  "permissions": ["scripting", "storage"],
  "host_permissions": ["<all_urls>"],
  "background": { "service_worker": "service_worker.js" },
  "content_scripts": [{
    "matches": ["<all_urls>"],
    "js": ["content_start.js"],
    "run_at": "document_start",
    "all_frames": true
  }],
  "web_accessible_resources": [{
    "resources": ["page_inject.js"],
    "matches": ["<all_urls>"]
  }]
}

Limitations

Text drawn in or images can’t be inverted.

Exotic masking might confuse color detection (fallbacks exist).

Highly dynamic/obfuscated pages may need per-site selector tweaks.

Roadmap

Persistent fingerprint cache (SW side).

Per-site selector presets and heuristics.

Options page (domain toggles, thresholds).

Streaming/partial overlays for very long blocks.

License

MIT — do what you want, no warranty.

About

NewsInverter - flips the meaning of headlines, sub-headlines, and article text

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages