Skip to content

Commit

Permalink
feat: update cli to use template engine based on the value stored in
Browse files Browse the repository at this point in the history
  • Loading branch information
jairo-bc committed Sep 1, 2020
1 parent b8de531 commit f9ea0a9
Show file tree
Hide file tree
Showing 3 changed files with 172 additions and 77 deletions.
1 change: 1 addition & 0 deletions server/plugins/renderer/renderer.module.js
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,7 @@ internals.getTemplatePath = function (path, data) {
*/
internals.getPencilResponse = function (data, request, response, configuration) {
data.context.theme_settings = configuration.settings;
data.context.template_engine = configuration.template_engine;

// change cdn settings to serve local assets
data.context.settings.cdn_url = '';
Expand Down
170 changes: 93 additions & 77 deletions server/plugins/renderer/responses/pencil-response.js
Original file line number Diff line number Diff line change
@@ -1,48 +1,36 @@
const _ = require('lodash');
const Paper = require('@bigcommerce/stencil-paper');
const internals = {};

module.exports = function (data, assembler) {
this.respond = function (request, h) {
const paper = new Paper(data.context.settings, data.context.theme_settings, assembler, "handlebars-v3");

// Set the environment to dev
data.context.in_development = true;
data.context.in_production = false;

paper.addDecorator(internals.makeDecorator(request, data.context));

// Plugins have the opportunity to add/modify the response by using decorators
_.each(request.app.decorators, function (decorator) {
paper.addDecorator(decorator);
});

const templatePath = internals.getTemplatePath(request, data);

return paper.loadTheme(templatePath, data.acceptLanguage)
.then(() => {
if (request.query.debug === 'context') {
return data.context;
}
})
.catch(err => console.error(err.message.red))
.then(() => paper.renderTheme(templatePath, data))
.catch(err => console.error(err.message.red))
.then(output => {
const response = h.response(output).code(data.statusCode);

if (data.headers['set-cookie']) {
response.header('set-cookie', data.headers['set-cookie']);
}

return response;
})
.catch(err => console.error(err.message.red));
/**
* Ecapes html entities
*
* @param {String} html
*/
const escapeHtml = html => {
const charsToReplace = {
'&': '&',
'<': '&lt;',
'>': '&gt;',
'"': '&#34;',
};

return html.replace(/[&<>"]/g, tag => charsToReplace[tag] || tag);
};

/**
* Scape special characters for regular expression
*
* @param {String} string
*/
const escapeRegex = string => string.replace(/[-\\^$*+?.()|[\]{}]/g, "\\$&");

internals.getTemplatePath = function (request, data) {
/**
* Returns template path
*
* @param {String} request
* @param {Object} data
*/
const getTemplatePath = (request, data) => {
let path = data.template_file;

if (request.headers['stencil-options']) {
Expand All @@ -65,56 +53,84 @@ internals.getTemplatePath = function (request, data) {
return path;
};

/**
* Returns boolean if this handlebars version is supported
*
* @param {String} version
*/
const isSupportedHandlebarsVersion = version => ['handlebars-v3', 'handlebars-v4'].includes(version);


/**
* Output post-processing
*
* @param request
* @param context
* @param {Object} request
* @param {Object} context
* @param {String} content
*/
internals.makeDecorator = function (request, context) {
return function(content) {
let regex,
debugBar;
const makeDecorator = (request, context) => content => {
let regex,
debugBar;

if (context.settings) {
regex = new RegExp(internals.escapeRegex(context.settings.base_url), 'g');
content = content.replace(regex, '');
if (context.settings) {
regex = new RegExp(escapeRegex(context.settings.base_url), 'g');
content = content.replace(regex, '');

regex = new RegExp(internals.escapeRegex(context.settings.secure_base_url), 'g');
content = content.replace(regex, '');
}
regex = new RegExp(escapeRegex(context.settings.secure_base_url), 'g');
content = content.replace(regex, '');
}

if (request.query.debug === 'bar') {
debugBar = '<pre style="background-color:#EEE; word-wrap:break-word;">';
debugBar += internals.escapeHtml(JSON.stringify(context, null, 2)) + '</pre>';
regex = new RegExp('</body>');
content = content.replace(regex, debugBar + '\n</body>');
}
if (request.query.debug === 'bar') {
debugBar = '<pre style="background-color:#EEE; word-wrap:break-word;">';
debugBar += escapeHtml(JSON.stringify(context, null, 2)) + '</pre>';
regex = new RegExp('</body>');
content = content.replace(regex, debugBar + '\n</body>');
}

return content;
};
return content;
};

/**
* Scape html entities
*/
internals.escapeHtml = function (html) {
const charsToReplace = {
'&': '&amp;',
'<': '&lt;',
'>': '&gt;',
'"': '&#34;',
};

return html.replace(/[&<>"]/g, tag => charsToReplace[tag] || tag);
};
module.exports = function (data, assembler) {
this.respond = function (request, h) {
const templateEngine = data.context.template_engine || "handlebars-v3";

/**
* Scape special characters for regular expression
*
* @param string
*/
internals.escapeRegex = function (string) {
return string.replace(/[-\\^$*+?.()|[\]{}]/g, "\\$&");
if (!isSupportedHandlebarsVersion(templateEngine)) {
throw new Error('Provided Handlebars version is not supported! Please use:handlebars-v3, handlebars-v4');
}

const paper = new Paper(data.context.settings, data.context.theme_settings, assembler, templateEngine);
// Set the environment to dev
data.context.in_development = true;
data.context.in_production = false;

paper.addDecorator(makeDecorator(request, data.context));

// Plugins have the opportunity to add/modify the response by using decorators
_.each(request.app.decorators, function (decorator) {
paper.addDecorator(decorator);
});

const templatePath = getTemplatePath(request, data);

return paper.loadTheme(templatePath, data.acceptLanguage)
.then(() => {
if (request.query.debug === 'context') {
return data.context;
}
})
.catch(err => console.error(err.message.red))
.then(() => paper.renderTheme(templatePath, data))
.catch(err => console.error(err.message.red))
.then(output => {
const response = h.response(output).code(data.statusCode);

if (data.headers['set-cookie']) {
response.header('set-cookie', data.headers['set-cookie']);
}

return response;
})
.catch(err => console.error(err.message.red));
};
};
78 changes: 78 additions & 0 deletions server/plugins/renderer/responses/pencil-response.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
const Code = require('code');
const Lab = require('@hapi/lab');
const sinon = require('sinon');

const PencilResponse = require('./pencil-response');

const lab = exports.lab = Lab.script();
const expect = Code.expect;
const it = lab.it;


lab.describe('PencilResponse', () => {
const assembler = {
getTemplates: path => new Promise(resolve => resolve({ path })),
getTranslations: () => new Promise(resolve => resolve([])),
};

let data;
let request;
let response;
let h;


lab.beforeEach(() => {
data = {
context: {
settings: {},
theme_settings: {},
template_engine: 'handlebars-v3',
},
headers: {},
template_file: null,
remote: true,
remote_data: '',
};

request = {
url: {},
path: '/',
app: {themeConfig: {variationIndex: 1}},
headers: {},
query: {},
};

response = {
code: () => response,
};

h = {
response: sinon.stub().returns(response),
};

});

it('should return error, when the wrong template_engine is sent', () => {
data.context.template_engine = "handlebars";
const pencilResponse = new PencilResponse(data, assembler);
expect(
() => pencilResponse.respond(request, h),
).to.throw(Error, 'Provided Handlebars version is not supported! Please use:handlebars-v3, handlebars-v4');
});

it('should render successfully with supported template_engine', async () => {
const pencilResponse = new PencilResponse(data, assembler);
await pencilResponse.respond(request, h);
console.log(h.response.called);
expect(h.response.called).to.be.true();
});

it('should default to handlebars_v3 when the template_engine doesn\'t exist', async () => {
delete data.context.template_engine;
console.log(data.context);
const pencilResponse = new PencilResponse(data, assembler);
await pencilResponse.respond(request, h);
console.log(h.response.called);
expect(h.response.called).to.be.true();
});
});

0 comments on commit f9ea0a9

Please sign in to comment.