Skip to content
Peter Naydenov edited this page Dec 23, 2017 · 8 revisions
WORK IN PROGRESS...

It's not a standard template engine

Engine works with templates, data and processes. All items are described in JSON compatible format, in a way to exchange resources via standard AJAX calls. Templates are logicless and are fully decoupled from the data. Partial rendering nature of this engine will give you an opportunity to balance rendering between server and client and you will be able to separate localization, design and data rendering processes. Choose a strategy on missing property values and have fine control on data during rendering process by using hook functions. In brief - Code-Assembly-Line.

This page describes general concepts and terms used in Code-Assembly-Line. If you know how engine was build, you will know how to use it on the best way. Let's get started.

Templates

Small-sized text blocks that contain text and placeholders only. Templates are not tied to the process-data model and do not have any logic. Real logicless templates! Templates are a simple Javascript object in which the key is the name of the template, and the value is the template itself. One JS object can contain a lot of templates and could be treated as a template library:

 const library = {
                     "welcome"     : "Welcome {{user}}"
                   , "age-message" : "{{user}} is {{age}} years old."
                }

Library contains two templates. Template 'welcome' has one placeholder 'user'. Placeholders are surrounded by double curly brackets. Template 'age-message' has two placeholders: 'user' and 'age'.

System placeholders

Code-Assembly-Line engine provides data that is not explicitly provided but can be used by templates.

  • _attr : Provides list of html attributes in specific order. But how the system recognize attributes? There is a configuration where you can define what process-data property should be treated as attribute and control the order of appearance. Default attribute list at this moment is:
[ 'id', 'name', 'href', 'src', 'value', 'data', 'alt', 'role', 'class' ]

Add new attributes, remove them or change their order of appearance by changing this configuration object. Put empty object and none of properties will be treated as attribute.

  • _count : Simple counter that will count how many process-data item was provided. Counting starts from 1.

Optional spaces

Did you see code like this:

  <a href="something.html"       >Link text</a>

It happen when code is generated by templates and there is missing information. Large blank spaces is not what we want to see. Optional spaces are here to solving exactly this problem. Define template like:

  { 'a' : '<a {{href}}{{~~class}}>{{text}}</a>'}
   // optional space: ~~
   // Can be used inside placeholder and could be before, after or both places.
   // Space will appear only if placeholder has value.

And result will become:

 <a href="something.html">Link text</a>
<!-- If process-data item has property 'class' is available then will look like this -->
 <a href="something.html" class="any">Link text</a>

Engine Data

Data records are represented by javascript object. Exactly like templates:

 const dataBank = {
                       'alt'  : 'This image has no description'
                     , 'name' : 'Anonymous' 
                  }

Data-record 'alt' with content This image has no description and data-record 'name' with content Anonymous. Data can be used for localization purposes or like general available information. Data-records are visible from all render processes. Data can be used also like a library with default values.

Process Data

Process data has no predefined data structure. It's the data provided on starting process.

  // process can be started with method 'run'
 tplEngine.run ( 'processName', processData )

Process data could be anything: string, array or object. If it is array every single item will be rendered with the template. Result of drawing process will be an array of rendered results.

Processes

All the magic happen here. Process is ordered list of process-steps. Steps could do data-object manipulations, drawing data with templates, create new templates, and more. Process name is like macro-instruction that will give you a power to make your project almost as you talk: 'Create header, horizontal navigation. Body should have slider and article. Finish page with standard footer.'. What process steps can do for you:

  • Manipulation of process-data. Change, remove or add properties to all or selected process-data items;
  • Rename properties to fit with template - alter;
  • Rename template placeholders during process to fit a data properties - alterTemplate;
  • Create new properties by render data in a template;
  • Merge rendered process-data items;
  • Convert string process-data items to object;
  • Render blocks

The Engine

Simple templates, powerful process-steps, engine and process data. Engine is the playground for them:

  • Take a template, render available data and set result as a new template for later use;
  • Hide missing process-data fields and save result as ready to use block;
  • Render process-data, but hide records that have missing data-fields;
  • Render missing data-fields with alternative content from the engine-data;
  • Use hook functions to customize render process during its execution;
  • System placeholder for '_count' process-data items;
  • System placeholder '_attr' for automatic html tags calculation;

Let's bring everything together in single code snippet:

const 
       CodeAssemblyLine = require ( 'code-assembly-line')
     , tplEngine = new CodeAssemblyLine()
     ;

// --- PREPARE RESOURCES
const templateLib = {
                         'a' : '<a href="{{href}}">{{text}}</a>'
                       , 'li': '<li{{~~_attr}}>{{text}}</li>'
                       , 'ul': '<ul>{{text}}</ul>'
                     };


// processes
const doNav = [
                     { do: 'alterTemplate', tpl: 'a', data: { 'href': 'link'}   }
                   , { do: 'draw', tpl: 'a', missData: '_hide' }
                   , { do: 'set', as: 'text' }
                   , { do: 'add', select:'first', data: { 'className': 'first'}  }
                   , { do: 'draw', tpl: 'li' }
                   , { do: 'block',  }
                   , { do: 'set', as: 'text' }
                   , { do: 'draw', tpl: 'ul' } 
              ];
const saveNav = [{do:'block', name: 'nav' }]



// --- LOAD RESOURCES
tplEngine
      .insertTemplate ( templateLib )
      .insertProcess ( doNav, 'nav' )      
      .insertProcess ( saveNav, 'saveNav')
      

// -- PROCESS-DATA FOR NAVIGATION
const myNavData = [
                        { text: 'Home', link: 'home.html' }
                      , { text: 'Services', link: 'services.html' }
                      , { text: 'About', link: 'about.html' }
                      , { text: 'Just text' } // Ignored - no link. Look 2 row of 'doNav' -> missData: '_hide'
                      , { text: 'Contact', link: 'contact.html' }
                 ];

// --- RENDER AND RETREAVE
tplEngine.run (['nav','saveNav'], myNavData )
tplEngine.getBlock ( 'nav' )

Try this code in Runkit: Code-assembly-line. Full render example.