UNPKG

@tangelo/tangelo-configuration-toolkit

Version:

Tangelo Configuration Toolkit is a command-line toolkit which offers support for developing a Tangelo configuration.

106 lines (87 loc) 3.63 kB
const fs = require('fs-extra'); const globby = require('globby'); const path = require('path'); const sass = require('sass'); const SaxonJS = require('saxon-js'); const url = require('url'); module.exports = class TclConfig { static #SEF_FILE_PATH = 'tcl/configToJson.sef.json'; static #JSON_TO_SCSS_FILE_PATH = 'tcl/configJsonToScss'; static #TCL_FILE_NAME = 'project.tcl'; static #TCL_JSON_FILE_NAME = 'tcl-config.json'; static #TCL_CSS_FILE_NAME = 'tcl-styles.css'; static #FONTO_HTML_FILE_NAME = 'index.html'; static #sefFile; static #jsonToScssFile; static #transformTclConfigToJson(tclFilePathRel) { this.#sefFile ??= _modulesTdi.require(this.#SEF_FILE_PATH, {message: false}); const messages = [` Warnings from transformation of ${tclFilePathRel}`]; const transformation = SaxonJS.transform({ stylesheetText: JSON.stringify(this.#sefFile), sourceFileName: tclFilePathRel, destination: 'raw', deliverMessage(messageNode) { messages.push(messageNode.textContent); } }); if (messages[1]) _warn(messages.join('\n ')); return transformation.principalResult ?? _error(`No result from transformation of ${tclFilePathRel}`); } static #transformJsonToCss(tclFilePathRel, json, moduleName) { this.#jsonToScssFile ??= _modulesTdi.require(this.#JSON_TO_SCSS_FILE_PATH, {message: false}); const scss = this.#jsonToScssFile(json.project, moduleName); const fileUrl = url.pathToFileURL(tclFilePathRel); return sass.compileString(scss, {url: fileUrl, style: 'compressed'}).css; } static #addCssImportToHtml(dir) { const filepath = path.join(dir, this.#FONTO_HTML_FILE_NAME); if (fs.existsSync(filepath)) { const html = fs.readFileSync(filepath).toString(); if (!RegExp(`<link[^>]*${this.#TCL_CSS_FILE_NAME}[^>]*>`).test(html)) { const newHtml = html.replace(/((\s+<link.*")[^"]+\.css(.*))/, `$1$2${this.#TCL_CSS_FILE_NAME}$3`); fs.outputFileSync(filepath, newHtml); } } } static findProjects() { return globby.sync('config/cmscustom/!(tdi)/!(fonts)').map(p => ({path: p, tcl: fs.existsSync(path.join(p, this.#TCL_FILE_NAME))})); } #outputFn; #doModifyFontoHtml; #tclFilePathRel; #tclFileExists; #resultJson; #resultCss = {}; constructor(tclFileRelDir, addToStreamFn) { this.#tclFilePathRel = path.join(tclFileRelDir, TclConfig.#TCL_FILE_NAME); this.#tclFileExists = fs.existsSync(this.#tclFilePathRel); this.#outputFn = addToStreamFn ?? fs.outputFileSync; this.#doModifyFontoHtml = !addToStreamFn; } #getJson() { return this.#resultJson ??= TclConfig.#transformTclConfigToJson(this.#tclFilePathRel); } #getCss(moduleName) { return this.#resultCss[moduleName] ??= TclConfig.#transformJsonToCss(this.#tclFilePathRel, this.#getJson(), moduleName); } outputJson(dir) { if (this.#tclFileExists) { const filepath = path.join(dir, TclConfig.#TCL_JSON_FILE_NAME); this.#outputFn(filepath, JSON.stringify(this.#getJson())); } return this; } outputCss(dir) { if (this.#tclFileExists) { const filepath = path.join(dir, TclConfig.#TCL_CSS_FILE_NAME); const moduleName = dir.includes('xbrl') ? 'XBRL' : 'FONTO'; this.#outputFn(filepath, this.#getCss(moduleName)); this.modifyFontoHtml(dir); } return this; } modifyFontoHtml(dir) { if (this.#tclFileExists && this.#doModifyFontoHtml) TclConfig.#addCssImportToHtml(dir); return this; } };