@gouvfr/dsfr-nexus
Version:
Le module `dsfr-nexus` est l'interface de ligne de commande (CLI) centrale du Système de Design de l’État - DSFR. Il offre des outils pour gérer et compiler les ressources du DSFR
167 lines (131 loc) • 4.91 kB
JavaScript
import { deepFreeze, log } from '@gouvfr/dsfr-forge';
import { sortMapItems } from '../../utiliy/sort/map-sorting.js';
const RESERVED_KEYS = ['$'];
const flatten = (mapLevel, defaultLocale, locales) => {
const urls = [];
if (mapLevel.hasOwnProperty(defaultLocale) && mapLevel[defaultLocale].hasOwnProperty('url')) {
urls.push({
loc: mapLevel[defaultLocale].url,
alts: locales.map(locale => ({ lang: locale, url: mapLevel[locale]?.url })),
});
}
for (const key in mapLevel) {
switch (true) {
case locales.includes(key):
case RESERVED_KEYS.includes(key):
continue;
case typeof mapLevel[key] === 'object':
urls.push(...flatten(mapLevel[key], defaultLocale, locales));
break;
}
}
return urls;
}
const urlMap = (mapLevel, locale, defaultLocale, locales) => {
const map = {};
if (mapLevel.$.noindex) return null;
const data = mapLevel[locale] || mapLevel[defaultLocale];
if (!data) return null;
map.text = data.text;
map.url = data.url;
const children = [];
for (const key in mapLevel) {
if (locales.includes(key) || RESERVED_KEYS.includes(key)) continue;
const child = mapLevel[key];
if (typeof child === 'object') {
const childMap = urlMap(child, locale, defaultLocale, locales);
if (childMap) children.push(childMap);
}
}
if (children.length > 0) map.children = children;
return map;
}
class MapState {
constructor (data) {
this._map = data;
deepFreeze(this._map);
Object.freeze(this);
}
getUrlset (defaultLocale, locales) {
return flatten(this._map, defaultLocale, locales);
}
getUrlMap (locale, defaultLocale, locales, version) {
return urlMap(this._map[version], locale, defaultLocale, locales);
}
getBase (path, version, context = 'unknown') {
if (typeof path !== 'string') {
log.error(`Invalid path '${path}' { context: '${context}' }`);
return null;
}
let base = this._map[version];
const segments = path.split('/').filter(segment => segment.length > 0);
for (const segment of segments) {
if (base[segment] === undefined) {
log.error(`Invalid path segment '${segment}' in '${path}' { context: '${context}' }`);
return null;
}
base = base[segment];
}
return base;
}
getNode (path, locale, defaultLocale, version, context = 'unknown', currentPath = null) {
const base = this.getBase(path, version, context);
if (base === null) return null;
const node = base?.[locale] ?? base?.[defaultLocale];
if (node === undefined) {
log.error(`Invalid '${path}' { context: '${context}' }`);
return null;
}
return {
...node,
isCurrent: currentPath && currentPath.indexOf(path) === 0
};
}
getChildNodes (path, locale, defaultLocale, locales, version, rank = null, sort = null, context = 'unknown', currentPath = null) {
const base = this.getBase(path, version, context);
if (base === null) return [];
const keys = Object.keys(base)
.filter(key => !locales.includes(key) && !RESERVED_KEYS.includes(key));
const nodes = [];
for (const key of keys) {
const settings = base[key].$;
const content = base[key]?.[locale] ?? base[key]?.[defaultLocale];
if (!settings || !content) continue;
if (!!rank && settings.rank !== rank) continue;
const itemPath = `${path}/${key}`;
const currentPathSegments = currentPath ? currentPath.split('/') : [];
const itemPathSegments = itemPath.split('/');
const itemIsCurrent = currentPathSegments.slice(0, itemPathSegments.length).join('/') === itemPathSegments.join('/');
nodes.push({
$: settings,
content: {
...content,
path: itemPath,
isCurrent: itemIsCurrent
}
});
}
if (sort) {
sortMapItems(nodes, sort);
}
return nodes.map(node => node.content);
}
getRelativeNode(from, to, locale, defaultLocale, version, context = 'unknown') {
const fromSegments = from.split('/').filter(segment => segment.length > 0);
const toSegments = to.split('/').filter(segment => segment.length > 0 && segment !== '.');
const partIndex = toSegments.findIndex(segment => segment === '_part');
const docIndex = toSegments.findIndex(segment => segment === 'doc');
if (partIndex > -1 && docIndex > -1 && docIndex === partIndex + 1) {
toSegments.splice(partIndex, 2);
if (toSegments[0] === '..' && toSegments[1] === '..') toSegments.splice(0, 2);
}
if (toSegments.length > 0 && toSegments[0] === '..') {
while (toSegments.length > 0 && toSegments[0] === '..') {
toSegments.shift();
fromSegments.pop();
}
}
return this.getNode([...fromSegments, ...toSegments].join('/'), locale, defaultLocale, version, context);
}
}
export { MapState };