早的時候我嘗試過用 Cirru 語法直接生成 HTML
後邊也嘗試過用 Cirru 語法生成 JavaScript 的模板
效果勉勉強強, 主要是學習的做用, 後來有了 React 就乾脆不用了
不過將來加載靜態資源, 仍是須要有 HTML, 就以爲麻煩, 搞出點東西來css
這個模塊通過幾回演變, 最終定型成爲 React 很類似的寫法
https://github.com/mvc-works/stir-template
代碼是用低版本的 CirruScript 寫的, API 也能在 CoffeeScript 裏調用html
stir = require :stir-tempate html = stir.html head = stir.head body = stir.body div = stir.createFactory :div renderPage = (data) -> stir.render stir.doctype() html null, head null, body null, div name: 'a', 'empty' div()
能夠看到模仿了 React, 渲染函數的第一個參數是屬性, 後邊是子元素
也提供了類似的輔助函數 render
, createElement
, createFactory
這樣寫出來的風格, 跟 CoffeeScript 裏寫 React 組件也就差很少了
本身須要生成個標籤的話, 能夠嘗試這樣的語法:react
newTag = stir.createFactory 'new-tag'
另外 <!DOCTYPE html>
算是個特殊的標籤, React 當中不提供
那麼 stir-template 就方便配合 React 用在後者不方便的地方webpack
個人我的項目目前已經大量使用 CirruScript.. 算是刷排名吧
https://github.com/mvc-works/webpack-workflow
CirruScript 首先是編譯到 ES5 的代碼生成器, 其次才當作模板語言用
我以爲 CoffeeScript 裏逗號太多, 縮進有 bug, 不開心一直用
CirruScript 配合 stir-template 跟 React 能夠這樣用:github
var stir $ require :stir-template React $ require :react var Page $ React.createFactory $ require :./src/page var ({}~ html head title body meta script link div a span) stir var line $ \ (text) (div ({} (:className :line)) text) = module.exports $ \ (data) return $ stir.render stir.doctype html null head null title null ":Coffee Webpack Starter" meta $ object (:charset :utf-8) link $ object (:rel :icon) :href :http://tp4.sinaimg.cn/5592259015/180/5725970590/1 link $ {} (:rel :stylesheet) :href $ cond data.dev :src/main.css data.style script $ object (:src data.vendor) (:defer true) script $ object (:src data.main) (:defer true) body null div ({} (:class :intro)) div ({} (:class :title)) ":This is a demo of Webpack usage." line ":Open Console to see how it loads." div null span null ":Read more at " a {} (:href :http://github.com/teambition/coffee-webpack-starter) , :github.com/teambition/coffee-webpack-starter span null :. div ({} (:class :demo)) React.renderToString (Page)
首先 HTML 的結構大概仍是能看到的, 接着就是語法了...web
縮進編程
Cirru 首先不是靠不少語法發揮做用的語言, 而是靠的縮進
整個代碼會先被解析成一棵樹, 這棵樹纔是後邊執行的重點
至少我在寫代碼的時候, 時時刻刻腦補他的樹是怎樣的, 能夠看 Demo:
http://repo.cirru.org/parser/json
美圓符號 $
gulp
美圓符號是爲了解決一類縮進而引入的, 好比說下邊這樣的代碼:
(set a (f1 (f2 (f3 x))))
縮進之後想一想都以爲很累, 會是這樣的, 還不如用括號
set a f1 f2 f3 x
那麼我引入 $
以後問題就輕鬆了, 直接就能夠這樣寫:
set a $ f1 $ f2 $ f3 x
逗號 ,
而後逗號也是爲了解決一類狀況引入的, 意思大概和 $
相反, 這樣的代碼
(set a (f1 a) (b) (f2))
改爲縮進的時候會是這樣的, 注意單行的 b
跟 f2
由於換行是有括號的:
set a f1 a b f2
那麼問題就來了, 有這樣的代碼怎麼表示, 這裏的 b
沒有括號了啊:
(set a (f1 a) b (f2))
因此我引入了 ,
, 做用就是去掉一層縮進, 大概就是這樣:
(set a (f1 a) (, b) (f2))
而後再用縮進的寫法, 就不會解析出錯了:
set a f1 a , b f2
根據上邊 3 條規則, Cirru 語法的縮進能表示絕大部分編程需求
除了表達式第一個操做符裏狂用括號的... 放哪一個語言裏都沒正常的辦法
CirruScript 的編譯器是經過識別表達式第一個操做符來轉換 AST 的
好比說 var
return
會被識別成對應的表達式或者語句的 AST
另外的 div
這樣的, 沒有對應的操做符, 就會被處理爲函數調用
object
操做符, 用來生成對象, 它的參數都是鍵值對
它有個 alias 是{}
, 我以爲看起來更習慣一些, 畢竟花括號仍是很眼熟的array
操做符一樣的意思, 用來生成數組, 它的參數就是元素了
它有個 alias 是 []
. 空數組可能會寫成 ([])
表示爲表達式了
字面量還有標識符我作了一些處理, 方便寫代碼用
這裏邊的 null
true
都是回自動識別的, 數字也作了處理
另外 data.main
這種, 也經過成員表達式的 AST 進行了處理
這裏邊還有些挺奇怪的好比說 {}~
, 實際上是 object~
可是可是, 這種正確的名稱應該是: **解構賦值**, 只是奇怪了點
奇怪的語法仍是到 http://script.cirru.org 看吧, 能夠看具體 AST 是什麼
字符串是個奇怪的事情, 由於 Cirru 是從圖形編輯器退化而來的..
退化嘛... 天然有的東西, 原來圖形很正常, 用文本表示就怪怪怪怪了的
Cirru 的語法裏 a
和 "a"
, 帶不帶引號, 其實是同樣的
不同的是 "a1 a2"
和 a1 a2
, 沒有引號就是兩個節點, 有就是一個
因此... 引號其實是爲了特殊字符的轉義用的, 還有這種呢 "a1\" a2"
你在 <textarea>
裏打字的時候不用轉義, 圖形界面嘛, 那是正常的時候
而後爲了表示字符串, 我動起來歪腦筋, 對, 用冒號 :
冒號開頭的就是字符串了, 沒有特殊字符的時候還能夠少一個字符:utf-8
跟 ":utf-8"
表示的是一個意思, 編譯的結果也是同樣的
必須加引號的是 ":hello world"
這樣的有特殊字符的節點
看多了 Clojure 的話其實冒號你是會習慣的...
最新版的 Gulp 應該是能識別 gulpfile.cirru
這樣的後綴的
我也寫了插件, 應該問題不大, CoffeeScript 這麼難用都用下來了
https://github.com/Cirru/gulp-cirru-script
通常我會寫個 template.cirru
文件, 從 Gulp 裏引用
最後執行一下函數, 就能從數據渲染出 HTML 來了:
require('cirru-script/lib/register') gulp.task 'html', (cb) -> html = require'./template.cirru' # <-- 引用看這裏 fs = require 'fs' if not env.dev assets = require './build/assets.json' env.main = "./build/#{assets.main}" env.vendor = "./build/#{assets.vendor}" fs.writeFile 'index.html', (html env), cb # <-- 調用看這裏
但願你有興趣用 CirruScript 生成 HTML. 早日淘汰手寫 HTML.