Naughty Platypus Memorabilia

    viu

    1.0.0 • Public • Published

    viu Build Status Code Climate

    Frustrated with the complexity
    of the existing JavaScript/Node.js rendering engines,
    I decided to write something light.

    The aim is Simplicity not "Bells and Whistles"
    Security not fancy feature "xyz"
    and Speed because time is our scarecest resource.

    slight detour. currently building an app in meteor. will come back to this soon.

    (Start With) Why?

    (Short) List of Gripes

    • Excessive Complexity (too many "Features")
    • Inconsistent (Unit/Client) Testing
    • Cryptic syntax (erb/jade ... :-( )

    Objectives

    • Minimal Learning Curve with micro-set of features allowing anyone with basic HTML skills to write templates
    • Logic-less (no code in views)
    • Security Focus: Code escaped by default
    • Translation without losing the will to live!

    List of Required Features

    • Parse HTML file and insert variables
    • Cache templates (both server & client side) for fast execution!
    • 100% Test Coverage with human-readable tests (without grunt!)
    • Use single curly brackets for variable placeholders {name}
    • Allow (encourage) use of partial templates
    • (Optional) Automatic reloading of changed templates (ect)
    • Valid and Accessible HTML using http://validator.w3.org/
    • Measurable Performance (see if/when/why your app is getting slower!)

    Security Focus

    (Very) Nice to Have

    • Automatic Translation to browser's headers['Accept-Language'] (with option for user to specify prefered language in their preferences e.g. if I'm visiting a foreign country or using my Russian friend's laptop...)
    • Client side view of all unit tests (do not require running tests from command line - which puts new people off!)

    How

    Simple Render Function

    A simple function call: (no template specified)

    V(options, function(err, data){
        response.end(data);
    });

    Try: nodemon test/exampleapp.js Visit: http://localhost:8000/ Run: ab -n 4000 -c 120 http://localhost:8000/

    Default Values

    The ability to have default values in templates is handy. e.g:

    { site_name or default_site_name }
    

    What type of configuration file should we use...? http://en.wikipedia.org/wiki/Configuration_file

    Unit Testing

    Rather than forcing people to download the code and run the tests on the command line I've decided to use the browser-based unit testing framework QUnit and blanket.js. This creates more work in the short-run but holds several clear benefits:

    • Anyone can run/view the tests simply by visiting the tests url.
    • No Command Line to overwhelm beginners.
    • Nothing to install/configure

    Next:

    Decisions

    Which Words / Characters will be Significant?

    The advantage of using characters is fewer bytes are consumed. Which means less data is transmitted over the wire and apps are faster. The dissadvantage is that templates are less human-readable...

    e.g:

    • # (hash) for iteration/enumeration (as in dust)
    <ul>
     {#names}
      <li>{name}</li>{~n}
     {/names}
    </ul>

    Handlebars by contrast uses the #each notation for itteration:

    <ul>
      {{#each names}}
      <li>{{name}}</li>
      {{/each}}
    </ul>

    The # (hash) character could be considered "loaded" because of its significance in CSS and Ruby (#id and #comment respectively) But there aren't that many characters available on a standard keyboard ... So we may need to repurpose a few ...

    I prefer to use (human-readable) words where ever possible to lower barriers to entry for "non-technical" people.

    <ul>
      {each names}
      <li>{name}</li>
      {end each}
    </ul>

    Parameters for Functions/Methods

    Need to decide how to set up the main method. We can either list out all the parameters inline. e.g:

    render(options, view, layout_file, callback) {
        // render code here
    }
    

    Or just use the options object to specify all parameters

    render(options) {
        // check view_file is set in options
        if (typeof options.view_file === 'undefined') {
            options.view_file = config.default_view;
        }
    }
    

    I tend to favor spelling out all the available parameters because it makes learning how to use a method/function easier. But one can just as easily argue that having too many parameters is confusing if they aren't all being used.

    Lets try the single options parameter and see what people think/say.

    For our first test we don't even need a parameter! So lets write that first!

    More Detail

    Partial Views

    We need to decide what the most intuitive way of rendering partials is. [ If you don't know what a partial is, see: http://stackoverflow.com/questions/7085156/what-are-partial-views ]

    Two Options:

    1 - Define a Layout File when rendering your view

    2 - Include a header and footer in your view

    Including a partial view:

    {include footer}

    Background

    There is no shortage of templating modules: https://github.com/joyent/node/wiki/modules#wiki-templating

    I am not a fan of how underscore/EJS require four signifier characters for each variable placeholder or iterator <%= name %>. EJS (rails) suffers from the same waste of bytes. Dust.js can do it with only two: {name} and since the curly brace already has auto-close/complete in most editors it makes it faster to type.

    Express View Renderer: https://github.com/visionmedia/express/blob/master/lib/response.js#L762

    http://expressjs.com/guide.html#debugging-express

    Inspiration

    Watching Files For Changes

    Quis custodiet ipsos custodes

    Headless Testing

    Parsing

    HTML Validation

    I love valid html

    This is a problem:

    Amazon fails validation

    Avoiding Information Overload

    When you first start learning a new framework/system its easy to be overwhelmed by an excess of jargon.

    What if instead of overloading people we had a learning process where each concept was broken down into a 5-30 second tutorial you had to go through before moving on?

    Auto-Generated Configuration File

    Rather than having a giant configuration file with many options most people aren't going to use. We build a file-scanner into the watcher that adds config option to the config.js file each time a variable is registered with the default_ prefix.

    e.g:

    <title>{title || default_page_title} </title>
    

    will create an entry in config.js for default_page_title

    (Premature) Optimization

    It occured to me that we could render templates without the whitespace (between tags) (i.e. minify our html) e.g:

    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="utf-8">
            <title>My Page Title</title>
        </head>
        <body>
            <h1>Whitespace aids readability</h1>
        </body>
    </html>

    Would become:

    <!DOCTYPE html><html><head><meta charset="utf-8"><title>My Page Title</title></head><body><h1>Goodbye Whitespace</h1></body></html>

    But this makes viewing/reading page source & debugging a nightmare! So lets put that off for as long as possible (until enough developers requests it).

    "Premature optimization is the root of all evil." ~ Donald Knuth (Computer Programming as an Art - 1974)

    The Rules Of Optimization

    1. Make it work.
    2. Make it right (the code is readable [uses IntentionRevealingNames] and every idea is expressed OnceAndOnlyOnce).
    3. Make everything work.
    4. Make everything right.
    5. Use the system and find performance bottlenecks.
    6. Use a profiler in those bottlenecks to determine what needs to be optimized. (ProfileBeforeOptimizing)
    7. Make it fast. You maintained unit tests, right? Then you can refactor the code mercilessly in order to improve the performance.

    Read

    Install

    npm i viu

    DownloadsWeekly Downloads

    2

    Version

    1.0.0

    License

    none

    Last publish

    Collaborators

    • nelsonic