Nested elements naming style (Jade, HAML, Slim)

797 Views Asked by At

Looking for solution how to use SMACSS naming convention with jade, haml or slim template engine.

Expect following jade code :

.module
  .child
  .child

as output i'll get following:

<div class="module">
  <div class="child"></div>
  <div class="child"></div>
</div>

but i'd like to reach following result:

<div class="module">
  <div class="module-child"></div>
  <div class="module-child"></div>
</div>

is there any solution to manage it like i can do it in SASS for example, i mean avoid adding 'module-' string to each 'child' manually ?

UPDATE

Also acceptable solutions with Haml and Slim

3

There are 3 best solutions below

2
On BEST ANSWER

This is the closest I got with jade (live playground here):

mixin e(elt)
  - var a = attributes;
  - var cl = attributes.class;delete attributes.class
  - var elt = elt ? elt : 'div' // If no parameter given
  if cl
    - var cl = parent + '-' + cl
  else
    - var cl = parent
  #{elt}&attributes({'class': cl}, attributes)
    block

- var parent = 'box'
+e('aside')#so-special
  +e('h2').title Related
  +e('ul').list
    +e('li').item: +e('a')(href='#').link Item 1
    +e('li').item: +e('span').link.current Item 2 and current
    +e('li').item#third(data-dash='fine', aria-live='polite') Item 3 not even a link
      | multi-line
      | block
    // - var parent = 'other' problem of scope I guess 
    +e('li').item lorem ipsum dolor sit amet

- var parent = 'footer'
+e('footer')(role='contentInfo')
  +e.inner © Company - 2014

A mixin named e will output an element taken as a parameter (default is div) with its attributes and content as is, except for the first class that'll be prefixed with the value of the variable parent (or will be the value of parent itself if it hasn't any class)
I prefer using default jade syntax for attributes, including class and id than passing many parameters to a mixin (this one doesn't need any if it's a div, as with .sth text'd output <div class="sth>text</div> and +e.sth text will output <div class="parent-sth>text</div>)
Mixin would be shorter if it didn't have to deal with other attributes (href, id, data-*, role, etc) Remaining problem: changing the value of parent has no effect when it's indented. It had with simpler previous attempts so I guess it's related to scope of variables. You theoretically don't want to change the prefix for child elements but in practice... Maybe as a second optional parameter?

Things I had problem with while playing with jade:

  • attributes doesn't work as expected. Now it's &attributes(attributes). Thanks to jade-book issue on GitHub
  • but it'll output class untouched plus the prefixed one, so I had to remove it (delete) in a place it'd be executed by jade
2
On

You should be able to achieve this with SASS. As long as you have the latest SASS version, you should be able to use the following syntax:

.module {
    &-child {

    }
}

Have a look at this article for more information on newer features of SASS http://davidwalsh.name/future-sass

1
On

Some thoughts from me: what's wrong with a variable?

- var myModule = 'module'
div(class="#{myModule}")
  div(class="#{myModule}-child")
  div(class="#{myModule}-child")

or combine it with an each:

- var myModule2 = 'foobar'
div(class="#{myModule2}")
  each idx in [0, 1, 2, 3]
    div(class="#{myModule2}-child") I'm child #{idx}

Sure, there is much more code to write, but if a change is neccessary then you must do this only at one point.

Ciao Ralf