Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
0f3bdff
chore: ignore markdown notes and generated dataset
Forthtilliath Oct 7, 2026
4879f0a
build: generate a single untracked class dataset
Forthtilliath Oct 7, 2026
5ca827d
refactor: split taxonomy into one file per category
Forthtilliath Oct 7, 2026
8fbdafd
ci: run checks on pull requests only with quota guards
Forthtilliath Oct 7, 2026
4556acc
build: add vitest unit test setup
Forthtilliath Oct 7, 2026
51dc03d
build: open a release pull request instead of pushing to main
Forthtilliath Oct 7, 2026
7ade902
fix: escape synthesized selectors and validate injected css
Forthtilliath Oct 7, 2026
2694967
feat: compose translucent colors in contrast checks
Forthtilliath Oct 7, 2026
c8f892f
feat: read site breakpoints from its media queries
Forthtilliath Oct 7, 2026
a129ad6
feat: validate runtime messages between panel and page
Forthtilliath Oct 7, 2026
c238507
feat: show a devtools-like box model overlay
Forthtilliath Oct 7, 2026
abe2e88
feat: add undoable change log and hover preview on page
Forthtilliath Oct 7, 2026
181afe4
fix: reconnect the panel after reload and close it with its tab
Forthtilliath Oct 7, 2026
978e09b
feat: translate the whole panel interface
Forthtilliath Oct 7, 2026
0cedfbb
style: split panel css into one file per component
Forthtilliath Oct 7, 2026
0ca36fb
feat: rank search results and match css values
Forthtilliath Oct 7, 2026
4b2068f
feat: add undo, hover preview and export to the panel
Forthtilliath Oct 7, 2026
68b3bed
test: add unit tests for core modules
Forthtilliath Oct 7, 2026
f583b56
test: cover undo, preview, export and reconnect end to end
Forthtilliath Oct 7, 2026
6e10e1f
docs: describe new editing features in readme
Forthtilliath Oct 7, 2026
4af0a35
build: stop tracking the generated class dataset
Forthtilliath Oct 7, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 24 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,13 +1,29 @@
name: CI

# Uniquement sur les PR vers main (pas de `push: main` en doublon : le contenu mergé en rebase a
# déjà été validé sur la PR). Les PR qui ne touchent que la doc/les images ne lancent rien.
on:
push:
branches: [main]
pull_request:
branches: [main]
types: [opened, synchronize, reopened, ready_for_review]
paths-ignore:
- '**.md'
- 'docs/**'
- '**.png'
- '**.jpg'
- '**.svg'
- 'LICENSE'

# Un nouveau push sur la PR annule l'exécution précédente, devenue obsolète.
concurrency:
group: ci-${{ github.event.pull_request.number }}
cancel-in-progress: true

jobs:
lint-and-build:
if: github.event.pull_request.draft == false
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- uses: actions/checkout@v4

Expand All @@ -23,6 +39,11 @@ jobs:

# tsc -b type-check aussi tests/e2e/ (cf. tsconfig.tests.json), sans avoir besoin de
# lancer Playwright ici : tester une extension Chrome en CI demande un Chromium headed
# (xvfb) et un profil persistant, pas encore mis en place — voir UPGRADES.md.
# (xvfb) et un profil persistant, pas encore mis en place.
- name: Build
run: npm run build

# Tests unitaires Vitest de src/core/ (< 1 s d'exécution, même job pour ne pas refaire
# checkout + install).
- name: Unit tests
run: npm test
1 change: 1 addition & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ permissions:
jobs:
release:
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- uses: actions/checkout@v4
with:
Expand Down
10 changes: 8 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,14 @@ dist-test
dist-ssr
*.local

# Notes de travail locales, jamais partagées (préférence utilisateur, tous projets)
UPGRADES.md
# Dataset de classes régénéré avant chaque dev/build/test (npm run generate:tw-data)
/src/data/generated/

# Notes de travail locales, jamais partagées (préférence utilisateur, tous projets) : tous les
# .md sauf README et CHANGELOG
*.md
!README.md
!CHANGELOG.md

# Playwright (tests/e2e)
/test-results/
Expand Down
1 change: 1 addition & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
git-tag-version=false
39 changes: 26 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,20 @@ Cible **Tailwind CSS v4** (thème par défaut en OKLCH, variables CSS `@theme`,

## Fonctionnalités

- **Picker visuel** : clic sur l'icône ou `Ctrl+Shift+K` pour activer le picker, clic sur un élément de la page pour sélectionner ce qu'on veut éditer. Fil d'ariane des ancêtres, navigation clavier (flèches), mode verrouillé pour interagir avec la page sans perdre la sélection (bouton 🔒 ou `Échap` directement sur la page).
- **Panneau dans une fenêtre séparée**, déplaçable indépendamment (utile sur un second écran) : classes regroupées par catégorie (couleurs, spacing, typographie, bordures, effets, filtres, transitions, interactivité...) dans un rail redimensionnable, recherche transversale, valeurs récentes, export en texte brut ou JSX.
- **Historique de session** : chaque ajout/retrait de classe, sur n'importe quel élément de la page (pas juste la sélection courante), est loggué avec un diff `+classe`/`−classe` — pratique pour retrouver l'ensemble des modifications faites à différents endroits avant de finaliser. Copiable, vidable.
- **Picker visuel** : clic sur l'icône ou `Ctrl+Shift+K` pour activer le picker, clic sur un élément de la page pour sélectionner ce qu'on veut éditer. Surbrillance façon DevTools (dimensions, marge et padding, survol en pointillé / sélection en trait plein), fil d'ariane des ancêtres, navigation clavier (flèches), mode verrouillé pour interagir avec la page sans perdre la sélection (bouton 🔒 ou `Échap` directement sur la page).
- **Panneau dans une fenêtre séparée**, déplaçable indépendamment (utile sur un second écran) : classes regroupées par catégorie (couleurs, spacing, typographie, bordures, effets, filtres, transitions, interactivité...) dans un rail redimensionnable, valeurs récentes, export en texte brut ou JSX.
- **Aperçu au survol** : survoler une valeur dans la liste d'une propriété l'applique temporairement sur la page, sans rien enregistrer ; le clic la valide.
- **Recherche transversale** : résultats classés (exact, puis début de nom…), recherche par valeur CSS (`16px` → `p-4`, `text-base`…), suggestions tolérantes aux fautes de frappe.
- **Variants** : breakpoints réels du site (lus dans ses media queries), pseudo-classes courantes en accès direct (`hover`, `focus-visible`, `group-hover`, `first`…), variant libre, réinitialisation en un clic.
- **Historique de session et annuler/rétablir** : chaque ajout/retrait de classe, sur n'importe quel élément de la page (pas juste la sélection courante), est loggué avec un diff `+classe`/`−classe`. `Ctrl+Z` / `Ctrl+Shift+Z` (ou les boutons ↶ ↷), annulation d'une entrée précise depuis l'historique. Export des modifications ou des classes finales de tous les éléments modifiés, chacun repéré par un sélecteur CSS unique.
- **Synthèse CSS live** : une classe choisie dans le panneau produit un effet visuel immédiat même si elle est absente du CSS déjà chargé sur la page (build de prod purgé) — variants `hover:`, `dark:`, breakpoints, `group-*`/`peer-*`, `aria-*`, `has-*`, `data-*`, opacité de couleur (`bg-red-500/80`), propriétés composites (transform/filter/backdrop-filter) synthétisées fidèlement au vrai moteur v4.
- **Détection du thème réel du site** : les classes synthétisées référencent les vraies variables CSS `@theme` du site (avec repli sur notre thème par défaut), y compris si le site utilise un préfixe Tailwind custom (`tw:bg-red-500` → `--tw-color-red-500`).
- **Navigateur de variables de thème** : liste les `--color-*`/`--radius-*`/`--spacing`/etc. réellement définis sur `:root` du site.
- **Scan CSS** : détecte les classes custom (non-Tailwind) utilisées sur la page en parsant les feuilles de style chargées (avec repli `fetch()` pour le cross-origin autorisant CORS), re-scanne automatiquement si le site charge du CSS dynamiquement.
- **Contrôle de contraste WCAG** : ratio texte/fond de l'élément sélectionné (AA/AAA), aperçu du contraste par couleur candidate avant de l'appliquer.
- Thème clair/sombre du panneau, libellés de catégorie en français ou anglais (toggle FR/EN, pas de mélange), raccourcis clavier, indicateur de classe non synthétisable.
- Interface en français ou en anglais (langue du navigateur par défaut, toggle FR/EN), thème clair/sombre du panneau, raccourcis clavier, indicateur de classe non synthétisable, reconnexion en un clic après rechargement de la page quand Chrome le permet.

Détail complet des fonctionnalités et idées futures : [UPGRADES.md](UPGRADES.md).
Bugs et idées d'amélioration : [issues GitHub](../../issues).

## Installation

Expand All @@ -50,21 +53,28 @@ Puis charger le dossier `dist/` de la même façon.
```sh
npm run dev # build en mode watch (HMR pour le panneau)
npm run lint # oxlint
npm test # tests unitaires (Vitest)
npm run build # build de production dans dist/
```

Le dataset de classes (`src/data/generated/`) est régénéré automatiquement avant chaque build (`npm run generate:tw-data`) à partir du thème par défaut Tailwind v4 croisé avec la taxonomie éditée à la main (`src/data/taxonomy.ts`) — jamais de classe tapée en dur.
Le dataset de classes (`src/data/generated/`, non versionné) est régénéré automatiquement avant chaque `dev`, `build` et `test` (`npm run generate:tw-data`) à partir du thème par défaut Tailwind v4 croisé avec la taxonomie éditée à la main (`src/data/taxonomy/`) — jamais de classe tapée en dur.

### Structure

- `src/core/` — logique indépendante du DOM/React : parsing de classes, diff, synthèse CSS live, scan CSS, contraste WCAG.
- `src/content/` — content script injecté à la demande sur la page éditée.
- `src/content/` — content script injecté à la demande sur la page éditée. Volontairement léger (~13 Ko) : il n'embarque ni la taxonomie ni le dataset ; le panneau calcule le diff de classes et le CSS de prévisualisation, la page se contente de les appliquer.
- `src/devpanel/` — l'interface React du panneau (fenêtre séparée).
- `src/background/` — service worker (activation, raccourcis).
- `src/data/taxonomy.ts` — la seule table éditée à la main ; `scripts/generate-tailwind-data.ts` en dérive le dataset complet des classes.
- `src/data/taxonomy/` — la seule table éditée à la main (un fichier par catégorie) ; `scripts/generate-tailwind-data.ts` en dérive le dataset complet des classes.

### Tests

Tests unitaires Vitest de `src/core/` (parsing, diff, synthèse CSS, variants, contraste, validation des messages) :

```sh
npm test
```

Suite e2e Playwright, extension chargée dans un vrai Chromium :

```sh
Expand All @@ -77,15 +87,18 @@ Le build de test (`npm run build:test`) diffère du build de production sur deux

### Publier une release

Une seule commande (working directory propre requis) :
Rien n'est poussé directement sur `main` : la release passe par une PR, puis le tag est posé après intégration (le rebase réécrit les SHA).

```sh
npm version patch # ou minor / major
npm version patch # ou minor / major — depuis main propre et à jour
# … intégrer la PR ouverte (rebase), puis :
npm run release:tag
```

`npm version` bump `package.json`, commit et tague (`vX.Y.Z`) en un coup ; les hooks `preversion`/`postversion` (voir `package.json`) font le reste automatiquement :
1. `preversion` — lint + type-check, annule tout si ça échoue (rien n'est bumpé/tagué).
2. `postversion` — pousse le commit ET le tag, ce qui déclenche `.github/workflows/release.yml` (build, zip, Release GitHub).
1. `preversion` — vérifie qu'on est sur `main` propre et aligné sur `origin/main`, puis lint + type-check ; annule tout si ça échoue (rien n'est bumpé).
2. `npm version` bump `package.json`/`package-lock.json` sans commit ni tag (`.npmrc` : `git-tag-version=false`).
3. `postversion` — crée la branche `release/vX.Y.Z`, commit `chore: release vX.Y.Z`, pousse la branche et ouvre la PR.
4. `npm run release:tag` — met `main` à jour, tague le commit de release (`vX.Y.Z`) et pousse le tag, ce qui déclenche `.github/workflows/release.yml`.

Le workflow `.github/workflows/release.yml` build, zippe `dist/` et publie automatiquement une Release GitHub avec le zip en pièce jointe.

Expand Down
10 changes: 7 additions & 3 deletions manifest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,13 @@ import pkg from './package.json' with { type: 'json' }

export default defineManifest(({ mode }) => ({
manifest_version: 3,
name: 'DevWind',
// Textes du manifest traduits par Chrome selon la langue du navigateur (public/_locales/,
// copié tel quel à la racine de dist/) ; l'interface du panneau a sa propre traduction,
// commutable à chaud (src/devpanel/i18n/).
default_locale: 'en',
name: '__MSG_extName__',
version: pkg.version,
description: 'Éditeur visuel de classes Tailwind CSS, en direct dans le navigateur.',
description: '__MSG_extDescription__',
// Fichiers dans public/icons/ : Vite copie déjà tout public/ tel quel à la racine de dist/
// (public/icons/icon16.png -> dist/icons/icon16.png), donc les chemins ci-dessous sont
// relatifs à dist/, pas au projet.
Expand Down Expand Up @@ -33,7 +37,7 @@ export default defineManifest(({ mode }) => ({
commands: {
'toggle-picker': {
suggested_key: { default: 'Ctrl+Shift+K', mac: 'Command+Shift+K' },
description: 'Activer/désactiver le picker DevWind',
description: '__MSG_commandToggle__',
},
},
permissions: ['activeTab', 'scripting', 'storage'],
Expand Down
Loading
Loading