Skip to content
This repository has been archived by the owner on Dec 5, 2022. It is now read-only.

Feature: Allow set specific template #171

Merged
91 changes: 73 additions & 18 deletions lib/fetch-template.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,45 +26,100 @@ class TemplateError extends Error {
*
* @param {string} path
*/
const readFile = (path) =>
const readFile = (path) =>
new Promise((resolve, reject) => {
fs.readFile(path, 'utf-8', (err, data) => {
if (err) {
reject(new TemplateError(err));
return;
}
}
resolve(data);
});
});

/**
* Returns the template path validating a exactly file or a directory
*
* @param {String} templatesPath - TemplatesPath config
* @param {String} pathname - Path name based on Request Object
*
* @return {Promise} Template Info object on success or TemplateError on fail
*/
const getTemplatePath = (templatesPath, pathname) =>
new Promise((resolve, reject) => {
fs.lstat(
templatesPath,
(err, data) => {
if (err) {
return reject(new TemplateError(err));
}

let templateStat = {
isFile: data.isFile()
};

if (templateStat.isFile) {
templateStat.path = templatesPath;
} else {
templateStat.path = factoryFilePath(templatesPath, pathname);
}

return resolve(templateStat);
}
);
});

/**
* Returns pathname by request
*
* @param {Object} request - Request Object
*
* @return {String} pathname
*/
const getPathName = (request) => url.parse(request.url, true).pathname;

/**
* Factory the complete file path
*
* @param {String} templatesPath - Templates dir path
* @param {String} filename - file name without extension
*
* @return {String} complete file path
*/
const factoryFilePath = (templatesPath, filename) =>
`${path.join(templatesPath, filename)}.html`;

/**
* Fetches the template from File System
*
* @param {string} templatesPath - The path where the templates are stored
* @param {function=} baseTemplateFn - Function that returns the Base template name for a given page
*/
module.exports = (templatesPath, baseTemplateFn) =>
module.exports = (templatesPath, baseTemplateFn) =>
(request, parseTemplate) => {
const pathname = url.parse(request.url, true).pathname;
const templatePath = path.join(templatesPath, pathname) + '.html';
const pathname = getPathName(request);

return readFile(templatePath)
.then((baseTemplate) => {
if (typeof baseTemplateFn !== 'function') {
return parseTemplate(baseTemplate);
}
return getTemplatePath(templatesPath, pathname)
.then((templateStat) => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just a small change to keep the indentation depth minimal

.then({path} => readFile(path))
.then(baseTemplate => ....)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vigneshshanmugam I understand your point of view, however i use the templateStat object to break the template parse logic on resolve the readFile promise. In your logic this not working apparently:

.then(({path}) => readFile(path))
.then(baseTemplate => {
    // templateStat is not defined
})

We can pass the complete object to readFile, add the baseTemplate to object and resolve the promise with the object. What do you think about it?

Copy link
Collaborator

@vigneshshanmugam vigneshshanmugam Aug 25, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh thanks for pointing out. No this is fine then, We can do the cleanup as part of using util.promisify library changes.
lets get this merged :)

return readFile(templateStat.path)
.then((baseTemplate) => {
if (templateStat.isFile || typeof baseTemplateFn !== 'function') {
return parseTemplate(baseTemplate);
}

const templateName = baseTemplateFn(pathname);
if (!templateName) {
return parseTemplate(baseTemplate);
}
const templateName = baseTemplateFn(pathname);
if (!templateName) {
return parseTemplate(baseTemplate);
}

const pageTemplate = baseTemplate;
const baseTemplatePath = path.join(templatesPath, templateName) + '.html';
return readFile(baseTemplatePath)
.then((baseTemplate) => parseTemplate(baseTemplate, pageTemplate));
const pageTemplate = baseTemplate;
const baseTemplatePath = factoryFilePath(templatesPath, templateName);
return readFile(baseTemplatePath)
.then((baseTemplate) => parseTemplate(baseTemplate, pageTemplate));
});
});
};


module.exports.TEMPLATE_ERROR = TEMPLATE_ERROR;
module.exports.TEMPLATE_NOT_FOUND = TEMPLATE_NOT_FOUND;