atomatic
Version:
An easy to use build and development tool for Atomic Design Systems, that works with rollup.js, Browserify, webpack and many more...
219 lines (188 loc) • 7.11 kB
JavaScript
const
fs = require('fs'),
path = require('path'),
glob = require('glob'),
sgUtil = require('../util');
class Collector {
constructor({conf, CollectorStore, CollectorPaths, TemplateEngine, DataLoader}) {
this.conf = conf;
this.CollectorStore = CollectorStore;
this.CollectorPaths = CollectorPaths;
this.TemplateEngine = TemplateEngine;
this.DataLoader = DataLoader;
this.copyExtend = conf.copyExtend;
this.baseDir = conf.get('baseDir');
this.viewerRootPath = conf.get('app.viewerRootPath');
this.templateExt = conf.get('templateExt');
this.htmlExt = conf.get('htmlExt');
this.globOptions = conf.get('globOptions');
this.logLevel = conf.get('logLevel', 0);
this.warnOnMissingDataFile = this.logLevel > 2;
this.globPattern = path.join('**', '**', `*.${this.templateExt}`);
this.logLevel = conf.get('logLevel', 0);
}
touchFileSystem(sourceDir) {
const {globPattern, globOptions} = this;
return glob.sync(path.join(sourceDir, globPattern), globOptions);
}
collectMatchingSections(sections, collector) {
sections
.filter((sectionConfig) => sectionConfig.collector === collector)
.map((sectionConfig) => this.collectSection.call(this, sectionConfig));
}
collectSection(sectionConfig) {
const {
baseDir, viewerRootPath, htmlExt, globPattern, warnOnMissingDataFile, CollectorStore,
setFile, unsetFile, updateFile, touchFileSystem, initDataLoader
} = this;
const {title, source, dest, collector} = sectionConfig;
const sourceDir = path.resolve(path.join(baseDir, source));
const destDir = dest || source;
const dataLoader = initDataLoader.call(this, sectionConfig);
const section = {
collector,
title,
destDir,
sourceDir,
dataLoader,
globPattern,
warnOnMissingDataFile,
watchPattern: path.join(baseDir, source, '**', '*'),
url: `/${viewerRootPath}/${destDir}`,
route: `/${viewerRootPath}/${destDir}/*.${htmlExt}`,
setFile: setFile.bind(this),
unsetFile: unsetFile.bind(this),
updateFile: updateFile.bind(this)
};
touchFileSystem
.call(this, sourceDir)
.map((filename) => {
setFile.call(this, {filename, section})
});
CollectorStore.setSection(section);
return section;
}
unsetFile(filename) {
this.CollectorStore.unsetFile(filename);
}
setFile(fileOptions) {
return this.CollectorStore.setFile(this.createFileObj(fileOptions));
}
updateFile(filename) {
this.CollectorStore.updateFile(filename);
}
createFileObj({filename, section: {sourceDir, destDir, url: sectionUrl, dataLoader, collector, warnOnMissingDataFile}}) {
const {
constructor: {name: instance}, logLevel,
getSaveHtmlFunction, getSaveLocalsFunction, getComponentName,
getCssFiles, getRenderHookFunction, getCopySourceFunction,
isExcluded, CollectorPaths, TemplateEngine
} = this;
CollectorPaths.set(filename, sourceDir, destDir);
const url = CollectorPaths.resolveUrl(filename);
const sectionPath = path.relative(sectionUrl, path.dirname(url));
const componentName = getComponentName.call(this, sourceDir, filename);
return {
filename,
collector,
destDir,
componentName,
instance,
sectionPath,
url,
warnOnMissingDataFile,
timestamp: Date.now(),
childComponents: [],
parentComponents: [],
exclude: isExcluded(filename, componentName),
extension: sgUtil.getFileExtension(filename),
cssFiles: getCssFiles.call(this),
saveHtml: getSaveHtmlFunction.call(this, filename),
saveLocals: getSaveLocalsFunction.call(this, filename),
renderHook: getRenderHookFunction.call(this),
copySource: getCopySourceFunction.call(this, filename, componentName),
get template() {
if (!this._template || this._template.timestamp !== this.timestamp) {
if (!fs.existsSync(this.filename)) {
return '';
}
this._template = {
content: sgUtil.readFileContents(this.filename),
timestamp: this.timestamp
};
}
return this._template.content;
},
get orderValue() {
return this.data.orderValue || sectionPath;
},
get data() {
if (!this._data || this._data.timestamp !== this.timestamp) {
this._data = dataLoader ? dataLoader.getData(this) : {};
this._data.title = this.title;
this._data.pageTitle = this.pageTitle || this._data.title;
this._data.instance = this.instance;
this._data.collector = this.collector;
this._data.timestamp = this.timestamp;
if (logLevel > 1) {
sgUtil.log(`Data: \u001b[1m${this.componentName}\u001b[22m generated. (${this.timestamp})`, 'info');
}
}
else if (logLevel > 1) {
sgUtil.log(`Data: \u001b[1m${this.componentName}\u001b[22m use cached. (${this.timestamp})`);
}
return this._data;
},
get render() {
return TemplateEngine.render(this);
},
get title() {
if (!this._title || !this._data || this._data.timestamp !== this.timestamp) {
const {title = sgUtil.getTitleFromFilename(this.filename)} =
sgUtil.readRelatedData(this.filename, this.warnOnMissingDataFile);
this._title = title;
}
return this._title;
}
};
}
readRelatedData(filename) {
return filename ? sgUtil.readJson5File(filename) : {};
}
initDataLoader(sectionConfig) {
return new this.DataLoader(this.copyExtend(sectionConfig), this.warnOnMissingDataFile);
}
getSaveHtmlFunction(filename) {
filename = this.CollectorPaths.resolveDestHtml(filename);
return ({html}) => sgUtil.writeFile(filename, html);
}
getSaveLocalsFunction(filename) {
filename = this.CollectorPaths.resolveDestData(filename);
return ({locals}) => sgUtil.writeJsonFile(filename, locals);
}
getRenderHookFunction() {
return ({data: {locals = {}}}, source) => ({source, locals});
}
getCopySourceFunction(_filename, _componentName) {
return (filename = _filename, componentName = _componentName) => {
const dest = this.CollectorPaths.resolveTemplateSourceDest(componentName);
sgUtil.copyFile(filename, dest, () => {});
};
}
getCssFiles() {
return [`/${this.viewerRootPath}/css/app.css`];
}
getGetSectionDataFunction() {
const {title, instance, cssFiles, sectionFiles} = this;
return {title, instance, app: {cssFiles}, locals: {files: sectionFiles}};
}
getComponentName(sourceDir, filename) {
const componentType = path.basename(sourceDir);
const componentName = path.basename(sgUtil.removeFileExtension(filename)).replace(/_/g, '');
return `${componentType}-${componentName}`;
}
isExcluded(filename, componentName) {
return path.basename(filename).substr(0, 1) === '_' || sgUtil.getFileExtension(componentName) !== '';
}
}
module.exports = Collector;