Skip to content

Asynchronous JavaScript templates `.atjs` rendered to a writable stream

License

Notifications You must be signed in to change notification settings

seam-project-studios/atjs

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Osiris and atjs

atjs is an asynchronous JavaScript template engine src

Designed 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>

Osiris is a framework built on top of atjs src

Designed 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/ and elements/

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');
  }
});

Osiris API src

Osiris 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 by q(), 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 with qMap 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

Osiris express src

Osiris 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();

Osiris express template API src

  • get, object containing get variables, parsed by url.parse
  • post, object containing post variables, taken from req.body
  • header: (...args), calls res.set
  • headersSent, boolean if headers have been sent yet
  • redirect: (...args), calls res.redirect
  • cookie, object containing cookie variables, taken from req.cookies
  • setCookie: (...args), calls res.cookie

Osiris i18n src

Designed 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 for localeString
  • watch(), call to let i18n reload when locale files change

Osiris i18n template API

Automated by Buddy

About

Asynchronous JavaScript templates `.atjs` rendered to a writable stream

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published