UNPKG

jffl4express

Version:

Fluid Fragmented HTML Loader for Express by Julian Frank

150 lines (128 loc) 6.7 kB
'use strict' const fs = require('fs') const inspect = require('util').inspect const path = require('path') /*Generic function to read file within express engine declaration...currently planned to be used only for HTML Add this into express using this statement => 'use strict' const app=require('express')() const loadJFFL=require('jffl4express').loadjffl app.set('views', '<./jfflview folder>') app.set('view engine', 'jffl') app.engine('jffl', loadJFFL) In your app render using the following command inside the middleware res.render(<your jffl>,options,callback with parameters (error,rendered html content)) This sample gets called when any '.jffl' file is rendered Parameters are called directly by express, so no coding needed*/ exports.loadjffl = (filePath, options, callback) => {//std pattern used by / provided by express //const params = "{ FilePath: " + filePath + ", Options: " + inspect(options) + ", LocalDir " + path.dirname(filePath) + " }"//Logging purpose only //console.info("Going to use Parameters as below:\n" + params) const localPath = path.dirname(filePath) let parsedOptions = {},//Holder for Parsed Options returnHTML = "",//Holder for final HTML document being constucted, config = {},//Holder for configuration loaded from jffl file runParams = ""//holder to Runtime Paramters provided as part of Options to be injected //Obtain new variables to be injected Object.keys(options).map((val) => { switch (val) { case 'settings': break case '_locals': break case 'cache': break default: parsedOptions[val] = options[val] } }) //Inject Parsed Options into HTML Document Object.keys(parsedOptions).map((val) => { switch (typeof parsedOptions[val]) { case 'string': runParams += "<script>var " + val + "='" + parsedOptions[val] + "'</Script>"; break case 'number': runParams += "<script>var " + val + "=" + parsedOptions[val] + "</Script>"; break default: runParams += "<script>var " + val + "='" + typeof parsedOptions[val] + "'</Script>" } }) //Read the jffl File provided fs.readFile(filePath, (err, content) => { if (err) { return callback(new Error(err.message)) } else { config = JSON.parse(content.toString()) //Helper Function that takes a Array of files, reads them and returns the content as a single String //When only a single file needs to be loaded, push it into a Array when feeding const loadFiles = (filesArray) => { //console.info('Going to read Array ->' + filesArray) return new Promise((resolve, reject) => { let readText = "" if (filesArray) { Object.keys(filesArray).map((val, ind) => { let fullPath = path.format({ dir: localPath, base: filesArray[val] }) //console.info('Going to read File ->' + fullPath) fs.readFile(fullPath, (err, content) => { if (err) { console.error('Error Reading File ' + filesArray[val] + ' Error: ' + err) reject(err) } else { readText += content.toString() if (ind === (filesArray.length - 1)) { resolve(readText) } } }) }) } else { resolve(readText) } }) } let loadSTD = new Promise((resolve, reject) => { if (config.html.std) { loadFiles([config.html.std]).then((fileText) => { resolve(fileText) }) } else { reject('<!doctype html>') } }) let loadHEAD = new Promise((resolve, reject) => { let headText = '<HEAD>' if (config.html.title) { headText += '<TITLE>' + config.html.title + '</TITLE>' } if (config.html.head) { loadFiles(config.html.head) .then((filesText) => { loadFiles(config.js) .then((jsText) => { if (runParams) { headText = headText + runParams + jsText } else { headText += jsText } loadFiles(config.css) .then((cssText) => { headText = headText + '<style>' + cssText + '</style>' + filesText + '</HEAD>' resolve(headText) }, (err) => { reject(headText += err) }) }, (err) => { reject(headText += err) }) }, (err) => { reject(headText += '</HEAD>') }) } else { reject(headText += '</HEAD>') } }) let loadBODY = new Promise((resolve, reject) => { let bodyText = '<BODY>' if (config.html.body) { loadFiles(config.html.body).then((filesText) => { resolve(bodyText + filesText + '</BODY>') }, (err) => { reject(bodyText += '</BODY>') }) } else { reject(bodyText += '</BODY>') } }) Promise.all([loadSTD, loadHEAD, loadBODY]).then((texts) => { let rendered = texts[0] + texts[1] + texts[2] //console.log('Rendered:', typeof rendered, rendered.toString()) return callback(null, rendered) }, (err) => { console.error('Error: ' + err) return callback(err, rendered += err) }) } }) }