Documentation - adamstallard/modest GitHub Wiki

Contents

Basic Modest

Modest can be used by simply downloading modest-preview.js and including it in an html file.

It allows you to write modest html which reuses html from module-files you create.

The head section

Modules are included using <include><include/> tags. The name of the module (with an optional .xml at the end) goes between the tags. The optional path attribute gives the relative location of the module (default is the current location). client="true" indicates that the module will be available to client-side javascript. (See Using modest in javascript.)

The head section of a modest html file (a -pre file) might look like this, with jquery (required) included first, then modest-preview.js and finally some included modules.

...
<html>
  <head>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
    <script src="modest-preview.js"></script>
    <include path="modules" client="true">animal</include>
  </head>
...

When this file is loaded in a browser or an ide window, it will display as it would if it were compiled.

The modest Command

Once you are ready to deploy to production, you can compile a modest html file into regular html. To do that, install the modest node package.

  1. Install node.js
  2. Install modest npm install -g modest

then

cd <directory>
modest

or

modest <dir1> <dir2> ...

This will prepare one or more directories for use with modest by copying the "modest-preview.js" script into that directory. It will compile any files ending in -pre (plus an optional extension). For example, index-pre.html would become index.html. It will create a javascript file called modest.js that includes compiled versions of any modules that had client="true" in their include tags. A <script> tag referencing modest.js will be automatically added to the compiled files (after the body tag) so that any javascript included by the compiled files can use the modules. The modest-preview.js <script> tag will be cleaned out, and the compiled html files will be placed next to the -pre files.

Command-line Options

To see what options are available to the modest command, type

modest --help

Grunt-modest

Grunt-modest is an alternative to using the modest command.

Directory Structure

Since a single modest.js file is created per directory, directories should be organized so that html files using the same modules are located in the same directory.

Demo Elements

An element marked with the attribute demo will be included in previews, but excluded from compilation. This lets designers see how programmatically-added elements would look--and communicate this to developers--without having to know about or create helper functions.

example-pre.html

...
<ul id="searchresults">
  <searchresult demo>
    <title>Goalzen</title>
    <url>www.goalzen.org</url>
    <description><lorem/></description>
  </searchresult>
</ul>
...

example.html (output)

...
<ul id="searchresults">
</ul>
...

Using Modest in Javascript

Modest modules and the modest class with its functions are available to any javascript run in the same context as either modest-preview.js or modest.js. They are also available to any preprocessed javascript.

On the client-side (using modest.js), only modules that had the client attribute set to true in their include tag are available.

Functions

render

To render a modest module in javascript, use the modest.render() function.

var out = modest.render('animal');

If the module takes parameters, supply them as an object.

var out = modest.render('animal', { name: "Lion", weight: "250 kg (550 lb)" });

data

To load parameters from a local json file, use modest.data().

var out = modest.render('animal', modest.data('cow.json'));

modest.data() will use node.js if it is run as preprocessed javascript, and jquery otherwise.

remoteData

To load parameters from a remote url, use modest.remoteData(_url_).

Creating Modules

Module Files

Modules are usually xml files with an .xml extension. (See exceptions.) They are included in modest html files using <include></include> tags. (The .xml extension can be omitted in the include tags.) If they are in a different location than the html file, specify the relative location with the path attribute.

The content of the module will be substituted whenever a tag with its name is used in modest html.

hello.xml

<p>Hello World.</p>

main-pre.xhtml

<?xml version='1.0' encoding='UTF-8'?>
<!doctype html>
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <include>hello</include>
  </head>
  <body>
    <hello/>
  </body>
</html>

Would be rendered as

main.xhtml (output)

<!doctype html>
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
  </head>
  <body>
    <p class="hello">Hello World.</p>
  </body>
</html>

The name of the module is added as a class to its root element. This makes it easy to find in javascript or css.

Module Parameters

Parameters can be handled in different ways, always with the uses attribute.

Parameter names are case-insensitive.

Simple Parameters

The simplest use of a parameter is a straight-forward substitution of element content with parameter content.

person.xml

<p>A person named <span uses="name"/>.</p>

example-pre.html

...
<person>
  <name>Bob</name>
</person>
...

example.html (output)

...
<p class="person">A person named <span class="name">Bob</span>.</p>
...

The name of the parameter is added as a class to the element that replaced it.

#### Multiple Parameters The same parameter can be substituted in multiple places.

person.xml

<div>
  <h1 class="title" uses="name"/>
  <p><span class="description" uses="name"/> is <span uses="age"/> years old.</p>
</div>

example-pre.html

...
<person>
  <name>Bob</name>
  <age>24</age>
</person>
...

example.html (output)

...
<div class="person">
  <h1 class="title name">Bob</h1>
  <p><span class="description name">Bob</span> is <span class="age">24</span> years old.</p>
</div>
...

Here, extra (optional) classes were added to the module elements to make it easier to find the different instances of "name."

Unused Parameters

Elements representing unused parameters are omitted from the output.

animal.xml

<div>
  <h1 uses="name"/>
  <p uses="weight"/>
</div>

example-pre.html

...
<animal>
  <name>Frog</name>
</animal>
...

example.html (output)

...
<div class="animal">
  <h1 class="name">Frog</h1>
</div>
...

See Dependent Elements.

Placeholder Parameters

Parameters can be left blank so they can be used a placeholders and filled in later.

animal.xml

<div>
  <h1 uses="name"/>
  <p uses="weight"/>
</div>

example-pre.html

...
<animal id="frog">
  <name>Frog</name>
  <weight/>
</animal>
...

example.html (output)

...
<div class="animal" id="frog">
  <h1 class="name">Frog</h1>
  <p class="weight></p>
</div>
...

addWeights.js

...
$('#frog .weight').html(animals['frog'].weight);
...

See Dependent Elements.

Attribute Parameters

Attributes of module elements can also receive parameters.

animal.xml

<div>
  <a uses="name href=url"/>
</div>

example-pre.html

...
<animal>
  <name>Frog</name>
  <url>"http://en.wikipedia.org/wiki/Frog"</url>
</animal>
...

example.html (output)

...
<div class="animal">
  <a class="name" href="http://en.wikipedia.org/wiki/Frog">Frog</a>
</div>
...

When defining a module, multiple parameters can be used for an element's attributes, and one parameter can be used for its content. Attribute parameters are of the form attribute=parameter. The content parameter is the one parameter that doesn't have an equals sign. The content parameter and the attribute parameters are supplied to the same uses parameter, separated by spaces.

For example:

<input type="checkbox" uses="name=category value=selection description"/>

Passthrough Parameters

Passthrough parameters make it easy to forward parameters to inner modules.

infoForm.xml

<div>
  <p>Here is the contact information for <span uses="name"/></p>
  <contact>
    <name uses="name"/>
    <cell uses="number"/>
  </contact>
</div>  

contact.xml

<div>
  <p>Name: <span uses="name"/></p>
  <p>Cell: <span uses="cell"/></p>
</div>

example-pre.html

...
<infoForm>
  <name>Jim Bob</name>
  <number>123-456-7890</number>
</infoForm>
...

example.html (output)

...
<div class="infoForm">
  <p>Here is the contact information for <span class="name">Jim Bob</span></p>
  <div class="contact">
    <p>Name: <span class="name">Jim Bob<span/></p>
    <p>Cell: <span class="cell number">123-456-7890</span></p>
  </div>
</div> 
...

The replaced element receives a class from each parameter it passes through.

Root Parameters

Parameters can be applied to the root element of a module

myLink.xml

<a uses="display href=url"/>

example-pre.html

...
<myLink>
  <display>go here</display>
  <url>http://some_rad-site.com</url>
</myLink>
...

example.html (output)

...
<a class="myLink display" href="http://some_rad-site.com">go here</a>
...

In this case, both the module name and the parameter name are added as classes to the replaced element.

Dependent Elements

Module elements can be displayed depending on the existence of a parameter.

Plus Parameters

A plus parameter causes an element to be displayed only if that parameter is supplied.

contact.xml

<div>
  <p>Name: <span uses="name"/></p>
  <p uses="+cell">Cell: <span uses="cell"/></p>
</div>

Minus Parameters

A minus parameter causes an element to be displayed only if that parameter is not supplied.

animal.xml

<div>
  <h1 uses="name"/>
  <p>Weight: <span uses="weight"/><span uses="-weight">unknown</span></p>
</div>

Module Comments

Text preceding the root element in a module is ignored, and can be used for comments. A <comment> (or any other) tag with the "uses" attribute set to "+" is also ignored. Any tags or text after the root element are ignored.

commentTest.xml

this is a comment
<div id="rootElement"/>
  <p>test</p>
  <comment uses="+">Another comment</comment>
</div>
<span>ignore me.</span>

example-pre.html

...
<commentTest/>
...

example.html (output)

...
<div id="rootElement" class="commentTest">
  <p>test</p>
</div>
...

Parameter Declarations

Parameters can be declared in the comment section. This makes it easier to see what parameters a module takes.

animal.xml

uses: name, url
<span>
  <a uses="name href=url"/>
</span>

String templates

String templates are useful when text needs to be reused, but it doesn't make sense to put it in its own element. For example

In attributes

greetButton.xml

uses: name
<button type="button" uses="onclick={{alert('Hello, {{name}}')}}">Greet</button>

The outer double-braces indicate that a string template will be used for the onclick attribute. {{name}} will get replaced by the value of the name parameter.

example-pre.html

...
<greetButton>
  <name>Bob</name>
</greetButton>
...

example.html (output)

...
<button type="button" class="greetButton" onclick="alert('Hello, Bob')">Greet</button>
...

For element content

A string template can be used to generate an element's content. For example

greeting.xml

<p uses="{{Hello, {{name}}}}"/>

would compile to

<p class="greeting">Hello, Bob</p>

With plain parameter substitution instead

greeting.xml

<p>Hello, <span uses="name"/></p>

would compile to

<p class="greeting">Hello, <span class="name">Bob</span></p> 
## Supplying Module Parameters _Supplying module parameters from javascript is described in [Using Modest in Javascript](#using-modest-in-javascript)_.

The methods for supplying module parameters are listed below in order of preference. If parameters from two methods conflict, the more-preferred method will override the less-preferred method.

  • html tags
  • the data attribute
  • the remotedata attribute

Html tags

This is the method used in the Module Parameters examples.

<person>
  <name>Bob</name>
</person>

The parameters are supplied by html tags inside the module element.

The data attribute

The data attribute gets the parameters from a local file. For example,

bob.json

{ 
  "name" : "Bob"
}

example-pre.html

<person data="bob.json"/>

would result in the same output as the html tags example above.

The remotedata attribute

The remotedata attribute is used for loading parameters from a remote url.

<person remotedata="http://dataserver/person/bob"/>

Preprocessing Javascript

Modest can preprocess javascript files. When the modest command is run, it looks for <script> tags that have the pre attribute. The javascript will be executed and the script tag will be removed.

example-pre.html

<html>
  <head>
    <include>animal</include>
  </head>
  <body>
    <script src="addCow.js" pre></script>
  </body>
</html>

animal.xml

uses: name, url
<div>
  <a uses="name href=url"/>
</div>

addCow.js

var cow = {
  "name" : "cow",
  "url" : "http://en.wikipedia.org/wiki/Cattle"
};
$(document.body).append(modest.render('animal',cow));

example.html (output)

<html>
  <head>
  </head>
  <body>
    <div class="animal">
      <a class="name" href="http://en.wikipedia.org/wiki/Cattle">cow</a>
    </div>
  </body>
</html>

HTML, XML, and XHTML

Compiling

Modest creates output that conforms to both HTML and XHTML standards. It will convert void HTML elements to use the optional /> ending to conform to XHTML. (E.g. <img> becomes <img />). It will convert self-closing tags to start and end tags to conform to HTML. (E.g. <script/> becomes <script></script>).

Modest removes XML declarations (e.g. <?xml version="1.0"?>), but preserves doctype declarations (e.g. <!doctype html>).

Though modest output files conform to both standards, input files (-pre files) are assumed to be html. If you want to use XHTML in a modest html (-pre) file, include an XML declaration at the top, e.g.

<?xml version='1.0' encoding='UTF-8'?>

This will alert the JSDOM that it should treat the file as XHTML.

Module files

Module files are XML by default, and if no extension is specified for an included module, .xml is assumed. Most HTML snippets will do fine as an XML module. The exception to this is if you want to use an HTML void element (such as <img>) without the optional /> ending in the tag.

To use a different extension for a module file, specify it in the include tag. For example:

<head>
  <include>image.html</include>
</head>
⚠️ **GitHub.com Fallback** ⚠️