Comparing version 0.1.0 to 0.1.1
@@ -17,2 +17,6 @@ "use strict"; | ||
var _lodash3 = require("lodash.merge"); | ||
var _lodash4 = _interopRequireDefault(_lodash3); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
@@ -83,5 +87,6 @@ | ||
exports.default = (options = {}) => { | ||
options = Object.assign({ | ||
options = (0, _lodash4.default)({ | ||
caching: false, | ||
layoutFile: null | ||
layoutFile: null, | ||
autoEscapedFunctions: [] | ||
}, options); | ||
@@ -88,0 +93,0 @@ |
@@ -14,2 +14,6 @@ "use strict"; | ||
const functionProxy = wrappedFn => function () { | ||
return escapeWrapper(wrappedFn.apply(this, arguments)); | ||
}; | ||
const proxyHandler = { | ||
@@ -26,2 +30,9 @@ get: function (target, prop, receiver) { | ||
case "function": | ||
if (Array.prototype[prop] && Array.prototype[prop] === value) { | ||
return value; | ||
} else { | ||
return functionProxy(value); | ||
} | ||
default: | ||
@@ -28,0 +39,0 @@ return value; |
{ | ||
"name": "backticks", | ||
"version": "0.1.0", | ||
"version": "0.1.1", | ||
"description": "Express engine creator for the basic use of ES6 template literals (backticks) for templating", | ||
@@ -19,2 +19,3 @@ "license": "MIT", | ||
"lodash.escape": "^4.0.1", | ||
"lodash.merge": "^4.6.0", | ||
"lodash.unescape": "^4.0.1" | ||
@@ -36,7 +37,7 @@ }, | ||
], | ||
"homepage": "https://github.com/cassiozen/es6template-express-engine", | ||
"bugs": "https://github.com/cassiozen/es6template-express-engine", | ||
"homepage": "https://github.com/cassiozen/backticks", | ||
"bugs": "https://github.com/cassiozen/backticks", | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/cassiozen/es6template-express-engine" | ||
"url": "https://github.com/cassiozen/backticks" | ||
}, | ||
@@ -43,0 +44,0 @@ "contributors": [ |
@@ -1,3 +0,3 @@ | ||
# template-literal-express-engine | ||
# Backticks | ||
A basic Express view engine for using ES2015 Template Literals for single-pass server-side templating. | ||
An Express view engine for using ES2015 Template Literals for single-pass server-side templating. |
@@ -5,2 +5,3 @@ import { readFile } from "fs"; | ||
import unescape from "lodash.unescape"; | ||
import merge from "lodash.merge"; | ||
@@ -70,6 +71,7 @@ const read = promisify(readFile); | ||
export default (options = {}) => { | ||
options = Object.assign( | ||
options = merge( | ||
{ | ||
caching: false, | ||
layoutFile: null | ||
layoutFile: null, | ||
autoEscapedFunctions: [], | ||
}, | ||
@@ -76,0 +78,0 @@ options |
import escape from 'lodash.escape'; | ||
const functionProxy = wrappedFn => function() { | ||
return escapeWrapper(wrappedFn.apply(this, arguments)); | ||
} | ||
const proxyHandler = { | ||
@@ -14,2 +18,9 @@ get: function(target, prop, receiver) { | ||
case "function": | ||
if(Array.prototype[prop] && Array.prototype[prop] === value) { | ||
return value; | ||
} else { | ||
return functionProxy(value); | ||
} | ||
default: | ||
@@ -16,0 +27,0 @@ return value; |
@@ -12,2 +12,4 @@ const { expect } = require("chai"); | ||
"./list.html": "<ul>${names.map(n => `<li>${n}</li>`).join('')}</ul>", | ||
"./object.html": "<h1>${user.name}</h1>", | ||
"./function.html": "<h1>${user.getUser()}</h1>", | ||
"./dump.html": "<h1>${unescaped(name)}</h1>", | ||
@@ -24,5 +26,11 @@ "./page.html": "<h2>Hi</h2>" | ||
fs.exists = () => { console.log("called exists") } | ||
fs.stat = () => { console.log("called stat") } | ||
fs.access = () => { console.log("called access") } | ||
fs.exists = () => { | ||
console.log("called exists"); | ||
}; | ||
fs.stat = () => { | ||
console.log("called stat"); | ||
}; | ||
fs.access = () => { | ||
console.log("called access"); | ||
}; | ||
}); | ||
@@ -35,3 +43,3 @@ | ||
describe("without caching", () => { | ||
describe("Layout", () => { | ||
it("renders with layout and interpolated data", () => { | ||
@@ -81,3 +89,47 @@ const engine = createEngine({ | ||
it("escapes locals to prevent XSS", () => { | ||
it("uses updated layout files when caching is not enabled", () => { | ||
const engine = createEngine({ | ||
layoutFile: "./layout.html" | ||
}); | ||
return new Promise((resolve, reject) => { | ||
engine("./index.html", { name: "Joe" }, (err, body) => { | ||
if (err) return reject(err); | ||
expect(body).to.be.equal("<div id='app'><h1>Joe</h1></div>"); | ||
files["./layout.html"] = "<span>${yield}</span>"; | ||
engine("./index.html", { name: "Joe" }, (err, body) => { | ||
if (err) return reject(err); | ||
expect(body).to.be.equal("<span><h1>Joe</h1></span>"); | ||
resolve(); | ||
}); | ||
}); | ||
}); | ||
}); | ||
}); | ||
describe("Caching", () => { | ||
it("should not produce new output when caching is enabled", () => { | ||
const engine = createEngine({ | ||
layoutFile: "./layout.html", | ||
caching: true | ||
}); | ||
return new Promise((resolve, reject) => { | ||
engine("./index.html", { name: "Joe" }, (err, body) => { | ||
if (err) return reject(err); | ||
expect(body).to.be.equal("<div id='app'><h1>Joe</h1></div>"); | ||
files["./layout.html"] = "<span>${yield}</span>"; | ||
files["./index.html"] = "<h4>{name}</h4>"; | ||
engine("./index.html", { name: "Joe" }, (err, body) => { | ||
if (err) return reject(err); | ||
expect(body).to.be.equal("<div id='app'><h1>Joe</h1></div>"); | ||
resolve(); | ||
}); | ||
}); | ||
}); | ||
}); | ||
}); | ||
describe("XSS", () => { | ||
it("escapes locals", () => { | ||
const engine = createEngine(); | ||
@@ -114,3 +166,3 @@ | ||
it("escapes locals to prevent XSS even in nested objects", () => { | ||
it("escapes locals inside nested objects", () => { | ||
const engine = createEngine(); | ||
@@ -122,3 +174,3 @@ | ||
"./list.html", | ||
{ names: ['Jon<script>alert("ES6 Renderer")</script>', 'Joe'] }, | ||
{ names: ['Jon<script>alert("ES6 Renderer")</script>', "Joe"] }, | ||
(err, body) => { | ||
@@ -136,7 +188,9 @@ if (err) return reject(err); | ||
engine( | ||
"./dump.html", | ||
{ name: 'Jon<script>alert("ES6 Renderer")</script>' }, | ||
"./object.html", | ||
{ user: { name: 'Jon<script>alert("ES6 Renderer")</script>' } }, | ||
(err, body) => { | ||
if (err) return reject(err); | ||
expect(body).to.be.equal('<h1>Jon<script>alert("ES6 Renderer")</script></h1>'); | ||
expect(body).to.be.equal( | ||
"<h1>Jon<script>alert("ES6 Renderer")</script></h1>" | ||
); | ||
resolve(); | ||
@@ -149,45 +203,43 @@ } | ||
it("uses updated layout files (aka does not cache)", () => { | ||
const engine = createEngine({ | ||
layoutFile: "./layout.html" | ||
}); | ||
it("escapes functions in locals", () => { | ||
const engine = createEngine(); | ||
return new Promise((resolve, reject) => { | ||
engine("./index.html", { name: "Joe" }, (err, body) => { | ||
if (err) return reject(err); | ||
expect(body).to.be.equal("<div id='app'><h1>Joe</h1></div>"); | ||
files["./layout.html"] = "<span>${yield}</span>"; | ||
engine("./index.html", { name: "Joe" }, (err, body) => { | ||
engine( | ||
"./function.html", | ||
{ | ||
user: { | ||
getUser: function() { | ||
return 'Jon<script>alert("ES6 Renderer")</script>'; | ||
} | ||
} | ||
}, | ||
(err, body) => { | ||
if (err) return reject(err); | ||
expect(body).to.be.equal("<span><h1>Joe</h1></span>"); | ||
expect(body).to.be.equal( | ||
"<h1>Jon<script>alert("ES6 Renderer")</script></h1>" | ||
); | ||
resolve(); | ||
}); | ||
}); | ||
}); | ||
}); | ||
}); | ||
} | ||
); | ||
}) | ||
}) | ||
describe("with caching", () => { | ||
it("should not produce new output when file system changes", () => { | ||
const engine = createEngine({ | ||
layoutFile: "./layout.html", | ||
caching: true | ||
}); | ||
it("selected functions (such as Array.prototype functions) are automaticaly unescaped", () => { | ||
const engine = createEngine(); | ||
return new Promise((resolve, reject) => { | ||
engine("./index.html", { name: "Joe" }, (err, body) => { | ||
if (err) return reject(err); | ||
expect(body).to.be.equal("<div id='app'><h1>Joe</h1></div>"); | ||
files["./layout.html"] = "<span>${yield}</span>"; | ||
files["./index.html"] = "<h4>{name}</h4>"; | ||
engine("./index.html", { name: "Joe" }, (err, body) => { | ||
engine( | ||
"./list.html", | ||
{ names: ['Jon', "Joe"] }, | ||
(err, body) => { | ||
if (err) return reject(err); | ||
expect(body).to.be.equal("<div id='app'><h1>Joe</h1></div>"); | ||
expect(body).to.be.equal( | ||
"<ul><li>Jon</li><li>Joe</li></ul>" | ||
); | ||
resolve(); | ||
}); | ||
}); | ||
}); | ||
}); | ||
} | ||
); | ||
}) | ||
}) | ||
}); | ||
}); |
No bug tracker
MaintenancePackage does not have a linked bug tracker in package.json.
Found 1 instance in 1 package
No bug tracker
MaintenancePackage does not have a linked bug tracker in package.json.
Found 1 instance in 1 package
17582
465
3
+ Addedlodash.merge@^4.6.0
+ Addedlodash.merge@4.6.2(transitive)