Skip to content

padolsey/SIML

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

77 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

SIML

SIML is the Simplified Markup Language. It is a conceptual hybrid strongly inspired by the simplicity of CSS selectors and SASS-style nesting.

Why did you make it?

  • This project was originally a personal exploration into the world of language parsing
  • Writing HTML isn't the worst thing in the world. But it takes time. And as a programmer, I'm lazy.
  • I enjoy the expressive power of tiny expressions (hence my love of Perl and RegExps)

Another templating hybrid whatchamacallit!1!?

No, SIML isn't a templating language. It doesn't currently provide constructs for including data, controlling flow or looping. Reasoning behind this:

  1. Feature bloat
  2. People still write plain ol' HTML
  3. Pure DOM templates are on the rise. See AngularJS or Knockout.

What is it?

SIML allows you to write HTML with more ease and less cruft. "SIML" is the name of the language, and also the utility for converting the language to HTML.

You can specify your elements through CSS selectors:

div           -> <div></div>
p.foo[baz]    -> <p class="foo" baz></p>
div#x.ace     -> <div id="x" class="ace"></div>
em > span     -> <em><span></span></em>
em 'Ok then'  -> <em>Ok then</em>

Ok, the last one wasn't a CSS selector, it included a string. But it makes sense, right?

SIML allows nesting with curlies, just like Sassy CSS:

section.body {
  h1#title {
    'Title'
  }
}

Or significant whitespace (i.e. indent to nest):

section.body
  h1#title
    'Title'

But you're not forced to build hierarchies with nesting; you can do one-liners instead:

section.body > h1#title 'Title'

That'll give you:

<section class="body">
  <h1 id="title">
    Title
  </h1>
</section>

As shown, SIML gives you the expressive power of CSS selectors. It also supports Attributes, Text and Directives.

section {          // Selector
  class: body      // Attribute
  ' foo blah '     // Text directive
  text: 'foo'      // Custom Text Attribute
  @foo(1,2,3)      // Custom directive
}

Note: You can extend SIML to support your own attributes, directives and psuedo-classes. For an example see generators/angular.js

SIML allows you to express more with less effort and, perhaps, more clarity:

section.contact > form

  h2 'Enter contact details'

  label[for=name]
    'Your name?'
    input#name
  
  label[for=human]
    'Are you human?'
    input:checkbox#human

  input:submit 'Submit form...'

That would give you:

<section class="contact">
  <form>
    <h2>
      Enter contact details
    </h2>
    <label for="name">
      Your name?
      <input id="name"/>
    </label>
    <label for="human">
      Are you human?
      <input type="checkbox" id="human"/>
    </label>
    <input type="submit"/>
  </form>
</section>

Is that it!?

Nope. SIML has some hidden gems. Some are still being tweaked.

For example, you can use the syntax (.../.../...) to form an ExclusiveGroup which will make SIML expand a hierarchy to conform to the alternates you specify:

a (b/c) // <a><b></b></a><a><c></c></a>

The above would be the same as writing:

a b
a c

A more useful example:

ul li ('wow'/'this'/'is'/'cool')

Becomes:

<ul>
  <li>wow</li>
  <li>this</li>
  <li>is</li>
  <li>cool</li>
</ul>

Another cool feature is multipliers (looks like a numeric psuedo class):

div a:3

Becomes:

<div>
  <a></a>
  <a></a>
  <a></a>
</div>

SIML's Extensibility

SIML allows you to make your own SIML generator by configuring:

  • Attribute handlers
  • Directive handlers
  • Pseudo-class handlers

This means, with a bit of configuration, you can write custom markup for your bespoke need. E.g.

This uses the angular generator which converts directives and undefined pseudo-classes to ng- attributes.

ul#todo-list > li
  @repeat( todo in todos | filter:statusFilter )
  @class({
    completed: todo.completed,
    editing: todo == editedTodo
  })

This would become:

<ul id="todo-list">
  <li
    ng-repeat="todo in todos | filter:statusFilter"
    ng-class="{ completed: todo.completed, editing: todo == editedTodo }"
  ></li>
</ul>

More info on AngularJS in SIML

Distributions

  • dist/siml.js: This is the default generator. No fancy stuff. Not even input:checkbox support.
  • dist/siml.html5.js: For now, this includes small things like doctype() support and input:type suppport.
  • dist/siml.angular.js: This is the angular generator, which makes it easier to write ng-... attributes with directives/pseudo-classes. (Example here). Currently also includes input:type support.
  • dist/siml.all.js: This includes html5 and angular.

How to use:

Browser:

<script src="dist/siml.all.min.js"></script>
<script>
  siml.html5.parse('a.foo#blah{span "ok"}', {
  	curly: false,  // [default=false] pass true if you're using curlies for hierarchy
  	pretty: false, // [default=true] Will give you pretty HTML
  	indent: '....' // [default='  '] Use custom indentation when pretty=true
  });
  // Generates:
  //   <a id="blah" class="foo">
  //   ....<span>
  //   ........ok
  //   ....</span>
  //   </a>
</script>

Node:

npm install siml
var siml = require('siml');

// Using the html5 generator (e.g. to support :checkbox)
siml.html5.parse('input:checkbox'); // => '<input type="checkbox" />'

More to come...

CHANGELOG

  • 0.2.0 Introduced single line macro-type selectors and quick-tags (vowelless) as part of the HTML5 generator, e.g. html hd{meta[charset=utf-8]+title{'Cool'}} bdy
  • 0.2.1 Various features added
  • 0.3.0
  • Many optimisations to prevent pointless backtracking in the parser
  • Refactor of parser components.
  • Introduction of ExclusiveGroups ((a/b)) and InclusiveGroups (a+b,d)
  • Improvement of specs
  • 0.3.1
  • Using Object.create shim (not exposed though)
  • Changed naming of customisable Parsers to "Generators" (makes more sense)
  • 0.3.2
  • Directives can now have children. See new feature specs.
  • Selector Prototypes. See Issue #2
  • 0.3.3
  • Break-out feature. See Issue #3
  • Support for here-doc style text (escaped) and HTML strings
  • 0.3.4
  • Fixed issue where attribute/directive values did not support backtick (no-escape) quotes. See Issue #4
  • 0.3.5
  • Fixed using quoted strings in 'heredoc' blocks. See Issue #5
  • 0.3.6
  • Fixed issue where singular tags would not multiply (selector:n). See Issue #6
  • Fixed issue where backtick quotes within regular quotes would get parsed and result in %HTML_TOKEN% tokens in the output.