Мой недавний/текущий проектик: hEmmet
Во многих редакторах, позволяющих работать с HTML, существует в том или ином виде поддержка сниппетов Emmet/ZenCoding. В общем случае это означает, что бы можете ввести строку типа
#container>.header+(ul.users>li.user*3)+.footer
затем нажать hotkey и получить
<div id="container">
<div class="header"></div>
<ul class="users">
<li class="user"></li>
<li class="user"></li>
<li class="user"></li>
</ul>
<div class="footer"></div>
</div>
Довольно удобная штука, согласитесь!
Недавно у нас в рабочем проекте возникла задача перегнать в rect-flux eDSL довольно развесистый макет, свёрстанный по методологии БЭМ. А БЭМ, это тэги с классами вида
<input class="login-form__login-field field field__disabled_t"/>
Смысл в таких классах, конечно же, есть и большой, но писать таковые руками - лениво. Поэтому довольно быстро нарисовался соответствующий (сабж).
Изначально утилита просто делала snippet -> eDSL
:
from:login$mixin>input.username+input.password+button.submit~disabled_t
разворачивался в
formc_ ("login" <> mixin) $ do
inputc_ "login__username" $ pure ()
inputc_ "login__password" $ pure ()
buttonc_ "login__submit login__submit_disabled_t" $ pure ()
Но потом я дописал генерацию заготовок для CSS
.login {
}
.login__password {
}
.login__submit {
}
.login__submit_disabled_t {
}
.login__username {
}
и, собственно, генерацию обычного HTML
<form class="login">
<input class="login__username"></input>
<input class="login__password"></input>
<button class="login__submit login__submit_disabled_t"></button>
</form>
(да, я знаю, что закрывающие тэги для <input>
излишни, и со временем это поправлю
)
В принципе подобным образом можно генерировать, скажем, деревья папок/файлов (этот вариант использования я планирую сделать) или JSON/YAML. Или, например, выдавать вёрстку в синтаксисе Elm'овского elm-html, Clojure'вского hiccup. Любые идеи для выходных форматов приветствуются!
Написан проект на Haskell. Легко прикручивается к любому редактору (у меня это Emacs), который умеет вызвать внешний процесс, скормить оному текст в STDIN и затем прочитать STDOUT.