'use strict'; const exphbs = require('express-handlebars'); const fs = require('fs'); const PageList = require('./PageList'); const resolve = require('./app-resolve'); const asset = require('./asset-finder'); const constants = require('./constants'); // in Layout we have a list of partials dir which is updated (the "dir" attr is updated) when we go to a new page class Layout { constructor(base, dataPath) { this._base = base; this._dataPath = dataPath; this.layoutsDir = `${this._base}/layouts`; this.pagesDir = `${this._base}/pages`; this.defaultLayout = constants.DEFAULT_LAYOUT; this.partialsDir = []; this.partialsDir_KeyMap = {}; this._setDefaultPartialsDir(); } getBase() { return this._base; } getDataDir() { return `${this._dataPath}/layouts`; } updatePagePartialsDirFor(page) { this._updatePartialsDir('page', `${this.pagesDir}/${page}`); this._updatePartialsDir('include', `${this.pagesDir}/${page}`); this._updatePartialsDir('layout', this.layoutsDir); } getPagePartialsDir(page) { return `${this.pagesDir}/partials/${page}`; } _setDefaultPartialsDir() { this._updatePartialsDir('layout', `${this.layoutsDir}/partials`); this._updatePartialsDir('page', `${this.pagesDir}/partials`); this._updatePartialsDir('include', `${this.pagesDir}/partials`); } _updatePartialsDir(namespace, dir) { if( !(this.partialsDir_KeyMap[namespace] instanceof Object) ) { this.partialsDir_KeyMap[namespace] = {namespace, dir}; this.partialsDir.push(this.partialsDir_KeyMap[namespace]); } else this.partialsDir_KeyMap[namespace].dir = dir; } } class Page { constructor(id, base, dataPath) { this.id = id; this._base = base; this._dataPath = dataPath; this._layout = null; this._pageList = new PageList(); // there may be a different `pages.json` file for this page ... for example `horizontal` and `dashboard-2` var dataFileFolder = resolve.HomeDir() + '/views/data/layouts/'; var dataFile = dataFileFolder + 'sidebar-' + id + '.json'; if (!fs.existsSync(dataFile)) dataFile = dataFileFolder + 'sidebar.json'; this._pageList.setDataFile(dataFile); this._pageList.initSidebarTree(); this._pageList.updateSelectedPage(id); //var sidebar = this.getSidebar(); } getTemplate() { return `${this._base}/pages/${this.id}/#index`; } getPartialsDir() { return `${this._base}/pages/${this.id}`; } getDataDir() { return `${this._dataPath}/pages/${this.id}`; } getSidebar() { return this._pageList.getSidebarTree(); } getBreadcrumbs() { return this._pageList.getBreadcrumbs(); } getTitle() { return this._pageList.getTitle(this.id); } getDescription() { return this._pageList.getDescription(this.id); } getLayoutInfo() { return this._pageList.getLayoutInfo(this.id); } setLayout(layout) { this._layout = layout; } getLayout() { return this._layout; } } class Display { constructor(base, data) { this.extname = '.hbs'; this.app = null; this._base = base; this._data = data; this._layout = new Layout(base, data); } setLayout(layout) { this._layout = layout; } getLayout() { return this._layout; } setApp(app) { this.app = app; } updatePagePartialsDirFor(page) { if( !this._layout || !page ) return; this._layout.updatePagePartialsDirFor(page.id); } connect(app) { this.setApp(app); if( !this.app || !this._layout ) return this; this.app.engine('.hbs', exphbs({ extname: this.extname, layoutsDir: this._layout.layoutsDir, defaultLayout: this._layout.defaultLayout, partialsDir: this._layout.partialsDir }) ); this.app.set('views', '.');//in expressjs default views location is "path.resolve('views')" this.app.set('view engine', this.extname); return this; } } class HbsHelpers { static GetArgs(options) { var attrs = []; for (var prop in options.hash) { attrs[prop] = options.hash[prop]; } return attrs; } static Include() { //var opts = GetArgs() /** if(process.env.BUILD == 'dist') { opts.dist; } else */ //var files = GetFiles(opts.files, type,); } //we keep a list of required assets //so when building release package's zip file, we include those assets from node_modules folder static keepRequiredAssets(keep=true) { HbsHelpers._keepRequiredAssets = keep; } static getRequiredAssets() { return HbsHelpers._requireAssetsList; } static IncludeJS(options) { var attrs = this.GetArgs(options); var build = process.env.BUILD; var min = process.env.MINIFIED == 'true' || process.env.MIN == 'true' || false; var files = attrs['files']; var combine = attrs['combine'] == 'true' ? true : false; var resultFiles = build === 'dist' ? asset.GetCdnJsFiles(files, min, combine) : asset.GetJsFiles(files); let res = ''; for(let file of resultFiles) { res += `\n`; // add to list of required assets if (HbsHelpers._keepRequiredAssets) HbsHelpers._requireAssetsList.push(file) } return res; } static IncludeCSS(options) { var attrs = this.GetArgs(options); var href = attrs['href']; if (href) { return `\n`; } var build = process.env.BUILD; var min = process.env.MINIFIED == 'true' || process.env.MIN == 'true' || false; var files = attrs['files']; var combine = attrs['combine'] == 'true' ? true : false; var resultFiles = build === 'dist' ? asset.GetCdnCssFiles(files, min, combine) : asset.GetCssFiles(files); var res = ''; for(let file of resultFiles) { res += `\n`; // add to list of required assets if (HbsHelpers._keepRequiredAssets) HbsHelpers._requireAssetsList.push(file) } return res; } static InlineJS(page) { if( !page || !(page instanceof Page) ) return ''; var src = page.getPartialsDir() + '/@page-script.js'; if ( fs.existsSync( src ) ) { var build = process.env.BUILD; if(build == 'dist') return '';//inline (inside HTML) return ``; } return ''; } static InlineCSS(page) { if( !page || !(page instanceof Page) ) return ''; var src = page.getPartialsDir() + '/@page-style.css'; if ( fs.existsSync( src ) ) { var build = process.env.BUILD; if(build == 'dist') return ''; return ``; } return ''; } static GetData(page, name) { if( !page || !(page instanceof Page) ) return {}; let dataFile = ''; let match = name.match(/layouts?\//); if( match ) { name = name.replace(match[0], ''); let layout = page.getLayout(); if( !layout || !(layout instanceof Layout) ) return {}; dataFile = layout.getDataDir() + '/' + name; } else { dataFile = page.getDataDir() + '/' + name; } return HbsHelpers._readData(dataFile); } /** static GetLayoutData(page, name) { if( !page || !(page instanceof Page) ) return {}; var layout = page.getLayout(); if( !layout || !(layout instanceof Layout) ) return {}; var dataFile = layout.getDataDir() + '/' + name; return HbsHelpers._readData(dataFile); } */ static _readData(dataFile) { var data = []; try { if( fs.existsSync(dataFile + '.json') ) { data = JSON.parse(fs.readFileSync(dataFile + '.json' , 'utf-8')); } else if( fs.existsSync(dataFile + '.csv') ) { const csvjson = require('csvjson'); data = fs.readFileSync(dataFile + '.csv' , 'utf-8'); var options = { delimiter : ',', quote : '"' }; data = csvjson.toObject(data, options); for(let item of data) if('status' in item) { let status = item['status'].trim(); item[status] = true; } } } catch(e) {} return data; } static Helpers(page) { var helpers = { 'get': function (name) {//this helper loads a specific piece of data for a page return HbsHelpers.GetData(page, name); }, '$$': function (name) {//this helper loads a specific piece of data for a page return HbsHelpers.GetData(page, name); }, 'include-js': function (options) { return HbsHelpers.IncludeJS(options); }, 'include-css': function (options) { return HbsHelpers.IncludeCSS(options); }, 'inline-js': function() { return HbsHelpers.InlineJS(page); }, 'inline-css': function() { return HbsHelpers.InlineCSS(page); }, 'random': function(min, max) { return min + Math.floor(Math.random() * (max - min + 1)); }, 'odd': function(conditional) { return conditional % 2; }, 'even': function(conditional) { return !(conditional % 2); }, 'eq': function (a, b, options) { if (a == b) { return options.fn(this); } return options.inverse(this); } } return helpers; } } HbsHelpers._keepRequiredAssets = false; HbsHelpers._requireAssetsList = []; ////////////// module.exports = { Page, Display, HbsHelpers }