jsmile-bundler

A build script for the JavaScript Markup Language view engine.


Keywords
jsml, html, browserify
License
Unlicense
Install
npm install jsmile-bundler@0.0.11

Documentation

JSMiLe-bundler

J:)

A build script for the JavaScript Markup Language view engine.

Installation

npm install jsmile-bundler

Usage

jsmile-bundler <viewDirectory> <includerFile> <outputPath>

This command will generate a script at the ouput path that bundles your views directory configured in line with [jsmile-express] with the functionality of jsmile-browser.

Views

View files are JavaScript modulees that exports a function. Views can be integrated with express with the help of the jsmile-express.

jsmile-bundler wll parse each view file and bundle them with browserify. Views must be located within in a single dedicated direcotry.

The views will be provided in the browser at jsmile.views. Views will be contained in an object indexed by their base path within the views directory.

views/
  layout.js
  molecules/
    block.js
  atoms/
    title.js
    content.js
console.log(jsmile.views)
// { layout: ..., "molecules/block": ..., "atoms/title": ..., "atoms/content": ... }

include

The jsmile.include method allows easy access to views and mimics the same method from jsmile-express in the browser. Included takes up to two arguments:

  1. The name of the view
  2. An options object. This defaults to an empty object.

The options will be passed to the view if defined. The view will be executed by name from jsmile.views. The returned value will be passed to jsmile.render and then returned. If the view is not defined, it will return null.

views/userLink

module.exports = (jsmile, options) => ({
  child: [
    options.name,
    jsmile.include('link', { href: '#', text: options.id })
  ]
})
const user = { name: 'David', id: '001' }
const userLink = jsmile.include('userLink', user)

console.log(userLink.outerHTML)
// <div>David<a href="#">001</a></div>

Rendered views can be passed to jsmile.render or its alias jsml just like other DOM elements.

jsml(document.querySelector('body'), jsmile.include('heading'), jsmile.include('content'))

Includers

Each view file can have an associated includer method. Includers allow you to associate the insertion of a view with client-side functionality.

Includers are exported via a JavaScript file passed to jsmile-bundler. The file should export a function that can takes 2 arguments:

  1. The jsmile library with views attached.
  2. The browser's current window instance.

The function should return an object with methods that can take 1 argument, the rendered value of the view function.

If there is a includer matching the name passed to include, it will be passed to the includer after rendering, and the value returned by the includer will ultimately be returned by jsmile.include instead of the rendered content itself. If there is no matching view defined, the includer will still be executed and passed null.

The includers object will also be accessible in the browser at jsmile.includers.

####Example:

Before bundling, the view is exported as a JavaScript module. views/footer.js

module.exports = () => ({ tag: 'footer', child: 'The End.' })

The includer is exported as a method of the "includers" JavaScript module. includers.js

module.exports = jsmile => {
  footer(window, footer) {
    window.document.querySelector('body').append(footer)

    return footer
  }
}

These views and includers are passed to jsmile-bundler.

jsmile-bundler views includers.js public/jsmile.js

The bundled JavaScript is included in the page.

// <html><head><script src="./jsmile.js"></script></head><body></body></html>

The view is included, perhaps from the browser console

> jsmile.include('button')

The view's function is passed to the included along with the window, which in this case attaches the rendered DOM element to the body.

// <html><head><script src="./jsmile.js"></script></head><body><footer>The End.</footer></body></html>

Depending

The jsmile.depend method controls access to views and includers to prevent content duplication. It takes two arguments:

  1. The name of a view.
  2. An options object for the dependency, which defaults to an empty object.

The first time a view is passed to to jsmile.depend, including inside of embedded views, it is rendered with it's options and and passed to its includer if defined. depend itself returns null, and can be inserted in rendered content with no effect. After the first time, additional calls to jsmile.depend for that view will have no effect.

####Example:

A view depends on another view. views/clicker.js

module.exports  = (jsmile, options) => {{
  tag: 'button',
  value: 'Click Me!'
  child: jsmile.depend('assets/button', { behavior: true })
})

Another view depends on the same view with a different set of options, in this case none. views/forbidden.js

module.exports = (jsmile, options) => {{
  tag: 'button',
  value: 'Don't click Me!'
  child: jsmile.depend('assets/button')
})

Both views are included in other views, in this case the same one. views/buttons.js

module.exports = jsmile => [jsmile.include('forbidden'), jsmile.include('clicker')]

The dependency is defined in its own view. views/assets/button.js

module.exports = (jsmile, options) => {
  const assets = [
    {
      tag: 'link',
      rel: 'stylesheet',
      type: 'text/css',
      href: '/button.css'
    },
  ]
  
  if (options.behavior) {
    assets.push({ tag: 'script', src: '/button.js' })
  }

  return assets
}

An includer matching the dependency is defined and exported in another file. includers.js

module.exports = jsmile => ({
  'assets/button.js'(window, assets) {
    window.document.querySelector('head').append(assets)
  }
})

The views and includers are passed to jsmile-bundler.

jsmile-bundler views includers.js public/jsmile.js

The bundled JavaScript is included in the page.

// <html><head><script src="./jsmile.js"></script><script src="./another-script.js"></script></head><body></body></html>

The view is included, perhaps from another script.

jsml(window.document.querySelector('body'), jsmile.include('buttons'))

The dependency is automatically rendered with its options and passed to its includer, in this case rendering the content and appending it to the head.

// <html><head><script src="./jsmile.js"></script><script src="./another-script.js"></script><link rel="stylesheet" type="text/css" href="/button.css"></head><body><button type="button" value="Don't click me!"></button><button type="button" value="Click me!"></button></body></html>

Note that the script asset was not included according the options of the first call.