@tangelo/tangelo-configuration-toolkit
Version:
Tangelo Configuration Toolkit is a command-line toolkit which offers support for developing a Tangelo configuration.
111 lines (86 loc) • 4.64 kB
JavaScript
const fs = require('fs');
const globby = require('globby');
const path = require('path');
const relPath = (d, p) => path.relative(d, p).toFws;
const resolveBind = (d, p) => p.replace('#{cmscustompath}', 'cmscustom/').replace('{$rsrcPath}', (d.replace('stylesheets', 'resources')+'/'));
module.exports = {
create (paths, {test, watch} = {}) {
const startTime = new Date();
this.filesToTransfer = watch ? paths : globby.sync([...paths, ..._filters.fontoSources], {nodir: true}); // get list of files to transfer
// get list of potential base files, if not previously done. Globby 6.x does not expand ** to symlinks, so use **/** to include those too
this.potentialBaseFilesCache ??= globby.sync(['**/**/*.{xml,xsd,xsl,scss}', ..._filters.fontoSources]);
this.potentialBaseFiles = this.potentialBaseFilesCache
.filter(p => !this.filesToTransfer.includes(p)) // subtract files to transfer from list of potential base files
.map(path => [path]); // make array so file contents can be added later
if (!this.filesToTransfer[0]) _error('No files found that qualify for transfer!');
let filesToTransferStart;
if (test) {
filesToTransferStart = Array.from(this.filesToTransfer);
_info('\nFiles selected:');
this.filesToTransfer.forEach(f => _write(f));
}
this.filesToTransfer.forEach((ftt, i, a) => {
a.push(...this.findBaseFiles(ftt)); // for each in list of files to transfer, find base files and add to list
});
if (test) {
_info('\nBase files added for files above:');
const baseFiles = this.filesToTransfer.filter(f => !filesToTransferStart.includes(f));
baseFiles.forEach(f => _write(f));
if (!baseFiles[0]) _write('None.');
_perf(startTime);
}
return this.filesToTransfer;
},
findBaseFiles (ftt) {
const baseFiles = [];
const fttObj = path.parse(ftt);
const fttExt = {};
fttExt[fttObj.ext.substr(1)] = true;
if (this.potentialBaseFiles && (fttExt.xsl || fttExt.scss || fttObj.dir.includes('xopus'))) {
const lookbehind =
fttExt.xml ? 'x:import src' :
fttExt.xsd ? '(xsd|schemaLocation)' :
fttExt.xsl ? '(xsl|href)' :
fttExt.js ? 'x:javascript src' :
''
;
const findIncExp = new RegExp(
fttExt.scss ? `(?<=@import ['"])[^'"]*?${fttObj.name.replace(/^_/, '')}` // for sass include, leading _ and extension are optional
: `(?<=${lookbehind}=")[^"]*?${fttObj.base}`
, 'g'
);
this.potentialBaseFiles.forEach((f) => {
const pbfExt = {};
pbfExt[path.extname(f[0]).substr(1)] = true;
const canInclude = (pbfExt.xml && !fttExt.scss) || (pbfExt.xsd && fttExt.xsd) || (pbfExt.xsl && (fttExt.xsl || fttExt.js)) || (pbfExt.scss && fttExt.scss);
if (canInclude) {
if (!f[1]) f.push(fs.readFileSync(f[0]).toString()); // only read file when needed, and save for next time
const includePaths = f[1].match(findIncExp); // find includes containing the correct filename, but not for sure the correct path
if (includePaths) {
// get relative path for the file (from filesToTransfer) from the potential base file (from potentialBaseFiles)
// then check if an include-path in the potential base file matches, if so it is in fact a base file
const pbfDir = path.dirname(f[0]);
const fttRelDir = path.dirname(relPath(pbfDir, ftt));
includePaths.forEach(ip => {
const ipRel = ip.includes('#{cmscustompath}') || ip.includes('{$rsrcPath}') ? relPath(pbfDir, resolveBind(pbfDir, ip)) : ip;
if (fttRelDir == path.dirname(ipRel)) baseFiles.push(f[0]);
});
}
}
});
}
if (baseFiles) {
this.potentialBaseFiles = this.potentialBaseFiles.filter(f => !baseFiles.includes(f[0])); // once added, do not search again
baseFiles.forEach((p, i, a) => {
a.push(...this.findBaseFiles(p)); // recursively search for base files having their own base files
});
}
return baseFiles;
},
addToCache (filepath) {
if (this.potentialBaseFilesCache) this.potentialBaseFilesCache.push(filepath.toFws);
},
removeFromCache (filepath) {
if (this.potentialBaseFilesCache) this.potentialBaseFilesCache = this.potentialBaseFilesCache.filter(fp => fp != filepath.toFws);
}
};