@gouvfr/dsfr-roller 1.0.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.
- package/LICENSE.md +21 -0
- package/README.md +11 -0
- package/index.js +5 -0
- package/package.json +65 -0
- package/src/component/component.js +50 -0
- package/src/component/components/action.js +28 -0
- package/src/component/components/breadcrumb.js +33 -0
- package/src/component/components/button.js +37 -0
- package/src/component/components/display-body.js +41 -0
- package/src/component/components/display-modal.js +29 -0
- package/src/component/components/footer.js +85 -0
- package/src/component/components/header.js +96 -0
- package/src/component/components/navigation.js +72 -0
- package/src/component/components/sidemenu.js +58 -0
- package/src/component/components/skiplink.js +49 -0
- package/src/component/components/translate.js +32 -0
- package/src/component/components/version.js +21 -0
- package/src/component/ejs/version/version.ejs +46 -0
- package/src/component/ejs/version/versions.ejs +31 -0
- package/src/component/ejs-pkg.js +6 -0
- package/src/component/render.js +19 -0
- package/src/constants.js +7 -0
- package/src/core/format-html.js +16 -0
- package/src/core/format-link.js +8 -0
- package/src/core/html-renderable.js +10 -0
- package/src/core/renderable.js +20 -0
- package/src/integration/bundler.js +47 -0
- package/src/integration/indexing/indexer.js +23 -0
- package/src/integration/indexing/sitemap.js +44 -0
- package/src/integration/redirect/redirection-type.js +4 -0
- package/src/integration/redirect/redirection.js +77 -0
- package/src/node/custom/html-container-node.js +7 -0
- package/src/node/directive/doc/accordion-container-directive.js +59 -0
- package/src/node/directive/doc/accordions-group-container-directive.js +12 -0
- package/src/node/directive/doc/anatomy-container-directive.js +61 -0
- package/src/node/directive/doc/button-leaf-directive.js +37 -0
- package/src/node/directive/doc/changelog-leaf-directive.js +238 -0
- package/src/node/directive/doc/figma-leaf-directive.js +21 -0
- package/src/node/directive/doc/guideline-container-directive.js +71 -0
- package/src/node/directive/doc/guidelines-container-directive.js +13 -0
- package/src/node/directive/doc/image-text-directive.js +13 -0
- package/src/node/directive/doc/pin-leaf-directive.js +46 -0
- package/src/node/directive/doc/storybook-leaf-directive.js +18 -0
- package/src/node/directive/doc/tab-container-directive.js +22 -0
- package/src/node/directive/doc/tab-navigation-container-directive.js +49 -0
- package/src/node/directive/doc/table-container-directive.js +56 -0
- package/src/node/directive/doc/tabs-container-directive.js +71 -0
- package/src/node/generic/blockquote-node.js +26 -0
- package/src/node/generic/break-node.js +11 -0
- package/src/node/generic/code-node.js +37 -0
- package/src/node/generic/definition-node.js +13 -0
- package/src/node/generic/emphasis-node.js +11 -0
- package/src/node/generic/heading-node.js +56 -0
- package/src/node/generic/html-node.js +11 -0
- package/src/node/generic/image-node.js +14 -0
- package/src/node/generic/image-reference-node.js +14 -0
- package/src/node/generic/inline-code-node.js +21 -0
- package/src/node/generic/link-node.js +26 -0
- package/src/node/generic/link-reference-node.js +14 -0
- package/src/node/generic/list-item-node.js +11 -0
- package/src/node/generic/list-node.js +15 -0
- package/src/node/generic/paragraph-node.js +11 -0
- package/src/node/generic/strong-node.js +11 -0
- package/src/node/generic/text-node.js +15 -0
- package/src/node/generic/thematic-break-node.js +12 -0
- package/src/node/gfm/table-body-node.js +11 -0
- package/src/node/gfm/table-cell-node.js +17 -0
- package/src/node/gfm/table-head-node.js +11 -0
- package/src/node/gfm/table-header-node.js +16 -0
- package/src/node/gfm/table-node.js +91 -0
- package/src/node/gfm/table-row-node.js +11 -0
- package/src/node/node-factory.js +128 -0
- package/src/node/node-root.js +25 -0
- package/src/node/node.js +106 -0
- package/src/page/body/custom-header.js +40 -0
- package/src/page/body/main.js +23 -0
- package/src/page/body/scheme.js +9 -0
- package/src/page/head/canonical.js +16 -0
- package/src/page/head/favicon.js +14 -0
- package/src/page/head/head.js +35 -0
- package/src/page/head/share.js +14 -0
- package/src/page/head/stylesheets.js +48 -0
- package/src/page/head/title.js +9 -0
- package/src/page/html.js +46 -0
- package/src/page/page.js +39 -0
- package/src/page/scripts/highlight.js +53 -0
- package/src/page/scripts/scripts.js +57 -0
- package/src/script/main/core/element.js +29 -0
- package/src/script/main/elements/copy-snippet.js +35 -0
- package/src/script/main/elements/searchbar.js +18 -0
- package/src/script/main/elements/storybook.js +20 -0
- package/src/script/main/index.js +10 -0
- package/src/script/search/index.js +0 -0
- package/src/style/main/components/_dsfr-doc-anatomy.scss +54 -0
- package/src/style/main/components/_dsfr-doc-code-snippet.scss +9 -0
- package/src/style/main/components/_dsfr-doc-figma-leaf.scss +6 -0
- package/src/style/main/components/_dsfr-doc-guideline.scss +58 -0
- package/src/style/main/components/_dsfr-doc-tab-navigation.scss +99 -0
- package/src/style/main/components/_dsfr-doc-version.scss +154 -0
- package/src/style/main/components/_index.scss +6 -0
- package/src/style/main/index.scss +3 -0
- package/src/style/main/third-party/_highlight.scss +227 -0
- package/src/style/main/third-party/_index.scss +1 -0
- package/src/style/main/utility/_dsfr-doc-code.scss +9 -0
- package/src/style/main/utility/_font.scss +31 -0
- package/src/style/main/utility/_icon.scss +4 -0
- package/src/style/main/utility/_index.scss +3 -0
- package/src/style/search/index.scss +0 -0
- package/src/template/template-factory.js +16 -0
- package/src/template/template.js +27 -0
- package/src/template/templates/editorial-template.js +45 -0
- package/src/template/templates/home-template.js +18 -0
- package/src/template/templates/search-template.js +20 -0
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { Component } from '../component.js';
|
|
2
|
+
|
|
3
|
+
class Translate extends Component {
|
|
4
|
+
constructor (data) {
|
|
5
|
+
super(data, 'translate');
|
|
6
|
+
}
|
|
7
|
+
get ejsPath () {
|
|
8
|
+
return 'src/dsfr/component/translate/template/ejs/translate.ejs';
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
async format () {
|
|
12
|
+
return {
|
|
13
|
+
id: 'translate',
|
|
14
|
+
button: { title: this.data.button, kind: 3 },
|
|
15
|
+
collapseId: 'translate-collapse',
|
|
16
|
+
languages: this._formatLanguages(this.data.languages)
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
_formatLanguages (languages) {
|
|
21
|
+
return languages.map(lang => this._formatLanguage(lang));
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
_formatLanguage (lang) {
|
|
25
|
+
return {
|
|
26
|
+
...lang,
|
|
27
|
+
href: lang.url
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export { Translate };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Component } from '../component.js';
|
|
2
|
+
import { EJS_PKG } from '../ejs-pkg.js';
|
|
3
|
+
class Version extends Component {
|
|
4
|
+
constructor (data) {
|
|
5
|
+
super(data, 'version', EJS_PKG.ROLLER);
|
|
6
|
+
}
|
|
7
|
+
get ejsPath () {
|
|
8
|
+
return 'src/component/ejs/version/version.ejs';
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
async format () {
|
|
12
|
+
return {
|
|
13
|
+
id: 'version',
|
|
14
|
+
button: { title: this.data.button, kind: 3 },
|
|
15
|
+
collapseId: 'version-collapse',
|
|
16
|
+
versions: this.data.versions
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export { Version };
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
<%#
|
|
2
|
+
# paramètres header version
|
|
3
|
+
|
|
4
|
+
* version (object, optional) : Paramètres du sélecteur de langue
|
|
5
|
+
** version.id (string) : id de l'élément
|
|
6
|
+
** version.button (object, optional) : Paramètres du bouton du sélecteur de langue (ex: {kind:3} pour un btn tertiary)
|
|
7
|
+
** version.collapseId (string, required) : Id du menu à controler
|
|
8
|
+
** version.versions (array, required) : Tableau d'objets langues
|
|
9
|
+
*** version.versions[].name (string, required) : Nom de la langue dans son alphabet
|
|
10
|
+
*** version.versions[].locale (string, required) : Code de la langue en 2 caratères
|
|
11
|
+
*** version.versions[].active (boolean, required) : La langue qui apparait dans le bouton et en style active dans la liste (1 seule langue active)
|
|
12
|
+
%>
|
|
13
|
+
<%
|
|
14
|
+
const version = locals.version || {};
|
|
15
|
+
const attributes = version.attributes || {};
|
|
16
|
+
attributes.id = version.id || uniqueId('version');
|
|
17
|
+
const collapseId = version.collapseId || uniqueId('version');
|
|
18
|
+
%>
|
|
19
|
+
|
|
20
|
+
<% eval(include(`${dsfrPkg}src/dsfr/core/index.ejs`)); %>
|
|
21
|
+
|
|
22
|
+
<nav role="navigation" class="dsfr-doc-version <%= prefix %>-nav" <%- includeAttrs(attributes) %>>
|
|
23
|
+
<div class="<%= prefix %>-nav__item">
|
|
24
|
+
<%
|
|
25
|
+
const versionBtn = version.button || {};
|
|
26
|
+
const activeVersion = version.versions.find(version => version.active === true);
|
|
27
|
+
versionBtn.label = activeVersion?.label ?? activeVersion?.text;
|
|
28
|
+
const minBtnClasses = [`dsfr-doc-version__btn`];
|
|
29
|
+
const minBtnAttrs = {
|
|
30
|
+
'aria-controls': collapseId,
|
|
31
|
+
'aria-expanded': false,
|
|
32
|
+
title: versionBtn.title
|
|
33
|
+
};
|
|
34
|
+
versionBtn.classes = versionBtn.classes !== undefined ? versionBtn.classes.concat(minBtnClasses) : minBtnClasses;
|
|
35
|
+
versionBtn.attributes = versionBtn.attributes !== undefined ? {...minBtnAttrs, ...versionBtn.attributes} : minBtnAttrs;
|
|
36
|
+
|
|
37
|
+
%>
|
|
38
|
+
|
|
39
|
+
<%- include(`${dsfrPkg}src/dsfr/component/button/template/ejs/button`, { button:versionBtn }); %>
|
|
40
|
+
|
|
41
|
+
<div class="<%= prefix %>-collapse dsfr-doc-version__menu <%= prefix %>-menu" id="<%= version.collapseId %>">
|
|
42
|
+
|
|
43
|
+
<%- include('versions.ejs', {versions: version.versions}) %>
|
|
44
|
+
</div>
|
|
45
|
+
</div>
|
|
46
|
+
</nav>
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
<%#
|
|
2
|
+
# paramètres versionSelect Versions
|
|
3
|
+
|
|
4
|
+
* versions (array, required) : Tableau d'objets versions
|
|
5
|
+
** versions[].id (string) : id de l'élément
|
|
6
|
+
** versions[].name (string, required) : Nom de la version
|
|
7
|
+
|
|
8
|
+
** versions[].url (string) : url de la version
|
|
9
|
+
** versions[].active (boolean, required) : La version qui apparait dans le bouton et en style active dans la liste (1 seule version active)
|
|
10
|
+
** versions[].badge (string) : complément au nom de version
|
|
11
|
+
%>
|
|
12
|
+
<%
|
|
13
|
+
const versions = locals.versions || {};
|
|
14
|
+
%>
|
|
15
|
+
|
|
16
|
+
<ul class="<%= prefix %>-menu__list">
|
|
17
|
+
<%
|
|
18
|
+
for (let i = 0; i < versions.length; i++) {
|
|
19
|
+
const version = versions[i];
|
|
20
|
+
const attrs = {
|
|
21
|
+
href: version.url,
|
|
22
|
+
id: version.id || uniqueId('version')
|
|
23
|
+
};
|
|
24
|
+
if (version.active) attrs['aria-current'] = true;
|
|
25
|
+
const badge = version.badge !== undefined ? ` <span class="${prefix}-badge ${prefix}-badge--new ${prefix}-badge--sm" >${version.badge}</span>` : '';
|
|
26
|
+
%>
|
|
27
|
+
<li>
|
|
28
|
+
<a class="dsfr-doc-version__version <%= prefix %>-nav__link" <%- includeAttrs(attrs); %> ><%= version.text %><%- badge %></a>
|
|
29
|
+
</li>
|
|
30
|
+
<% } %>
|
|
31
|
+
</ul>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import ejs from 'ejs';
|
|
2
|
+
import { EJS_PKG } from './ejs-pkg.js';
|
|
3
|
+
|
|
4
|
+
let count = 0;
|
|
5
|
+
|
|
6
|
+
const uniqueId = (module) => {
|
|
7
|
+
count++;
|
|
8
|
+
return `${module}-${count}`;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
const DATA = {
|
|
12
|
+
uniqueId: uniqueId,
|
|
13
|
+
dsfrPkg: EJS_PKG.DSFR,
|
|
14
|
+
relativeRoot: '/'
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const render = async (template, data, pkg = EJS_PKG.DSFR) => await ejs.render(`<%- include('${pkg}${template}') %>`, {...DATA, ...data});
|
|
18
|
+
|
|
19
|
+
export default render;
|
package/src/constants.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { log } from '@gouvfr/dsfr-forge';
|
|
2
|
+
import * as prettier from 'prettier';
|
|
3
|
+
import htmlParser from 'prettier/parser-html';
|
|
4
|
+
|
|
5
|
+
export const formatHtml = async (html, src = 'unknown') => {
|
|
6
|
+
try {
|
|
7
|
+
const pretty = await prettier.format(html, { parser: 'html', plugins: [htmlParser], tabWidth: 2, });
|
|
8
|
+
return pretty;
|
|
9
|
+
}
|
|
10
|
+
catch (error) {
|
|
11
|
+
log.error(`Error while formatting HTML @ ${src}`);
|
|
12
|
+
log.error(error);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
return html;
|
|
16
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
class Renderable {
|
|
2
|
+
constructor (data) {
|
|
3
|
+
data = this.structure(data);
|
|
4
|
+
this._data = data;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
structure (data) {
|
|
8
|
+
return data;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
get data () {
|
|
12
|
+
return this._data;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
async render () {
|
|
16
|
+
return '';
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export { Renderable };
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { ROLLER_MODULE, BANNER } from '../constants.js';
|
|
2
|
+
import { copyDir, getPackagePath, log } from '@gouvfr/dsfr-forge';
|
|
3
|
+
import { ScriptCompiler, StyleCompiler } from '@gouvfr/dsfr-alchemist'
|
|
4
|
+
import path from 'path'
|
|
5
|
+
import fs from 'fs'
|
|
6
|
+
|
|
7
|
+
class Bundler {
|
|
8
|
+
constructor (dest) {
|
|
9
|
+
this._dest = dest;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
async copy () {
|
|
13
|
+
await copyDir(`${ROLLER_MODULE}/static`, `${this._dest}/static`);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
async compile () {
|
|
17
|
+
await this._compileScripts();
|
|
18
|
+
await this._compileStyles();
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
async _compileScripts () {
|
|
22
|
+
const scriptCompiler = new ScriptCompiler();
|
|
23
|
+
const entries = fs.readdirSync(`${ROLLER_MODULE}/src/script`, { withFileTypes: true });
|
|
24
|
+
for (const entry of entries) {
|
|
25
|
+
if (!entry.isDirectory()) continue;
|
|
26
|
+
const index = `${ROLLER_MODULE}/src/script/${entry.name}/index.js`;
|
|
27
|
+
if (!fs.existsSync(index)) continue;
|
|
28
|
+
await scriptCompiler.compile(index, `${this._dest}/lib`, `dsfr-doc-${entry.name}`, {
|
|
29
|
+
minify: true, sourceMap: true, banner: BANNER
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
async _compileStyles () {
|
|
35
|
+
const modulesPath = path.resolve(getPackagePath('@gouvfr/dsfr-publisher'), '../../') + '/';
|
|
36
|
+
const styleCompiler = new StyleCompiler();
|
|
37
|
+
const entries = fs.readdirSync(`${ROLLER_MODULE}/src/style`, { withFileTypes: true });
|
|
38
|
+
for (const entry of entries) {
|
|
39
|
+
if (!entry.isDirectory()) continue;
|
|
40
|
+
const index = `${ROLLER_MODULE}/src/style/${entry.name}/index.scss`;
|
|
41
|
+
if (!fs.existsSync(index)) continue;
|
|
42
|
+
await styleCompiler.compile(index, `${this._dest}/lib`, `dsfr-doc-${entry.name}`, { minify: true, sourceMap: true, banner: BANNER, loadPaths: [modulesPath] });
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export { Bundler };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Sitemap } from './sitemap.js';
|
|
2
|
+
import { createFile } from '@gouvfr/dsfr-forge';
|
|
3
|
+
import { DOMAIN } from '../../constants.js';
|
|
4
|
+
|
|
5
|
+
class Indexer {
|
|
6
|
+
constructor (urlSet, dest) {
|
|
7
|
+
this._urlSet = urlSet;
|
|
8
|
+
this._dest = dest;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
async write () {
|
|
12
|
+
const sitemap = new Sitemap(this._urlSet);
|
|
13
|
+
await sitemap.generate();
|
|
14
|
+
|
|
15
|
+
createFile( `${this._dest}/sitemap.txt`, sitemap.text);
|
|
16
|
+
createFile( `${this._dest}/sitemap.xml`, sitemap.xml);
|
|
17
|
+
|
|
18
|
+
const robots = `Sitemap: ${DOMAIN}/sitemap.xml`;
|
|
19
|
+
createFile( `${this._dest}/robots.txt`, robots);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export { Indexer };
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { DOMAIN } from '../../constants.js';
|
|
2
|
+
import { formatHtml } from '../../core/format-html.js';
|
|
3
|
+
|
|
4
|
+
class Sitemap {
|
|
5
|
+
constructor (urlSet) {
|
|
6
|
+
this._urlSet = urlSet;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
async generate () {
|
|
10
|
+
let xml = '<?xml version="1.0" encoding="UTF-8"?>\n<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml">\n';
|
|
11
|
+
let text = '';
|
|
12
|
+
|
|
13
|
+
for (const url of this._urlSet) {
|
|
14
|
+
xml += '<url>\n';
|
|
15
|
+
if (url.hasOwnProperty('loc')) {
|
|
16
|
+
xml += `<loc>${DOMAIN}${url.loc}</loc>\n`;
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
if (Array.isArray(url.alts)) {
|
|
20
|
+
xml += url.alts.map(alt => `<xhtml:link rel="alternate" hreflang="${alt.lang}" href="${DOMAIN}${alt.url}"/>\n`).join('');
|
|
21
|
+
text += url.alts.map(alt => `${DOMAIN}${alt.url}\n`).join('\n');
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
text += `${DOMAIN}${url.loc}\n`;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
xml += '</url>\n';
|
|
28
|
+
}
|
|
29
|
+
xml += '</urlset>';
|
|
30
|
+
|
|
31
|
+
this._xml = await formatHtml(xml, 'sitemap');
|
|
32
|
+
this._text = text;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
get text () {
|
|
36
|
+
return this._text;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
get xml () {
|
|
40
|
+
return this._xml;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export { Sitemap };
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { HtmlRenderable } from '../../core/html-renderable.js';
|
|
2
|
+
import { RedirectionType } from './redirection-type.js'
|
|
3
|
+
|
|
4
|
+
class Redirection extends HtmlRenderable {
|
|
5
|
+
constructor (data) {
|
|
6
|
+
super(data);
|
|
7
|
+
this._dest = data.dest;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
get dest () {
|
|
11
|
+
return this._dest;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
get meta () {
|
|
15
|
+
return `
|
|
16
|
+
<meta http-equiv="refresh" content="0; url=${this.data.url}">
|
|
17
|
+
`;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
get script () {
|
|
21
|
+
return `
|
|
22
|
+
<script>
|
|
23
|
+
const locales = ${JSON.stringify(this.data.locales)};
|
|
24
|
+
const urls = new Map(${JSON.stringify(Object.entries(this.data.urls))});
|
|
25
|
+
const language = navigator.language;
|
|
26
|
+
const code = language.split('-')[0];
|
|
27
|
+
|
|
28
|
+
switch (true) {
|
|
29
|
+
case locales.includes(language):
|
|
30
|
+
window.location.href = urls.get(language);
|
|
31
|
+
break;
|
|
32
|
+
|
|
33
|
+
case locales.includes(code):
|
|
34
|
+
window.location.href = urls.get(code);
|
|
35
|
+
break;
|
|
36
|
+
|
|
37
|
+
case locales.some(locale => locale.startsWith(code)):
|
|
38
|
+
const locale = locales.find(locale => locale.startsWith(code));
|
|
39
|
+
window.location.href = urls.get(locale);
|
|
40
|
+
break;
|
|
41
|
+
|
|
42
|
+
default:
|
|
43
|
+
window.location.href = '${this.data.url}';
|
|
44
|
+
break;
|
|
45
|
+
}
|
|
46
|
+
</script>
|
|
47
|
+
`;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
get redirection () {
|
|
51
|
+
switch (this.data.type) {
|
|
52
|
+
case RedirectionType.META:
|
|
53
|
+
return this.meta;
|
|
54
|
+
case RedirectionType.SCRIPT:
|
|
55
|
+
return this.script;
|
|
56
|
+
default:
|
|
57
|
+
return '';
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
async render () {
|
|
62
|
+
return this.format(`
|
|
63
|
+
<html lang="${this.data.code}">
|
|
64
|
+
<head>
|
|
65
|
+
<meta charset="UTF-8">
|
|
66
|
+
<title>${this.data.title}</title>
|
|
67
|
+
${this.redirection}
|
|
68
|
+
</head>
|
|
69
|
+
<body>
|
|
70
|
+
<p>${this.data.text}</p>
|
|
71
|
+
</body>
|
|
72
|
+
</html>
|
|
73
|
+
`);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export { Redirection };
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { Node } from '../../node.js'
|
|
2
|
+
import { log } from '@gouvfr/dsfr-forge';
|
|
3
|
+
|
|
4
|
+
class AccordionContainerDirective extends Node {
|
|
5
|
+
structure (data) {
|
|
6
|
+
if (!data.attributes.id) {
|
|
7
|
+
log.warn('AccordionContainerDirective: missing "accordion id"');
|
|
8
|
+
return data;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const accordionId = data.attributes.id;
|
|
12
|
+
const titleChildren = data.children.filter(child => child?.data?.directiveLabel)?.[0]?.children;
|
|
13
|
+
const contentChildren = data.children.filter(child => !child?.data?.directiveLabel);
|
|
14
|
+
const titleType = titleChildren[0].value.startsWith('#') ? 'heading' : 'paragraph';
|
|
15
|
+
const titleDepth = /^(#+)/.exec(titleChildren[0].value)?.[1]?.length;
|
|
16
|
+
if (titleType === 'heading') {
|
|
17
|
+
titleChildren[0].value = titleChildren[0].value.replace(/^(#+)\s*/, '');
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return super.structure({
|
|
21
|
+
type: 'htmlContainer',
|
|
22
|
+
tagName: 'div',
|
|
23
|
+
classes: ['fr-accordion'],
|
|
24
|
+
children: [
|
|
25
|
+
{
|
|
26
|
+
type: titleType,
|
|
27
|
+
depth: titleDepth,
|
|
28
|
+
classes: ['fr-accordion__title'],
|
|
29
|
+
children: [
|
|
30
|
+
{
|
|
31
|
+
type: 'htmlContainer',
|
|
32
|
+
tagName: 'button',
|
|
33
|
+
classes: ['fr-accordion__btn'],
|
|
34
|
+
attributes: {
|
|
35
|
+
type: 'button',
|
|
36
|
+
'aria-expanded': data.attributes['aria-expanded'] || false,
|
|
37
|
+
'aria-controls': accordionId
|
|
38
|
+
},
|
|
39
|
+
children: titleChildren
|
|
40
|
+
}
|
|
41
|
+
]
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
type: 'htmlContainer',
|
|
45
|
+
tagName: 'div',
|
|
46
|
+
attributes: {
|
|
47
|
+
id: accordionId
|
|
48
|
+
},
|
|
49
|
+
classes: ['fr-collapse'],
|
|
50
|
+
children: contentChildren
|
|
51
|
+
}
|
|
52
|
+
]
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
AccordionContainerDirective.NAME = 'fr-accordion';
|
|
58
|
+
|
|
59
|
+
export { AccordionContainerDirective };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Node } from '../../node.js'
|
|
2
|
+
|
|
3
|
+
class AccordionsGroupContainerDirective extends Node {
|
|
4
|
+
constructor (data) {
|
|
5
|
+
super(data, 'div');
|
|
6
|
+
this.attributes.addClass('fr-accordions-group');
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
AccordionsGroupContainerDirective.NAME = 'fr-accordions-group';
|
|
11
|
+
|
|
12
|
+
export { AccordionsGroupContainerDirective };
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { Node } from '../../node.js'
|
|
2
|
+
import { log } from '@gouvfr/dsfr-forge';
|
|
3
|
+
|
|
4
|
+
class AnatomyContainerDirective extends Node {
|
|
5
|
+
structure (data) {
|
|
6
|
+
const image = Node.getImageChild(data);
|
|
7
|
+
const col = data.attributes?.col ?? 12;
|
|
8
|
+
|
|
9
|
+
if (!image) {
|
|
10
|
+
log.warn('GuidelineContainerDirective: missing image');
|
|
11
|
+
return data;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const contentChildren = data.children.filter(child => !Node.getImageChild(child));
|
|
15
|
+
|
|
16
|
+
return super.structure({
|
|
17
|
+
type: 'htmlContainer',
|
|
18
|
+
tagName: 'div',
|
|
19
|
+
classes: ['fr-grid-row', 'fr-grid-row--gutters'],
|
|
20
|
+
children: [
|
|
21
|
+
{
|
|
22
|
+
type: 'htmlContainer',
|
|
23
|
+
tagName: 'div',
|
|
24
|
+
classes: ['fr-col-12', `fr-col-sm-${col}`],
|
|
25
|
+
children: [
|
|
26
|
+
{
|
|
27
|
+
type: 'htmlContainer',
|
|
28
|
+
tagName: 'div',
|
|
29
|
+
classes: ['dsfr-doc-anatomy'],
|
|
30
|
+
children: [
|
|
31
|
+
{
|
|
32
|
+
type: 'htmlContainer',
|
|
33
|
+
tagName: 'div',
|
|
34
|
+
classes: ['dsfr-doc-anatomy__image'],
|
|
35
|
+
children: [
|
|
36
|
+
{
|
|
37
|
+
...image,
|
|
38
|
+
classes: ['fr-responsive-img']
|
|
39
|
+
}
|
|
40
|
+
]
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
type: 'htmlContainer',
|
|
44
|
+
tagName: 'ol',
|
|
45
|
+
classes: ['dsfr-doc-anatomy__content'],
|
|
46
|
+
children: contentChildren
|
|
47
|
+
}
|
|
48
|
+
]
|
|
49
|
+
}
|
|
50
|
+
]
|
|
51
|
+
}
|
|
52
|
+
]
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
AnatomyContainerDirective.NAME = 'dsfr-doc-anatomy';
|
|
60
|
+
|
|
61
|
+
export { AnatomyContainerDirective };
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { Node } from '../../node.js';
|
|
2
|
+
import { Button } from '../../../component/components/button.js';
|
|
3
|
+
|
|
4
|
+
class ButtonLeafDirective extends Node {
|
|
5
|
+
constructor (data) {
|
|
6
|
+
super(data);
|
|
7
|
+
this.button = new Button(this.data.attributes);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
structure (data) {
|
|
11
|
+
if (!data.children.some(child => child.type === 'link')) {
|
|
12
|
+
return super.structure(data);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const link = data.children.find(child => child.type === 'link');
|
|
16
|
+
const children = data.children.slice();
|
|
17
|
+
children.splice(data.children.indexOf(link), 1, ...link.children);
|
|
18
|
+
|
|
19
|
+
return super.structure({
|
|
20
|
+
...data,
|
|
21
|
+
attributes: {
|
|
22
|
+
...data.attributes,
|
|
23
|
+
url: link.url
|
|
24
|
+
},
|
|
25
|
+
children: children
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async render () {
|
|
30
|
+
const data = { label: await this.renderChildren() };
|
|
31
|
+
return this.button.render(data);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
ButtonLeafDirective.NAME = 'fr-button';
|
|
36
|
+
|
|
37
|
+
export { ButtonLeafDirective };
|