Skip to content

Commit

Permalink
feat: support bracket notation with quotes and dot notation (#41)
Browse files Browse the repository at this point in the history
* feat: support bracket notation with quotes

* feat: support dot notation
  • Loading branch information
heenakwag authored Dec 11, 2019
1 parent c0c085e commit 5b91727
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 7 deletions.
22 changes: 17 additions & 5 deletions domUtil/template.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@ var isArray = require('../type/isArray');
var isString = require('../type/isString');
var extend = require('../object/extend');

var EXPRESSION_REGEXP = /{{\s?(\/?[a-zA-Z0-9_.@[\] ]+)\s?}}/g;
var BRACKET_REGEXP = /^([a-zA-Z0-9_@]+)\[([a-zA-Z0-9_@]+)\]$/;
var EXPRESSION_REGEXP = /{{\s?(\/?[a-zA-Z0-9_.@[\]"'\- ]+)\s?}}/g;
var BRACKET_REGEXP = /^([a-zA-Z0-9_@]+)\[([a-zA-Z0-9_@"']+)\]$/;
var DOT_REGEXP = /^([a-zA-Z_]+)\.([a-zA-Z_]+)$/;
var STRING_REGEXP = /^["'](\w+)["']$/;
var NUMBER_REGEXP = /^-?\d+\.?\d*$/;

var EXPRESSION_INTERVAL = 2;
Expand All @@ -30,17 +32,23 @@ var BLOCK_HELPERS = {
* @returns {*}
* @private
*/
// eslint-disable-next-line complexity
function getValueFromContext(exp, context) {
var bracketExps;
var splitedExps;
var value = context[exp];

if (exp === 'true') {
value = true;
} else if (exp === 'false') {
value = false;
} else if (STRING_REGEXP.test(exp)) {
value = STRING_REGEXP.exec(exp)[1];
} else if (BRACKET_REGEXP.test(exp)) {
bracketExps = exp.split(BRACKET_REGEXP);
value = getValueFromContext(bracketExps[1], context)[getValueFromContext(bracketExps[2], context)];
splitedExps = exp.split(BRACKET_REGEXP);
value = getValueFromContext(splitedExps[1], context)[getValueFromContext(splitedExps[2], context)];
} else if (DOT_REGEXP.test(exp)) {
splitedExps = exp.split(DOT_REGEXP);
value = getValueFromContext(splitedExps[1], context)[splitedExps[2]];
} else if (NUMBER_REGEXP.test(exp)) {
value = parseFloat(exp);
}
Expand Down Expand Up @@ -296,6 +304,10 @@ function compile(sources, context) {
* <br>
* If expression exists in the context, it will be replaced.
* ex) '{{title}}' with context {title: 'Hello!'} is converted to 'Hello!'.
* An array or object can be accessed using bracket and dot notation.
* ex) '{{odds[2]}}' with context {odds: [1, 3, 5]} is converted to '5'.
* ex) '{{evens[first]}}' with context {evens: [2, 4], first: 0} is converted to '2'.
* ex) '{{project["name"]}}' and '{{project.name}}' with context {project: {name: 'CodeSnippet'}} is converted to 'CodeSnippet'.
* <br>
* If replaced expression is a function, next expressions will be arguments of the function.
* ex) '{{add 1 2}}' with context {add: function(a, b) {return a + b;}} is converted to '3'.
Expand Down
22 changes: 20 additions & 2 deletions test/template.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,21 +21,39 @@ describe('{{expression}}', function() {
it('should bind with number if value is a number.', function() {
expect(template('<p>{{ 3 }}</p>', {})).toBe('<p>3</p>');
expect(template('<p>{{123.4567}}</p>', {})).toBe('<p>123.4567</p>');
expect(template('<p>{{-1}}</p>', {})).toBe('<p>-1</p>');
expect(template('<p>{{-0}}</p>', {})).toBe('<p>0</p>');
expect(template('<p>{{-123.4567}}</p>', {})).toBe('<p>-123.4567</p>');
});

it('should access the value with brackets if value is an object or array.', function() {
expect(template('<p>{{ arr[2] }}</p>', {arr: [0, 1, 2]})).toBe('<p>2</p>');
expect(template('<p>{{obj[key]}}</p>', {
expect(template('<p>{{obj["key"]}}</p>', {obj: {key: 'value'}})).toBe('<p>value</p>');
expect(template('<p>{{obj[name]}}</p>', {
obj: {key: 'value'},
key: 'key'
name: 'key'
})).toBe('<p>value</p>');
expect(template('{{each nums}}{{nums[@index]}}{{/each}}', {nums: [1, 2, 3]})).toBe('123');
});

it('should access the value with dots if value is an object.', function() {
expect(template('<p>{{obj.key}}</p>', {obj: {key: 'value'}})).toBe('<p>value</p>');
});

it('should bind with boolean if value is "true" or "false".', function() {
expect(template('<p>{{ false }}</p>', {})).toBe('<p>false</p>');
expect(template('<p>{{true}}</p>', {})).toBe('<p>true</p>');
});

it('should bind with string if value is string with quotes.', function() {
var context = {
sayHello: function(name) {
return 'Hello, ' + name;
}
};
expect(template('<p>{{ sayHello "CodeSnippet" }}</p>', context)).toBe('<p>Hello, CodeSnippet</p>');
expect(template('<p>{{sayHello \'world\'}}</p>', context)).toBe('<p>Hello, world</p>');
});
});

describe('{{helper arg1 arg2}}', function() {
Expand Down

0 comments on commit 5b91727

Please sign in to comment.