dsfr_accessible_skip_links 0.1.2 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +23 -0
- data/README.md +255 -107
- data/lib/dsfr_accessible_skip_links/configuration.rb +26 -0
- data/lib/dsfr_accessible_skip_links/engine.rb +11 -2
- data/lib/dsfr_accessible_skip_links/skip_links.rb +11 -3
- data/lib/dsfr_accessible_skip_links/skip_links_implemented_checker.rb +32 -0
- data/lib/dsfr_accessible_skip_links/version.rb +1 -1
- data/lib/dsfr_accessible_skip_links.rb +2 -0
- data/lib/generators/dsfr_accessible_skip_links/install_generator.rb +57 -22
- metadata +5 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: cde36b7db7ed5759c035c760be7723d3c06e3912182688148c1adf62a59b827d
|
|
4
|
+
data.tar.gz: 1df51f6f597f5811c5b42cf66a9a1960cc7c307eb46140781f056581dc22edf2
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 35aa47a41dcee7700f425b87436042d71504532aace7a6316621a7da99e510ee090567d0ee3fae28a53414be0c24e1615e7b831c2ed744eb66dc208e9d0545a3
|
|
7
|
+
data.tar.gz: 9351451e96a6859ea8f35934e99222c4f90d3685f11eb684a031e8a7bfe18d69fd9172606d3d33cd80b0d3e9fb94b2736571bc92b25e80beb5fff9ad0c9940ed
|
data/CHANGELOG.md
CHANGED
|
@@ -7,11 +7,34 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.2.0] - 2025-08-28
|
|
11
|
+
### Added
|
|
12
|
+
- **SkipLinksImplementedChecker**: New validation service to ensure skip links are properly implemented across applications
|
|
13
|
+
- **Configuration system**: Allow users to configure whitelisted routes that are exempt from validation
|
|
14
|
+
- **Disable validation option**: New `disable_validation` configuration for projects with existing validation systems
|
|
15
|
+
- Comprehensive test coverage for validation functionality
|
|
16
|
+
|
|
17
|
+
### Changed
|
|
18
|
+
- Improved README documentation with clearer installation and usage instructions
|
|
19
|
+
- Enhanced generator functionality and reliability
|
|
20
|
+
- Updated README with complete documentation for validation features and configuration options
|
|
21
|
+
|
|
22
|
+
## [0.1.3] - 2025-08-27
|
|
23
|
+
### Fixed
|
|
24
|
+
- Generator now uses `copy_file` instead of `template` to avoid evaluating ERB in the partial during generation. This prevents `NameError` for `skip_links_content`.
|
|
25
|
+
- Ensure DsfrAccessibleSkipLinks::SkipLinks is automatically included using `ActiveSupport.on_load` hooks:
|
|
26
|
+
- Included into `ActionController::Base` (controller-side) and exposed as view helpers
|
|
27
|
+
- Included into `ActionView` (view-side) so helpers are available in templates without manual setup
|
|
28
|
+
|
|
10
29
|
## [0.1.2] - 2025-08-27
|
|
11
30
|
### Added
|
|
12
31
|
- Rails generator `dsfr_accessible_skip_links:install` to copy the skip links partial and inject the render call into the application layout.
|
|
13
32
|
- README updated with installation instructions using the generator.
|
|
14
33
|
|
|
34
|
+
## [0.1.1] - 2025-08-27
|
|
35
|
+
### Fixed
|
|
36
|
+
- Minor bug fixes and improvements
|
|
37
|
+
|
|
15
38
|
## [0.1.0] - 2025-08-27
|
|
16
39
|
|
|
17
40
|
### Added
|
data/README.md
CHANGED
|
@@ -1,70 +1,76 @@
|
|
|
1
1
|
# DsfrAccessibleSkipLinks
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Une gem Ruby qui aide les projets à implémenter des liens d’évitement accessibles conformément au Système de design de l’État français (DSFR). Cette gem fournit des helpers et utilitaires pour créer des liens d’évitement de navigation qui améliorent l’accessibilité du web.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Ajoutez cette ligne au Gemfile de votre application :
|
|
8
8
|
|
|
9
9
|
```ruby
|
|
10
10
|
gem 'dsfr_accessible_skip_links'
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
Puis installez la gem :
|
|
14
14
|
|
|
15
15
|
$ bundle install
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
Lancez l’installateur pour configurer les liens d’évitement dans votre application Rails :
|
|
18
18
|
|
|
19
19
|
$ bin/rails g dsfr_accessible_skip_links:install
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
Cela va :
|
|
22
|
+
- Copier le partial des liens d’évitement vers `app/views/shared/_skip_links.html.erb`
|
|
23
|
+
- Afficher des instructions pour l’ajouter à votre layout
|
|
22
24
|
|
|
23
|
-
|
|
25
|
+
**Étape suivante :** Ajoutez l’appel à `render` dans votre layout (généralement `app/views/layouts/application.html.erb`) :
|
|
26
|
+
|
|
27
|
+
```erb
|
|
28
|
+
<body>
|
|
29
|
+
<%= render 'shared/skip_links' %>
|
|
30
|
+
<!-- le reste de votre contenu -->
|
|
31
|
+
</body>
|
|
32
|
+
```
|
|
24
33
|
|
|
25
|
-
|
|
34
|
+
**Option d’installation rapide :** utilisez l’option `--inject-layout` pour ajouter automatiquement l’appel à `render` :
|
|
35
|
+
|
|
36
|
+
$ bin/rails g dsfr_accessible_skip_links:install --inject-layout
|
|
37
|
+
|
|
38
|
+
Vous pouvez aussi installer directement la gem :
|
|
39
|
+
|
|
40
|
+
$ gem install dsfr_accessible_skip_links
|
|
26
41
|
|
|
27
|
-
|
|
42
|
+
## Utilisation
|
|
28
43
|
|
|
29
|
-
|
|
44
|
+
### Éléments requis
|
|
30
45
|
|
|
31
|
-
|
|
46
|
+
Assurez‑vous que votre layout contient ces éléments avec les bons identifiants (ID) :
|
|
32
47
|
|
|
33
48
|
```erb
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
</header>
|
|
46
|
-
|
|
47
|
-
<main id="content">
|
|
48
|
-
<%= yield %>
|
|
49
|
-
</main>
|
|
50
|
-
|
|
51
|
-
<footer id="footer">
|
|
52
|
-
<!-- your footer -->
|
|
53
|
-
</footer>
|
|
54
|
-
</body>
|
|
55
|
-
</html>
|
|
49
|
+
<header id="header">
|
|
50
|
+
<!-- votre navigation -->
|
|
51
|
+
</header>
|
|
52
|
+
|
|
53
|
+
<main id="content">
|
|
54
|
+
<%= yield %>
|
|
55
|
+
</main>
|
|
56
|
+
|
|
57
|
+
<footer id="footer">
|
|
58
|
+
<!-- votre pied de page -->
|
|
59
|
+
</footer>
|
|
56
60
|
```
|
|
57
61
|
|
|
58
|
-
|
|
62
|
+
La gem s’intègre automatiquement à Rails via un Rails Engine. Les méthodes helper sont disponibles automatiquement dans tous les contrôleurs et vues.
|
|
63
|
+
|
|
64
|
+
### Liens d’évitement par défaut
|
|
59
65
|
|
|
60
|
-
|
|
61
|
-
-
|
|
62
|
-
-
|
|
63
|
-
-
|
|
66
|
+
Par défaut, la gem fournit trois liens d’évitement :
|
|
67
|
+
- **« Aller au contenu »** → `#content`
|
|
68
|
+
- **« Menu »** → `#header`
|
|
69
|
+
- **« Pied de page »** → `#footer`
|
|
64
70
|
|
|
65
|
-
###
|
|
71
|
+
### Liens d’évitement personnalisés
|
|
66
72
|
|
|
67
|
-
|
|
73
|
+
Vous pouvez personnaliser les liens d’évitement page par page grâce à `content_for` de Rails :
|
|
68
74
|
|
|
69
75
|
```erb
|
|
70
76
|
<% content_for :skip_links do %>
|
|
@@ -74,44 +80,44 @@ You can customize skip links on a per-page basis using Rails' `content_for`:
|
|
|
74
80
|
<% end %>
|
|
75
81
|
```
|
|
76
82
|
|
|
77
|
-
###
|
|
83
|
+
### Texte du lien vers le contenu
|
|
78
84
|
|
|
79
|
-
|
|
85
|
+
Vous pouvez personnaliser le texte du lien vers le contenu principal :
|
|
80
86
|
|
|
81
87
|
```erb
|
|
82
|
-
<% content_for :content_skip_link_text, '
|
|
88
|
+
<% content_for :content_skip_link_text, 'Aller au contenu principal' %>
|
|
83
89
|
```
|
|
84
90
|
|
|
85
|
-
###
|
|
91
|
+
### Liens préfixés par « tab- »
|
|
86
92
|
|
|
87
|
-
|
|
93
|
+
Pour les liens nécessitant une interaction JavaScript, utilisez le préfixe `tab-` :
|
|
88
94
|
|
|
89
95
|
```erb
|
|
90
|
-
<%= skip_link('
|
|
96
|
+
<%= skip_link('Navigation par onglet', 'tab-special-section') %>
|
|
91
97
|
```
|
|
92
98
|
|
|
93
|
-
|
|
99
|
+
Cela ajoutera un attribut `data-anchor` pour la gestion côté JavaScript.
|
|
94
100
|
|
|
95
|
-
###
|
|
101
|
+
### Méthodes helper
|
|
96
102
|
|
|
97
|
-
|
|
103
|
+
La gem fournit ces méthodes helper (disponibles automatiquement dans les contrôleurs et vues) :
|
|
98
104
|
|
|
99
|
-
- `skip_link(text, anchor)` -
|
|
100
|
-
- `default_skip_links` -
|
|
101
|
-
- `skip_links_content` -
|
|
102
|
-
- `content_skip_link_text` -
|
|
105
|
+
- `skip_link(text, anchor)` - Crée un lien d’évitement
|
|
106
|
+
- `default_skip_links` - Renvoie l’ensemble par défaut de liens d’évitement
|
|
107
|
+
- `skip_links_content` - Renvoie les liens personnalisés ou, à défaut, les liens par défaut
|
|
108
|
+
- `content_skip_link_text` - Renvoie le texte du lien vers le contenu
|
|
103
109
|
|
|
104
|
-
### CSS
|
|
110
|
+
### Classes CSS
|
|
105
111
|
|
|
106
|
-
|
|
107
|
-
- `.fr-skiplinks` -
|
|
108
|
-
- `.fr-container` - DSFR
|
|
109
|
-
- `.fr-skiplinks__list` -
|
|
110
|
-
- `.fr-link` -
|
|
112
|
+
La gem utilise les classes CSS officielles du DSFR :
|
|
113
|
+
- `.fr-skiplinks` - Conteneur principal
|
|
114
|
+
- `.fr-container` - Conteneur DSFR
|
|
115
|
+
- `.fr-skiplinks__list` - Liste des liens
|
|
116
|
+
- `.fr-link` - Style du lien individuel
|
|
111
117
|
|
|
112
|
-
### HTML
|
|
118
|
+
### Structure HTML
|
|
113
119
|
|
|
114
|
-
|
|
120
|
+
Le HTML généré suit cette structure :
|
|
115
121
|
|
|
116
122
|
```html
|
|
117
123
|
<div class="fr-skiplinks">
|
|
@@ -125,104 +131,246 @@ The generated HTML follows this structure:
|
|
|
125
131
|
</div>
|
|
126
132
|
```
|
|
127
133
|
|
|
128
|
-
##
|
|
134
|
+
## Validation des liens d’évitement
|
|
135
|
+
|
|
136
|
+
La gem inclut un service de validation pour s’assurer que les liens d’évitement sont correctement implémentés dans votre application pendant les tests.
|
|
137
|
+
|
|
138
|
+
### SkipLinksImplementedChecker
|
|
139
|
+
|
|
140
|
+
Le service `SkipLinksImplementedChecker` vérifie automatiquement que les pages :
|
|
141
|
+
- ont des liens d’évitement personnalisés définis via `content_for(:skip_links)`, ou
|
|
142
|
+
- sont incluses dans votre configuration de routes en liste blanche (whitelist)
|
|
143
|
+
|
|
144
|
+
Cette validation s’exécute automatiquement en environnement de test lorsque les liens d’évitement sont rendus.
|
|
145
|
+
|
|
146
|
+
### Configuration
|
|
147
|
+
|
|
148
|
+
Configurez les routes qui doivent être exemptées de la validation des liens d’évitement :
|
|
149
|
+
|
|
150
|
+
```ruby
|
|
151
|
+
# config/initializers/dsfr_accessible_skip_links.rb
|
|
152
|
+
DsfrAccessibleSkipLinks.configure do |config|
|
|
153
|
+
config.whitelisted_routes = [
|
|
154
|
+
'pages#home',
|
|
155
|
+
'pages#about',
|
|
156
|
+
'admin/dashboard#index',
|
|
157
|
+
'users#show',
|
|
158
|
+
'posts#index'
|
|
159
|
+
]
|
|
160
|
+
end
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
### Désactiver la validation
|
|
129
164
|
|
|
130
|
-
|
|
165
|
+
Si votre projet dispose déjà de son propre système de validation des liens d’évitement, vous pouvez désactiver la validation intégrée de la gem :
|
|
131
166
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
167
|
+
```ruby
|
|
168
|
+
# config/initializers/dsfr_accessible_skip_links.rb
|
|
169
|
+
DsfrAccessibleSkipLinks.configure do |config|
|
|
170
|
+
config.disable_validation = true
|
|
171
|
+
end
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
Lorsque `disable_validation` est défini à `true` :
|
|
175
|
+
- `SkipLinksImplementedChecker` ne s’exécute pas automatiquement dans les tests
|
|
176
|
+
- Vous pouvez toujours utiliser les helpers de la gem pour générer les liens d’évitement
|
|
177
|
+
- Aucune erreur de validation n’est levée, vous gardez la main sur les contrôles d’accessibilité
|
|
178
|
+
|
|
179
|
+
### Utilisation manuelle
|
|
180
|
+
|
|
181
|
+
Vous pouvez aussi utiliser le vérificateur manuellement dans vos tests ou votre application :
|
|
182
|
+
|
|
183
|
+
```ruby
|
|
184
|
+
# Dans un contrôleur ou un test
|
|
185
|
+
checker = DsfrAccessibleSkipLinks::SkipLinksImplementedChecker.new(
|
|
186
|
+
controller_name: 'posts',
|
|
187
|
+
action_name: 'show',
|
|
188
|
+
has_skip_links: content_for?(:skip_links)
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
begin
|
|
192
|
+
checker.perform!
|
|
193
|
+
# Les liens d’évitement sont correctement configurés
|
|
194
|
+
rescue DsfrAccessibleSkipLinks::SkipLinksImplementedChecker::SkipLinksNotDefinedError => e
|
|
195
|
+
# Gérer l’absence de liens d’évitement
|
|
196
|
+
puts e.message
|
|
197
|
+
end
|
|
198
|
+
```
|
|
137
199
|
|
|
138
|
-
|
|
200
|
+
### Intégration dans les tests Rails
|
|
139
201
|
|
|
140
|
-
|
|
202
|
+
La validation s’exécute automatiquement pendant les tests. Si une page n’a pas de liens d’évitement et n’est pas en liste blanche, vous verrez :
|
|
141
203
|
|
|
142
|
-
|
|
143
|
-
|
|
204
|
+
```
|
|
205
|
+
DsfrAccessibleSkipLinks::SkipLinksImplementedChecker::SkipLinksNotDefinedError:
|
|
206
|
+
No skip links defined for this page (posts#show). Use content_for(:skip_links)
|
|
207
|
+
to define skip links or define them in a view-specific helper.
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
Pour corriger cela, soit :
|
|
211
|
+
1. Ajoutez la route à votre configuration de liste blanche
|
|
212
|
+
2. Définissez des liens d’évitement personnalisés dans votre vue :
|
|
213
|
+
|
|
214
|
+
```erb
|
|
215
|
+
<% content_for :skip_links do %>
|
|
216
|
+
<%= skip_link('Aller au contenu', 'main-content') %>
|
|
217
|
+
<%= skip_link('Aller aux commentaires', 'comments') %>
|
|
218
|
+
<% end %>
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
## Fonctionnalités d’accessibilité
|
|
222
|
+
|
|
223
|
+
Cette gem implémente des liens d’évitement conformément aux [WCAG 2.2](https://www.w3.org/WAI/WCAG22/quickref/) et aux spécifications du [DSFR (Système de design de l’État français)](https://www.systeme-de-design.gouv.fr/).
|
|
224
|
+
|
|
225
|
+
### Conformité aux standards
|
|
226
|
+
- **WCAG 2.2 niveau AA** : conforme aux standards internationaux d’accessibilité
|
|
227
|
+
- **Recommandations DSFR** : suit les exigences d’accessibilité du système de design de l’État
|
|
228
|
+
- **RGAA 4.1** : compatible avec le Référentiel Général d’Amélioration de l’Accessibilité
|
|
229
|
+
|
|
230
|
+
### Caractéristiques techniques
|
|
231
|
+
- **HTML sémantique** : structure adéquate avec l’élément `<nav>` et `role="navigation"`
|
|
232
|
+
- **Compatibilité lecteurs d’écran** : `aria-label="Accès rapide"` descriptif pour les aides techniques
|
|
233
|
+
- **Navigation au clavier** : accessibilité complète avec gestion correcte du focus
|
|
234
|
+
- **Aller au contenu** : navigation directe vers les zones principales (#content, #header, #footer)
|
|
235
|
+
- **Design visuel** : compatible avec les classes CSS officielles du DSFR pour un style cohérent
|
|
236
|
+
|
|
237
|
+
### Assurance qualité
|
|
238
|
+
- **Validation automatisée** : un vérificateur intégré évite d’oublier les liens d’évitement
|
|
239
|
+
- **Intégration aux tests** : vérifie la présence des liens pendant les exécutions de test
|
|
240
|
+
- **Validation configurable** : liste blanche des routes ne nécessitant pas de liens d’évitement
|
|
241
|
+
- **Retour développeur** : messages d’erreur clairs pour guider l’implémentation
|
|
242
|
+
|
|
243
|
+
### Intégration DSFR
|
|
244
|
+
Cette gem implémente le composant officiel [liens d’évitement DSFR](https://www.systeme-de-design.gouv.fr/elements-d-interface/composants/liens-d-evitement) en respectant :
|
|
245
|
+
- Les classes CSS officielles (`.fr-skiplinks`, `.fr-container`, `.fr-skiplinks__list`, `.fr-link`)
|
|
246
|
+
- La structure HTML recommandée et les attributs ARIA
|
|
247
|
+
- Les libellés en français par défaut pour les sites publics
|
|
248
|
+
- La compatibilité responsive
|
|
249
|
+
|
|
250
|
+
### Bénéfices en accessibilité
|
|
251
|
+
- **Navigation plus rapide** : les utilisateurs de lecteurs d’écran et au clavier peuvent aller directement au contenu
|
|
252
|
+
- **Charge cognitive réduite** : une structure claire améliore l’expérience utilisateur
|
|
253
|
+
- **Conformité réglementaire** : aide à satisfaire les exigences françaises pour le secteur public
|
|
254
|
+
- **Conception universelle** : profite à tous, notamment aux personnes avec déficiences motrices ou visuelles
|
|
255
|
+
|
|
256
|
+
Pour en savoir plus sur les exigences d’accessibilité web en France :
|
|
257
|
+
- [Documentation officielle DSFR](https://www.systeme-de-design.gouv.fr/)
|
|
258
|
+
- [RGAA](https://www.numerique.gouv.fr/publications/rgaa-accessibilite/)
|
|
259
|
+
- [WCAG 2.2](https://www.w3.org/WAI/WCAG22/quickref/)
|
|
260
|
+
|
|
261
|
+
## Comment tester cette gem
|
|
262
|
+
|
|
263
|
+
Il y a deux façons principales de tester cette gem :
|
|
264
|
+
|
|
265
|
+
1) Exécuter la suite de tests localement (rapide, pas besoin d’une app Rails)
|
|
266
|
+
- Installer les dépendances :
|
|
144
267
|
```bash
|
|
145
268
|
bundle install
|
|
146
269
|
```
|
|
147
|
-
-
|
|
270
|
+
- Lancer RSpec :
|
|
148
271
|
```bash
|
|
149
272
|
bundle exec rake spec
|
|
150
273
|
```
|
|
151
|
-
-
|
|
274
|
+
- Lancer RuboCop :
|
|
152
275
|
```bash
|
|
153
276
|
bundle exec rake rubocop
|
|
154
277
|
```
|
|
155
|
-
-
|
|
278
|
+
- Lancer les deux (tâche par défaut) :
|
|
156
279
|
```bash
|
|
157
280
|
bundle exec rake
|
|
158
281
|
```
|
|
159
282
|
|
|
160
|
-
2)
|
|
161
|
-
-
|
|
283
|
+
2) L’essayer dans une vraie application Rails (pour tester le générateur et l’intégration)
|
|
284
|
+
- Créer une nouvelle application Rails (ou utiliser une existante) :
|
|
162
285
|
```bash
|
|
163
286
|
rails new demo_app --skip-javascript --skip-hotwire --skip-action-mailbox --skip-action-text --skip-active-storage --skip-active-job --skip-system-test
|
|
164
287
|
cd demo_app
|
|
165
288
|
```
|
|
166
|
-
-
|
|
289
|
+
- Pointer l’app vers votre copie locale de cette gem. Dans demo_app/Gemfile, ajoutez :
|
|
167
290
|
```ruby
|
|
168
291
|
gem 'dsfr_accessible_skip_links', path: '../path/to/your/dsfr_accessible_skip_links'
|
|
169
292
|
```
|
|
170
|
-
|
|
293
|
+
Puis exécutez :
|
|
171
294
|
```bash
|
|
172
295
|
bundle install
|
|
173
296
|
```
|
|
174
|
-
-
|
|
297
|
+
- Lancer l’installateur :
|
|
175
298
|
```bash
|
|
176
299
|
bin/rails g dsfr_accessible_skip_links:install
|
|
177
300
|
```
|
|
178
|
-
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
```erb
|
|
182
|
-
<%= render partial: 'shared/skip_links' %>
|
|
183
|
-
```
|
|
184
|
-
- Ensure your layout has the anchor targets used by default links:
|
|
185
|
-
```erb
|
|
186
|
-
<header id="header"></header>
|
|
187
|
-
<main id="content"><%= yield %></main>
|
|
188
|
-
<footer id="footer"></footer>
|
|
189
|
-
```
|
|
190
|
-
- Start the server and check the skip links at the top of the page:
|
|
301
|
+
- Vérifier que le partial existe : `app/views/shared/_skip_links.html.erb`
|
|
302
|
+
- Ajouter l’appel au partial dans votre layout et vérifier la présence des éléments HTML requis (voir section Utilisation ci‑dessus)
|
|
303
|
+
- Démarrer le serveur et vérifier les liens d’évitement en haut de la page :
|
|
191
304
|
```bash
|
|
192
305
|
bin/rails s
|
|
193
306
|
```
|
|
194
|
-
|
|
195
|
-
(
|
|
307
|
+
Rendez‑vous sur http://localhost:3000 et repérez le balisage des liens d’évitement
|
|
308
|
+
(« Aller au contenu », « Menu », « Pied de page »).
|
|
309
|
+
|
|
310
|
+
**Notes :**
|
|
311
|
+
- Le générateur est idempotent : il n’insérera pas la ligne `render` deux fois si elle existe déjà.
|
|
312
|
+
|
|
313
|
+
### Mettre en place la validation des liens d’évitement
|
|
314
|
+
|
|
315
|
+
Après avoir installé la gem, créez un initializer pour configurer les routes en liste blanche :
|
|
316
|
+
|
|
317
|
+
```bash
|
|
318
|
+
# Créer le fichier d’initialisation
|
|
319
|
+
touch config/initializers/dsfr_accessible_skip_links.rb
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
Ajoutez votre configuration :
|
|
323
|
+
|
|
324
|
+
```ruby
|
|
325
|
+
# config/initializers/dsfr_accessible_skip_links.rb
|
|
326
|
+
DsfrAccessibleSkipLinks.configure do |config|
|
|
327
|
+
config.whitelisted_routes = [
|
|
328
|
+
# Pages d’atterrissage utilisant les liens d’évitement par défaut
|
|
329
|
+
'pages#home',
|
|
330
|
+
'pages#about',
|
|
331
|
+
'pages#contact',
|
|
332
|
+
|
|
333
|
+
# Pages d’admin avec layout standard
|
|
334
|
+
'admin/dashboard#index',
|
|
335
|
+
'admin/users#index',
|
|
336
|
+
|
|
337
|
+
# Endpoints d’API ou pages sans layout standard
|
|
338
|
+
'api/health#check',
|
|
339
|
+
'errors#not_found'
|
|
340
|
+
]
|
|
341
|
+
end
|
|
342
|
+
```
|
|
196
343
|
|
|
197
|
-
|
|
198
|
-
-
|
|
199
|
-
-
|
|
344
|
+
Cette configuration garantit que :
|
|
345
|
+
- Les routes listées ne déclencheront pas d’erreurs de validation dans les tests
|
|
346
|
+
- Les pages hors liste blanche doivent définir des liens d’évitement personnalisés
|
|
347
|
+
- Vous maintenez la conformité d’accessibilité dans toute votre application
|
|
200
348
|
|
|
201
|
-
##
|
|
349
|
+
## Développement
|
|
202
350
|
|
|
203
|
-
|
|
351
|
+
Après avoir cloné le dépôt, exécutez `bundle install` pour installer les dépendances.
|
|
204
352
|
|
|
205
|
-
|
|
353
|
+
Lancer la suite de tests :
|
|
206
354
|
```bash
|
|
207
355
|
bundle exec rake spec
|
|
208
356
|
```
|
|
209
357
|
|
|
210
|
-
|
|
358
|
+
Lancer RuboCop pour les contrôles de qualité de code :
|
|
211
359
|
```bash
|
|
212
360
|
bundle exec rake rubocop
|
|
213
361
|
```
|
|
214
362
|
|
|
215
|
-
|
|
363
|
+
Lancer à la fois les tests et RuboCop :
|
|
216
364
|
```bash
|
|
217
365
|
bundle exec rake
|
|
218
366
|
```
|
|
219
367
|
|
|
220
|
-
|
|
368
|
+
Pour installer cette gem sur votre machine locale, exécutez `bundle exec rake install`.
|
|
221
369
|
|
|
222
|
-
##
|
|
370
|
+
## Contribuer
|
|
223
371
|
|
|
224
|
-
|
|
372
|
+
Les rapports de bug et les pull requests sont les bienvenus sur GitHub : https://github.com/Isalafont/dsfr_accessible_skip_links.
|
|
225
373
|
|
|
226
|
-
##
|
|
374
|
+
## Licence
|
|
227
375
|
|
|
228
|
-
|
|
376
|
+
Cette gem est disponible en open source selon les termes de la [licence MIT](https://opensource.org/licenses/MIT).
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module DsfrAccessibleSkipLinks
|
|
4
|
+
class Configuration
|
|
5
|
+
attr_accessor :whitelisted_routes, :disable_validation
|
|
6
|
+
|
|
7
|
+
def initialize
|
|
8
|
+
@whitelisted_routes = []
|
|
9
|
+
@disable_validation = false
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
class << self
|
|
14
|
+
def configuration
|
|
15
|
+
@configuration ||= Configuration.new
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def configure
|
|
19
|
+
yield(configuration)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def reset_configuration!
|
|
23
|
+
@configuration = Configuration.new
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -14,8 +14,17 @@ module DsfrAccessibleSkipLinks
|
|
|
14
14
|
end
|
|
15
15
|
end
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
# Ensure helpers are available automatically in controllers and views
|
|
18
|
+
initializer "dsfr_accessible_skip_links.helpers" do
|
|
19
|
+
ActiveSupport.on_load(:action_controller_base) do
|
|
20
|
+
include DsfrAccessibleSkipLinks::SkipLinks
|
|
21
|
+
|
|
22
|
+
helper DsfrAccessibleSkipLinks::SkipLinks if respond_to?(:helper)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
ActiveSupport.on_load(:action_view) do
|
|
26
|
+
include DsfrAccessibleSkipLinks::SkipLinks
|
|
27
|
+
end
|
|
19
28
|
end
|
|
20
29
|
end
|
|
21
30
|
end
|
|
@@ -41,9 +41,17 @@ module DsfrAccessibleSkipLinks
|
|
|
41
41
|
private
|
|
42
42
|
|
|
43
43
|
def validate_skip_links_in_test!
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
true
|
|
44
|
+
return true unless defined?(Rails) && Rails.env.test?
|
|
45
|
+
return true unless respond_to?(:controller)
|
|
46
|
+
return true if DsfrAccessibleSkipLinks.configuration.disable_validation
|
|
47
|
+
|
|
48
|
+
has_custom_skip_links = content_for?(:skip_links)
|
|
49
|
+
|
|
50
|
+
SkipLinksImplementedChecker.new(
|
|
51
|
+
controller_name: controller.controller_name,
|
|
52
|
+
action_name: controller.action_name,
|
|
53
|
+
has_skip_links: has_custom_skip_links
|
|
54
|
+
).perform!
|
|
47
55
|
end
|
|
48
56
|
end
|
|
49
57
|
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module DsfrAccessibleSkipLinks
|
|
4
|
+
class SkipLinksImplementedChecker
|
|
5
|
+
attr_reader :controller_name, :action_name, :has_skip_links
|
|
6
|
+
|
|
7
|
+
def initialize(controller_name:, action_name:, has_skip_links: false)
|
|
8
|
+
@controller_name = controller_name
|
|
9
|
+
@action_name = action_name
|
|
10
|
+
@has_skip_links = has_skip_links
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def perform!
|
|
14
|
+
return true if has_skip_links
|
|
15
|
+
return true if whitelisted?
|
|
16
|
+
|
|
17
|
+
current_route = "#{controller_name}##{action_name}"
|
|
18
|
+
raise SkipLinksNotDefinedError,
|
|
19
|
+
"No skip links defined for this page (#{current_route}). " \
|
|
20
|
+
"Use content_for(:skip_links) to define skip links or " \
|
|
21
|
+
"define them in a view-specific helper."
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
private
|
|
25
|
+
|
|
26
|
+
def whitelisted?
|
|
27
|
+
DsfrAccessibleSkipLinks.configuration.whitelisted_routes.include?("#{controller_name}##{action_name}")
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
class SkipLinksNotDefinedError < StandardError; end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require_relative "dsfr_accessible_skip_links/version"
|
|
4
|
+
require_relative "dsfr_accessible_skip_links/configuration"
|
|
4
5
|
require_relative "dsfr_accessible_skip_links/engine" if defined?(Rails)
|
|
5
6
|
require_relative "dsfr_accessible_skip_links/skip_links"
|
|
7
|
+
require_relative "dsfr_accessible_skip_links/skip_links_implemented_checker"
|
|
6
8
|
|
|
7
9
|
module DsfrAccessibleSkipLinks
|
|
8
10
|
class Error < StandardError; end
|
|
@@ -8,46 +8,81 @@ module DsfrAccessibleSkipLinks
|
|
|
8
8
|
source_root File.expand_path("templates", __dir__)
|
|
9
9
|
|
|
10
10
|
desc(
|
|
11
|
-
"Installs DsfrAccessibleSkipLinks by copying the skip links partial " \
|
|
12
|
-
"
|
|
11
|
+
"Installs DsfrAccessibleSkipLinks by copying the skip links partial. " \
|
|
12
|
+
"No manual controller configuration is needed; helpers are auto-included."
|
|
13
13
|
)
|
|
14
14
|
def copy_partial
|
|
15
|
-
|
|
15
|
+
copy_file "_skip_links.html.erb", "app/views/shared/_skip_links.html.erb"
|
|
16
16
|
end
|
|
17
17
|
|
|
18
|
-
#
|
|
18
|
+
# For backward compatibility, provide an optional injection step disabled by default.
|
|
19
|
+
class_option :inject_layout, type: :boolean, default: false,
|
|
20
|
+
desc: "Also inject <%= render 'shared/skip_links' %> into application layout"
|
|
21
|
+
|
|
19
22
|
def inject_into_layout
|
|
23
|
+
return unless options[:inject_layout]
|
|
24
|
+
|
|
20
25
|
layout_path = "app/views/layouts/application.html.erb"
|
|
21
26
|
return unless File.exist?(layout_path)
|
|
27
|
+
return if layout_contains_render?(layout_path)
|
|
22
28
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
content = File.read(layout_path)
|
|
26
|
-
if content.include?("render partial: 'shared/skip_links'") || content.include?("render 'shared/skip_links'")
|
|
27
|
-
return
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
if content =~ /<body[^>]*>/
|
|
31
|
-
insert_into_file layout_path, after: /<body[^>]*>\s*\n?/ do
|
|
32
|
-
render_snippet
|
|
33
|
-
end
|
|
29
|
+
if layout_has_body_tag?(layout_path)
|
|
30
|
+
insert_render_after_body(layout_path)
|
|
34
31
|
else
|
|
35
|
-
|
|
36
|
-
prepend_to_file layout_path, render_snippet
|
|
32
|
+
prepend_render_to_layout(layout_path)
|
|
37
33
|
end
|
|
38
34
|
end
|
|
39
|
-
# rubocop:enable Metrics/MethodLength
|
|
40
35
|
|
|
36
|
+
# rubocop:disable Metrics/MethodLength
|
|
41
37
|
def readme
|
|
42
38
|
say <<~MSG
|
|
43
|
-
DsfrAccessibleSkipLinks installed
|
|
39
|
+
DsfrAccessibleSkipLinks installed successfully!
|
|
40
|
+
|
|
41
|
+
📁 Files created:
|
|
42
|
+
• app/views/shared/_skip_links.html.erb (skip links partial)
|
|
43
|
+
|
|
44
|
+
🔧 Next steps:
|
|
45
|
+
1. Add <%= render 'shared/skip_links' %> to your layout file (typically app/views/layouts/application.html.erb)
|
|
46
|
+
Place it right after the <body> tag for best accessibility.
|
|
47
|
+
|
|
48
|
+
2. Ensure your layout has these elements with IDs:
|
|
49
|
+
• #header (main navigation)
|
|
50
|
+
• #content (main content area)#{' '}
|
|
51
|
+
• #footer (page footer)
|
|
44
52
|
|
|
45
|
-
|
|
46
|
-
|
|
53
|
+
💡 Quick setup option:
|
|
54
|
+
Run `bin/rails g dsfr_accessible_skip_links:install --inject-layout` to automatically
|
|
55
|
+
add the render call to your application layout.
|
|
47
56
|
|
|
48
|
-
|
|
57
|
+
ℹ️ Helpers are automatically available in all controllers and views.
|
|
49
58
|
MSG
|
|
50
59
|
end
|
|
60
|
+
# rubocop:enable Metrics/MethodLength
|
|
61
|
+
|
|
62
|
+
private
|
|
63
|
+
|
|
64
|
+
def layout_contains_render?(layout_path)
|
|
65
|
+
content = File.read(layout_path)
|
|
66
|
+
content.include?("render partial: 'shared/skip_links'") ||
|
|
67
|
+
content.include?("render 'shared/skip_links'")
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def layout_has_body_tag?(layout_path)
|
|
71
|
+
File.read(layout_path) =~ /<body[^>]*>/
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def insert_render_after_body(layout_path)
|
|
75
|
+
render_snippet = " <%= render 'shared/skip_links' %>\n"
|
|
76
|
+
insert_into_file layout_path, after: /<body[^>]*>\s*\n?/ do
|
|
77
|
+
render_snippet
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# If <body> tag is not found, append at the beginning of the file as a fallback
|
|
82
|
+
def prepend_render_to_layout(layout_path)
|
|
83
|
+
render_snippet = " <%= render 'shared/skip_links' %>\n"
|
|
84
|
+
prepend_to_file layout_path, render_snippet
|
|
85
|
+
end
|
|
51
86
|
end
|
|
52
87
|
end
|
|
53
88
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: dsfr_accessible_skip_links
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Isabelle Lafont
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2025-08-
|
|
11
|
+
date: 2025-08-28 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|
|
@@ -112,8 +112,10 @@ files:
|
|
|
112
112
|
- Rakefile
|
|
113
113
|
- app/views/shared/_skip_links.html.erb
|
|
114
114
|
- lib/dsfr_accessible_skip_links.rb
|
|
115
|
+
- lib/dsfr_accessible_skip_links/configuration.rb
|
|
115
116
|
- lib/dsfr_accessible_skip_links/engine.rb
|
|
116
117
|
- lib/dsfr_accessible_skip_links/skip_links.rb
|
|
118
|
+
- lib/dsfr_accessible_skip_links/skip_links_implemented_checker.rb
|
|
117
119
|
- lib/dsfr_accessible_skip_links/version.rb
|
|
118
120
|
- lib/generators/dsfr_accessible_skip_links/install_generator.rb
|
|
119
121
|
- lib/generators/dsfr_accessible_skip_links/templates/_skip_links.html.erb
|
|
@@ -127,7 +129,7 @@ metadata:
|
|
|
127
129
|
changelog_uri: https://github.com/Isalafont/dsfr_accessible_skip_links/blob/main/CHANGELOG.md
|
|
128
130
|
rubygems_mfa_required: 'true'
|
|
129
131
|
post_install_message: |
|
|
130
|
-
Thank you for installing dsfr_accessible_skip_links (v0.
|
|
132
|
+
Thank you for installing dsfr_accessible_skip_links (v0.2.0)!
|
|
131
133
|
|
|
132
134
|
To complete setup in your Rails app, run:
|
|
133
135
|
bin/rails g dsfr_accessible_skip_links:install
|