Introduce a Node build system for minified CSS/JS with content hashes, add PWA support, i18n helpers, accessibility improvements, and more translatable strings. Move theme configuration from bookmarks to localStorage, add Playwright tests, and set up CI workflows.
14 KiB
Plan d'amélioration – Shaarli Professional Theme (shaarli-pro)
Objectif : transformer le thème actuel, riche en fonctionnalités mais encore très artisanal, en une solution professionnelle, sécurisée, maintenable, performante et accessible.
Ce plan repose sur une analyse statique complète du code (README, rapport d'analyse existant, templates, CSS, JS, comparaison avec le thème default officiel de Shaarli).
1. Synthèse de l'état actuel
1.1 Métriques
| Fichier / catégorie | Taille | Remarque |
|---|---|---|
js/script.js |
~3 620 lignes | Thème, navigation, recherche, lecteur, multi-sélection, etc. |
js/custom_views.js |
~6 160 lignes | Notes, todos, archive, color picker, background studio |
js/shaarit-rules.js |
377 lignes | Règles métier ShaarIt (tags, détection, URLs) |
css/style.css |
~4 700 lignes | Design system principal |
css/custom_views.css |
~1 780 lignes | Styles des vues notes/todos |
css/themes.css |
~1 680 lignes | 16 palettes de couleurs |
| Templates HTML | ~40 fichiers | Dont plusieurs non documentés |
| Tests / CI / lint | 0 | Aucun outil d'assurance qualité |
1.2 Forces à préserver
- UI moderne, cohérente, avec sidebar + header.
- Mode clair/sombre et système de thèmes multiples.
- Fonctionnalités avancées : notes, todos, archive, lecteur média, multi-sélection, recherche Spotlight.
- Variables CSS et design system en place.
- Utilisation de
localStoragepour la persistance locale.
1.3 Appréciation globale
Le thème vaut ~6,5 / 10 en termes de professionnalisation. Il est fonctionnellement abouti, mais accumule de la dette technique : failles XSS potentielles, code monolithique, duplication, dépendances externes non maîtrisées, absence de tests et documentation obsolète.
2. Problèmes critiques – à traiter en priorité (Phase 1)
Ces points bloquent une mise en production professionnelle.
2.1 Sécurité
| Problème | Fichier(s) | Risque | Action |
|---|---|---|---|
XSS via innerHTML sur descriptions, previews, lecteur popup, tags |
js/script.js (l. 1547, 1603, 2151…), js/custom_views.js (passim) |
Exécution de code si un bookmark contient du HTML/JS malveillant | Tout contenu dynamique doit passer par textContent ou être échappé avec escapeHtml. Remplacer innerHTML par innerText / création DOM sécurisée. |
| Génération de code JavaScript en chaîne pour la popup lecteur | js/script.js buildPlayerHTML() (l. 2523–3053) |
Injection possible si titre/URL contiennent des quotes ou du code | Supprimer buildPlayerHTML() ; utiliser le template player.html existant ou un composant DOM réel. |
Persistance de la configuration via un bookmark privé (shaarit_config) |
js/script.js ShaaritThemeConfig (l. 7–154) |
Fuite de config, pollution de la base, risque si un attaquant crée un bookmark avec ce tag | Remplacer par localStorage uniquement, ou par un vrai plugin backend dédié. |
URLs internes fixes vers shaarit.app |
js/shaarit-rules.js (l. 142–148), js/script.js, migrate-todos.php |
Dépendance externe, fuite de données, rupture si le domaine change | Rendre les schémas d'URLs internes configurables (note://, todo://, ou URLs relatives). |
| Script PHP de migration dans le thème | migrate-todos.php |
Modification directe de la base, pas de contrôle d'accès, exécutable via web | Supprimer du thème ; en faire un plugin admin ou un script CLI documenté hors tpl/. |
descEl.innerHTML utilisé comme source de Markdown |
js/custom_views.js (l. 2422, 2492, 4239) |
Récupère le HTML rendu par Shaarli, potentiellement exécutable | Utiliser textContent comme source unique. |
2.2 Bugs et instabilités
| Problème | Fichier(s) | Action |
|---|---|---|
player.html n'est jamais utilisé mais dupliqué en JS |
player.html, js/script.js |
Supprimer player.html si inutile, ou l'utiliser comme cible de la popup. |
Template officiel pluginscontent.html absent |
tpl/default/pluginscontent.html |
Ajouter pluginscontent.html pour ne pas casser les plugins qui utilisent plugin_content. |
Gestion d'erreurs fetch insuffisante |
js/script.js, js/custom_views.js |
Ajouter des try/catch, vérifier response.ok, informer l'utilisateur en cas d'échec. |
| Écouteurs d'événements ajoutés mais jamais supprimés | js/script.js (102 addEventListener), js/custom_views.js (104) |
Nettoyer les listeners dans les modales, popups, sidebars mobile. |
tools_plugin inclus deux fois |
tools.html (l. 217 et 283) |
Ne garder qu'une seule zone. |
Hidden tags stockés uniquement dans localStorage |
hidden-tags.html, tools.html |
Per-browser, non synchronisés. Persister côté serveur (plugin) ou au minimum documenter la limitation. |
| Sélecteurs DOM très longs et fragiles | css/style.css, JS |
Raccourcir et utiliser des classes sémantiques (BEM ou équivalent). |
2.3 Compatibilité avec Shaarli officiel
- Le thème
defaultutilise{$version_hash}pour le cache-busting ;shaarli-proutilise des versions codées en dur (v=1.0.5, etc.) qui ne correspondent pas àtheme_info.php(1.0.0). - OpenGraph et
apple-touch-iconsont absents duincludes.htmlalors que le thème officiel les fournit. - Les templates officiels utilisent systématiquement
{'key'|t}pour l'internationalisation ;shaarli-promélange français, anglais et textes en dur.
3. Points non finis / fonctionnalités à finaliser
3.1 Vue Archive
initArchiveView()existe (js/custom_views.js) mais l'expérience semble moins aboutie que Notes/Todos (moins de styles dédiés, pas de création d'archive explicite).- Action : finaliser l'UI archive ou fusionner avec une fonction "archiver" depuis la vue Notes.
3.2 Gestion des tags cachés
- Double implémentation :
hidden-tags.htmlet le panneau danstools.html. - La logique est dupliquée entre
js/script.js(chargement) et le script inline dehidden-tags.html. - Action : centraliser la liste des tags système, définir une source unique (idéalement côté serveur via un plugin).
3.3 Lecteur média
- Le lecteur inline et la popup partagent un état via
localStorageetBroadcastChannel, ce qui est complexe. player.htmln'est pas utilisé.- Action : choisir une architecture unique (inline OU popup via un vrai template) et la stabiliser.
3.4 Panneau des thèmes
themes.csscharge 16 palettes (37 Ko) même si l'utilisateur n'en utilise qu'une.- Action : charger dynamiquement le CSS du thème actif, ou au minimum splitter
themes.csspar thème.
3.5 README et documentation
- Le README annonce une "Structure du Projet" incomplète : il omet
custom_views.js/css,themes.css,player.html,hidden-tags.html,install.html,migrate-todos.php,shaarit-rules.js,backgrounds-manifest.json, les fonds d'écrannote-bg-*. - Action : réécrire le README, ajouter un CHANGELOG et un guide de contribution.
4. Axes d'amélioration structurants
4.1 Qualité et maintenabilité du code
- Modulariser le JavaScript
- Découper
script.jsen modules thématiques :theme.js,search.js,media-player.js,bulk-actions.js,editor.js,mobile-nav.js. - Découper
custom_views.jsen :notes.js,todos.js,archive.js,palette.js,background-studio.js.
- Découper
- Supprimer les
console.logde debug (calendar, pin, theme sync, etc.). - Uniformiser la gestion des erreurs : toutes les fonctions
asyncdoivent avoir untry/catchet un retour utilisateur. - Réduire la spécificité CSS : éviter les sélecteurs de plus de 3 niveaux, nettoyer les
!important(26 danscustom_views.css). - Dédupliquer la navigation sidebar / header, soit via un template partagé, soit via génération JS à partir d'un tableau de liens.
4.2 Performance
- Mettre en place un build frontend (Vite, Webpack ou Rollup) pour :
- minifier JS/CSS,
- splitter les thèmes,
- ajouter des hashes de cache-busting,
- héberger localement les polices et les icônes si possible.
- Charger
custom_views.jsuniquement sur les pages concernées (actuellement chargé partout viaincludes.html). - Remplacer l'
@importGoogle Fonts par un<link rel="preload" as="style">ou des polices locales. - Optimiser les images de fond (
note-bg-*) : WebP/AVIF, redimensionnement, lazy-loading. - Supprimer le CSS mort avec un outil comme PurgeCSS ou un audit manuel des classes.
4.3 Accessibilité (a11y)
- Rendre les modales focus-trap (recherche, filtres, QR code, notes, todos).
- Utiliser
aria-selectedsur les boutons de mode de recherche et les onglets. - Ajouter
prefers-reduced-motionpour désactiver les animations. - Vérifier tous les contrastes (notamment
--tag-green-textsignalé comme limite). - Ajouter des skip-links et s'assurer que tous les boutons icônes ont un
aria-labelexplicite. - Remplacer les emojis utilisés comme indicateurs (📌 dans
linklist.html) par des icônes sémantiques.
4.4 Internationalisation (i18n)
- Extraire toutes les chaînes des templates vers le format Shaarli :
{'Ma clé'|t}. - Faire de même pour les textes générés en JS (labels de boutons, messages d'erreur, placeholders).
- Documenter les nouvelles clés de traduction ajoutées.
4.5 Architecture des fonctionnalités ShaarIt
- Rendre les règles ShaarIt configurables : le serveur Shaarli, pas
shaarit.app, doit être la source de vérité pour les URLs internes. - Ne plus utiliser des tags comme base de données pour stocker la config thème ; utiliser
localStorageou un plugin backend. - Réfléchir à un backend dédié pour notes/todos (plugin PHP) afin d'éviter les contournements par bookmarks et
fetchsur les formulaires d'édition.
5. Nouvelles idées à intégrer (par ordre de valeur)
| Idée | Intérêt | Complexité |
|---|---|---|
| Service Worker / PWA (offline, manifest, icônes) | Professionnalisation forte, usage mobile | Moyenne |
| Tests E2E avec Playwright (recherche, thème, multi-sélection, lecteur) | Garantie de non-régression | Moyenne |
| CI/CD GitHub Actions (lint, build, tests, release) | Qualité continue | Faible |
| ESLint + Stylelint + Prettier | Maintenabilité, style cohérent | Faible |
Mode haut contraste (prefers-contrast) |
Accessibilité | Faible |
| Amélioration du lecteur : playlist, historique, gestion des erreurs | UX | Moyenne |
| Recherche serveur pour les grosses collections (au lieu de parser le DOM) | Performance | Moyenne/forte |
| API côté serveur pour notes/todos/tags cachés | Sécurité, fiabilité | Forte |
| Dashboard de statistiques plus riche dans Tools | UX | Moyenne |
| Documentation technique auto-générée (JSDoc, Storybook-like) | Maintenabilité | Moyenne |
6. Roadmap recommandée
Phase 1 – Sécurité et stabilité (2 à 3 semaines)
- Audit XSS : remplacer tous les
innerHTMLà risque par du DOM sécurisé. - Supprimer ou sécuriser
buildPlayerHTML(); utiliserplayer.htmlou un composant DOM. - Retirer
migrate-todos.phpdu thème (plugin/CLI séparé). - Remplacer la persistance "bookmark config" par
localStoragepur ou un plugin backend. - Ajouter le template
pluginscontent.htmlmanquant. - Nettoyer les
console.logde debug. - Gestion d'erreurs robuste sur tous les
fetch. - Tests manuels complets sur une instance Shaarli propre.
Phase 2 – Qualité et maintenabilité (2 à 3 semaines)
- Découper
script.jsetcustom_views.jsen modules thématiques. - Refactoriser la navigation sidebar/header pour supprimer la duplication.
- Unifier le CSS variables et supprimer les variables mortes.
- Extraire les textes en dur vers
{'key'|t}. - Mettre en place ESLint + Stylelint + Prettier.
- Réécrire le README et ajouter un CHANGELOG.
Phase 3 – Performance et accessibilité (1 à 2 semaines)
- Mettre en place un build (minification, hash, split des thèmes).
- Charger
custom_views.jsà la demande. - Optimiser les polices et icônes (local/swap).
- Audit a11y complet (modales, contrastes, reduced-motion).
- Optimiser les images de fond.
Phase 4 – Évolutions (selon les priorités utilisateur)
- PWA / Service Worker.
- Tests E2E Playwright.
- CI/CD GitHub Actions.
- Backend plugin pour notes/todos/config.
- Améliorations du lecteur (playlist, historique).
7. Critères de validation
Pour considérer le thème comme professionnel, les critères suivants doivent être atteints :
- Sécurité : aucune alerte critique (XSS, injection,
eval,document.write) ; contenu utilisateur toujours échappé. - Stabilité : aucune erreur JS en console sur les parcours principaux (login, liste, ajout, édition, recherche, notes, todos, tools).
- Compatibilité : tous les templates officiels sont présents ou justifiés ; les plugins standard fonctionnent.
- Performance : score Lighthouse > 90 sur Performance et Accessibilité (sur une instance de référence).
- Maintenabilité : code modularisé, linté, documenté.
- Internationalisation : toutes les chaînes utilisateur passent par le système de traduction Shaarli.
- Tests : tests E2E critiques passants (recherche, multi-sélection, changement de thème, lecteur).
8. Premières actions immédiates (si vous voulez démarrer demain)
- Corriger les failles XSS dans
js/script.js::renderResults,js/custom_views.jset la popup lecteur. - Supprimer
migrate-todos.phpdu dossier thème. - Décider de l'avenir de la persistance thème :
localStorageuniquement ou plugin backend ? - Créer
pluginscontent.html. - Nettoyer les
console.logrestants. - Mettre à jour le README avec la structure réelle.
Plan rédigé le 8 août 2026. Il doit être affiné avec les retours utilisateurs et les contraintes réelles de déploiement (version de Shaarli, hébergement, usage du mobile).