https://github.com/mikaleb/hidepuretech
π Hide car ads with Puretech engine
https://github.com/mikaleb/hidepuretech
car chrome extension firefox hide-puretech opera productivity puretech react
Last synced: 3 months ago
JSON representation
π Hide car ads with Puretech engine
- Host: GitHub
- URL: https://github.com/mikaleb/hidepuretech
- Owner: Mikaleb
- License: other
- Created: 2024-08-26T17:06:46.000Z (almost 2 years ago)
- Default Branch: main
- Last Pushed: 2025-12-03T23:28:31.000Z (7 months ago)
- Last Synced: 2025-12-07T05:26:46.197Z (7 months ago)
- Topics: car, chrome, extension, firefox, hide-puretech, opera, productivity, puretech, react
- Language: TypeScript
- Homepage: https://chromewebstore.google.com/detail/hide-puretech/jphlfplfmjdbbjnegonboddmfgdkdkgi?authuser=0&hl=fr
- Size: 3.76 MB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Contributing: CONTRIBUTING.md
- Funding: .github/FUNDING.yml
- License: LICENSE
Awesome Lists containing this project
README

# Le Cache Misère (LCM)

## Features
**Le Cache Misère (LCM)** is a browser extension that filters car listings on supported websites containing problematic engines (PureTech, BlueHDi 1.5, etc.). Two hiding modes:
- **Grey-out mode** β listings are dimmed, grayscaled, and struck through; still visible but clearly marked
- **Hide completely** β listings are fully removed and replaced by a slim placeholder bar showing the vehicle title; clicking the bar reveals the listing in a faded "reviewed" state with a re-hide button
### Supported websites
-
[LaCentrale](https://www.lacentrale.fr/)
-
[AramisAuto](https://www.aramisauto.com/)
-
[LeBonCoin](https://www.leboncoin.fr/)
-
[AutoSphere](https://www.autosphere.fr/)
### Settings
- Toggle filtering per website (on/off)
- Toggle filtering per motor type independently (PureTech, BlueHDi 1.5, THP, etc.)
- **Hide completely** β remove listings entirely and show a placeholder (default: on)
- **Show placeholder icon** β display the extension icon inside the placeholder bar
---
## Architecture
This is a **Manifest V3 browser extension** built with Vite + `@crxjs/vite-plugin`, React 18, MUI v6, and SCSS.
## Development
### Prerequisites
- Node.js 18+
- npm
### Setup
```bash
npm install
```
### Dev commands
| Command | Description |
| ------------------ | ---------------------------------------------------------------- |
| `npm run dev` | Chrome dev mode β Vite with HMR on port 5173 |
| `npm run start:ff` | Firefox dev mode β watch build + auto-launch Firefox with reload |
| `npm run watch` | Watch build β updates `dist/` on every save (no browser launch) |
| `npm run build` | TypeScript check + Vite build β `dist/` |
| `npm run lint` | ESLint (TypeScript + React rules) |
| `npm run deploy` | Build + zip β `le-cache-misere.zip` |
| `npm run release` | Bump version, build, zip, push GitHub release |
### Contexts
| Context | Entry point | Purpose |
| ------------------ | -------------------------- | ---------------------------------------------------------------------------------------- |
| **Popup** | `src/main.tsx` β `App.tsx` | Settings UI β reads/writes `chrome.storage.sync`, sends messages to content scripts |
| **Content script** | `src/content.tsx` | Runs on supported sites β applies/removes `.lcm-disabled` CSS class on matched listings |
The popup communicates with live tabs via `browser.tabs.sendMessage`. The content script also reads `browser.storage.sync` directly on page load for its initial state.
### Storage schema (`chrome.storage.sync`)
```ts
{
websites: {
title: string;
url: string;
active: boolean;
}
[];
motors: {
title: string;
active: boolean;
pattern: string;
}
[];
hideCompletely: boolean; // default: true
showPlaceholderIcon: boolean; // default: false
}
```
All keys are initialised on first load from `src/store/initialState.ts` if missing. `pattern` is a case-insensitive regex string compiled at runtime.
Default motors:
- `PureTech` β pattern: `puretech|pure[- ]tech`
- `BlueHDi 1.5` β pattern: `(?=.*1\.5)(?=.*blue[- ]?hdi)` (matches any order)
### How filtering works
1. On page load, the content script reads all storage keys and uses `initialState.ts` defaults for any that are missing
2. If the current URL matches an active website, active motor patterns are compiled into regexes
3. Vendor-specific selectors identify listing card containers; each card's full text + ARIA attributes are tested against the regexes
4. Matched cards either get `.lcm-disabled` (grey-out) or `.lcm-hide-completely` + a placeholder bar (hide mode), depending on the `hideCompletely` setting
5. Clicking a placeholder sets `data-lcm-user-show="true"` on the card β it reappears dimmed with a "Re-hide" button overlay
6. The popup sends partial state updates via `browser.tabs.sendMessage`; the content script also stays in sync via `browser.storage.onChanged` for cross-tab reactivity
7. A debounced `MutationObserver` re-runs filtering automatically when the page DOM changes (e.g. infinite scroll)
---
## Debugging
### Load the unpacked extension (Chrome)
1. Run `npm run build`
2. Open `chrome://extensions/`
3. Enable **Developer mode** (top right)
4. Click **Load unpacked** β select the `dist/` folder
5. After code changes, run `npm run build` again and click the refresh icon on the extension card
### Load the unpacked extension (Firefox)
Run `npm run start:ff` β this concurrently starts the watch build and launches Firefox with the extension auto-loaded and auto-reloaded on every `dist/` change.
### Inspect the popup
- **Chrome:** `chrome://extensions/` β click **Inspect views: popup.html** under the extension
- **Firefox:** `about:debugging` β click **Inspect** next to the extension β open popup manually
### Inspect the content script
Open DevTools on any supported site (F12) β **Console** tab. The content script runs in the page context, not the extension background.
### Inspect storage
In the extension's DevTools console (popup inspector):
```js
chrome.storage.sync.get(null, console.log);
```
To reset storage to defaults:
```js
chrome.storage.sync.clear();
```
---
## License
MIT