资源说明:Haml compiler for client side javascript view templates
# Client-side HAML compiler for Javascript and CoffeeScript The clientside-haml-js is a compiler written in CoffeeScript that compiles text templates in HAML format into Javascript functions that generate HTML. It has been inspired by the server side [haml Javascript project](https://github.com/creationix/haml-js), and has been written to be feature compatible with [Ruby server side HAML](http://haml-lang.com/docs/yardoc/file.HAML_REFERENCE.html), supports all major browsers (IE 7+, Firefox 3.6+, Chrome 10+, Safari), have minimal runtime dependencies (only [underscore.js (1.1.6+)](http://documentcloud.github.com/underscore/), [underscore.string (1.1.4+)](https://github.com/edtsech/underscore.string) and CoffeeScript if using CoffeeScript in your templates and jQuery 1.5.1+ if using compilation of templates from a URL). **NOTE:** The haml compiler requires a browser with a JSON parser. For browsers like IE7, you need to also include a JSON implementation. See [http://www.json.org/] for more details. A JSON implementation is available at [https://github.com/douglascrockford/JSON-js]. Thanks to following people who have contributed: [translated](https://github.com/translated), [pjmurray](https://github.com/pjmurray), [ramoney75](https://github.com/ramoney75), [jasonxia](https://github.com/jasonxia), [makevoid](https://github.com/makevoid) #Releases * Release 5.4 - 2013-11-18 - [https://github.com/uglyog/clientside-haml-js/tarball/release_5_4] [Release Notes](Release-5.4.markdown) * Release 5.3 - 2013-08-21 - [https://github.com/uglyog/clientside-haml-js/tarball/release_5_3] [Release Notes](Release-5.3.markdown) * Release 5.2 - 2013-08-11 - [https://github.com/uglyog/clientside-haml-js/tarball/release_5_2] [Release Notes](Release-5.2.markdown) * Release 5.1 - 2012-10-11 - [https://github.com/uglyog/clientside-haml-js/tarball/release_5_1] [Release Notes](Release-5.1.markdown) * Release 5 - 2012-08-09 - [https://github.com/uglyog/clientside-haml-js/tarball/release_5] [Release Notes](Release-5.markdown) * Release 4.5 - 2012-07-02 - [https://github.com/uglyog/clientside-haml-js/tarball/release_4_5] [Release Notes](Release-4.5.markdown) * Release 4.4 - 2012-05-15 - [https://github.com/uglyog/clientside-haml-js/tarball/release_4_4] [Release Notes](Release-4.4.markdown) * Release 4.3 - 2012-04-02 - [https://github.com/uglyog/clientside-haml-js/tarball/release_4_3] [Release Notes](Release-4.3.markdown) * Release 4.2 - 2012-03-13 - [https://github.com/uglyog/clientside-haml-js/tarball/release_4_2] [Release Notes](Release-4.2.markdown) * Release 4.1 - 2012-01-14 - [https://github.com/uglyog/clientside-haml-js/tarball/release_4_1] [Release Notes](Release-4.1.markdown) * Release 4 - 2012-01-08 - [https://github.com/uglyog/clientside-haml-js/tarball/release_4_0] [Release Notes](Release-4.markdown) * Release 3 - 2011-12-11 - [https://github.com/uglyog/clientside-haml-js/tarball/release_3_0] [Release Notes](Release-3.markdown) * Release 2 - 2011-12-10 - [https://github.com/uglyog/clientside-haml-js/tarball/release_2_0] [Release Notes](Release-2.markdown) * Release 1.1 - 2011-10-15 - [https://github.com/uglyog/clientside-haml-js/tarball/release_1_1] [Release Notes](Release-1.1.markdown) * Release 1 - 2011-07-25 - [https://github.com/uglyog/clientside-haml-js/tarball/release_1] [Release Notes](Release-1.markdown) * Release 0 - 2011-06-28 - [https://github.com/uglyog/clientside-haml-js/tarball/release_0] [Release Notes](Release-0.markdown) # To use it * Include the haml.js in your page: ```javascript ``` * The HAML can either be passed in as a String, as in: ```javascript var fn = haml.compileHaml({source: "%h1\n %div\n %p\n %span"}); var html = fn(); ``` * or added to the body of the web page in a script tag (with a unique ID), as in: ```html ``` * and calling ```javascript haml.compileHaml({sourceId: 'simple'}); ``` This will produce the following Javascript function: ```javascript function anonymous(context) { var html = []; var hashFunction = null, hashObject = null, objRef = null, objRefFn = null; with (context || {}) { html.push("\n
\n"); } return html.join(""); } ``` * The function can be called, and it takes one option parameter: a context object. ```javascript var fn = haml.compileHaml({sourceId: 'simple'}); var html = fn(); ``` This will produce the following HTML: ```html\n\n\n
\n \n \n``` # HAML Templates with embedded CoffeeScript clientside-haml-js also can compile templates with embedded CoffeeScript in it. There are equivalent functions to compile these templates (use the generator option set to 'coffeescript'). The main difference in using compiled functions from the Javascript ones is that you pass the template context as the `this` pointer to the function via the call function instead of a parameter. You can then access the context variables using `@name` notation. For example, with the following template: ```html ``` and calling ```coffescript model = foo: "hello" html = haml.compileHaml(sourceId: 'evaluation-using-context', generator: 'coffeescript').call(model: model) ``` will generate the following function: ```coffeescript html = [] html.push("
\n") foo = @model.foo foo += " world" html.push(" \n ") try exp = CoffeeScript.compile(" foo", bare: true) value = eval(exp) value ?= "" html.push(haml.HamlRuntime.escapeHTML(String(value))) catch e throw new Error(haml.HamlRuntime.templateError(6, 5, " = foo", "Error evaluating expression - " + e)) html.push("\n \n\n") return html.join("") ``` and the resulting javascript function will render ```htmlhello world``` # Produced Javascript functions For the Javascript compiler, the generated javascript functions take a single optional context variable which provide the context to the template. All the properties of the context variable will be available as variables in the template. See the examples below for more details on how to use this. In the case of the CoffeeScript version, the functions use the context passed in as the `this` pointer via the call function. The variables are then available using the `@name` notation. There is also a production javascript code generator (_productionjavascript_) which will produce slightly faster functions at the cost of feedback while evaluating expressions. The main idea would be to use the standard generator while developing and then switch to the production one when your code is released. The production version will run about 25% faster, depending on browser (see http://jsperf.com/eval-cost-in-templates/3, safari 6 was 5 times faster) # Client-side HAML API The `haml.compileHaml` takes a single parameter. As a string value (legacy form), it expects the string to be an ID of a script element in the DOM. Otherwise, it accepts the following key/value pairs: * _source_ - This contains the template in string form * _sourceId_ - This contains the element ID in the dom which contains the haml source * _sourceUrl_ - This contains the URL where the template can be fetched from (requires jQuery) * _outputFormat_ - This determines what is returned, and can be one of the following values: - function - A javascript function (default) - string - The javascript source code * _generator_ - Which code generator to use, the following values are accepted: - javascript (default) - coffeescript - productionjavascript * _tolerateFaults_ - The default behaviour when encountering errors is to raise an exception and stop parsing. With this option set to true, errors will be logged to the console and the parser will attempt to continue parsing. One of either _source_, _sourceId_ or _sourceUrl_ **must** be provided. **Note**, also, that the _sourceUrl_ options requires jQuery 1.5.1+ as a dependency. # Client-side HAML Flavour Although I tried keep the implementation as close to the Ruby one as possible, there are some differences. Also, currently not all features are implemented (see the release notes for details). ## Element Attributes with {} Elements with {} attributes are evaluated at runtime as Javascript code. This is similar to the ruby implementation, but with Javascript or CoffeeScript code instead of Ruby. Values that result to null or false are excluded, and 'checked', 'selected' and 'disabled' attributes are handled as boolean values. Ids will be joined by dashes (-) and classes by spaces. The following template ```haml %h1 %div{id: "test"} %p{id: \'test2\', ' + class: "blah", name: null, test: false, checked: false, selected: true} This is some text This is some text This is some div text %div{id: [\'test\', 1], class: [model.name, "class2"]} ``` should generate ```html``` ## Element Attributes with () As with the ruby implementation, HTML style attributes are also supported. However, these are evaluated at compile time and not runtime as the ruby HAML does. This allows the template writer decide which attributes are pre-compiled and which are evaluated at run-time. ```haml %h1 %div(id = "test") %p(id=test2 class="blah" selected="selected") This is some text This is some text This is some div text %div(id=test){id: 1, class: [model.name, "class2"]} ``` ```html
This is some text This is some text
This is some div text``` ## Unescaped Lines Any line starting with an exclamation is skipped over by the parser and copied as is to the output buffer. This allows lines which may cause parsing issues to be included in the output. ```haml %h1 !
This is some text This is some text
This is some div text!#test.test !%p#test.blah{id: 2, class: "test"} This is some text !This is some text ! This is sometext ! ``` ```html
#test.test %p#test.blah{id: 2, class: "test"} This is some text This is some text This is sometext ``` ## Embedded Javascript or CoffeeScript There are 4 ways you can embed code in your template, with {} attributes (see above), = expressions and - lines and \#{} blocks in plain text and filter blocks. ### Assigning an expression to a tag Adding an equals (=) to the end of a tag or at the start of a line allows a javascript expression to be evaluated and the result escaped and added to the contents of the tag. So for the following template ```haml .box.error %span = errorTitle .clear %span= errorHeading = "Calculation: " + (1 + 2 * 3) = ["hi", "there", "reader!"] = evilScript ``` and calling ```javascript var html = haml.compileHaml('evaluation')({ errorTitle: "Error Title", errorHeading: "Error Headingdiv text", evilScript: '' }); ``` should render ```htmlError Title``` In the case of CoffeeScript, you would use the call function: ```coffeescript html = haml.compileCoffeeHaml('evaluation').call(errorTitle: "Error Title", errorHeading: "Error HeadingError Heading <div>div text</div> Calculation: 7 hi,there,reader! <script>alert("I'm evil!");</script>div text", evilScript: '') ``` ### Adding code to the template Any line starting with a minus (-) will be copied to the generated javascript function. For the Javascript version of the compiler, you can leave the closing block out if the javascript line ends in either a brace ({), in which case a closing brace is added, or if it ends in an anonymous function (like `(function(...) {`), in which case a closing brace and bracket is added. ```haml .main - var foo = "hello"; - foo += " world"; %span = foo ``` ```htmlhello world``` With loops, Javascript: ```haml .main - _(["Option 1", "Option 2", "Option 3"]).each(function (option) { %span= option - for (var i = 0; i < 5; i++) { %p= i ``` and CoffeeScript: ```haml .main - for option in ["Option 1", "Option 2", "Option 3"] %span= option - for i in [0..4] %p= i ``` ```htmlOption 1 Option 2 Option 3``` ### Multiline statements Code lines can be extended over multiple lines by added a pipe (|) at the end of each line. Remember that the last line must also end with a pipe. ### Object references - [] You can use object references to supply the id and class attributes of a tag by placing the object variable within square brackets. The Haml compiler will look for an id and class attribute on the object to use, and if not found, will look for a `get` function to call which takes the name of the attribute as a parameter. This will allow you to use objects from frameworks like [Backbone.js](http://documentcloud.github.com/backbone/) to set the id and class of a tag. So, the following Haml and Javascript: ```haml %h1 %div[test] %p[test2] This is some text This is some text This is some div text .class1[test3]{id: 1, class: "class3", for: "something"} ``` ```javascript var context = { test: { id: 'test' }, test2: { id: 'test2', 'class': 'blah' }, test3: { attributes: { id: 'test', 'class': 'class2' }, get: function (name) { return this.attributes[name]; } } }; var html = haml.compileHaml('object-reference')(context); ``` should result in the following HTML: ```html0
1
2
3
4
``` ### \#{} Interpolated code blocks You can add code blocks using \#{} form within any plain text and filter blocks. For example: ```haml %p This is #{quality} cake! #{"Yay!"} ``` and passing in `quality: 'scrumptious'` results in ```html
This is some text This is some text
This is some div textThis is scrumptious cake! Yay!
``` ## Filters The following filter blocks are supported: * **plain** - just renders the text in the block * **javascript** - wraps the filter block in a javascript and cdata tag * **css** - wraps the filter block in a style and cdata tag * **cdata** - wraps the filter block in a CDATA tag * **preserve** - preserved blocks of text aren't indented, and newlines within tags are replaced with the HTML escape code for newlines * **escaped** - renders the text in the block with html escaped Additional filters can be added by adding an entry to `haml.filters` that maps the filter name to a filter function. See filters.coffee for examples of filter functions. \#{} Interpolated code blocks are also supported within filter blocks. For example: ```haml %body :javascript $(document).ready(function() { alert("#{message}"); }); %p :preserve Foo #{"Bar\\nBaz"} Test Test Other :escape Foo #{"'Bar'\\nBaz"} Test Test Other& ``` results in ```htmlFoo
Bar\nBazTest Test Other Foo <pre>'Bar' Baz</pre> <a>Test Test </a> Other& ``` ## Jasmine Tests For more information on what is implemented, have a look at the release notes and the jasmine tests in the spec folder.
本源码包内暂不包含可直接显示的源代码文件,请下载源码包。