UNPKG

@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

238 lines (191 loc) 6.58 kB
import fs from 'fs'; import { createYAMLFile, log, readYAMLSync } from '@gouvfr/dsfr-forge'; import { DocParser } from './doc/doc-parser.js'; import { PageRank } from '../../../common/constants.js' import { sortMapItems } from '../../../common/utiliy/sort/map-sorting.js'; import { ComponentParser } from './component/component-parser.js'; import path from 'path'; import { GenerationParser } from './generation/generation-parser.js'; const getPartIndexSrc = (state) => `${state.src}/_part/index.yml`; class PartParser { constructor (state, parent) { this._state = state; this._parent = parent; this._ascendants = parent ? [parent, ...parent.ascendants] : []; this._depth = parent ? parent.depth + 1 : 0; this._root = parent ? parent.root : this; this._children = []; this._descendants = []; this._has = false; this._isDraft = false; this._isDetached = false; this._isIgnored = false; this._isAuxiliary = false; this._map = null; } get id () { return this._id; } get has () { return this._has; } get isDraft () { return this._isDraft; } get isDetached () { return this._isDetached; } get isIgnored () { return this._isIgnored; } get isAuxiliary () { return this._isAuxiliary; } get children () { return this._children; } get parent () { return this._parent; } get state () { return this._state; } get ascendants () { return this._ascendants } get depth () { return this._depth; } get root () { return this._root; } get descendants () { return this._descendants; } get doc () { return this._doc; } get map () { return this._map; } get descriptor () { return Object.assign(this._component?.descriptor ?? {}, ...this._children.map(child => child.descriptor)); } getPart (id) { return this.root.id === id ? this.root : this.root.descendants.find(descendant => descendant.id === id); } async read () { const indexSrc = getPartIndexSrc(this._state); if (!fs.existsSync(indexSrc)) return; this._index = readYAMLSync(indexSrc); this._isIgnored = this._index.isIgnored === true; if (this._isIgnored) return; this._id = this._index.id; this._state = this._state.setPart(this._id); const duplicated = this.root.descendants.filter(part => part.id === this._id) if (duplicated.length) { log.error(`Part with id '${this._id}' (${this._state.src}) already exists in [${duplicated.map(part => part.src).join(',')}]`); return; } this._has = true; this._isDraft = this._index.isDraft === true; this._isDetached = this._index.isDetached === true; this._isAuxiliary = this._index.isAuxiliary === true; await this.readStyle(this._index.style); await this.readScript(this._index.script); await this.readComponent(this._index.component); await this.readGeneration(this._index.generation); await this.readDoc(this._index.doc); await this.readChildren(); } async readStyle (data = {}) { // Placeholder for future style reading logic } async readScript (data = {}) { // Placeholder for future script reading logic } async readComponent (data = {}) { const componentState = this._state.descend('_part/component'); const component = new ComponentParser(componentState, { ...data, id: this._id }); await component.read(); if (!component.has) return; this._component = component; } async readGeneration (data = {}) { const generationState = this._state.descend('_part/generation').setDest(`${this._state.src}/_generated`); const generation = new GenerationParser(generationState, { ...data, id: this._id }); await generation.read(); if (!generation.has) return; this._generation = generation; } async readDoc (data = {}) { const docState = data.isStatic ? this._state.statify(this._id) : this._state.descend('_part/doc'); const doc = new DocParser(docState, this._parent?.doc, this, this._id, this._isAuxiliary ? PageRank.AUXILIARY : PageRank.PART); await doc.read(); if (!doc.has) return; this._doc = doc; this._map = doc.map; } async readChildren () { const entries = fs.readdirSync(this.state.src, { withFileTypes: true }); for (const entry of entries) { if (!entry.isDirectory() || entry.name.startsWith('_')) continue; const state = this._state.descend(entry.name); const childIndexSrc = getPartIndexSrc(state); if (!fs.existsSync(childIndexSrc)) continue; const childIndex = readYAMLSync(childIndexSrc); if (!childIndex || !childIndex.id) { log.error(`Part index file is malformed or missing 'id' property: ${childIndexSrc}`); continue; } if (childIndex.isIgnored === true) continue; const childState = state.setPath(path.join(state.path, childIndex.id)); const child = new PartParser(childState, this); await child.read(); if (!child.has) continue; this._children.push(child); this._descendants.push(child, ...child.descendants); } const childrenMaps = this._children.filter(child => child.doc).map(child => child.map); if (childrenMaps.length === 0) return; if (!this._map) this._map = {}; if (this._map.$?.sort) { sortMapItems(childrenMaps, this._map.$.sort); } childrenMaps.forEach(mapItem => { this._map[mapItem.$.id] = mapItem; }) } async write () { const data = { id: this._id, src: this._state.src, banner: this._state.banner, isDraft: this._isDraft, isDetached: this._isDetached, parent: this._parent?.id, children: this._children.map(child => child.id), ascendants: this._ascendants.map(ascendant => ascendant.id), depth: this._depth, descendants: this._descendants.map(descendant => descendant.id) }; if (this._component) { data.component = this._component.data; } if (this._generation) { data.generation = this._generation.data; } if (this._doc) { data.doc = this._doc.data; } createYAMLFile(this.state.configFile('data.yml'), data); if (this._component) await this._component.write(); if (this._generation) await this._generation.write(); if (this._doc) await this._doc.write(); for (const child of this._children) await child.write(); } async describe () { createYAMLFile(this.state.initial.configFile('components.yml'), this.descriptor); } } export { PartParser };