dsfr_accessible_skip_links 0.1.3 → 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1c1aa834669fc2810bad9ffe69cad4af0d1640ea1b294d514c755b72e80cea81
4
- data.tar.gz: 57a4ffa98aa9217fd8937a137df89a810ddf04fbda942e5b1736baabbf5c3911
3
+ metadata.gz: cde36b7db7ed5759c035c760be7723d3c06e3912182688148c1adf62a59b827d
4
+ data.tar.gz: 1df51f6f597f5811c5b42cf66a9a1960cc7c307eb46140781f056581dc22edf2
5
5
  SHA512:
6
- metadata.gz: b2fa2f71d3ed56fe3dbbc9966e57ff9743a2bdc360a16fb17574396fcbb978d1659abfd5e865e5c2addb95a69dd350b9b39e9bc681a852598a2245b9a276ebd5
7
- data.tar.gz: d4ca7582ffe46826b82801d41f673b29cbae349e01be2d0c77f54450d09f1e0ad957440b74fc0f5128b64c2ecdf2549d550ddb1eb0e631474b944f4921dfaffb
6
+ metadata.gz: 35aa47a41dcee7700f425b87436042d71504532aace7a6316621a7da99e510ee090567d0ee3fae28a53414be0c24e1615e7b831c2ed744eb66dc208e9d0545a3
7
+ data.tar.gz: 9351451e96a6859ea8f35934e99222c4f90d3685f11eb684a031e8a7bfe18d69fd9172606d3d33cd80b0d3e9fb94b2736571bc92b25e80beb5fff9ad0c9940ed
data/CHANGELOG.md CHANGED
@@ -7,6 +7,18 @@ 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
+
10
22
  ## [0.1.3] - 2025-08-27
11
23
  ### Fixed
12
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`.
@@ -19,6 +31,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
19
31
  - Rails generator `dsfr_accessible_skip_links:install` to copy the skip links partial and inject the render call into the application layout.
20
32
  - README updated with installation instructions using the generator.
21
33
 
34
+ ## [0.1.1] - 2025-08-27
35
+ ### Fixed
36
+ - Minor bug fixes and improvements
37
+
22
38
  ## [0.1.0] - 2025-08-27
23
39
 
24
40
  ### Added
data/README.md CHANGED
@@ -1,70 +1,76 @@
1
1
  # DsfrAccessibleSkipLinks
2
2
 
3
- A Ruby gem that helps projects implement accessible skip links according to the French government design system (DSFR - Système de design de l'État français). This gem provides helpers and utilities for creating navigation skip links that improve web accessibility.
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
- Add this line to your application's Gemfile:
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
- Then install the gem:
13
+ Puis installez la gem :
14
14
 
15
15
  $ bundle install
16
16
 
17
- Run the installer to set up the skip links in your Rails app (copies the partial and injects the render in your layout):
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
- You can also install the gem itself directly as:
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
- $ gem install dsfr_accessible_skip_links
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
- ## Usage
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
- ### Rails Integration
42
+ ## Utilisation
28
43
 
29
- The gem automatically integrates with Rails through a Rails Engine. The `SkipLinks` module is automatically included in controllers and views (via Rails on_load hooks), so you can call the helpers directly from templates and controllers.
44
+ ### Éléments requis
30
45
 
31
- In your layout file (e.g., `app/views/layouts/application.html.erb`), add the skip links at the top:
46
+ Assurez‑vous que votre layout contient ces éléments avec les bons identifiants (ID) :
32
47
 
33
48
  ```erb
34
- <!DOCTYPE html>
35
- <html>
36
- <head>
37
- <!-- head content -->
38
- </head>
39
- <body>
40
- <%= render partial: 'shared/skip_links' %>
41
-
42
- <!-- rest of your layout -->
43
- <header id="header">
44
- <!-- your navigation -->
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
- ### Default Skip Links
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
- By default, the gem provides three skip links:
61
- - **"Aller au contenu"** → `#content`
62
- - **"Menu"** → `#header`
63
- - **"Pied de page"** → `#footer`
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
- ### Custom Skip Links
71
+ ### Liens d’évitement personnalisés
66
72
 
67
- You can customize skip links on a per-page basis using Rails' `content_for`:
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
- ### Custom Content Link Text
83
+ ### Texte du lien vers le contenu
78
84
 
79
- You can customize the main content link text:
85
+ Vous pouvez personnaliser le texte du lien vers le contenu principal :
80
86
 
81
87
  ```erb
82
- <% content_for :content_skip_link_text, 'Go to main content' %>
88
+ <% content_for :content_skip_link_text, 'Aller au contenu principal' %>
83
89
  ```
84
90
 
85
- ### Tab-Prefixed Links
91
+ ### Liens préfixés par « tab- »
86
92
 
87
- For links that need JavaScript interaction, use the `tab-` prefix:
93
+ Pour les liens nécessitant une interaction JavaScript, utilisez le préfixe `tab-` :
88
94
 
89
95
  ```erb
90
- <%= skip_link('Tab Navigation', 'tab-special-section') %>
96
+ <%= skip_link('Navigation par onglet', 'tab-special-section') %>
91
97
  ```
92
98
 
93
- This will add a `data-anchor` attribute for JavaScript handling.
99
+ Cela ajoutera un attribut `data-anchor` pour la gestion côté JavaScript.
94
100
 
95
- ### Helper Methods
101
+ ### Méthodes helper
96
102
 
97
- The gem provides these helper methods (automatically available in controllers and views):
103
+ La gem fournit ces méthodes helper (disponibles automatiquement dans les contrôleurs et vues) :
98
104
 
99
- - `skip_link(text, anchor)` - Creates a single skip link
100
- - `default_skip_links` - Returns the default set of skip links
101
- - `skip_links_content` - Returns either custom or default skip links
102
- - `content_skip_link_text` - Returns the content 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 Classes
110
+ ### Classes CSS
105
111
 
106
- The gem uses official DSFR CSS classes:
107
- - `.fr-skiplinks` - Main container
108
- - `.fr-container` - DSFR container wrapper
109
- - `.fr-skiplinks__list` - List container
110
- - `.fr-link` - Individual link styling
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 Structure
118
+ ### Structure HTML
113
119
 
114
- The generated HTML follows this structure:
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
- ## Accessibility Features
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
- This gem implements skip links following WCAG 2.2 guidelines and DSFR specifications:
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
- - Proper semantic HTML structure with `nav` element and `role="navigation"`
133
- - Descriptive `aria-label` for screen readers
134
- - Keyboard navigation support
135
- - Focus management
136
- - Compatible with DSFR CSS for visual styling
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
- ## How to test this gem
200
+ ### Intégration dans les tests Rails
139
201
 
140
- There are two main ways to test this gem:
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
- 1) Run the gem's test suite locally (fast, no Rails app needed)
143
- - Install dependencies:
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
- - Run RSpec:
270
+ - Lancer RSpec :
148
271
  ```bash
149
272
  bundle exec rake spec
150
273
  ```
151
- - Run RuboCop:
274
+ - Lancer RuboCop :
152
275
  ```bash
153
276
  bundle exec rake rubocop
154
277
  ```
155
- - Run both (default task):
278
+ - Lancer les deux (tâche par défaut) :
156
279
  ```bash
157
280
  bundle exec rake
158
281
  ```
159
282
 
160
- 2) Try it inside a real Rails app (to test the generator and integration)
161
- - Create a new Rails app (or use an existing one):
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
- - Point the app to your local copy of this gem. In demo_app/Gemfile add:
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
- Then run:
293
+ Puis exécutez :
171
294
  ```bash
172
295
  bundle install
173
296
  ```
174
- - Run the installer (copies the partial and injects a render line into your layout):
297
+ - Lancer l’installateur :
175
298
  ```bash
176
299
  bin/rails g dsfr_accessible_skip_links:install
177
300
  ```
178
- - Verify changes:
179
- - The partial should exist at: app/views/shared/_skip_links.html.erb
180
- - Your app layout (app/views/layouts/application.html.erb) should include:
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
- Visit http://localhost:3000 and look for the skip links markup
195
- ("Aller au contenu", "Menu", "Pied de page").
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
- Notes
198
- - The generator is idempotent: it wont insert the render line twice if it already exists.
199
- - You can customize the skip links in any view using `content_for :skip_links` as described below in Usage.
344
+ Cette configuration garantit que :
345
+ - Les routes listées ne déclencheront pas derreurs 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
- ## Development
349
+ ## Développement
202
350
 
203
- After checking out the repo, run `bundle install` to install dependencies.
351
+ Après avoir cloné le dépôt, exécutez `bundle install` pour installer les dépendances.
204
352
 
205
- Run the test suite:
353
+ Lancer la suite de tests :
206
354
  ```bash
207
355
  bundle exec rake spec
208
356
  ```
209
357
 
210
- Run RuboCop for code quality checks:
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
- Run both tests and RuboCop:
363
+ Lancer à la fois les tests et RuboCop :
216
364
  ```bash
217
365
  bundle exec rake
218
366
  ```
219
367
 
220
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
368
+ Pour installer cette gem sur votre machine locale, exécutez `bundle exec rake install`.
221
369
 
222
- ## Contributing
370
+ ## Contribuer
223
371
 
224
- Bug reports and pull requests are welcome on GitHub at https://github.com/Isalafont/dsfr_accessible_skip_links.
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
- ## License
374
+ ## Licence
227
375
 
228
- The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
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
@@ -18,6 +18,7 @@ module DsfrAccessibleSkipLinks
18
18
  initializer "dsfr_accessible_skip_links.helpers" do
19
19
  ActiveSupport.on_load(:action_controller_base) do
20
20
  include DsfrAccessibleSkipLinks::SkipLinks
21
+
21
22
  helper DsfrAccessibleSkipLinks::SkipLinks if respond_to?(:helper)
22
23
  end
23
24
 
@@ -41,9 +41,17 @@ module DsfrAccessibleSkipLinks
41
41
  private
42
42
 
43
43
  def validate_skip_links_in_test!
44
- # This would be implemented to validate skip links in test environment
45
- # For now, just a placeholder
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,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DsfrAccessibleSkipLinks
4
- VERSION = "0.1.3"
4
+ VERSION = "0.2.0"
5
5
  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,47 +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
- "and injecting the render call into the application layout."
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
- # Use copy_file instead of template to avoid evaluating ERB in the generator context
16
15
  copy_file "_skip_links.html.erb", "app/views/shared/_skip_links.html.erb"
17
16
  end
18
17
 
19
- # rubocop:disable Metrics/MethodLength
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
+
20
22
  def inject_into_layout
23
+ return unless options[:inject_layout]
24
+
21
25
  layout_path = "app/views/layouts/application.html.erb"
22
26
  return unless File.exist?(layout_path)
27
+ return if layout_contains_render?(layout_path)
23
28
 
24
- render_snippet = " <%= render partial: 'shared/skip_links' %>\n"
25
-
26
- content = File.read(layout_path)
27
- if content.include?("render partial: 'shared/skip_links'") || content.include?("render 'shared/skip_links'")
28
- return
29
- end
30
-
31
- if content =~ /<body[^>]*>/
32
- insert_into_file layout_path, after: /<body[^>]*>\s*\n?/ do
33
- render_snippet
34
- end
29
+ if layout_has_body_tag?(layout_path)
30
+ insert_render_after_body(layout_path)
35
31
  else
36
- # If <body> tag is not found, append at the beginning of the file as a fallback
37
- prepend_to_file layout_path, render_snippet
32
+ prepend_render_to_layout(layout_path)
38
33
  end
39
34
  end
40
- # rubocop:enable Metrics/MethodLength
41
35
 
36
+ # rubocop:disable Metrics/MethodLength
42
37
  def readme
43
38
  say <<~MSG
44
- 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)
45
52
 
46
- - A copy of the skip links partial has been placed at app/views/shared/_skip_links.html.erb
47
- - Your application layout has been updated to render the skip links.
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.
48
56
 
49
- Ensure your layout contains elements with ids: #header, #content, and #footer for the default links.
57
+ ℹ️ Helpers are automatically available in all controllers and views.
50
58
  MSG
51
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
52
86
  end
53
87
  end
54
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.1.3
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-27 00:00:00.000000000 Z
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.1.3)!
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