@gouvfr/dsfr-roller 1.0.17 → 1.0.18

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.
@@ -1 +1,4 @@
1
- {}
1
+ {
2
+ "env": "local",
3
+ "domain": "gva.et-gv.fr"
4
+ }
package/env/prod/env.json CHANGED
@@ -1 +1,4 @@
1
- {}
1
+ {
2
+ "env": "prod",
3
+ "domain": "zmmt.systeme-de-design.gouv.fr"
4
+ }
@@ -1 +1,4 @@
1
- {}
1
+ {
2
+ "env": "staging",
3
+ "domain": "gva.et-gv.fr"
4
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gouvfr/dsfr-roller",
3
- "version": "1.0.17",
3
+ "version": "1.0.18",
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.17",
59
+ "@gouvfr/dsfr-forge": "=1.0.18",
60
60
  "@gouvfr/dsfr-publisher": "npm:@gouvfr/dsfr@1.13.1",
61
61
  "deepmerge": "^4.3.1",
62
62
  "ejs": "^3.1.10",
@@ -24,6 +24,7 @@ class Breadcrumb extends Component {
24
24
  chunks.push(...missing);
25
25
 
26
26
  return {
27
+ id: `breadcrumb-${missing.join('-')}`,
27
28
  label: segment.label ?? segment.text,
28
29
  path: missing.join('/')
29
30
  };
@@ -20,6 +20,7 @@ class Header extends Component {
20
20
  const search = {
21
21
  id: 'search',
22
22
  modalId: 'search-modal',
23
+ btnId: 'search-modal-button',
23
24
  input: { placeholder: this.data.search.label, label: this.data.search.label },
24
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 } }
25
26
  };
@@ -11,7 +11,7 @@ class Translate extends Component {
11
11
  async format () {
12
12
  return {
13
13
  id: 'translate',
14
- button: { title: this.data.button, kind: 3 },
14
+ button: { title: this.data.button, kind: 3, id: 'header__tools--translate' },
15
15
  collapseId: 'translate-collapse',
16
16
  languages: this._formatLanguages(this.data.languages)
17
17
  };
@@ -31,6 +31,7 @@ const collapseId = version.collapseId || uniqueId('version');
31
31
  'aria-expanded': false,
32
32
  title: versionBtn.title
33
33
  };
34
+ versionBtn.id = 'header__tools--version';
34
35
  versionBtn.classes = versionBtn.classes !== undefined ? versionBtn.classes.concat(minBtnClasses) : minBtnClasses;
35
36
  versionBtn.attributes = versionBtn.attributes !== undefined ? {...minBtnAttrs, ...versionBtn.attributes} : minBtnAttrs;
36
37
 
@@ -1,6 +1,8 @@
1
1
  export const formatLink = (link) => {
2
2
  if (!link) return undefined;
3
3
  const url = link.url ?? link.href;
4
+ const segments = url && url.split('/');
5
+ if (segments) link.id = link.id ?? `link-${segments.join('-')}`;
4
6
  if (/^(https:|http:|www\.)\S*$/.test(url)) link.blank = true;
5
7
  link.href = url;
6
8
  link.label = link.label ?? link.text;
@@ -2,9 +2,20 @@ import { CardContainerDirective } from '../components/card/card-container-direct
2
2
 
3
3
  class PageItemCardContainerDirective extends CardContainerDirective {
4
4
  structure (data) {
5
+ const cols = {
6
+ col: data.properties?.col || 12,
7
+ colSm: data.properties?.colSm,
8
+ colMd: data.properties?.colMd,
9
+ colLg: data.properties?.colLg
10
+ }
11
+ if (!data.horizontal) {
12
+ cols.colSm = cols.colSm || 6;
13
+ cols.colLg = cols.colLg || 4;
14
+ }
5
15
  data.properties = {
6
- horizontal: false,
7
- download: false,
16
+ horizontal: data.horizontal || false,
17
+ download: data.download || false,
18
+ ...cols,
8
19
  ...data.properties,
9
20
  };
10
21
 
@@ -42,10 +53,8 @@ class PageItemCardContainerDirective extends CardContainerDirective {
42
53
  ],
43
54
  });
44
55
  }
45
-
46
56
  return super.structure(data);
47
57
  }
48
-
49
58
  }
50
59
 
51
60
  PageItemCardContainerDirective.NAME = 'dsfr-doc-page-item-card';
@@ -0,0 +1,47 @@
1
+ import { Node } from '../../node.js'
2
+
3
+ class PageItemHeadingContainerDirective extends Node {
4
+ structure (data) {
5
+ const children = [
6
+ {
7
+ type: 'heading',
8
+ depth: 3,
9
+ children: [
10
+ {
11
+ type: 'link',
12
+ url: data.url,
13
+ children: [
14
+ {
15
+ type: 'text',
16
+ value: data.text
17
+ },
18
+ ],
19
+ },
20
+ ],
21
+ }
22
+ ];
23
+
24
+ if (data.shortDescription || data.excerpt) {
25
+ children.push({
26
+ type: 'paragraph',
27
+ children: [
28
+ {
29
+ type: 'text',
30
+ value: data.shortDescription || data.excerpt,
31
+ },
32
+ ],
33
+ });
34
+ }
35
+
36
+ return super.structure({
37
+ type: 'htmlContainer',
38
+ tagName: 'div',
39
+ classes: ['fr-col-12'],
40
+ children: children,
41
+ });
42
+ }
43
+ }
44
+
45
+ PageItemHeadingContainerDirective.NAME = 'dsfr-doc-page-item-heading';
46
+
47
+ export { PageItemHeadingContainerDirective };
@@ -1,19 +1,29 @@
1
1
  import { Node } from '../../node.js';
2
2
 
3
+ const mapItem = (item) => {
4
+ const nodes = [
5
+ {
6
+ ...item,
7
+ type: 'containerDirective',
8
+ name: item.name ?? 'dsfr-doc-page-item-card',
9
+ }
10
+ ];
11
+
12
+ if (item.items) {
13
+ for (const childItem of item.items) {
14
+ nodes.push(...mapItem(childItem));
15
+ }
16
+ }
17
+
18
+ return nodes
19
+ };
20
+
3
21
  class PageItemListLeafDirective extends Node {
4
22
  structure (data) {
5
- const children = data.items.map((item) => ({
6
- type: 'htmlContainer',
7
- tagName: 'div',
8
- classes: ['fr-col-12', 'fr-col-sm-6', 'fr-col-lg-4'],
9
- children: [
10
- {
11
- ...item,
12
- type: 'containerDirective',
13
- name: data.itemDirectiveName ?? 'dsfr-doc-page-item-card'
14
- }
15
- ]
16
- }));
23
+ const children = [];
24
+ for (const item of data.items) {
25
+ children.push(...mapItem(item));
26
+ }
17
27
 
18
28
  return super.structure({
19
29
  type: 'htmlContainer',
@@ -54,6 +54,7 @@ import { TabNavigationContainerDirective } from './directive/doc/tab-navigation-
54
54
  import { StorybookLeafDirective } from './directive/doc/storybook-leaf-directive.js';
55
55
  import { FigmaLeafDirective } from './directive/doc/figma-leaf-directive.js';
56
56
  import { PageItemListLeafDirective } from './directive/doc/page-item-list-leaf-directive.js';
57
+ import { PageItemHeadingContainerDirective } from './directive/doc/page-item-heading-container-directive.js';
57
58
  import { PageItemCardContainerDirective } from './directive/doc/page-item-card-container-directive.js';
58
59
  import { VideoLeafDirective } from './directive/doc/video-leaf-directive.js';
59
60
  import { ImageTextDirective } from './directive/doc/image-text-directive.js'
@@ -107,6 +108,7 @@ const DIRECTIVE_CONTAINERS = [
107
108
  AccordionsGroupContainerDirective,
108
109
  CardContainerDirective,
109
110
  PageItemCardContainerDirective,
111
+ PageItemHeadingContainerDirective,
110
112
  TileContainerDirective,
111
113
  GuidelineContainerDirective,
112
114
  GuidelinesContainerDirective,
package/src/node/node.js CHANGED
@@ -11,7 +11,19 @@ class Node extends Renderable {
11
11
  this._children = Array.isArray(this.data.children) ? this.data.children.map(childData => nodeFactory.create(childData)) : [];
12
12
  if (typeof this.data?.attributes === 'object' && Object.keys(this.data.attributes).length > 0) {
13
13
  Object.entries(this.data.attributes).forEach(([key, value]) => {
14
- this.attributes.setAttribute(key, value);
14
+ switch (key) {
15
+ case 'classes':
16
+ if (typeof value === 'string') {
17
+ this.attributes.setClasses(value.split(' '));
18
+ } else if (Array.isArray(value)) {
19
+ this.attributes.setClasses(value);
20
+ }
21
+ break;
22
+
23
+ default:
24
+ this.attributes.setAttribute(key, value);
25
+ }
26
+
15
27
  });
16
28
  }
17
29
  if (typeof this.data?.classes === 'object' && Array.isArray(this.data.classes)) {
@@ -0,0 +1,29 @@
1
+ import { Renderable } from '../../core/renderable.js';
2
+
3
+ class AnalyticsConfig extends Renderable {
4
+ constructor (data) {
5
+ super(data, 'analyticsConfig');
6
+ this._analytics = data.analytics;
7
+ this._analytics.domain = '$(1)';
8
+ this._analytics.site.environment = '$(2)';
9
+ }
10
+
11
+ async render () {
12
+ return `
13
+ <script>
14
+ const xhr = new XMLHttpRequest();
15
+ xhr.open('GET', '/env.json', false);
16
+ xhr.send(null);
17
+
18
+ if (xhr.status === 200) {
19
+ const env = JSON.parse(xhr.responseText);
20
+ const analytics = ${JSON.stringify(this._analytics).replace('"$(1)"', 'env.domain').replace('"$(2)"', 'env.env')};
21
+ window.dsfr = { analytics };
22
+ } else {
23
+ console.error('Failed to load JSON:', xhr.status, xhr.statusText);
24
+ }
25
+ </script>`;
26
+ }
27
+ }
28
+
29
+ export { AnalyticsConfig };
@@ -5,6 +5,7 @@ import { Renderable } from '../../core/renderable.js';
5
5
  import { Favicon } from './favicon.js';
6
6
  import { Resource } from './resource.js';
7
7
  import { Share } from './share.js';
8
+ import { AnalyticsConfig } from './analytics-config.js';
8
9
 
9
10
  class Head extends Renderable {
10
11
 
@@ -16,6 +17,7 @@ class Head extends Renderable {
16
17
  this._resource = new Resource(data);
17
18
  this._share = new Share(data);
18
19
  this._stylesheets = new Stylesheets(data);
20
+ this._analyticsConfig = new AnalyticsConfig(data);
19
21
  }
20
22
 
21
23
  async render () {
@@ -30,6 +32,7 @@ class Head extends Renderable {
30
32
  ${await this._share.render()}
31
33
  ${await this._stylesheets.render()}
32
34
  ${await this._resource.render()}
35
+ ${await this._analyticsConfig.render()}
33
36
  </head>
34
37
  `;
35
38
  }
package/src/page/html.js CHANGED
@@ -9,7 +9,7 @@ import { Scripts } from './scripts/scripts.js';
9
9
  import { HtmlRenderable } from '../core/html-renderable.js';
10
10
 
11
11
  class Html extends HtmlRenderable {
12
- constructor(data) {
12
+ constructor (data) {
13
13
  super(data);
14
14
 
15
15
  this._head = new Head(data);
@@ -4,6 +4,7 @@ import { HIGHLIGHT_SCRIPTS } from './highlight.js'
4
4
 
5
5
  const DIST_FILES = [
6
6
  'dsfr',
7
+ 'analytics/analytics',
7
8
  ];
8
9
 
9
10
  const DEFAULT_LIB_FILES = [