@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
200 lines (165 loc) • 5.11 kB
JavaScript
import yaml from 'yaml';
import { PageNode } from '../page-node.js';
import { log } from '@gouvfr/dsfr-forge';
class DirectiveNode extends PageNode {
constructor (data, state) {
super(data, state);
this._name = data.name;
this._properties = data.properties;
}
structure (data, state) {
const parameters = data.attributes;
delete data.attributes;
if (!parameters) {
return super.structure(data, state);
}
const properties = {};
const attributes = {};
for (const key in parameters) {
const parts = key.split('.');
let current = properties;
switch (parts[0]) {
case 'attributes':
current = attributes;
parts.shift();
break;
case 'id':
attributes.id = parameters[key];
break; // TODO: id outside properties
case 'class':
if (!data.classes) data.classes = [];
data.classes.push(...parameters.class.split(' ').map(c => c.trim()).filter(Boolean));
// TODO: class outside properties (in attributes and remove classes)
continue;
}
while (parts.length > 1) {
const part = parts.shift();
if (!current[part]) current[part] = {};
current = current[part];
}
const lastPart = parts.shift();
if (lastPart) {
try {
current[lastPart] = yaml.parse(parameters[key]);
}
catch (e) {
log.warn(`Failed to parse property "${key}" as YAML : ${e.message}`);
// If parsing fails, store the value as a string
current[lastPart] = parameters[key];
}
}
}
data.properties = properties;
data.attributes = attributes;
return super.structure(data, state);
}
get properties () {
return this._properties;
}
getStringProperty (key) {
const value = this.properties[key];
if (value === undefined || value === null) return undefined;
return String(value).trim();
}
getBooleanProperty (key) {
const value = this.properties[key];
if (value === undefined || value === null) return undefined;
switch (typeof value) {
case 'string':
return value.toLowerCase() === 'true';
case 'boolean':
return value;
case 'number':
return value !== 0;
default:
log.error(`Unsupported type for boolean property "${key}": ${typeof value}`);
}
return undefined;
}
getNumberProperty (key) {
const value = this.properties[key];
if (value === undefined || value === null) return undefined;
const number = Number(value);
return isNaN(number) ? undefined : number;
}
getArrayProperty (key, type = 'string', length = null) {
const value = this.properties[key];
if (value === undefined || value === null) return undefined;
let array;
switch (typeof value) {
case 'string':
array = value.split(',').map(item => item.trim()).filter(Boolean);
break;
case 'object':
if (Array.isArray(value)) {
array = value;
}
else {
array = Object.values(value);
}
break;
case type:
array = [value];
break;
default:
log.error(`Unsupported type for array property "${key}": ${typeof value}`);
return undefined;
}
if (array.length === 0 || array[0] === undefined) return undefined;
if (length !== null && !isNaN(length) && length > 0) {
if (array.length > length) array.length = length;
if (array.length < length) array.push(...new Array(length - array.length).fill(array[0]));
}
switch (type) {
case 'string':
return array.map(item => String(item));
case 'number':
return array.map(item => {
const number = Number(item);
return isNaN(number) ? array[0] : number;
});
case 'boolean':
return array.map(item => item === true);
//TODO: case 'object':
default:
throw new Error(`Unsupported type: ${type}`);
}
}
getObjectProperty (key) {
const value = this.properties[key];
if (value === undefined || value === null) return undefined;
if (typeof value === 'string') {
if (/"\s*:/.test(value)) {
// If the value looks like a JSON object, try to parse it as JSON first
try {
return JSON.parse(value);
} catch (e) {
log.warn(`Failed to parse object property "${key}" as JSON : ${e.message}`);
}
}
if (/:\s+/.test(value)) {
// If the value looks like a YAML object, try to parse it as YAML
try {
return yaml.parse(value);
} catch (e) {
log.warn(`Failed to parse object property "${key}" as YAML : ${e.message}`);
}
}
}
if (typeof value !== 'object') {
return undefined;
}
return value;
}
get name () {
return this._name;
}
get data () {
return {
...super.data,
name: this.name,
properties: this.properties,
};
}
}
export { DirectiveNode };