Osiris and atjs
src
atjs is an asynchronous JavaScript template engineDesigned to build static sites or be used with express using simple template syntax that supports native JS within templates. Written from the ground up to achieve full async/await abilities.
atjs provides a print
function and it must be called with await
as the writableStream may have closed or be buffering. This allows for low memory and cpu usage and high throughput from a single thread.
Installation
npm i --save atjs
atjs Template syntax:
<?
// we start our javascript content with <? and end it with ?>
// we can use <?='hi' ?> to print any statement, this will automatically be awaited
let myWelcome = 'Hi from JavaScript!';
// anything javascript goes, here's a test function
const myFunction = async () => { // async lets us await
await print('<p>Hi from myFunction</p>'); // we must await our prints
};
?>
<!DOCTYPE html>
<html>
<head>
<title><?=myWelcome ?></title>
</head>
<body>
<?
await print('<p>We must await our print statements</p>');
await print('<p>Everything is asynchronous here</p>');
await myFunction(); // we can await our own functions too
?>
<?=myFunction(); /* short tags automatically await function calls and skip anything not printable (like undefined) */ ?>
</body>
</html>
src
Osiris is a framework built on top of atjsDesigned to facility code re-use and organisation of files, Osiris and its modules are all built with asynchronicity in mind to allows IO requests to not bottleneck the system.
Files are organised into your projects ./src/
with the following folders:
-
locales/
, for i18n support -
pages/
, the web root, landing page templates go here - osiris.templateMap folders resolve here, defaults are
snippets/
andelements/
Please check out our examples:
Osiris build example
const fs = require('fs');
const osiris = require('osiris-atjs');
osiris.mode = 'development'; // or 'production'
osiris.templateMap = { // default settings, included for completeness
snippet: 'snippets',
element: 'elements'
};
// we can inject things into scope to be used by all renderings
osiris.use({
aGlobalFunction: async () => {
await this.print('Hi from aGlobalFunction');
}
});
let writeFile = fs.createWriteStream('myBuilt.html'); // open a file to put the result in
await osiris.render(writeFile, 'myToBuild.atjs', {
myLocalFunction: async () => { // we can inject things just for this rendering
await this.print('Hi from myLocalFunction');
}
});
src
Osiris APIOsiris features the following configuration via the osiris object
-
mode = 'development' or 'production'
, default development, development disables atjs caching and directs errors to the web browser. -
qMap = Object
, character mapping to html entities, used byq()
, default translates <, >, ', " and & -
templateMap = Object
, key/value pairs, key represent the name of the function added to the template scope and the value represents the path within./src/
default
Osiris exposes the following functions to the templates, as well as the default print()
provided by atjs
-
q: async? (str='')
, translates a strings HTML entities withqMap
so it can be used within quoted attributes, returns a promise if given a promise -
js: (str)
, bundles collections of JavaScript for footer insertion -
css: (str)
, bundles collections of CSS for footer insertion -
bundleJs
, retrieves the JS bundle for output -
bundleCss
, retrieves the CSS bundle for output -
locals
, a persistent object that allows for a global namespace between template calls -
onClose = function
, bind a function to this hook to be called when the connection is lost mid-template. Also available in atjs -
onError = function (errorText)
, bind a function to handle errors. Also available in atjs, default
src
Osiris expressOsiris comes with hooks to get functionality within express, usage:
const HTTP_PORT = 8080;
const osiris = require('osiris-atjs');
const atjsExpress = require('osiris-atjs/express');
const express = require('express');
const app = express();
const fs = require('mz/fs'); // modernizer fs uses promises instead of callbacks
const main = async () => {
app.use(async (req, res, next) => {
let filename = req.path.substr(1); // trim starting /
if (filename === '') {
filename = 'index'; // default page for directory index
}
if (!await fs.exists('./src/pages/' + filename + '.atjs')) {
return next(); // file doesn't exist, bail
}
res.header('content-type', 'text/html'); // we have something
// call renderer with our addons, we can block here with await if we need any clean up after render
await osiris.render(
res, // our writableStream
'./src/pages/' + filename + '.atjs', // our template file
atjsExpress(req, res), // this gives templates access to get, post, header() and headersSent, cookie and setCookie()
express: atjsExpress(req, res) // we can also do this if we want to put all of that in scope of an express object instead of top level
});
// render complete, res.end() sent, perform any required clean up
});
await app.listen(HTTP_PORT);
console.log('Node process listening on ' + HTTP_PORT);
};
main();
src
Osiris express template API-
get
, object containing get variables, parsed byurl.parse
-
post
, object containing post variables, taken fromreq.body
-
header: (...args)
, callsres.set
-
headersSent
, boolean if headers have been sent yet -
redirect: (...args)
, callsres.redirect
-
cookie
, object containing cookie variables, taken fromreq.cookies
-
setCookie: (...args)
, callsres.cookie
src
Osiris i18nDesigned to facilitate internationalisation of HTML templates. It does this by JIT searching the src/locales/ folder for folders for each locale, then searches within those for translations
Example as before but with:
const atjsi18n = await require('osiris-atjs/i18n')(); // searches for locales and exposes nodeJS API
await osiris.render(writeFile, file, {
i18n: atjsi18n.locale(locale), // locale being the viewers current locale, exposes: t(), d(), n(), locale, locales, setLocale()
});
More complete examples:
Osiris i18n nodeJS API
-
locales
, array of strings of locales available -
locale: (localeString)
, returns template API forlocaleString
-
watch()
, call to let i18n reload when locale files change
Osiris i18n template API
-
locale
, string of current locale -
setLocale: (localeString)
, sets the locale for the current request -
locales
, array containing string of all available locales -
t: async (namespaceString)
, splits the namespaceString by "." and recurses down src/locales/locale
/ folders/JSON structures (JS and JSON files supported) until a valid key is found. If a function is found it is called (async), returns "[locale.locale
.namespaceString
]" on failure -
d: (dateObject, options?)
, localize datetime according to https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DateTimeFormat -
n: (numberObject, options?)
, localize number according to https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/NumberFormat