Giter Site home page Giter Site logo

calliope's Introduction

Calliope

Calliope - An Elixir Haml Parser Build Status

For those of you that prefer the poetic beauty of HAML templates over HTML, then Calliope is the package for you. Calliope is a parser written in Elixir that will render HAML/Elixir templates into HTML. For example, we can render the following HAML:

!!! 5
%html{lang: "en-US"}
  %head
    %title Welcome to Calliope
  %body
    %h1 Calliope
    %h2 The muse of epic poetry

Into this HTML:

<!DOCTYPE html>
<html lang="en-US">
  <head>
    <title>Welcome to Calliope</title>
  </head>
  <body>
    <h1>Calliope</h1>
    <h2>The muse of epic poetry</h2>
  </body>
</html>

Using

Calliope is simple to add to any project. If you are using the hex package manager, just add the following to your mix file:

def deps do
  [ { :calliope, '~> 0.4.2' } ]
end

If you aren't using hex, add the reference to the github repo.

def deps do
  [ { :calliope, github: "nurugger07/calliope" } ]
end

Then run mix deps.get in the shell to fetch and compile the dependencies. Then you can either call to Calliope directly:

iex(1)> Calliope.render "%h1 Welcome to Calliope"
"<h1>Welcome to Calliope</h1>"

Or you can use Calliope in a module and call through your module:

defmodule MyModule do
  use Calliope
end
iex(1)> MyModule.render "%h1 Welcome to Calliope"
"<h1>Welcome to Calliope</h1>"

Formating

If you are not familiar with HAML syntax I would suggest you checkout the reference page. Most of the syntax has been accounted for but we are in the process of adding more functionality.

HAML is basically a whitespace sensitive shorthand for HTML that does not use end-tags. Although Calliope uses HAML formating, it does use its own flavor. Sounds great but what does it look like:

%tag{ attr: "", attr: "" } Content

Or you could use the following:

%tag(attr="" attr="" ) Content

The id and class attributes can also be assigned directly to the tag:

%tag#id.class Content

If you are creating a div you don't need to include the tag at all. This HAML

#main
  .blue Content

Will generate the following HTML

<div id='main'>
  <div class='blue'>
    Content
  </div>
</div>

Passing Arguments

The render function will also take a list of named arguments that can be evaluated when compiling the HTML

Given the following HAML:

#main
  .blue= content

Then call render and pass in the haml and content:

Calliope.render haml, [content: "Hello, World"]

Calliope will render:

<div id='main'>
  <div class='blue'>
    Hello, World
  </div>
</div>

Embedded Elixir

Calliope doesn't just evaluate arguments, you can actually embed Elixir directly into the templates:

for

- for { id, headline, content } <- posts do
  %h1
    %a{href: "posts/#{id}"}= headline
  .content
    = content

Pass that to render with a list of posts

Calliope.render haml, [posts: [{1, "Headline 1", "Content 1"}, {2, "Headline 2", "Content 2"}]

Will render

<h1>
  <a href="/posts/1">Headline 1</a>
</h1>
<div class="content">
  Content 1
</div>
<h1>
  <a href="/posts/2">Headline 2</a>
</h1>
<div class="content">
  Content 2
</div>

if, else, and unless

- if post do 
  %h1= post.title
  - if post.comments do
    %p Has some comments
  - else
    %p No Comments
- unless user_guest(user)
  %a{href: "posts/edit/#{id}"}= Edit

case

- case example do
  - "one" -> 
    %p Example one
  - other -> 
    %p Other Example  
      #{other}

Local Variables

- answer = 42
%p= "What is the answer #{answer}"

Anonymous Functions

- form_for @changeset, @action, fn f ->
  .form-group
    = label f, :name, "Name", class: "control-label" 
    = text_input f, :name, class: "form-control" 
  .form-group
    = submit "Submit", class: "btn btn-primary" 

Precompile Templates

Calliope provides an Engine to precompile your haml templates into functions. This parses the template at compile time and creates a function that takes the name and args needed to render the page. These functions are scoped to the module that uses the engine.

Adding this functionality is easy.

  defmodule Simple do

    use Calliope.Engine

    def show do
      content_for(:show, [title: Calliope])
    end

  end

If you are using layouts, you can set the layout and call the content_with_layout function.

  defmodule Simple do

    use Calliope.Engine, layout: "application"

    def show do
      content_with_layout(:show, [title: Calliope])
    end

  end

In addition to :layout, you can also set the following options:

:path - provides the root path. The default is the current working directory. :templates - used to define where the templates are stored. By default it will use :path :alias - used to set the directory where the templates are located. The default value is 'templates'. :layout_directory - the directory that your layouts are stored relative to the templates path. The default directory is layouts :layout - the layout to use for templates. The default is :none or you can pass in the name of a layout.

Coming Soon

  • Rendering partials
  • Exception messages

calliope's People

Contributors

alco avatar alg avatar hashrocketeer avatar joakimk avatar lowks avatar mgwidmann avatar mkasztelnik avatar mkompanets avatar nurugger07 avatar pavloo avatar phillipp avatar ponty96 avatar sergiorivas avatar smpallen99 avatar ugisozols avatar vicmargar avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

calliope's Issues

Evaluate cond conditionals

Evaluating cond conditionals requires compiling a smart script.
Given the following haml:

- cond do
-  1 + 1 == 1 -> 
  %p Never matches
-  2 * 2 != 4 ->
  %p Nor this
-  true ->
  %p This matches

Then the html output will be:

<p>This matches</p>

Attributes with names ending with "id" get interpreted as the "id" attribute

Steps to repro (on version 0.3.0, first and fourth lines are the bug):

iex(1)> Calliope.render(".foo{attr-id: \"bar\"}")
"<div id=\"bar\" class=\"foo\" attr-></div>"
iex(2)> Calliope.render(".foo{attr-id-bar: \"bar\"}")
"<div class=\"foo\" attr-id-bar=\"bar\"></div>"
iex(3)> Calliope.render(".foo{id-bar: \"bar\"}")
"<div class=\"foo\" id-bar=\"bar\"></div>"
iex(4)> Calliope.render(".foo(attr-id= \"bar\")")
"<div id=\"bar\" class=\"foo\" attr-></div>"

I'd expect the output of the first/fourth line to be "<div class=\"foo\" attr-id=\"bar\"></div>" similar to lines 2/3. I ran across this while trying to create an element with a data-form-id attribute, which I couldn't find a way to do.

Raise an error when 2 ids are provided

When a tag contains two id attributes an exception should be raised.
Given the following haml:

#post{id: 'article'}

or this:

#post#article

Raise an exception.

A problem with string interpolation in HTML attributes

A statement like this

%link(rel="stylesheet" href="#{ static_path(@conn, "/p/css/responsive.css") }")

produces this

<link rel="stylesheet" href="#{ static_path(@conn "/p/css/responsive.css">}")

while we expect the result should be similar to EEx like this

<link rel="stylesheet" href="<%= static_path @conn, "/p/css/responsive.css" %>">

Could you help?

BTW, Thank you very much for this excellent library. It helps us (and many others) switch from Ruby to Elixir easier. ๐Ÿ˜„

Allow use of parens and brackets in haml content

First - love the library. Had a lot of fun playing with it this evening :)

I was playing with Angular and was running into some issues with the paren and bracket characters being picked up as attributes every time they appear in a line. A few examples:

%h1 {{user.name}}

would ideally parse to

<h1>{{user.name}}</h1>

and

%a{ng-click: "doSomething()"} Click Me

would parse to

<a ng-click="doSomething()"> Click Me </a>

In both of those cases I believe the ( or { character is being picked up by the parser as an indicator of an attribute on the element itself versus html content. I tried to glance at the parser to see if it was a reasonably easy fix to submit a PR, but without a lot of time tonight and being brand new to Elixir I didn't have much luck.

Thanks for the awesome work!

Explicit end needed for anonymous functions

So I was trying to make some forms in a Phoenix application using phoenix_haml/Calliope and I ran into some problems.

First, what I ultimately want to produce is something equivalent to this:

<%= form_for @changeset, @action, fn f -> %>
  <div class="form-group">
    <label for="page[title]">Title</label>
    <%= text_input f, :title, class: "form-control" %>
  </div>
  <div class="form-group">
    <label for="page[body"]>Body</label>
    <%= textarea f, :body, class: "form-control" %>
  </div>
  <div class="form-group">
    <%= submit "Submit", class: "btn btn-primary" %>
  </div>
<% end %>

And here's what I had to do in order to get it working:

= form_for @changeset, @action, fn f ->
  .form-group
    %label{ for: "page[title]" }
      Title
    = text_input f, :title, class: "form-control"
  .form-group
    %label{ for: "page[body]" }
      Body
    = textarea f, :body, class: "form-control"
  .form-group
    = submit "Submit", class: "btn btn-primary"
- end

Initially I had tried this:

- form_for @changeset, @action, fn f ->

but I found that the compiler was treating everything inside the anonymous function as if it were Elixir instead of HAML. As you can imagine this causes all sorts of mysterious and obtuse errors. I believe it was this pull request: #40, that introduced that functionality.

After playing around with the compiler I was able to determine that the issue with the output had to do with with this line:

Regex.match? ~r/(fn )|(fn\()[a-zA-Z0-9,\) ]+->/, script ->

My understanding is that the parser translates - into :smart_script which gets evaluated differently from a regular script. Regular scripts don't add the closing <% end %> so it's necessary to add it manually in this particular case.

I was able to come up with something of a fix for this whole thing. By adding this:

Regex.match? ~r/(fn [a-zA-Z0-9,\) ]+=>)|(fn\()[a-zA-Z0-9,\) ]+=>/, script ->
  %{cmd: String.replace(script, ~r/=>$/, "->"), wraps_end: "<% end %>", end_tag: "%>", open_tag: "<%="}

before the previously mentioned cond match I was able to make it so that smart scripts which ended an anonymous function that use a => were treated correctly as HAML and correctly wrapped the end tag (note: the fat arrow gets replaced so the resulting EEX is good). The existing functionality for smart scripts didn't appear to be impacted.

Rather than submit a pull request I figured I'd open an issue to make this known. I'm aware there's already some non-standard stuff in Calliope as a matter of necessity. Adding more without a really good reason seems less than ideal. But on the flip side; having to explicitly add an end statement is already non-standard HAML.

Either way I suggest that the documentation be updated to explain the need for using - and adding a closing end manually since I imagine I won't be the only person to run into this. Without first really digging into the parser and compiler the error messages that Elixir produces for this are worse than useless.

Doesn't preserve returns

The content:

.simple_div
    %b Label:
    Content
Outside the div

should render to:

<div class='simple_div'>
  <b>Label:</b>
  Content
</div>
Outside the div

Instead, it renders to:

<div class="simple_div"><b>Label:</b>Content</div>Outside the div

Losing the returns means that the html renderer doesn't put a space in between Label: and Content. So it looks like this: "Label:Content" instead of "Label: Content"

The ruby HAML gem does preserve the returns.

Version 0.4.2 is unusable

After wasting a bunch of time trying to figure out why all my haml was failing to compile I discovered that the changes between 0.4.1 and 0.4.2 broke a bunch of stuff.

  • issue #78 is already reported
  • issues with calling functions in = and - tags

I spent some time refactoring the tokenizer and resolved the #78 issue (not commited), but found other issues. I don't have a lot of time to look at it right now. 0.4.1 is working fine for me.

I think we should roll back to 0.4.1.

Old HAML hash rocket syntax breaks.

Sticking the generated app.layout into a HTML => HAML converter will produce a page that renders a raw string.

!!!
%html{:lang => "en"}
  %head
    %meta{:charset => "utf-8"}
    %meta{:content => "IE=edge", "http-equiv" => "X-UA-Compatible"}
    %meta{:content => "width=device-width, initial-scale=1", :name => "viewport"}
  %body
    .container{:role => "main"}
      .header
        %ul.nav.nav-pills.pull-right
          %li
            %a{:href => "http://www.phoenixframework.org/docs"} Get Started
        %span.logo
      %p.alert.alert-info{:role => "alert"}= get_flash(@conn, :info)
      %p.alert.alert-danger{:role => "alert"}= get_flash(@conn, :error)
      = @inner
    / /container
    %script{:src => static_path(@conn, "/js/app.js")}
    :javascript
      require("web/static/js/app")

Switching the hash rockets from

%p.alert.alert-info{:role => "alert"}= get_flash(@conn, :info)

to

%p.alert.alert-info{role: "alert"}= get_flash(@conn, :info)

fixes this issue.

At a minimum, this should throw an error.

Phoenix static_path/2 call in attribute values

Just following up to an issue I mentioned in chrismccord/phoenix_haml#14.

I was trying to convert phoenix's default web/templates/layout/application.html.eex:

<link href="<%= static_path(@conn, "/css/app.css") %>" rel="stylesheet" >

Which renders out to something similar to this:

<link href="/css/app.css?vsn=12AB1212" rel="stylesheet">

HAML equivalent:

%link{href: "#{static_path(@conn, "/css/app.css")}" rel: "stylesheet"}

will give the following when I attempt to run it under phoenix 0.13.1:

== Compilation error on file web/views/layout_view.ex ==
** (ArgumentError) cannot set attribute @conn inside function/macro
    (elixir) lib/kernel.ex:2025: Kernel.do_at/4
    (elixir) expanding macro: Kernel.@/1
    (test) web/views/layout_view.ex:1: Test.LayoutView."application.html"/1
    (phoenix) ~/.../web/views/layout_view.ex:1: Phoenix.Template.__before_compile__/1

This was my workaround:

- item = static_path(@conn, "/js/app.js")
      %script{src: "#{item}"}

Should I be using a different syntax to make that call?

Angular expression in attribute doesn't parse nicely

We found a problem when parsing the following tag with angular expression in the attribute:

%li(ng-repeat="pager in paging.pagers" ng-class=" paging.pagination.current_page === pager ? 'active' : '' ")

Somehow, it's generated as:

<li class="paging.pagination.current_page === pager ? ng-scope" ng-repeat="pager in paging.pagers" ng-active'="" "=""></li>

While the expected behavior is this:

<li ng-repeat="pager in paging.pagers" ng-class=" paging.pagination.current_page === pager ? 'active' : '' " class="ng-scope"></li>

Would really appreciate if it can be fixed. Thank you. :)

Tag with attributes not rendered as one-liner

I am not sure if the issue is related to calliope or to the integration with phoenix, but I have an issue when rendering a tag with attributes:

%a{ href: "http://api.phoenixframework.org/" }= "Docs"
# renders nothing

%a{ href: "http://api.phoenixframework.org/" } Docs
# <a href="http://api.phoenixframework.org/" }="" doc=""></a>

%a{ href: "http://api.phoenixframework.org/" }
  Docs
# <a href="http://api.phoenixframework.org/">Docs</a>

I tried the same with a tag without attributes and everything rendered fine.

I also tried the alternative markup:

%a( href="http://api.phoenixframework.org/" )= "Docs"
# renders nothing

%a( href="http://api.phoenixframework.org/" ) Docs
# <a href="http://api.phoenixframework.org/" )="" doc=""></a>   

%a( href="http://api.phoenixframework.org/" )
  Docs
# <a href="http://api.phoenixframework.org/">Docs</a>

So the same behavior as with the default haml syntax.

Syntax Issues with Attribute Values

I am looking to use Calliope for standard HTML rendering, but running into a serious issue.

iex> Calliope.render "%a{href: page_path(@conn, 1)} Link"
"<a href='<%= page_path %>'(@conn 1)} Lin></a>"

The expected result is <a href="/pages/1">Link</a>. Notice the difference in attribute grouping, and the lack of final k on Link.

I would appreciate any feedback on how to get this case to work. I am using this via phoenix_haml and phoenix.

Evaluate conditions in attributes

Calliope does not seem to support advanced attribute syntax like this:

.field{class: Game.finished?(game) && "finished"}

Calliope will not evaluate any code inside attribute tags, and attempt to add above-mentioned code as a string to the class attribute. When attempting to use string-interpolation instead, Calliope will attempt to read it as AST and choke on it with other errors.

This would be a great feature to have. I have no idea how to add conditional classes to my elements without it.

It is described under 'Attributes' in the original Haml reference guide

Support setting local variables

Support setting local variables with smart script per this example:

- var = "testing"
%p= var

It should generate the following EEx:

<% var = "testing" %>
<p><%= var %></p>

I'll have a pull request for this soon.

Incorrectly generates ng-class attribute

I've found another bug as follows:

%li(ng-class="followees_tab") generates <li class="followees_tab" ng->

It should generates <li ng-class="followee_tabs">

BTW, we start using more calliope now. This library will be important for the success of phoenix framework. Probably, we will have chances to send pull requests soon.

Attributes: function evaluation without interpolation

Hi,
I've wondered why string interpolation is necessary for setting attributes like this:

%tr{class: "#{my_function(my_data)}"}

I could not find an issue where this is discussed in detail. I'd rather like the following syntax (my_function may be replaced with MyModule.my_function):

%tr{class: my_function(my_data)}

What exactly is the problem with making this possible?

Evaluate case conditionals

Evaluating case conditionals requires compiling a smart script.
Given the following haml:

- case data do
-  { :ok, content } ->
    %p= content
-  :error ->
    %p Something went wrong

When data has the value { :ok, "Hello"}
Then the html output would be the following:

<p>Hello</p>

Support Haml comments

Need to add support for haml comments. This would prevent the compiling of haml markup to html

Given the following:

%p foo
  -#  This would 
    Not be
    out put
% bar

Then only the following would be output:

<p>foo</p>
<p>bar</p>

Calliope chokes on functions that take a block.

(This was first posted on the (phoenix_haml github project](chrismccord/phoenix_haml#35), and there I was guided here)

First and foremost: How nice that there is a HAML-parser for Elixir! :-)

I have this file (saved as templates/layout/menu.html.haml)

%nav.ui.top.fixed.menu
  .header.item
    Cyclicash
  .right.menu
    =link to: login_path, class: "item" do
      login

    = link to: register_path, class: "item" do
      register

link is a phoenix_html function that optionally takes a do: block as parameter. This way, in EEx, you can embed more complex html in your links.

However, this breaks the Calliope's HAML-parsing. Here is the stacktrace:

== Compilation error on file web/views/layout_view.ex ==
** (EEx.SyntaxError) web/templates/layout/menu.html.haml:11: unexpected end of string, expected a closing '<% end %>'
    (eex) lib/eex/compiler.ex:68: EEx.Compiler.generate_buffer/4
    (eex) lib/eex/compiler.ex:41: EEx.Compiler.generate_buffer/4
    (phoenix) lib/phoenix/template.ex:321: Phoenix.Template.compile/2
    (phoenix) lib/phoenix/template.ex:154: Phoenix.Template."-MACRO-__before_compile__/2-fun-0-"/3
    (elixir) lib/enum.ex:1473: Enum."-reduce/3-lists^foldl/2-0-"/3
    (phoenix) expanding macro: Phoenix.Template.__before_compile__/1
    web/views/layout_view.ex:1: Heads.LayoutView (module)
    (elixir) lib/kernel/parallel_compiler.ex:100: anonymous fn/4 in Kernel.ParallelCompiler.spawn_compilers/8

I think it chokes on the optional block-passing.

Double interpolation does not parse correctly

~S/%a(href="#{a} #{b}")/ does not parse correctly. Here is the result of a test case.

    ** (CalliopeException) Invalid attribute 'href="1{a' on line number 1`
     stacktrace:
       (calliope) lib/calliope/parser.ex:183: Calliope.Parser.raise_error/3
       (calliope) lib/calliope/parser.ex:140: Calliope.Parser.merge_attributes/2
       (calliope) lib/calliope/parser.ex:38: Calliope.Parser.parse_line/2
       (calliope) lib/calliope/parser.ex:22: Calliope.Parser.parse_lines/1
       (calliope) lib/calliope/parser.ex:18: Calliope.Parser.parse/1
       (calliope) lib/calliope/render.ex:7: Calliope.Render.precompile/1
       test/calliope/render_test.exs:4: CalliopeRenderTest.render/2
       test/calliope/render_test.exs:165: (test)

Should pipe character be considered white space?

I noticed that the pipe character | is included in the white space regex. I question if that was intent. Tests still pass with it removed. Furthermore, it breaks my implementation of multiline fn, issue #37.

What was the intended purpose of including this character in white space? Note that ruby haml uses the pipe at the end of a line for string continuation.

Render a partial with arguments

Calling render and passing a partial file name should compile. Render partial should also accept arguments. This should be in the similar to the current render but need to test.
Given the following haml:

%p
  = render "templates/shared/partial", [ arg: "New Partial" ] 

Angular string interpolation doesn't always work correctly.

Sometimes, when I put an angular string interpolation ( using {{ }} ) in the attribute, for example:

%textarea.form-control(id="{{ journal_entry.id }}" rows=5)

It might generate an invalid HTML like this:

<textarea id="{{" class="form-control" rows="5"></textarea>

While the expected result is like this:

<textarea class="form-control" id="420" rows="5"></textarea>''

However, it doesn't always behave like that, which is confusing, the following generates the correct result:

%a.pull-left.hidden-sm.hidden-xs(ng-hide="show_new_entry_form" ng-href="/user/{{ current_user.username }}/profile")

converted to:

<a class="pull-left hidden-sm hidden-xs" ng-hide="show_new_entry_form" ng-href="/user/helloworld/profile" href="/user/helloworld/profile"></a>

Would really appreciate if it can be fixed, otherwise we need to check our templates back and forth, and convert some lines to regular html to make it work.

TIA,
~ John

Incorrectly removed a comma in an attribute string

This line

%a.btn.btn-default.btn-lg(href="" ng-click="loadMore(pagination, get_page)")"

returns

<a class="btn btn-default btn-lg" href="" ng-click="loadMore(pagination get_page)"></a>

The expected result is

<a class="btn btn-default btn-lg" href="" ng-click="loadMore(pagination, get_page)"></a>

We use attribute strings to call Angular functions, so this bug breaks a lot of our code. Could you please fix it? Thank you very much. ๐Ÿ˜„

Question: why use `-` instead of `=`?

I see docs say to use:

- if post do 
  %h1= post.title

But in EEx, you would've used <%= if %>, as that's the elixir way of doing things. Why does Calliope go with - instead of =?

Evaluate multiline fn

I'd like the ability to generate the following EEx code.

 <%= for item <- items do %>
   <%= ExForm.form_for(item, "/" fn(f) -> 
          f
          |> ExForm.input(:name)
          |> ExForm.submit("save")
         end) %>
  <%= end %>

I have implemented it as the following haml:

 - for item <- items do
   = ExForm.form_for(item, "/" fn(f) -> 
     f
     |> ExForm.input(:name)
     |> ExForm.submit("save")

A can submit a pull request soon if we agree on the syntax.

Handle invalid indentation

The indentation should be consistent and nested correctly.
Given the following haml:

%p
      %h1 Calliope
    %h2 Doesn't like this

Then an invalid indentation exception should be raised

link do .. end block

You can use link method as such:

link to: "/hello" do
  "world"
end

The only way to make it work in calliope is to write it like this:

= link to: "/hello" do
  world
- end

Is that normal? I'd expect it to function the same as conditionals being handled right now.

Pre-compile haml templates

Should be able to pre-compile and index haml templates. Then execute elixir code when args are supplied at runtime.

Attributes are often not parsed correctly

This does not parse correctly:

iex> Calliope.Render.precompile(".foo{a: 1, b: mystruct.foo, data: %{foo: 3}}")
"<div class=\"foo\" a='<%= 1 %>' b='<%= mystruct %>'.foo data: %{foo='<%= 3 %>'></div>\n"

Note that instead of mystruct.foo being escaped, only mystruct is escaped.

Also note that the data attribute, which contains a nested map, is not properly turned into HTML, but its nested foo tag for some reason is. Ruby's HAML would turn nested maps into attributes separated with - (so %mytag{data: %{foo: 1, bar: 2} would result in <mytag data-foo=1 data-bar=2>), and I would also accept this to not work, and Calliope raising an error because a plain map does not implement the String.Chars protocol. The current output is clearly wrong and unusuable.

Support json style keys

HAML supports json style quoted keys on ruby 2.2, it would be great if calliope would too:

%meta{"http-equiv": "content-type", "content": "text/html; charset=utf-8"}

Markdown ?

hey there

I did a quick search of the code and couldn't see anything about Markdown ?

any thoughts on how I might add a Markdown filter?

I dont see any cross reference from Earmark

if this hasn't come up before am interested in looking into this myself

Evaluate if/else conditionals

Evaluating if/else conditionals requires compiling a smart script.
Given the following haml:

- if true do
  %p foo
- else
  %p bar

Then is should output the following html:

<p>foo</p>

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.