UNPKG

13.9 kBMarkdownView Raw
1# Slm
2
3Slm is a template language for js. Port of [Slim](http://slim-lang.com/) but slimmer :)
4
5[![Build Status](https://img.shields.io/travis/slm-lang/slm/master.svg)](https://travis-ci.org/slm-lang/slm)
6[![Dependency Status](https://img.shields.io/gemnasium/slm-lang/slm.svg)](https://gemnasium.com/slm-lang/slm)
7[![NPM version](https://badge.fury.io/js/slm.svg)](http://badge.fury.io/js/slm)
8[![Code Climate](https://codeclimate.com/github/slm-lang/slm/badges/gpa.svg)](https://codeclimate.com/github/slm-lang/slm)
9[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/slm-lang/slm?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
10
11
12## A little bit of history
13
14HAML -> Jade -> Slim -> Slm
15
16### Short list of the features
17
18* Elegant syntax
19 * Short syntax without closing tags (Using indentation instead)
20 * HTML style mode with closing tags
21 * Shortcut tags (based on css selectors)
22* Safety
23 * Automatic HTML escaping by default
24 * Support `htmlSafe` attribute on String objects
25* Highly configurable and extendable via plugins
26* High performance
27 * Comparable speed to ECT and Hogan [see benchmakrs](https://github.com/slm-lang/template-benchmark#results)
28* Easy integration with hapijs
29* Embedded engines like [Markdown](https://github.com/slm-lang/slm-markdown) and Textile (TBD)
30
31## Links
32
33* Source: <http://github.com/slm-lang/slm>
34* Bugs: <http://github.com/slm-lang/slm/issues>
35* Highlighters:
36 * Atom: <https://github.com/slm-lang/language-slm>
37 * Sublime: <https://github.com/slm-lang/sublime-slm>
38 * Vim: <https://github.com/slm-lang/vim-slm>
39* Benchmark: <https://github.com/slm-lang/template-benchmark#results>
40* Gulp: <https://github.com/simnalamburt/gulp-slm>
41* Grunt: <https://github.com/MichaelDanilov/grunt-slm>
42
43### How to start?
44
45Install Slm with npm:
46
47 npm install slm --save
48
49### Configure to work with hapijs
50
51```js
52var Hapi = require('hapi');
53
54var server = new Hapi.Server(3000);
55server.views({
56 engines: {
57 'slm': require('slm')
58 },
59 basePath: __dirname + '/views',
60 compileOptions: {
61 basePath: __dirname + '/views',
62 useCache: false // disable internal cache - useful for development
63 },
64 isCached: false // disable hapi view cache
65});
66
67server.route({
68 method: 'GET', path: '/',
69 handler: function (request, reply) {
70 reply.view('index', {hello: "word"});
71 }
72});
73
74server.start(function () {
75 console.log('Server running at:', server.info.uri);
76});
77```
78
79### Syntax example
80
81Here's a quick example to demonstrate what a Slm template looks like:
82
83 doctype html
84 html
85 head
86 title Slm Examples
87 meta name="keywords" content="template language"
88 meta name="author" content=this.author
89 javascript:
90 alert('Slm supports embedded javascript!')
91
92 body
93 h1 Markup examples
94
95 #content
96 p This example shows you how a basic Slm file looks.
97
98 == content()
99
100 - if this.items.length
101 table#items
102 - for item in this.items
103 tr
104 td.name = item.name
105 td.price = item.price
106 - else
107 p No items found Please add some inventory.
108 Thank you!
109
110 div id="footer"
111 == partial('footer')
112 | Copyright &copy; ${this.year} ${this.author}
113
114Indentation matters, but the indentation depth can be chosen as you like. If you want to first indent 2 spaces, then 5 spaces, it's your choice. To nest markup you only need to indent by one space, the rest is gravy.
115
116## Line indicators
117
118### Text `|`
119
120The pipe tells Slm to just copy the line. It essentially escapes any processing.
121Each following line that is indented greater than the pipe is copied over.
122
123 body
124 p
125 |
126 This is a test of the text block.
127
128 The parsed result of the above:
129
130 <body><p>This is a test of the text block.</p></body>
131
132 The left margin is set at the indent of the pipe + one space.
133 Any additional spaces will be copied over.
134
135 body
136 p
137 | This line is on the left margin.
138 This line will have one space in front of it.
139 This line will have two spaces in front of it.
140 And so on...
141
142You can also embed html in the text line
143
144 - for (var a in this.articles)
145 | <tr><td>${a.name}</td><td>${a.description}</td></tr>
146
147### Text with trailing white space `.`
148
149The single dot tells Slm to copy the line (similar to `|`), but makes sure that a single trailing white space is appended.
150
151### Inline html `<` (HTML style)
152
153You can write html tags directly in Slm which allows you to write your templates in a more html like style with closing tags or mix html and Slm style.
154
155 <html>
156 head
157 title Example
158 <body>
159 - if this.articles.length
160 table
161 - for (var a in this.articles)
162 <tr><td>${a.name}</td><td>${a.description}</td></tr>
163 </body>
164 </html>
165
166### Control code `-`
167
168The dash denotes control code. Examples of control code are loops and conditionals. Blocks are defined only by indentation.
169If your js code needs to use multiple lines, append a backslash `\` at the end of the lines. If your line ends with comma `,` (e.g because of a method call) you don't need the additional backslash before the linebreak.
170Slm inserts `(` and `)` for `if`, `for`, `else if` automatically. So you JS code is more readable.
171
172 body
173 - if !this.articles.length
174 | No inventory
175
176### Output `=`
177
178The equal sign tells Slm it's a JS call that produces output to add to the buffer. If your JS code needs to use multiple lines, append a backslash `\` at the end of the lines, for example:
179
180 = javascript_include_tag(\
181 "jquery",
182 "application")
183
184If your line ends with comma `,` (e.g because of a method call) you don't need the additional backslash before the linebreak. For trailing or leading whitespace the modifiers `>` and `<` are supported.
185
186* Output with trailing white space `=>`. Same as the single equal sign (`=`), except that it adds a trailing white space. The legacy syntax `='` is also supported.
187* Output with leading white space `=<`. Same as the single equal sign (`=`), except that it adds a leading white space.
188
189
190### Output without HTML escaping `==`
191
192Same as the single equal sign (`=`), but does not go through the `escapeHtml` method. For trailing or leading whitespace the modifiers `>` and `<` are supported.
193
194* Output without HTML escaping and trailing white space `==>`. Same as the double equal sign (`==`), except that it adds a trailing white space. The legacy syntax `=='` is also supported.
195* Output without HTML escaping and leading white space `==<`. Same as the double equal sign (`==`), except that it adds a leading white space.
196
197### Code comment `/`
198
199Use the forward slash for code comments - anything after it won't get displayed in the final render. Use `/` for code comments and `/!` for html comments
200
201 body
202 p
203 / This line won't get displayed.
204 Neither does this line.
205 /! This will get displayed as html comments.
206
207 The parsed result of the above:
208
209 <body><p><!--This will get displayed as html comments.--></p></body>
210
211### HTML comment `/!`
212
213Use the forward slash immediately followed by an exclamation mark for html comments (`<!-- ... -->`).
214
215### IE conditional comment `/[...]`
216
217 /[if IE]
218 p Get a better browser.
219
220renders as
221
222 <!--[if IE]><p>Get a better browser.</p><![endif]-->
223
224
225## HTML tags
226
227### Doctype tag
228
229The doctype tag is a special tag which can be used to generate the complex doctypes in a very simple way.
230
231XML VERSION
232
233 doctype xml
234 <?xml version="1.0" encoding="utf-8" ?>
235
236 doctype xml ISO-8859-1
237 <?xml version="1.0" encoding="iso-8859-1" ?>
238
239XHTML DOCTYPES
240
241 doctype html
242 <!DOCTYPE html>
243
244 doctype 5
245 <!DOCTYPE html>
246
247 doctype 1.1
248 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
249 "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
250
251 doctype strict
252 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
253 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
254
255 doctype frameset
256 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN"
257 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
258
259 doctype basic
260 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN"
261 "http://www.w3.org/TR/xhtml-basic/xhtml-basic11.dtd">
262
263 doctype transitional
264 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
265 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
266
267HTML 4 DOCTYPES
268
269 doctype strict
270 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
271 "http://www.w3.org/TR/html4/strict.dtd">
272
273 doctype frameset
274 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN"
275 "http://www.w3.org/TR/html4/frameset.dtd">
276
277 doctype transitional
278 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
279 "http://www.w3.org/TR/html4/loose.dtd">
280
281### Closed tags (trailing `/`)
282
283You can close tags explicitly by appending a trailing `/`.
284
285 img src="image.png"/
286
287Note, that this is usually not necessary since the standard html
288tags (img, br, ...) are closed automatically.
289
290### Trailing and leading whitespace (`<`, `>`)
291
292You can force Slm to add a trailing whitespace after a tag by adding a >.
293
294 a> href='url1' Link1
295 a> href='url2' Link2
296
297You can add a leading whitespace by adding <.
298
299 a< href='url1' Link1
300 a< href='url2' Link2
301
302You can also combine both.
303
304 a<> href='url1' Link1
305
306### Inline tags
307
308Sometimes you may want to be a little more compact and inline the tags.
309
310 ul
311 li.first: a href="/a" A link
312 li: a href="/b" B link
313
314For readability, don't forget you can wrap the attributes.
315
316 ul
317 li.first: a[href="/a"] A link
318 li: a[href="/b"] B link
319
320### Text content
321
322Either start on the same line as the tag
323
324 body
325 h1 id="headline" Welcome to my site.
326
327Or nest it. You must use a pipe or an apostrophe to escape processing
328
329 body
330 h1 id="headline"
331 | Welcome to my site.
332
333### Dynamic content (`=` and `==`)
334
335Can make the call on the same line
336
337 body
338 h1 id="headline" = this.pageHeadline
339
340Or nest it.
341
342 body
343 h1 id="headline"
344 = this.pageHeadline
345
346### Attributes
347
348You write attributes directly after the tag. For normal text attributes you must use double `"` or single quotes `'` (Quoted attributes).
349
350 a href="http://slm-lang.com" title='Slm Homepage' Goto the Slm homepage
351
352You can use text interpolation in the quoted attributes.
353
354#### Attributes wrapper
355
356If a delimiter makes the syntax more readable for you,
357you can use the characters `(...)`, `[...]` to wrap the attributes.
358You can configure these symbols.
359
360 body
361 h1(id="logo") = this.pageLogo
362 h2[id="tagline" class="small tagline"] = this.pageTagline
363
364If you wrap the attributes, you can spread them across multiple lines:
365
366 h2[id="tagline"
367 class="small tagline"] = this.pageTagline
368
369You may use spaces around the wrappers and assignments:
370
371 h1 id = "logo" = page_logo
372 h2 [ id = "tagline" ] = this.pageTagline
373
374#### Quoted attributes
375
376Example:
377
378 a href="http://slm-lang.com" title='Slm Homepage' Goto the slm homepage
379
380You can use text interpolation in the quoted attributes:
381
382 a href="http://${url}" Goto the ${url}
383
384The attribute value will be escaped by default. Use == if you want to disable escaping in the attribute.
385
386 a href=="&amp;"
387
388You can break quoted attributes with backslash `\`
389
390 a data-title="help" data-content="extremely long help text that goes on\
391 and one and one and then starts over...."
392
393#### Javascript attributes
394
395Write the javascript code directly after the `=`. If the code contains spaces you have to wrap
396the code into parentheses `(...)`. You can also directly write hashes `{...}` and arrays `[...]`.
397
398 body
399 table
400 - for var user in this.users
401 td id="user-#{user.id}" class=user.role
402 a href=userAction(user, 'edit') Edit ${user.name}
403 a href=pathToUser(user) = user.name
404
405The attribute value will be escaped by default. Use == if you want to disable escaping in the attribute.
406
407 a href==actionPath('start')
408
409You can also break javascript attributes with backslash `\` or trailing `,` as describe for control sections.
410
411#### Boolean attributes
412
413The attribute values `true`, `false`, `null` and `undefinded` are interpreted
414as booleans. If you use the attribute wrapper you can omit the attribute assigment.
415
416 input type="text" disabled="disabled"
417 input type="text" disabled=true
418 input(type="text" disabled)
419
420 input type="text"
421 input type="text" disabled=false
422 input type="text" disabled=null
423
424
425#### Attribute merging
426
427 a.menu class="highlight" href="http://slm-lang.com/" Slm-lang.com
428
429This renders as
430
431 <a class="menu highlight" href="http://slm-lang.com/">Slm-lang.com</a>
432
433You can also use an `Array` as attribute value and the array elements will be merged using the delimiter.
434
435 a class=['menu','highlight']
436 a class='menu','highlight'
437
438## Text interpolation
439
440Use ES6 interpolation. The text will be html escaped by default.
441
442 body
443 h1 Welcome ${current_user.name} to the show.
444 | Unescaped ${=content} is also possible.
445
446To escape the interpolation (i.e. render as is)
447
448 body
449 h1 Welcome \${current_user.name} to the show.
450
451
452
453
454# Special Thanks
455
456* [Andrew Stone](https://github.com/stonean), for [Slim](https://github.com/slim-template/slim)
457* [Magnus Holm](https://github.com/judofyr), for [Temple](https://github.com/judofyr/temple)
458* [Daniel Mendler](https://github.com/minad), for maintenance of both
459* [John Firebaugh](https://github.com/jfirebaugh), for [Skim](https://github.com/jfirebaugh/skim)
460* [AnjLab](http://anjlab.com), for such great team