@gouvfr/dsfr-roller 1.0.16 → 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.
- package/env/local/env.json +4 -1
- package/env/prod/env.json +4 -1
- package/env/staging/env.json +4 -1
- package/package.json +2 -2
- package/src/component/components/breadcrumb.js +1 -0
- package/src/component/components/header.js +1 -0
- package/src/component/components/translate.js +1 -1
- package/src/component/ejs/version/version.ejs +1 -0
- package/src/core/format-link.js +2 -0
- package/src/node/directive/doc/page-item-card-container-directive.js +13 -4
- package/src/node/directive/doc/page-item-heading-container-directive.js +47 -0
- package/src/node/directive/doc/page-item-list-leaf-directive.js +22 -12
- package/src/node/directive/doc/storybook-leaf-directive.js +8 -7
- package/src/node/node-factory.js +2 -0
- package/src/node/node.js +13 -1
- package/src/page/head/analytics-config.js +29 -0
- package/src/page/head/head.js +3 -0
- package/src/page/html.js +1 -1
- package/src/page/scripts/scripts.js +1 -0
- package/src/script/main/elements/storybook.js +44 -8
- package/src/script/main/index.js +1 -1
package/env/local/env.json
CHANGED
package/env/prod/env.json
CHANGED
package/env/staging/env.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gouvfr/dsfr-roller",
|
|
3
|
-
"version": "1.0.
|
|
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.
|
|
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",
|
|
@@ -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
|
|
package/src/core/format-link.js
CHANGED
|
@@ -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 =
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
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',
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import { Node } from '../../node.js';
|
|
2
2
|
|
|
3
3
|
class StorybookLeafDirective extends Node {
|
|
4
|
+
constructor (data) {
|
|
5
|
+
super(data, 'iframe');
|
|
6
|
+
}
|
|
4
7
|
|
|
5
|
-
// TODO:
|
|
6
|
-
// - script externe pour le resize de l'iframe
|
|
7
|
-
// - apossibilité de multiple storybook (baser sur id de la story ?)
|
|
8
|
-
// - bug resize down
|
|
9
|
-
// - bouton communication avec iframe pour changer le theme exemple
|
|
10
|
-
// - changement theme iframe en fonction theme parent
|
|
11
8
|
async render() {
|
|
12
|
-
return
|
|
9
|
+
return `
|
|
10
|
+
<div class="dsfr-doc-storybook-leaf">
|
|
11
|
+
${await super.render()}
|
|
12
|
+
</div>
|
|
13
|
+
`;
|
|
13
14
|
}
|
|
14
15
|
}
|
|
15
16
|
|
package/src/node/node-factory.js
CHANGED
|
@@ -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
|
-
|
|
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 };
|
package/src/page/head/head.js
CHANGED
|
@@ -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
|
@@ -1,19 +1,55 @@
|
|
|
1
|
-
import { Element } from '../core/element.js'
|
|
1
|
+
import { Element } from '../core/element.js';
|
|
2
2
|
|
|
3
3
|
class Storybook extends Element {
|
|
4
|
-
get iframe
|
|
4
|
+
get iframe() {
|
|
5
5
|
return this.element;
|
|
6
6
|
}
|
|
7
7
|
|
|
8
8
|
init() {
|
|
9
|
-
this.
|
|
10
|
-
|
|
11
|
-
this.
|
|
9
|
+
this.isResized = false;
|
|
10
|
+
this.setIframeTheme();
|
|
11
|
+
this.listenChangeDisplay();
|
|
12
|
+
window.addEventListener('message', this.handleMessage.bind(this));
|
|
12
13
|
}
|
|
13
14
|
|
|
14
|
-
|
|
15
|
-
const
|
|
16
|
-
|
|
15
|
+
handleMessage(event) {
|
|
16
|
+
const eventType = JSON.parse(event.data)?.event?.type;
|
|
17
|
+
if (!eventType) return;
|
|
18
|
+
|
|
19
|
+
if (eventType === 'storyRendered') {
|
|
20
|
+
this._iframeDoc = this.iframe.contentDocument;
|
|
21
|
+
if (!this._iframeDoc || this.isResized) return;
|
|
22
|
+
|
|
23
|
+
this.resize();
|
|
24
|
+
this.isResized = true;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
resize() {
|
|
29
|
+
const height =
|
|
30
|
+
this._iframeDoc.body?.scrollHeight ??
|
|
31
|
+
this._iframeDoc.documentElement?.scrollHeight;
|
|
32
|
+
this.iframe.style.height =
|
|
33
|
+
isNaN(height) || !height ? '100%' : height + 'px';
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
setIframeTheme() {
|
|
37
|
+
const theme = document.documentElement.getAttribute('data-fr-theme');
|
|
38
|
+
if (theme) {
|
|
39
|
+
const url = new URL(window.location.origin + this.iframe.dataset.src);
|
|
40
|
+
url.searchParams.set('globals', `theme:${theme}`);
|
|
41
|
+
this.iframe.src = url.toString();
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
listenChangeDisplay() {
|
|
46
|
+
const display = document.getElementById('fr-display');
|
|
47
|
+
const radios = display.querySelectorAll('input');
|
|
48
|
+
radios.forEach((radio) => {
|
|
49
|
+
radio.addEventListener('change', () => {
|
|
50
|
+
this.setIframeTheme();
|
|
51
|
+
});
|
|
52
|
+
});
|
|
17
53
|
}
|
|
18
54
|
}
|
|
19
55
|
|
package/src/script/main/index.js
CHANGED
|
@@ -7,7 +7,7 @@ import { ConsentManagementPlatform } from './cmp/index.js';
|
|
|
7
7
|
|
|
8
8
|
window.onload = async () => {
|
|
9
9
|
await instantiateElements('.code-snippet--copy', CopySnippet);
|
|
10
|
-
await instantiateElements('.storybook-leaf iframe', Storybook);
|
|
10
|
+
await instantiateElements('.dsfr-doc-storybook-leaf iframe', Storybook);
|
|
11
11
|
await instantiateElements('#search', SearchBar);
|
|
12
12
|
};
|
|
13
13
|
|