Research
Security News
Malicious npm Packages Inject SSH Backdoors via Typosquatted Libraries
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
Remember the "good old days" when PHP reigned supreme and you could write your code directly into webpages? NoTpl aims to do just that with Node & JavaScript.
Most js template engines require you to learn their typically tedious API. Using NoTpl, all you need to know is HTML and JavaScript.
$ npm install notpl
Most JavaScript template engines require a special "templating syntax." Lexing and parsing these special syntaxes takes execution time and requires you to learn new markup.
NoTpl's philsophy is: since a page is rendered by the browser in HTML, it should be (at least partially) written in HTML. NoTpl removes "the middle man" and allows you to write full JavaScript within HTML documents (similar to PHP).
######How does it work?
Before a template is redered it is scanned by a scanner (see: scanner.js). As it scans the file, chunks of the file are inserted into an array. If a chunk is HTML it is wrapped within a print()
function call. Once the file has been scanned, the array is joined, creating a string, and then a function is created from that string. The function is then executed to produce the template's rendered output.
Once a template has been scanned once, it doesn't need to be scanned again unless a file change is detected. Rather than re-scanning the whole file, the template's js function can simply be executed again to produce the "same output with different results," i.e. if a variable has been modified within the template's scope.
Additionally, you can use node modules from within templates using require()
.
<html>
<head>
</head>
<body>
<div>
<$ for(var i in scope) {
print(scope[i]);
} $>
</div>
</body>
</html>
<html>
<head>
</head>
<body>
<div>
<$ for(var i in scope): $>
<$ print(scope[i]); $>
<$ endfor; $>
</div>
</body>
</html>
// Grab the notpl object
var notpl = require('notpl');
// Set your options, and scope to pass into the template
var options = { style: 'compressed' };
var scope = {
foo: 'foo',
bar: 'bar',
// etc. etc.
}
// Create the template
var template = notpl.new('test.html', options, scope);
var output1 = template.render();
scope.foo = 'baz';
// Now, change scope.foo and re-render
var output2 = template.render();
// Do whatever with output... perhaps, pass it to the request.
console.log(output1, output2);
var output1 results | var output2 results |
---|---|
<html><head></head><body><div> foo bar </div></body></html> | <html><head></head><body><div> baz bar </div></body></html> |
<!-- Sample Useage -->
<html>
<head>
<$ print(scope.scripts) $>
<$ print(scope.styles) $>
</head>
<body>
<div id="<$ print('foo-bar'); $>">
<$ for(var i in scope) {
print(scope.i);
} $>
</div>
<div id="some-file-content">
<$ // Read a file's contents and print it within this div..
var fs = require('fs');
print(fs.readFileSync('somefile.txt').toString());
$>
</div>
<$ for(var i in scope.users): ?>
<div id="user-<$ print(scope.users[i].id) $>">
<$ print(scope.users[i].name); $>
</div>
<$ endfor; $>
</body>
</html>
print
:<!-- helloworld.html -->
<div>
<$ print('hello world!'); $>
</div>
Rendering this template will produce:
<div>hello world!</div>
<!-- Template #1 (people.html): -->
<!DOCTYPE html>
<html>
<head>
</head>
<body id="page-people">
<$
var people = [
{ id: 0, name : { first: 'John', last: 'Doe' }, sex: 'male' },
{ id: 1, name : { first: 'Bruce', last: 'Wayne' }, sex: 'male' },
{ id: 2, name : { first: 'Bill', last: 'Gates' }, sex: 'male' }
];
// Note that we passed the scope as the third parameter...
render('names.html', {}, people);
$>
</body>
</html>
<!-- Template #2 (names.html): -->
<div id="people">
<$ var people = scope; $>
<$ for(var i in people) print('<div id="name-' + people[i].id + '">', people[i].name.last, ', ', people[i].name.first, '</div>'); $>
</div>
// Render people.html...
var notpl = require('./notpl.js');
var output = notpl.new('people.html').render();
console.log(output);
Rendering this template will produce:
<!DOCTYPE html>
<html>
<head>
</head>
<body id="page-people">
<div id="people">
<div id="name-0">Doe, John</div>
<div id="name-1">Wayne, Bruce</div>
<div id="name-2">Gates, Bill</div>
</div>
</body>
</html>
<html>
<head>
<!-- Include the NoTpl Script -->
<script src="notpl.min.js"></script>
<script>
var scope = { a: 'foo', b: 'bar' }; // The scope to pass to the script
var options = {} // NoTpl options
var callback = function() {} // A callback to be executed after rendering (and doc.ready).
var errorMsg = function() {} // An errorMsg if the template fails to render (can be string, function,
// or an object with the property 'file' to render another template instead).
// You MUST call the notpl() function explicitly, otherwise nothing will happen. Note also,
// that all arguments are optional.
notpl(options, scope, callback, errorMsg);
</script>
</head>
<body>
<div>
<$ for(var i in scope) {
print(scope[i] + " ");
} $>
</div>
</body>
</html>
Render Results | Output |
---|---|
<html><head><script src="../notpl.min.js"></script><script> var scope ={a: 'foo', b: 'bar'} var options ={} var callback = function(){} var errorMsg = function(){} notpl(options, scope, callback, errorMsg); </script></head><body><div> foo bar </div></body></html> | foo bar |
<head>
<!-- Include the NoTpl Script -->
<script src="notpl.min.js"></script>
<script>
// Call the notpl function to render the page
notpl();
</script>
</head>
<body>
<$ print('hello world!'); $>
</body>
</html>
Render the child template inside of the parent template using AJAX.
<!-- parent.html -->
<html>
<head>
<!-- Include the NoTpl Script -->
<script src="notpl.min.js"></script>
<script>
// Call the notpl function to render the page
notpl();
</script>
</head>
<body>
<$ render('child.html', options, scope); $>
</body>
</html>
<!-- child.html -->
<div>Hello World!</div>
Rendering this template will produce:
<head><script src="../notpl.min.js"></script><script>notpl()</script><script> notpl();</script></head><body><div> Hello World!</div></body>
and output
Hello World!
<!DOCTYPE html>
<html>
<head>
<!-- Include notpl.min.js -->
<script src="../notpl.js"></script>
<script>
// Create the scope
var scope = { x: "foo" }
var template;
// Render the page, grab the template using the callback:
notpl({}, scope,
function (error, tpl) {
template = tpl;
},
function() {
/* Do some error handling */
return "Oops. Something went wrong."
}
);
// Create a function to change the scope after 2 seconds...
function changeScope() {
setTimeout(function () {
scope.x = "bar";
// Do something with the rendered page...
// We could get fancy and do some animation here or something:
document.documentElement.innerHTML = template.render();
}, 2000);
} // End changeScope();
</script>
</head>
<body onload="changeScope()" id="<$ print('body-id'); $>">
This is the body text.
<$ print(scope.x); $>
</body>
</html>
Page Results Initially | Page Results After 2 Seconds |
---|---|
This is the body text. foo | This is the body text. bar |
Within each template NoTpl provides a few pre-defined helper functions. Do not reassign these variables! Doing so could potentially break a template.
print
or echo
in php.print
scope
object.The NoTplMgr
object is what is actually exported when you call require
within node. It creates a CRUD like wrapper around the NoTpl class.
templateFilename
.NoTplMgr.cache
).The NoTpl
class is the actual template class.
None accessible from outside the class scope
renderOptions
stats
object for this template.A list of keys for the 'options' object.
print
,render
, and echo
un-reassignable (immutable).&
into &amp;
, for example... so escaping is currently unenabled.)FAQs
The "No Template" Javascript Templating Engine
The npm package notpl receives a total of 2 weekly downloads. As such, notpl popularity was classified as not popular.
We found that notpl demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
Security News
MITRE's 2024 CWE Top 25 highlights critical software vulnerabilities like XSS, SQL Injection, and CSRF, reflecting shifts due to a refined ranking methodology.
Security News
In this segment of the Risky Business podcast, Feross Aboukhadijeh and Patrick Gray discuss the challenges of tracking malware discovered in open source softare.