@gouvfr/dsfr-roller 1.0.26 → 1.0.27

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.
Files changed (51) hide show
  1. package/package.json +2 -2
  2. package/src/component/components/button.js +3 -1
  3. package/src/component/components/edit.js +20 -0
  4. package/src/component/components/header.js +2 -2
  5. package/src/component/components/sidemenu.js +60 -3
  6. package/src/component/components/skiplink.js +1 -1
  7. package/src/component/ejs/edit/edit.ejs +32 -0
  8. package/src/component/ejs/version/version.ejs +2 -4
  9. package/src/core/format-link.js +6 -0
  10. package/src/node/directive/components/accordion/accordions-group-container-directive.js +1 -0
  11. package/src/node/directive/components/button/button-leaf-directive.js +1 -1
  12. package/src/node/directive/components/card/card-container-directive.js +3 -0
  13. package/src/node/directive/components/table/table-container-directive.js +1 -1
  14. package/src/node/directive/core/grid-container-directive.js +1 -0
  15. package/src/node/directive/doc/guidance/guideline-container-directive.js +1 -1
  16. package/src/node/directive/doc/page-item-card-container-directive.js +1 -1
  17. package/src/node/directive/doc/storybook-leaf-directive.js +1 -1
  18. package/src/node/directive/doc/tab-navigation-container-directive.js +25 -30
  19. package/src/node/directive/doc/video-leaf-directive.js +0 -2
  20. package/src/node/directive/home/hp-analytics-container-directive.js +3 -2
  21. package/src/node/directive/home/hp-community-container-directive.js +7 -2
  22. package/src/node/directive/home/hp-community-tile-container-directive.js +2 -1
  23. package/src/node/directive/home/hp-discover-tile-container-directive.js +4 -1
  24. package/src/node/directive/home/hp-hero-container-directive.js +4 -4
  25. package/src/node/directive/home/hp-showcase-card-container-directive.js +1 -1
  26. package/src/node/directive/home/hp-showcase-container-directive.js +1 -1
  27. package/src/node/directive/home/hp-slice-video-container-directive.js +11 -3
  28. package/src/node/generic/blockquote-node.js +1 -0
  29. package/src/node/generic/code-node.js +1 -1
  30. package/src/page/body/custom-header.js +8 -2
  31. package/src/page/body/toc.js +1 -1
  32. package/src/script/home/inject-svg.js +1 -2
  33. package/src/script/main/cmp/tarteaucitron/services.js +1 -1
  34. package/src/script/main/cmp/tarteaucitron/tarteaucitron.js +7 -7
  35. package/src/script/main/elements/pagination/pagination-list.js +89 -113
  36. package/src/script/main/elements/search-bar/index.js +15 -5
  37. package/src/script/main/elements/search-bar/results/results-button.js +1 -1
  38. package/src/script/main/elements/search-bar/results/results-dropdown.js +1 -0
  39. package/src/script/main/elements/storybook.js +1 -4
  40. package/src/script/search/elements/search-page.js +1 -0
  41. package/src/style/home/_community.scss +22 -19
  42. package/src/style/home/_showcase.scss +3 -0
  43. package/src/style/main/components/_dsfr-doc-code-snippet.scss +3 -2
  44. package/src/style/main/components/_dsfr-doc-edit.scss +34 -0
  45. package/src/style/main/components/_dsfr-doc-tab-navigation.scss +3 -3
  46. package/src/style/main/components/_dsfr-doc-version.scss +4 -3
  47. package/src/style/main/components/_index.scss +1 -0
  48. package/src/style/main/utility/_global.scss +64 -0
  49. package/src/style/main/utility/_index.scss +1 -0
  50. package/src/template/templates/editorial-template.js +8 -2
  51. package/src/template/templates/search-template.js +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gouvfr/dsfr-roller",
3
- "version": "1.0.26",
3
+ "version": "1.0.27",
4
4
  "description": "Le module `dsfr-roller` permet de publier le site de documentation du Système de Design de l’État - DSFR",
5
5
  "keywords": [
6
6
  "Système de Design de l'État",
@@ -56,7 +56,7 @@
56
56
  ],
57
57
  "main": "./index.js",
58
58
  "dependencies": {
59
- "@gouvfr/dsfr-forge": "=1.0.26",
59
+ "@gouvfr/dsfr-forge": "=1.0.27",
60
60
  "@gouvfr/dsfr-publisher": "npm:@gouvfr/dsfr@1.13.1",
61
61
  "deepmerge": "^4.3.1",
62
62
  "ejs": "^3.1.10",
@@ -14,6 +14,8 @@ class Button extends Component {
14
14
  const index = [, , 'secondary', 'tertiary', 'tertiary-no-outline'].indexOf(this.data.kind);
15
15
  const url = this.data.url ?? this.data.href;
16
16
  const blank = Boolean(this.data.blank) || /^(http|www)/.test(url);
17
+ const classes = ['fr-mb-6v'];
18
+ classes.push(...(this.data.classes || []));
17
19
  return {
18
20
  markup: url ? 'a' : this.data.markup,
19
21
  kind: index > -1 ? index : parseInt(this.data.kind),
@@ -26,7 +28,7 @@ class Button extends Component {
26
28
  blank,
27
29
  self: !blank || Boolean(this.data.self),
28
30
  disabled: this.data.disabled,
29
- classes: this.data.classes,
31
+ classes: classes,
30
32
  attributes: this.data.attributes,
31
33
  icon: this.data.icon,
32
34
  iconPlace: this.data['icon-place'],
@@ -0,0 +1,20 @@
1
+ import { Component } from '../component.js';
2
+ import { EJS_PKG } from '../ejs-pkg.js';
3
+ class Edit extends Component {
4
+ constructor (data) {
5
+ super(data, 'edit', EJS_PKG.ROLLER);
6
+ }
7
+ get ejsPath () {
8
+ return 'src/component/ejs/edit/edit.ejs';
9
+ }
10
+
11
+ async format () {
12
+ return {
13
+ title: this.data.title,
14
+ description: this.data.description,
15
+ link: { label: this.data.link, href: this.data.editUrl, blank: true, attributes: {title: `${this.data.link} - ${this.data.blankLabel}`} },
16
+ };
17
+ }
18
+ }
19
+
20
+ export { Edit };
@@ -21,8 +21,8 @@ class Header extends Component {
21
21
  id: 'search',
22
22
  modalId: 'search-modal',
23
23
  btnId: 'search-modal-button',
24
- input: { placeholder: this.data.search.label, label: this.data.search.label },
25
- button: { id: 'search-button', label: this.data.search.label, title: this.data.search.title ?? this.data.search.label, markup: 'a', href: this.data.search.url, attributes: { 'data-href': this.data.search.url } }
24
+ input: { id: 'search-input', placeholder: this.data.search.title, label: this.data.search.title },
25
+ button: { id: 'search-button', label: this.data.search.title, title: this.data.search.title, markup: 'button', attributes: { 'data-href': this.data.search.url } }
26
26
  };
27
27
 
28
28
  return {
@@ -1,9 +1,28 @@
1
1
  import { Component } from '../component.js';
2
2
  import { formatLink } from '../../core/format-link.js';
3
+ import { log } from '@gouvfr/dsfr-forge';
4
+
5
+ const Badges = {
6
+ BETA: {
7
+ id: 'beta',
8
+ type: 'info',
9
+ icon: false,
10
+ size: 'sm',
11
+ },
12
+ NEW: {
13
+ id: 'new',
14
+ type: 'new',
15
+ icon: true,
16
+ size: 'sm',
17
+ }
18
+ }
19
+
20
+ const BadgesMap = new Map(Object.values(Badges).map(badge => [badge.id, badge]));
3
21
 
4
22
  class Sidemenu extends Component {
5
- constructor (data) {
23
+ constructor (data, badgeLabels) {
6
24
  super(data, 'sidemenu');
25
+ this.badgeLabels = badgeLabels;
7
26
  }
8
27
  get ejsPath () {
9
28
  return 'src/dsfr/component/sidemenu/template/ejs/sidemenu.ejs';
@@ -13,8 +32,9 @@ class Sidemenu extends Component {
13
32
  return {
14
33
  id: 'sidemenu',
15
34
  collapseId: this.uniqueId(),
35
+ buttonLabel: this.data.buttonLabel,
16
36
  titleId: this.uniqueId(),
17
- title: this.data.title,
37
+ title: this.data.text,
18
38
  items: this.data?.items?.map(item => this._formatItem(item)).filter(item => item)
19
39
  };
20
40
  }
@@ -30,13 +50,50 @@ class Sidemenu extends Component {
30
50
  }
31
51
 
32
52
  _formatLink (link) {
53
+ const badge = link.badge ? this._formatBadge(link.badge) : '';
54
+ const label = link.badge ? link.text + badge : link.text;
33
55
  return {
34
56
  ...formatLink(link),
35
57
  active: link.isCurrent,
36
- type: 'link'
58
+ type: 'link',
59
+ label: label,
37
60
  };
38
61
  }
39
62
 
63
+ _formatBadge (ids) {
64
+ if (typeof ids === 'string') ids = ids.split(',');
65
+ if (!Array.isArray(ids)) {
66
+ log.error(`Badge must be a string or an array of strings, received: ${typeof ids}`);
67
+ return '';
68
+ }
69
+ return ids.map(id => {
70
+ const badgeData = BadgesMap.get(id);
71
+ if (!badgeData) {
72
+ log.error(`Unknown badge type: ${id}`);
73
+ return '';
74
+ }
75
+ const classes = ['fr-badge'];
76
+ if (badgeData.size) {
77
+ classes.push(`fr-badge--${badgeData.size}`);
78
+ }
79
+ if (badgeData.type) {
80
+ classes.push(`fr-badge--${badgeData.type}`);
81
+ }
82
+ switch (true) {
83
+ case badgeData.icon === true:
84
+ break;
85
+ case badgeData.icon === false:
86
+ classes.push(`fr-badge--no-icon`);
87
+ break;
88
+ case typeof badgeData.icon === 'string':
89
+ classes.push(`fr-icon-${badgeData.icon}`);
90
+ break;
91
+ }
92
+ const badgeLabel = this.badgeLabels[id];
93
+ return `&nbsp;<span class="${classes.join(' ')}">${badgeLabel}</span>`;
94
+ }).join('');
95
+ }
96
+
40
97
  _formatMenu (menu) {
41
98
  return {
42
99
  id: menu.id,
@@ -18,7 +18,7 @@ class Skiplink extends Component {
18
18
  id: 'skiplink-content',
19
19
  },
20
20
  label: this.data.resource.skiplink.content,
21
- href: '#content',
21
+ href: this.data.path === '' ? '#content' : '#breadcrumb',
22
22
  },
23
23
  {
24
24
  attributes: {
@@ -0,0 +1,32 @@
1
+ <%#
2
+ # paramètres du bloc d'édition
3
+
4
+ * edit (object, optional) : Paramètres du bloc édit
5
+ ** edit.title (string) : titre du bloc
6
+ ** edit.description (string) : description du bloc
7
+ ** edit.icon (string, optional) : icône du bloc (par défaut : 'edit-fill')
8
+ ** edit.link (object) : lien vers la page d'édition
9
+ *** edit.link.label (string) : libellé du lien
10
+ *** edit.link.url (string) : url du lien
11
+ *** edit.link.blank (boolean, optional) : ouvre le lien dans un nouvel onglet
12
+ %>
13
+ <%
14
+ const edit = locals.edit || {};
15
+ const icon = edit.icon || 'edit-fill';
16
+ const classes = edit.classes || [];
17
+ classes.push(`fr-link`);
18
+ %>
19
+
20
+ <% eval(include(`${dsfrPkg}src/dsfr/core/index.ejs`)); %>
21
+
22
+ <div class="dsfr-doc-edit <%= prefix %>-background-alt--blue-france <%= prefix %>-icon-<%= icon %>">
23
+ <p class="dsfr-doc-edit__title fr-h5">
24
+ <%= edit.title %>
25
+ </p>
26
+ <p class="dsfr-doc-edit__description">
27
+ <%= edit.description %>
28
+ </p>
29
+ <p class="dsfr-doc-edit__link">
30
+ <%- include(`${dsfrPkg}src/dsfr/core/template/ejs/action/action.ejs`, { action: {...edit.link, markup: 'a', classes: classes} }); %>
31
+ </p>
32
+ </div>
@@ -19,7 +19,7 @@ const collapseId = version.collapseId || uniqueId('version');
19
19
 
20
20
  <% eval(include(`${dsfrPkg}src/dsfr/core/index.ejs`)); %>
21
21
 
22
- <nav role="navigation" class="dsfr-doc-version <%= prefix %>-nav" <%- includeAttrs(attributes) %>>
22
+ <div class="dsfr-doc-version <%= prefix %>-nav" <%- includeAttrs(attributes) %>>
23
23
  <div class="<%= prefix %>-nav__item">
24
24
  <%
25
25
  const versionBtn = version.button || {};
@@ -34,14 +34,12 @@ const collapseId = version.collapseId || uniqueId('version');
34
34
  versionBtn.id = 'header__tools--version';
35
35
  versionBtn.classes = versionBtn.classes !== undefined ? versionBtn.classes.concat(minBtnClasses) : minBtnClasses;
36
36
  versionBtn.attributes = versionBtn.attributes !== undefined ? {...minBtnAttrs, ...versionBtn.attributes} : minBtnAttrs;
37
-
38
37
  %>
39
38
 
40
39
  <%- include(`${dsfrPkg}src/dsfr/component/button/template/ejs/button`, { button:versionBtn }); %>
41
40
 
42
41
  <div class="<%= prefix %>-collapse dsfr-doc-version__menu <%= prefix %>-menu" id="<%= version.collapseId %>">
43
-
44
42
  <%- include('versions.ejs', {versions: version.versions}) %>
45
43
  </div>
46
44
  </div>
47
- </nav>
45
+ </div>
@@ -6,5 +6,11 @@ export const formatLink = (link) => {
6
6
  if (/^(https:|http:|www\.)\S*$/.test(url)) link.blank = true;
7
7
  link.href = url;
8
8
  link.label = link.label ?? link.text;
9
+ link.attributes = link.attributes || {};
10
+ if (link.blank) {
11
+ const title = `${link.label} - ${link.blankTitle}`
12
+ link.attributes.title = title;
13
+ link.title = title;
14
+ }
9
15
  return link;
10
16
  };
@@ -4,6 +4,7 @@ class AccordionsGroupContainerDirective extends Node {
4
4
  constructor (data) {
5
5
  super(data, 'div');
6
6
  this.attributes.addClass('fr-accordions-group');
7
+ this.attributes.addClass('fr-mb-6v');
7
8
  }
8
9
  }
9
10
 
@@ -4,7 +4,7 @@ import { Button } from '../../../../component/components/button.js';
4
4
  class ButtonLeafDirective extends Node {
5
5
  constructor (data) {
6
6
  super(data);
7
- this.button = new Button(this.data.properties);
7
+ this.button = new Button({...this.data.properties, ...this.data.attributes});
8
8
  }
9
9
 
10
10
  structure (data) {
@@ -81,6 +81,9 @@ class CardContainerDirective extends Node {
81
81
  children: [
82
82
  {
83
83
  classes: ['fr-responsive-img'],
84
+ attributes: {
85
+ alt: ' ',
86
+ },
84
87
  ...image
85
88
  }
86
89
  ]
@@ -51,6 +51,6 @@ class TableContainerDirective extends Node {
51
51
  }
52
52
  }
53
53
 
54
- TableContainerDirective.NAME = 'dsfr-doc-table'; //TODO: fr-table ?
54
+ TableContainerDirective.NAME = 'fr-table';
55
55
 
56
56
  export { TableContainerDirective };
@@ -4,6 +4,7 @@ class GridContainerDirective extends Node {
4
4
  constructor (data) {
5
5
  super(data, 'div');
6
6
  this.attributes.addClass('fr-grid-row');
7
+ this.attributes.addClass('fr-mb-3v');
7
8
  if (data.properties.gutters !== false) this.attributes.addClass('fr-grid-row--gutters');
8
9
  if (data.properties.alignV) this.attributes.addClass(`fr-grid-row--${data.properties.alignV}`);
9
10
  if (data.properties.alignH) this.attributes.addClass(`fr-grid-row--${data.properties.alignH}`);
@@ -32,7 +32,7 @@ class GuidelineContainerDirective extends Node {
32
32
  {
33
33
  type: 'htmlContainer',
34
34
  tagName: 'div',
35
- classes: ['dsfr-doc-guideline', `dsfr-doc-guideline--${valid ? 'do' : 'dont'}`],
35
+ classes: ['dsfr-doc-guideline', 'fr-mb-6v', `dsfr-doc-guideline--${valid ? 'do' : 'dont'}`],
36
36
  children: [
37
37
  {
38
38
  type: 'image',
@@ -30,7 +30,7 @@ class PageItemCardContainerDirective extends CardContainerDirective {
30
30
 
31
31
  data.children.push({
32
32
  type: 'heading',
33
- depth: 2,
33
+ depth: 3,
34
34
  children: [
35
35
  {
36
36
  type: 'link',
@@ -7,7 +7,7 @@ class StorybookLeafDirective extends Node {
7
7
 
8
8
  async render() {
9
9
  return `
10
- <div class="dsfr-doc-storybook-leaf">
10
+ <div class="dsfr-doc-storybook-leaf fr-mb-6v">
11
11
  ${await super.render()}
12
12
  </div>
13
13
  `;
@@ -2,36 +2,31 @@ import { Node } from '../../node.js';
2
2
  import { HtmlNode } from '../../generic/html-node.js';
3
3
 
4
4
  class TabNavigationContainerDirective extends Node {
5
- constructor(data) {
6
- super(data);
7
- this._id = data.properties.id || 'dsfr-doc-tab-navigation--collapse';
8
- const list = this.findDescendantsByType('list')[0];
9
- list.attributes.setAttribute('role', 'tablist');
10
- const items = list.findDescendantsByType('listItem');
11
- for (const item of items) {
12
- item.attributes.setAttribute('role', 'presentation');
13
- let node;
14
- let isSelected = false;
15
- const link = item.findDescendantsByType('link')[0];
16
- if (link) {
17
- node = link;
18
- } else {
19
- this._currentNode = item._children[0];
5
+ constructor (data) {
6
+ super(data);
7
+ this._id = data.properties.id || 'dsfr-doc-tab-navigation--collapse';
8
+ const list = this.findDescendantsByType('list')[0];
9
+ const items = list.findDescendantsByType('listItem');
10
+ for (const item of items) {
11
+ let node;
12
+ const link = item.findDescendantsByType('link')[0];
13
+ if (link) {
14
+ node = link;
15
+ } else {
16
+ this._currentNode = item._children[0];
20
17
 
21
- node = new HtmlNode({ type: 'html', value: '<div>' });
22
- const close = new HtmlNode({ type: 'html', value: '</div>' });
23
- item._children = [node, ...item._children, close];
24
- isSelected = true;
25
- }
26
- node.attributes.setAttribute('role', 'tab');
27
- node.attributes.setAttribute('aria-selected', isSelected);
28
- node.attributes.addClass('dsfr-doc-tab-navigation__tab');
29
- }
18
+ node = new HtmlNode({ type: 'html', value: '<div>' });
19
+ const close = new HtmlNode({ type: 'html', value: '</div>' });
20
+ item._children = [node, ...item._children, close];
21
+ node.attributes.setAttribute('aria-current', 'page');
22
+ }
23
+ node.attributes.addClass('dsfr-doc-tab-navigation__tab');
30
24
  }
31
- async render() {
32
- this.attributes.setAttribute('role', 'navigation');
33
- this.attributes.addClass('dsfr-doc-tab-navigation');
34
- return `<nav ${this.renderAttributes()}>
25
+ }
26
+
27
+ async render () {
28
+ this.attributes.addClass('dsfr-doc-tab-navigation');
29
+ return `<div ${this.renderAttributes()}>
35
30
  <div class="fr-sidemenu">
36
31
  <div class="fr-sidemenu__inner">
37
32
  <button aria-expanded="false" aria-controls="${this._id}" type="button" class="fr-sidemenu__btn">${await this._currentNode.render()}</button>
@@ -40,8 +35,8 @@ class TabNavigationContainerDirective extends Node {
40
35
  </div>
41
36
  </div>
42
37
  </div>
43
- </nav>`;
44
- }
38
+ </div>`;
39
+ }
45
40
  }
46
41
 
47
42
  TabNavigationContainerDirective.NAME = 'dsfr-doc-tab-navigation';
@@ -23,8 +23,6 @@ class VideoLeafDirective extends Node {
23
23
  ...(data.attributes || {}),
24
24
  ...videoAttributes,
25
25
  'data-videoid': data.properties.videoId,
26
- width: data.properties.width || '100%',
27
- height: data.properties.height || '100%',
28
26
  };
29
27
 
30
28
  return super.structure(data);
@@ -13,7 +13,7 @@ class HpAnalyticsContainerDirective extends Node {
13
13
  return super.structure({
14
14
  type: 'htmlContainer',
15
15
  tagName: 'div',
16
- classes: ['dsfr-doc-hp-analytics', 'fr-background-alt--blue-france'],
16
+ classes: ['dsfr-doc-hp-analytics', 'fr-background-alt--blue-france', 'fr-mb-n6v'],
17
17
  children: [
18
18
  {
19
19
  type: 'htmlContainer',
@@ -31,7 +31,8 @@ class HpAnalyticsContainerDirective extends Node {
31
31
  tagName: 'img',
32
32
  attributes: {
33
33
  src: data.imgUrl,
34
- alt: ''
34
+ alt: '',
35
+ 'aria-hidden': 'true'
35
36
  }
36
37
  }
37
38
  ]
@@ -13,6 +13,9 @@ class HpCommunityContainerDirective extends Node {
13
13
  type: 'htmlContainer',
14
14
  tagName: 'div',
15
15
  classes: ['dsfr-doc-hp-community'],
16
+ attributes: {
17
+ 'dsfr-doc-show-on-scroll': ''
18
+ },
16
19
  children: [
17
20
  {
18
21
  type: 'htmlContainer',
@@ -38,7 +41,8 @@ class HpCommunityContainerDirective extends Node {
38
41
  classes: ['fr-responsive-img'],
39
42
  attributes: {
40
43
  src: data.imgUrl,
41
- alt: ''
44
+ alt: '',
45
+ 'aria-hidden': 'true'
42
46
  }
43
47
  }
44
48
  ]
@@ -53,7 +57,8 @@ class HpCommunityContainerDirective extends Node {
53
57
  classes: ['fr-responsive-img'],
54
58
  attributes: {
55
59
  src: data.imgDarkUrl,
56
- alt: ''
60
+ alt: '',
61
+ 'aria-hidden': 'true'
57
62
  }
58
63
  }
59
64
  ]
@@ -21,7 +21,8 @@ class HpCommunityTileContainerDirective extends Node {
21
21
  type: 'image',
22
22
  attributes: {
23
23
  src: data.imgUrl,
24
- alt: ''
24
+ alt: '',
25
+ 'aria-hidden': 'true'
25
26
  }
26
27
  } : {}
27
28
  ]
@@ -30,6 +30,9 @@ class HpDiscoverTileContainerDirective extends Node {
30
30
  children: [
31
31
  {
32
32
  classes: ['dsfr-doc-discover-tile__img--light'],
33
+ attributes: {
34
+ 'aria-hidden': 'true',
35
+ },
33
36
  ...image,
34
37
  },
35
38
  data.imgDarkUrl ? {
@@ -37,7 +40,7 @@ class HpDiscoverTileContainerDirective extends Node {
37
40
  type: 'image',
38
41
  attributes: {
39
42
  src: data.imgDarkUrl,
40
- alt: image.alt
43
+ 'aria-hidden': 'true'
41
44
  }
42
45
  } : {}
43
46
  ]
@@ -34,12 +34,12 @@ class HpHeroContainerDirective extends Node {
34
34
  <div class="dsfr-doc-hp-hero">
35
35
  <div class="fr-container">
36
36
  <div class="dsfr-doc-hp-hero__img">
37
- <img class="fr-hidden-md" src="${this.imgFirstUrl}" alt="">
38
- <img class="fr-hidden fr-unhidden-md" src="${this.imgMdUrl}" alt="">
37
+ <img class="fr-hidden-md" src="${this.imgFirstUrl}" alt="" aria-hidden="true">
38
+ <img class="fr-hidden fr-unhidden-md" src="${this.imgMdUrl}" alt="" aria-hidden="true">
39
39
  </div>
40
40
  <div class="dsfr-doc-hp-hero__img dsfr-doc-hp-hero__img--dark">
41
- <img class="fr-hidden-md" src="${this.imgDarkFirstUrl}" alt="">
42
- <img class="fr-hidden fr-unhidden-md" src="${this.imgDarkMdUrl}" alt="">
41
+ <img class="fr-hidden-md" src="${this.imgDarkFirstUrl}" alt="" aria-hidden="true">
42
+ <img class="fr-hidden fr-unhidden-md" src="${this.imgDarkMdUrl}" alt="" aria-hidden="true">
43
43
  </div>
44
44
 
45
45
  ${await super.render()}
@@ -14,7 +14,7 @@ class HpShowcaseCardContainerDirective extends Node {
14
14
 
15
15
  return super.structure({
16
16
  type: 'htmlContainer',
17
- tagName: 'div',
17
+ tagName: 'li',
18
18
  classes: ['dsfr-doc-hp-showcase-card'],
19
19
  children: [
20
20
  {
@@ -28,7 +28,7 @@ class HpShowcaseContainerDirective extends Node {
28
28
  },
29
29
  {
30
30
  type: 'htmlContainer',
31
- tagName: 'div',
31
+ tagName: 'ul',
32
32
  classes: ['dsfr-doc-hp-showcase__container'],
33
33
  children: showcaseCards
34
34
  },
@@ -5,7 +5,9 @@ class HpSliceVideoContainerDirective extends Node {
5
5
  }
6
6
 
7
7
  structure (data) {
8
- const title = data.children[0];
8
+ const title = data.children.find(child => child.type === 'heading');
9
+ const transcription = data.children.find(child => child.name === 'fr-accordion');
10
+
9
11
  const categoryLabel = data.properties.category;
10
12
  const imgUrl = data.imgUrl;
11
13
  const imgDarkUrl = data.imgDarkUrl;
@@ -113,7 +115,8 @@ class HpSliceVideoContainerDirective extends Node {
113
115
  classes: ['dsfr-doc-hp-slice-video__img--light'],
114
116
  attributes: {
115
117
  src: imgUrl,
116
- alt: ''
118
+ alt: '',
119
+ 'aria-hidden': 'true'
117
120
  }
118
121
  },
119
122
  {
@@ -121,7 +124,8 @@ class HpSliceVideoContainerDirective extends Node {
121
124
  classes: ['dsfr-doc-hp-slice-video__img--dark'],
122
125
  attributes: {
123
126
  src: imgDarkUrl,
124
- alt: ''
127
+ alt: '',
128
+ 'aria-hidden': 'true'
125
129
  }
126
130
  }
127
131
  ]
@@ -205,9 +209,13 @@ class HpSliceVideoContainerDirective extends Node {
205
209
  {
206
210
  type: 'leafDirective',
207
211
  name: 'dsfr-doc-video',
212
+ classes: ['fr-mb-6v'],
208
213
  properties: {
209
214
  ...videoProperties,
210
215
  }
216
+ },
217
+ {
218
+ ...transcription
211
219
  }
212
220
  ]
213
221
  }
@@ -15,6 +15,7 @@ class BlockquoteNode extends Node {
15
15
  this.attributes.addClass('fr-callout fr-mb-6v');
16
16
 
17
17
  if (data?.level && LEVELS.has(data.level)) {
18
+ this.children[0].attributes.addClass('fr-callout__title');
18
19
  const level = LEVELS.get(data.level);
19
20
  this.attributes.addClasses(`fr-icon-${level.icon}`, `fr-callout--${level.color}`);
20
21
  }
@@ -24,7 +24,7 @@ class CodeNode extends Node {
24
24
  async render () {
25
25
  if (this.lang) this.attributes.addClass(`language-${this.lang}`);
26
26
  return `
27
- <div class="code-snippet">
27
+ <div class="code-snippet fr-mb-6v">
28
28
  <pre><code${this.renderAttributes()}>${convertHTMLEntities(this.value)}</code></pre>
29
29
  <button type="button" class="code-snippet--copy fr-btn fr-btn--sm fr-btn--tertiary" data-label-copied="${this.data?.fragments?.button?.copied}">${this.data?.fragments?.button?.copy}</button>
30
30
  </div>
@@ -14,10 +14,16 @@ class CustomHeader extends Renderable {
14
14
  }
15
15
  async render () {
16
16
  let toolsContent = await this._version.render({ id: 'version', collapseId: 'version-collapse' });
17
- if (this._translate) toolsContent += await this._translate.render({ id: 'translate', collapseId: 'translate-collapse' });
17
+ if (this._translate) {
18
+ const translate = await this._translate.render({ id: 'translate', collapseId: 'translate-collapse' });
19
+ toolsContent += translate.replace('<nav', '<div').replace('</nav>', '</div>').replace('role="navigation" ', '');
20
+ }
18
21
 
19
22
  let menuContent = await this._version.render({ id: 'version-menu', collapseId: 'version-collapse-menu' });
20
- if (this._translate) menuContent += await this._translate.render({ id: 'translate-menu', collapseId: 'translate-collapse-menu' });
23
+ if (this._translate) {
24
+ const translate = await this._translate.render({ id: 'translate-menu', collapseId: 'translate-collapse-menu' });
25
+ menuContent += translate.replace('<nav', '<div').replace('</nav>', '</div>').replace('role="navigation" ', '');
26
+ }
21
27
 
22
28
  const navigation = await this._navigation.format();
23
29
 
@@ -85,7 +85,7 @@ class TOC extends Renderable {
85
85
  break;
86
86
  }
87
87
 
88
- const summary = new Summary({ list: mainList });
88
+ const summary = new Summary({ title: this.data?.fragments?.summary?.title, list: mainList });
89
89
 
90
90
  return `<div class="fr-mb-6v" >
91
91
  ${await summary.render()}
@@ -18,11 +18,10 @@ class InjectSvg extends Element {
18
18
  const svgElement = svgDocument.querySelector('svg');
19
19
  if (this._class) svgElement.setAttribute('class', this._class);
20
20
  if (this._ariaHidden !== null) svgElement.setAttribute('aria-hidden', this._ariaHidden);
21
- if (this._alt) svgElement.setAttribute('aria-label', this._alt);
22
21
  this._element.parentNode.insertBefore(svgElement, this._element);
23
22
  this._element.remove();
24
23
  });
25
24
  }
26
25
  }
27
26
 
28
- export { InjectSvg };
27
+ export { InjectSvg };
@@ -6301,7 +6301,7 @@ export const vimeo = {
6301
6301
  'use strict';
6302
6302
  tarteaucitron.fallback(['vimeo_player'], function (x) {
6303
6303
  var frame_title =
6304
- tarteaucitron.getElemAttr(x, 'title') || 'Vimeo iframe',
6304
+ tarteaucitron.getElemAttr(x, 'title') || 'Vimeo',
6305
6305
  video_width = tarteaucitron.getElemAttr(x, 'width'),
6306
6306
  frame_width = 'width=',
6307
6307
  video_height = tarteaucitron.getElemAttr(x, 'height'),