Skip to content
This repository has been archived by the owner on Feb 12, 2022. It is now read-only.

Jade Compatibility #21

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 66 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ Table of select contents:
- [Usage](#usage)
- [Installation](#installation) - `npm install --save secure-filters`
- [EJS](#with-ejs)
- [Jade](#with-jade)
- [Normal functions](#as-normal-functions)
- [Client-side](#client-side)
- [Functions](#functions)
Expand All @@ -24,6 +25,9 @@ Table of select contents:
- [`uri(value)`](#urivalue) - Sanitizes URI contexts using percent-encoding.
- [`css(value)`](#cssvalue) - Sanitizes CSS contexts using backslash-encoding.
- [`style(value)`](#stylevalue) - Sanitizes CSS contexts _in an HTML `style` attribute_
- [Utility Functions](#utility)
- [`configure(ejs)`](#configureejs)
- [`inject(obj)`](#injectobj)
- [Contributing](#contributing)
- [Support](#support)
- [Legal](#legal)
Expand Down Expand Up @@ -161,6 +165,40 @@ Or, you can namespace using a parametric style, similar to how EJS' pre-defined
</script>
```

## With Jade

Integrating with [Jade](http://jade-lang.org) isn't quite as easy as EJS, but
still somewhat readable.

```js
var config = { loggedIn: true };
var locals = secureFilters.inject({
config: config
});
jade.render(template, locals);
```

And in the template you use the `!{}` interpolation operator

```jade
script.
var config = !{jsObj(config)};
```

Produces

```html
<script>var config = {"loggedIn":true};</script>
```

### Replacing Jade's default escape

Replacing Jade's default escaping is easy

```js
jade.runtime.escape = secureFilters.html;
```

## As Normal Functions

The filter functions are just regular functions and can be used outside of EJS.
Expand Down Expand Up @@ -191,6 +229,8 @@ don't pre-define a name, but suggest that you use 'secure-filters'.

# Functions

## Filters

By convention in the Contexts below, `USERINPUT` should be replaced with the
output of the filter function.

Expand Down Expand Up @@ -405,6 +445,32 @@ Encodes the value first as in the `css()` filter, then HTML entity-encodes the r

For example, the string `<wow>` becomes `&#92;3c wow&#92;3e `.

## Utility

### configure(ejs)

Configures EJS with the filter functions in this module. Returns the `ejs` module you passed in.

```js
var ejs = require('ejs');
ejs = secureFilters.configure(ejs);
```

Note that this doesn't modify EJS's default escape routine. [See
above](#replacing-ejss-default-escape) for instructions on how to do this.

### inject(obj)

Adds all of the filter functions in this module into an object. Returns the same, modified object.

```js
var locals = {
name: 'bob'
};
secureFilters.inject(locals);
someTemplateLang.render(template, locals);
```

# Contributing

If you'd like to contribute to or modify secure-filters, here's a quick guide
Expand Down
15 changes: 13 additions & 2 deletions lib/secure-filters.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,22 @@ var TO_CONFIGURE = ['html','js','jsAttr','uri','jsObj','css','style'];
*/
secureFilters.configure = function(ejs) {
ejs.filters = ejs.filters || {};
secureFilters.inject(ejs.filters);
return ejs;
};

/**
* Adds this module's filters to an arbitrary object.
*
* @param {Object} obj any writable object
* @return {Object} the same, modified, object
*/
secureFilters.inject = function(obj) {
for (var i = 0; i < TO_CONFIGURE.length; i++) {
var filterName = TO_CONFIGURE[i];
ejs.filters[filterName] = secureFilters[filterName];
obj[filterName] = secureFilters[filterName];
}
return ejs;
return obj;
};

var QUOT = /\x22/g; // "
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"component": "0.18.0",
"coveralls": "2.3.0",
"mocha-lcov-reporter": "0.0.1",
"blanket": "1.1.5"
"blanket": "1.1.5",
"jade": "~0.35.0"
}
}
40 changes: 40 additions & 0 deletions test.js
Original file line number Diff line number Diff line change
Expand Up @@ -324,4 +324,44 @@ describe('exporting to EJS', function() {
});
});

var jade;
try {
jade = require('jade');
} catch (e) {
}

if (jade) {
describe('jade integration', function() {
describe('default escape', function() {
it('has not-so-safe escaping before', function() {
var result = jade.render('a(href=foo)',{foo: 'some="where"'});
assert.equal(result, '<a href="some=&quot;where&quot;"></a>');
});
it('has slightly better escaping after', function() {
var origEscape = jade.runtime.escape;
jade.runtime.escape = secureFilters.html;
try {
var result = jade.render('a(href=foo)',{foo: 'some="where"'});
assert.equal(result, '<a href="some&#61;&quot;where&quot;"></a>');
} finally {
jade.runtime.escape = origEscape;
}
});
});

describe('custom escaping', function() {
it('jsObj interpolation', function() {
var template = 'script.\n' +
' var name = !{jsObj(name)};\n';
var opts = {
jsObj: secureFilters.jsObj,
name: '</script>'
};
var result = jade.render(template, opts);
assert.equal(result, '<script>var name = "\\x3C\\x2Fscript\\x3E";</script>');
});
});
});
}

}(this));