forget underpowered template languages - build HTML with the full power of coffeescript
nodejs: npm install kup
then Kup = require 'kup'
browser: include lib/kup.js which sets window.Kup
Kup = require 'kup'
k = new Kup
k.doctype()
k.html ->
k.head ->
k.title "a title"
k.script {
src: "/script.js"
type: "text/javascript"
}
k.body ->
k.div {id: "container"}, ->
k.h1 "a heading"
k.h2 {class: "secondary-heading"}, "another heading"
k.ul ->
"red green blue".split(' ').forEach (color) ->
k.li ->
k.a {
style: {color: color}
href: "http://www.example.com"
}, "a #{color} link"
k.p ->
k.unsafe "not html encoded plaintext: &<>\"'/"
k.br()
k.safe "html encoded plaintext: &<>\"'/"
k.span {
style: {fontWeight: "bold"}
}, "bold"
console.log k.htmlOut
produces the following HTML (whitespace added for readability):
<!DOCTYPE html>
<html>
<head>
<title>a title</title>
<script src="/script.js" type="text/javascript"></script>
</head>
<body>
<div id="container">
<h1>a heading</h1>
<h2 class="secondary-heading">another heading</h2>
<ul>
<li>
<a style="color: red;" href="http://www.example.com">
a red link
</a>
</li>
<li>
<a style="color: green;" href="http://www.example.com">
a green link
</a>
</li>
<li>
<a style="color: blue;" href="http://www.example.com">
a blue link
</a>
</li>
</ul>
<p>
not html encoded plaintext: &<>"'/
<br />
html encoded plaintext: &<>"'/
<span font-weight="bold">bold</span>
</p>
</div>
</body>
</html>
if the style
attribute is a string it is added to the tag unchanged.
if the style
attribute is an object it is converted to a css style string.
camelcased keys are converted to dashcase:
k = new Kup
k.div
style: 'color: red'
k.div
style:
color: 'blue'
backgroundImage: 'url(test.png)'
msTransition: 'all'
console.log k.htmlOut
produces the following HTML:
<div style="color: red"></div>
<div style="color: blue; background-image: url(test.png); ms-transition: all;">
</div>
if you want a similar special treatment for attributes other than style
overwrite Kup.prototype.attributeToString = (key, value) -> ...
.
it's 3 lines of code that are easily customized.
kup implements RULE 1 and RULE 2 of the OWASP XSS prevention cheat sheet. reading it is highly recommended ! kup can not protect you from the many other XSS attack vectors described there. that requires a bit of effort on your part.
kup will properly quote attributes using double quotes:
properly quoted attributes can only be escaped with the corresponding quote.
kup escapes all double quotes inside attribute values to prevent escaping out of the double quote context.
attribute values are escaped with the function Kup.prototype.encodeAttribute
that you can overwrite.
kup will HTML escape text content.
content is encoded with the function Kup.prototype.encodeContent
that you can overwrite.
use the unsafe
function to insert text which should not be escaped:
k.script ->
k.unsafe 'javascript which should not be escaped'
use the safe
function to insert text which should be escaped:
k.p ->
k.safe 'this will be escaped'
kup doesn't insert any newlines into the generated HTML.
for some very basic pretty printing you can configure kup to insert newlines after each opening tag (that has inner HTML) and each closing tag:
Kup.prototype.tag = (tag, attrs, content) ->
if 'object' isnt typeof attrs
content = attrs
attrs = undefined
@_open tag, attrs
if 'function' is typeof content
@htmlOut += '\n'
@_content content
@_close tag
@htmlOut += '\n'
TLDR: bugfixes, issues and discussion are always welcome. ask me before implementing new features.
i will happily merge pull requests that fix bugs with reasonable code.
i will only merge pull requests that modify/add functionality if the changes align with my goals for this package and only if the changes are well written, documented and tested.
communicate: write an issue to start a discussion before writing code that may or may not get merged.
kup is inspired by mark hahn's drykup