inem / hamdown

[WIP] Next generation template language for fans of Haml and Markdown
MIT License
111 stars 4 forks source link

Logo

Demo app

https://github.com/kopylovvlad/rails_app_with_hamdown

Why: To achieve hyper-efficiency when working on static websites

It is very efficient to use Markdown with static site generators, like Jekyll or Middleman. Although, sometimes Markdown is not enough.

For example, if you might want to add some custom styling with libraries like Tachyons or TailwindCSS to a certain element, there is no easy way to do that.

It would be great to write something like this:

# Main Title

%h2.f2.helvetica.strike 
  Fancy title
  **with some bold**

Some content

and have it transformed into:

<h1>Main Title</h1>
<h2 class=“f2 helvetica strike”>Fancy title <strong>with some bold</strong></h2>
<p>Some content</p>

The suggestion is to develop a new format called Hamdown to combine the power of both Markdown and Haml.

Current status

Proposal draft (no implementation yet)

Key features of Hamdown:

  1. Support both Haml and Markdown in the same format
  2. Built-in front-matter support
  3. (Optionally) plug common CSS libraries directly from frontmatter
  4. Tweak markdown generation rules from frontmatter

1. Haml & Markdown together

Hamdown:

%section.container
  # Title
  ## Subtitle
  .content
    ![](/images/main.png)

Resulting HTML:

<section class="container">
<h1>Title</h1>
<h2>Subtitle</h2>
<div class="content">
  <img src="https://github.com/inem/hamdown/raw/master/images/main.png"/>
</div>
</section>

2. Built-in front-matter support

Now, front-matter is handled by static site generators. But I see no reason why it couldn't be a part of Hamdown. This should significantly reduce the amount of work to be done by static site generator, and even remove need in them in simple cases.

Hamdown:

---
title: Colored cars
colors: 
  - blue
  - red
  - black
---
%h1= @title
- @colors.each do |color|
  === ![](/images/#{color}_car.png)

Resulting HTML:

<h1>Colored cars</h1>
<img src="https://github.com/inem/hamdown/raw/master/images/blue_car.png"/>
<img src="https://github.com/inem/hamdown/raw/master/images/red_car.png"/>
<img src="https://github.com/inem/hamdown/raw/master/images/black_car.png"/>

3. (Optionally) plug common CSS libraries directly from frontmatter

Hamdown:

---
css: tachyons
---

# Hey hey

Resulting HTML:

<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/tachyons/4.9.1/tachyons.min.css">

<h1>Hey hey</h1>

4. Tweak markdown generation rules from frontmatter

Hamdown:

---
defaults: 
  p: .f6.purple.m4.p2
  h2: .f4.red
---

# Title
## Subtitle

Some text

More text

Resulting HTML:

<h1>Title</h1>
<h2 class="f4 red">Subtitle</h2>

<p class="f6 purple m4 p2">Some text</p>

<p class="f6 purple m4 p2">More text</p>

Current alternatives (suck)

1. Plain HTML inside Markdown

## Main Title

<h2 class=“f2 helvetica strike”>Fancy title</h2>

Some content

You can't do nested markdown inside HTML blocks:

<aside class="pic">
  ![](https://i.imgur.com/rZ183q9.png)
</aside>

^Markdown inside <aside> tag is treated like regular text.

2. Template parsers chaining (.md.erb)

Ruby on Rails brought the idea of template parsers chaining. Examples:

With md.erb chain you can define and use your own helpers, so your code looks like this:

## Main Title

<%= fancy_h2 "Fancy title" %>

Some content

Limitations are obvious:

3. Use markdown filters inside Haml

Then you simply use haml as the main format, but switch to markdown when you have big chunks of texts:

%h1 Main Title

%h2.f2.helvetica.strike Fancy title

:markdown
  Some content

As you see, all of the options have significant limitations. This is why Hamdown format and generator have to be developed.

Challenges

Obviously, there could be some clashes between Haml and Markdown generation rules. The general idea is to treat blocks starting with ., % like Haml, and blocks starting with *, _, #, - (and so on) treat like Markdown.

An example of conflict is "#" symbol. It is used in Haml for id attribute, and in Markdown as headers.

A quick solution might be to prohibit ids in Haml part of Hamdown. A smarter solution would be to treat #person_233 Max as Haml, and # Max as Markdown

Anyway, it makes sense to start with only a subset of Markdown features.

Roadmap

Contribution

You are very welcome to contribute! Whether you'll write a spec, decide to develop a proof of concept of Hamdown, or share an idea of how to approach the development - it all would be very valuable.

Idea author has no experience in template engines development. Although I am willing to educate myself and work on the specification, I don't see myself as the main developer of the Hamdown engine yet.

Implementation ideas

  1. Use hamlit as a starting point, and implement additional conversion rules for markdown blocks
  2. Convert hamdown to kramdown format, and then simply use kramdown to generate HTML
  3. Try Redcarpet Custom Renderers.
  4. Reuse haml parser
  5. Your suggestion

Criticism

Hamdown goes against the idea of content and representation rules separation.

It does. Although the hypothesis is that this approach would be extremely useful for quick experiments and non-pretentious personal websites.

The idea of Markdown to be human-readable, and HAML makes it look awful.

HAML usage is not the obligation, it is an opportunity. The idea is to provide a cheap way to experiment with look and feel for static websites. With libraries like Tachions it is just a matter of adding a few classes to an element. Once you've finished experimenting, simply update your site-wide CSS rules, and throw away temporary HAML stuff, if needed.

Look at the Clojure. Clojure code might look confusing and weird for an unprepared mind, but no doubts Clojure is a very powerful insrument. In Hamdown we consciously trade a bit of Markdown's elegance for more possibilities.

You can use plain HTML or ERB if Markdown is not enough

Yes, but HTML closing tags bring too much overhead, and non-trivial constructions take too much visual space, so it stops look like Markdown at all.

Simply use kramdown

Yes, it looks like it is possible to achieve similar functionality by chaining Kramdown with ERB (file.md.erb), but it is hard to switch to kramdown, when you're used to HAML.