@libriciel/ls-password
v2.0.0
Published
A dependency-free vanilla JS component for password fields at Libriciel SCOP. It adds a toggler and a strength meter (with respect to ANSSI recommendations) to password fields.
Downloads
64
Keywords
Readme
ls-password
Description
Un composant sans dépendance (JS vanilla) pour les champs de mot de passe de Libriciel SCOP. Il ajoute un bouton d'affichage/masquage et un indicateur de robustesse (conforme aux recommandations de l'ANSSI) aux champs de mot de passe. Ni jQuery, ni Bootstrap, ni police d'icônes requis.
La version 2.x est sans dépendance — jQuery n'est plus requis (le paquet a été renommé de
@libriciel/ls-jquery-password). Voir le guide de migration si vous effectuez une mise à niveau depuis la 1.x.
L'indicateur de robustesse a été inspiré par la bande dessinée xkcd « Password Strength », afin d'encourager des mots de passe faciles à retenir pour un humain tout en offrant une grande entropie (nombre de valeurs possibles).

Le bouton d'affichage permet à l'utilisateur de basculer le champ de mot de passe en champ texte afin de vérifier ce qu'il a saisi.
L'indicateur de robustesse doit devenir vert et atteindre 100 % une fois l'entropie souhaitée atteinte. Il prend uniquement en compte l'entropie du mot de passe (force brute). Contrairement à d'autres indicateurs de robustesse, il ne vérifie pas les répétitions, les mots de passe courants, les mots de passe divulgués, les mots du dictionnaire, etc.
Installation
npm install @libriciel/ls-passwordUtilisation
Modules ES (bundler)
import { toggler, strengthMeter } from '@libriciel/ls-password'
import '@libriciel/ls-password/dist/css/ls-password.css'
const field = document.querySelector('input[type=password]')
strengthMeter(field) // par défaut : cible d'entropie 130 (administrateurs RSSI)
toggler(field)Balise <script> simple (global LsPassword)
<link rel="stylesheet" href="dist/css/ls-password.css">
<script src="dist/js/ls-password.min.js"></script>
<script>
LsPassword.strengthMeter('input[type=password]', LsPassword.strengthMeter.configure(80)); // cible d'entropie 80 (utilisateurs)
LsPassword.toggler('input[type=password]');
</script>Symfony AssetMapper (sans bundler)
Ajoutez le paquet à l'importmap :
php bin/console importmap:require @libriciel/ls-passwordLe paquet déclarant sa feuille de style (champ style du package.json), la CSS est ajoutée
automatiquement à l'importmap. Puis, dans votre point d'entrée JS (ex. assets/app.js) :
import { toggler, strengthMeter } from '@libriciel/ls-password'
import '@libriciel/ls-password/dist/css/ls-password.css' // AssetMapper génère automatiquement le <link>
const field = document.querySelector('input[type=password]')
strengthMeter(field) // par défaut : cible d'entropie 130 (administrateurs RSSI)
toggler(field)Les deux fonctions acceptent un élément, une NodeList, un tableau d'éléments ou un sélecteur CSS (chaîne de caractères). Le fichier CSS est requis (il met en forme la barre et le bouton, et expose les variables de thème).
API
toggler(target, options?)
Ajoute un <button type="button"> accessible d'affichage/masquage à côté du champ, en enveloppant les deux
dans un conteneur .ls-pw. L'icône est un SVG intégré (aria-hidden) ; le libellé accessible est porté par
les attributs title / aria-label du bouton.
| Option | Défaut | Description |
| --- | --- | --- |
| position | after | Position du bouton par rapport au champ (before/after) ; after = œil à droite |
| showTitle | Afficher le mot de passe | Libellé lorsque le mot de passe est masqué |
| hideTitle | Masquer le mot de passe | Libellé lorsque le mot de passe est affiché |
| className | ls-pt | Classe du bouton |
| wrapperTag | div | Balise du conteneur créé autour du champ |
| wrapperClass | ls-pw | Classe du conteneur (partagée avec l'indicateur de robustesse) |
| iconShow | (SVG œil barré) | Balisage SVG affiché lorsque le mot de passe est masqué |
| iconHide | (SVG œil) | Balisage SVG affiché lorsque le mot de passe est affiché |
Balisage généré (par défaut) :
<div class="ls-pw">
<button type="button" class="ls-pt" title="Afficher le mot de passe" aria-label="Afficher le mot de passe">
<svg class="ls-pt__icon" aria-hidden="true" focusable="false">…</svg>
</button>
<input type="password" …>
</div>strengthMeter(target, options?)
Ajoute une barre de robustesse après le champ (ou après le conteneur .ls-pw si le bouton d'affichage est
également utilisé). Elle se met à jour automatiquement lors des événements input / change / blur.
Utilisez strengthMeter.configure(target) pour construire les options, où target est la cible
d'entropie (en bits) à laquelle la barre atteint 100 % :
strengthMeter(field, strengthMeter.configure(130))
// équivalent au comportement par défaut :
{
"className": "ls-pm",
"barClassName": "ls-pm__bar",
"levelClassName": "ls-pm__level",
"complementClassName": "ls-pm__complement",
"hintClassName": "ls-pm__hint",
"levelPrefix": "Niveau de sécurité : ",
"complement": { "empty": "", "very-weak": "", "weak": "Un peu plus", "average": "Encore un effort", "strong": "Presque, continuez", "very-strong": "Niveau de sécurité du mot de passe excellent." },
"hint": { "empty": "Augmentez la longueur…", "very-weak": "Augmentez la longueur…", "weak": "Augmentez la longueur…", "average": "Augmentez la longueur…", "strong": "Augmentez la longueur…", "very-strong": "" },
"inputGroupClass": "ls-pw",
"inputGroupTag": "div",
"target": 130
}Les 2ᵉ à 4ᵉ arguments personnalisent les textes : le préfixe du texte de niveau, ainsi que les messages
complement et hint par niveau (fusionnés avec les valeurs par défaut, ce qui permet de surcharger
un seul niveau) :
strengthMeter(field, strengthMeter.configure(80, 'Robustesse : ')) // "Robustesse : Moyen"
strengthMeter(field, strengthMeter.configure(80, '')) // "Moyen" (sans préfixe)
strengthMeter(field, strengthMeter.configure(80, undefined, { average: 'Presque !' }, { average: 'Ma consigne.' }))La cible suit les préconisations du RSSI. Deux constantes nommées sont exposées par commodité :
| Constante | Entropie | Cas d'usage |
| --- | --- | --- |
| strengthMeter.configure.USER | 80 | utilisateurs finaux |
| strengthMeter.configure.ADMIN | 130 | administrateurs / matériel cryptographique sensible — par défaut |
strengthMeter(field, strengthMeter.configure(strengthMeter.configure.USER)) // cible 80
strengthMeter(field) // pas d'options → cible par défaut 130 (ADMIN)Une cible invalide (non numérique ou ≤ 0) génère une erreur dans la console et retombe sur la valeur par défaut (130). La barre se remplit jusqu'à 100 % une fois l'entropie atteignant la cible ; sa couleur reflète la progression vers celle-ci.
La barre comporte 5 niveaux de robustesse (plus un état empty pour un champ vide). Les quatre niveaux
en dessous de la cible découpent la plage [0, target) en quarts ; atteindre la cible (100 %) donne
very-strong :
| Niveau | Classe | Plage (% de la cible) | aria-valuetext |
| --- | --- | --- | --- |
| empty | ls-pm__bar--empty | champ vide | Vide |
| very-weak | ls-pm__bar--very-weak | [0 %, 25 %) | Très faible |
| weak | ls-pm__bar--weak | [25 %, 50 %) | Faible |
| average | ls-pm__bar--average | [50 %, 75 %) | Moyen |
| strong | ls-pm__bar--strong | [75 %, 100 %) | Fort |
| very-strong | ls-pm__bar--very-strong | ≥ 100 % | Très fort |
Sous la barre, trois éléments de texte reformulent la progression (afin que l'information ne soit pas transmise par la couleur seule — WCAG) et sont mis à jour à chaque changement :
div.ls-pm__level— le niveau courant sous la forme<préfixe><libellé>(ex.Niveau de sécurité : Moyen), coloré comme le niveau. Vide tant que le champ est vide.div.ls-pm__complement— un court complément par niveau, coloré comme le niveau (Un peu plus/Encore un effort/Presque, continuez/Niveau de sécurité du mot de passe excellent.; aucun pourvery-weak).div.ls-pm__hint— une consigne de format affichée dès le départ (champ vide inclus) et partagée par tous les niveaux en dessous de la cible (Augmentez la longueur ou ajoutez des types de caractères différents…) ; absente uniquement une fois la cible atteinte.
Le complément et la consigne sont masqués (CSS :empty) dès que leur contenu est vide. Tous les textes sont
configurables (voir les arguments de configure ci-dessus).
Balisage généré (barre de progression accessible avec aria-valuetext, puis les trois éléments de texte) :
<div class="ls-pm">
<div class="ls-pm__bar ls-pm__bar--empty" role="progressbar"
aria-label="Indicateur de robustesse du mot de passe"
aria-valuenow="0" aria-valuemin="0" aria-valuemax="100"
aria-valuetext="Vide" style="width:0%;">0%</div>
</div>
<div class="ls-pm__level ls-pm__level--empty"></div>
<div class="ls-pm__complement ls-pm__complement--empty"></div>
<div class="ls-pm__hint">Augmentez la longueur ou ajoutez des types de caractères différents (chiffres, majuscules, caractères spéciaux).</div>Personnalisation du thème
Les couleurs sont personnalisables via des variables CSS. Le composant utilise la variable de votre système de design lorsqu'elle est définie, avec une valeur de repli codée en dur sinon :
:root {
/* Fond de la barre */
--ls-pm-color-empty: var(--ds-color-grey-200, #d3d3d3);
--ls-pm-color-very-weak: var(--ds-color-danger-600, #c02b2b);
--ls-pm-color-weak: var(--ds-color-danger-600, #c02b2b);
--ls-pm-color-average: var(--ds-color-warning-600, #c07000);
/* « Fort » reste orange : le vert est réservé à la validation (cible atteinte, very-strong) */
--ls-pm-color-strong: var(--ds-color-warning-600, #c07000);
--ls-pm-color-very-strong: var(--ds-color-success-600, #23a237);
/* Texte de niveau visible — seuls average/strong/very-strong nécessitent une teinte plus foncée que la
barre pour le contraste WCAG AA sur fond clair ; les autres réutilisent les variables de barre ci-dessus */
--ls-pm-level-color-average: var(--ds-color-warning-800, #843500);
--ls-pm-level-color-strong: var(--ds-color-warning-800, #843500);
--ls-pm-level-color-very-strong: var(--ds-color-success-800, #02590f);
--ls-pm-hint-color: var(--ds-color-grey-600, #5c6370); /* texte de la consigne de format */
--ls-pt-icon-color: var(--ds-color-grey-600, #5c6370); /* icône œil */
--ls-pt-hover-bg: var(--ds-color-grey-200, #d3d3d3); /* survol du bouton */
}Développement
Toutes les commandes s'exécutent dans Docker (voir CLAUDE.md) ; l'installation Node de l'hôte n'est pas utilisée.
make test # lance la suite de tests (Vitest)
make coverage # lance les tests avec rapport de couverture (coverage/)
make build # construit dist/ (ESM + UMD + CSS) avec Vite
make dev # démo de développement avec rechargement à chaud → http://localhost:5173/