ember-awesome-macros
A collection of Ember computed macros. All the macros are composable, meaning you can nest them to your heart's content, like so:
result: conditional(and(not('value1'), 'value2'), sum('value3', 1), collect('value4', toUpper('value5'))) // lisp much?
Arguments to macros can be:
- A string, in which case it references the name of a property whose value is used for the calculation
- A non-string value, in which case it is used as such
- A raw macro, which lets you use a string as the value without referencing a property
- Another macro
Examples of these different usages:
source1: 'my value',
source2: 2
value1: equal('source1', 'source2'), // false
value2: equal('source2', 2), // true
value3: equal('source1', raw('my value')) // true
value4: equal('source2', sum(1, 1)) // true
Three essential primitive macros are re-exported from a different addon: ember-macro-helpers
- computed makes composing macros easier
- raw allows you to escape string literals to be used in macros
- writable makes setting macros possible
import computed from 'ember-awesome-macros/computed';
import raw from 'ember-awesome-macros/raw';
import writable from 'ember-awesome-macros/writable';
// or
import { computed, raw, writable } from 'ember-awesome-macros';
If you have any opinions or want a new macro added, just ask! Or feel free to submit a pull request.
Introduction Video
Compatibility
- Ember.js v3.8 or above
- Ember CLI v2.13 or above
- Node.js v8 or above
Installation
ember install ember-awesome-macros
Usage
import nameOfMacro from 'ember-awesome-macros/name-of-macro';
// or
import { nameOfMacro } from 'ember-awesome-macros';
Macro list
Array
array.any
collect
array.compact
array.concat
array.every
array.filterBy
array.filter
array.findBy
array.find
array.first
array.groupBy
array.includes
array.indexOf
array.invoke
array.isAny
array.isEvery
array.join
array.lastIndexOf
array.last
array.length
array.mapBy
array.map
array.objectAt
array.reduce
array.reverse
array.rejectBy
array.slice
array.sortBy
array.sort
array.uniqBy
array.uniq
array.without
Boolean
Comparison
Number
Object
Math
Promise
String
string.camelize
string.capitalize
string.classify
string.dasherize
string.decamelize
string.escapeExpression
string.htmlSafe
string.indexOf
string.isHtmlSafe
string.lastIndexOf
string.length
string.match
string.replace
string.split
string.substr
string.substring
tag
string.titleize
string.toLower
string.toUpper
string.trim
string.underscore
Custom macros
See [https://github.com/kellyselden/ember-macro-helpers#custom-macros].
Details
add
alias for sum
and
same as Ember.computed.and
, but allows composing
source1: false,
source2: true,
source3: false,
value1: and('source1', 'source2', 'source3'), // false
value2: and(not('source1'), 'source2', not('source3')) // true
array.any
wraps Ember.Array.any
, allows composing
array: Ember.A([1, 2]),
value1: array.any('array', val => val === 2), // true
value2: array.any('array', val => val === 3) // false
array.compact
wraps Ember.Array.compact
, allows composing
array: Ember.A([1, 2, null]),
value: array.compact('array') // [1, 2]
array.concat
wraps Array.prototype.concat()
, allows composing
array1: Ember.A([1, 2]),
array2: Ember.A([3, 4]),
string: '3,4',
example: array.concat('array1', 'array2'), // [1, 2, 3, 4]
composingExample: array.concat('array1', split('string', raw(','))) // [1, 2, 3, 4]
array.every
wraps Ember.Array.every
, allows composing
array: Ember.A([1, 1]),
value1: array.every('array', val => val === 1), // true
value2: array.every('array', val => val === 2) // false
array.filterBy
wraps Ember.Array.filterBy
, allows composing
array: Ember.A([{ test: 1 }, { test: 2 }]),
key: 'test',
referenceValue: 1,
value1: array.filterBy('array', 'key', 2), // [{ test: 2 }]
value2: array.filterBy('array', raw('test'), 'referenceValue') // [{ test: 1 }]
array.filter
wraps Ember.Array.filter
, allows composing
array: Ember.A([{ test: 1 }, { test: 2 }]),
value: array.filter('array', item => item.test === 2) // [{ test: 2 }]
array.findBy
wraps Ember.Array.findBy
, allows composing
array: Ember.A([{ test: 1 }, { test: 2 }]),
key: 'test',
referenceValue: 1,
value1: array.findBy('array', 'key', 2), // { test: 2 }
value2: array.findBy('array', raw('test'), 'referenceValue') // { test: 1 }
array.find
wraps Ember.Array.find
, allows composing
array: Ember.A([{ test: 1 }, { test: 2 }]),
value: array.find('array', item => item.test === 2) // { test: 2 }
array.first
get the first item of an array
array: ['1', '2'],
string: '1, 2',
example: array.first('array'), // '1'
composingExample: array.first(split('string', raw(', '))) // '1'
array.groupBy
allows to group an array of objects by key with an optional comparator
array: Ember.A([{ test: 1, name: 'foo'}, { test: 2, name: 'foo' }, { test: 1, name: 'bar' }]),
key: 'test',
value: array.groupBy('array', 'key')
/*
[
{
key: 'test',
value: 1,
items: [{ test: 1 , name: 'foo' }, { test: 1 , name: 'bar' }]
},
{
key: 'test',
value: 2,
items: [{ test: 2 , name: 'foo' }]
}
]
*/
The comparator is required if grouping by a key representing a complex object like Date
// Given two different objects that represent the same info
// today1 = new Date();
// today2 = new Date();
// randomDate = new Date(2017, 1, 1);
array: Ember.A([
{ test: 1 , date: today1 },
{ test: 2 , date: today2 },
{ test: 1 , date: randomDate }
]),
key: 'date'
// without comparator
value1: array.groupBy('array', 'key'),
/*
[
{
key: 'date',
value: today1,
items: [{ test: 1 , date: today1 }]
},
{
key: 'date',
value: today2,
items: [{ test: 2 , date: today2 }]
},
{
key: 'date',
value: randomDate,
items: [{ test: 1 , date: randomDate }]
}
]
*/
// with comparator
value2: array.groupBy('array', 'key', (groupValue, currentValue) => {
return groupValue.getTime() === currentValue.getTime();
})
/*
[
{
key: 'date',
value: today1,
items: [{ test: 1 , date: today1 }, { test: 2 , date: today2 }]
},
{
key: 'date',
value: randomDate,
items: [{ test: 1 , date: randomDate }]
}
]
*/
array.includes
implements Array.prototype.includes()
, allows composing
array: Ember.A(['my value 1', 'my value 2']),
source1: 'my value 2',
source2: 'my value 3',
value1: array.includes('array', 'source1'), // true
value2: array.includes('array', 'source2'), // false
value3: array.includes(collect(raw('my value 1'), raw('my value 2')), raw('my value 1')) // true
array.indexOf
wraps Array.prototype.indexOf()
, allows composing
array: [2, 5, 9, 2],
referenceValue: 9,
value1: array.indexOf('array', 2), // 0
value2: array.indexOf('array', 2, 2), // 3
value3: array.indexOf('array', 'referenceValue') // 2
array.invoke
wraps Ember.Array.invoke()
, allows composing
array: [{
foo(arg) {
return 'bar-' + arg;
}
}],
value1: array.invoke('array', 'foo', raw('baz')), // ['bar-baz']
value2: array.invoke('array', 'foo', 'arg'), // ['bar-hello']
value3: array.invoke('array', 'foo'), // ['bar-']
arg: 'hello'
array.isAny
wraps Ember.Enumerable.isAny
, allows composing
array: Ember.A([{ test: 1 }, { test: 2 }]),
key: 'test',
value1: 2,
value2: 3,
result1: array.isAny('array', 'key', 'value1'), // true
result2: array.isAny('array', 'key', 'value2') // false
array.isEvery
wraps Ember.Enumerable.isEvery
, allows composing
array1: Ember.A([{ test: 1 }, { test: 1 }]),
key: 'test',
value1: 1,
value2: 2,
result1: array.isEvery('array', 'key', 'value1'), // true
result2: array.isEvery('array', 'key', 'value2') // false
array.join
wraps Array.prototype.join()
, allows composing
array: Ember.A(['1', '2']),
separator: ', ',
value1: array.join('values', 'separator'), // '1, 2'
value2: array.join(collect(raw('1'), raw('2')), raw(', ')) // '1, 2'
array.lastIndexOf
wraps Array.prototype.lastIndexOf()
, allows composing
array: [2, 5, 9, 2],
referenceValue: 9,
value1: array.lastIndexOf('array', 2), // 3
value2: array.lastIndexOf('array', 2, 2), // 0
value3: array.lastIndexOf('array', 'referenceValue') // 2
array.last
get the last item of an array
array: ['1', '2'],
string: '1, 2',
example: array.last('array'), // '2'
composingExample: array.last(split('string', raw(', '))) // '2'
array.length
wraps Array.prototype.length
, allows composing
array: Ember.A([1, 2]),
string: '1,2',
example: array.length('array'), // 2
composingExample: array.length(split('string', raw(','))) // 2
array.mapBy
wraps Ember.Array.mapBy
, allows composing
array: Ember.A([{ test: 1 }, { test: 2 }]),
key: 'test',
value: array.mapBy('array', 'key') // [1, 2]
array.map
wraps Ember.Array.map
, allows composing
array: Ember.A([{ test: 1 }, { test: 2 }]),
value: array.map('array', item => item.test) // [1, 2]
array.objectAt
wraps Ember.Array.objectAt
, allows composing
array: Ember.A(['my value']),
source1: 0,
source2: 1,
value1: array.objectAt('array', 'source1'), // 'my value'
value2: array.objectAt('array', 'source2'), // undefined
value3: array.objectAt(collect(raw('my value 1')), raw(0)) // 'my value'
array.reduce
wraps Array.prototype.reduce()
, allows composing
Your initial value must be a factory function if you plan to mutate it in the reduce, otherwise it would continually mutate the same object every recalculation. You can still pass an object, just be careful not to mutate it.
array: ['one', 'two'],
value1: array.reduce(
'array',
(obj, cur, i) => {
obj[cur] = i;
return obj;
},
// initial value is a factory function because we mutate the object
() => ({})
), // { one: 0, two: 1 }
string: 'one, two',
value2: array.reduce(
split('string', raw(', ')),
(arr, cur, i) => arr.concat(cur, i),
//initial value is an array because it is not mutated
[]
) // ['one', 0, 'two', 1]
array.rejectBy
wraps Ember.Array.rejectBy
, allows composing
array: Ember.A([{ test: 1 }, { test: 2 }]),
key: 'test',
value: array.rejectBy('array', 'key', 2) // [{ test: 1 }]
array.reverse
wraps Array.prototype.reverse()
(calls slice() first as to not mutate), allows composing
array: [1, 2, 3],
value1: array.reverse('array'), // [3, 2, 1]
value2: array.reverse(array.reverse('array')) // [1, 2, 3]
array.slice
wraps Array.prototype.slice()
, allows composing
array: [1, 2, 3],
value1: array.slice('array', 1), // [2, 3]
value2: array.slice('array', difference('array.length', 1)) // [3]
array.sortBy
sorts the given array of objects by key
array1: Ember.A([{ key: 'abc' }, { key: 'xyz' }]),
value1: array.sortBy('array1', 'key'), // [{ key: 'abc' }, { key: 'xyz' }]
value2: array.sortBy('array1', 'key:desc'), // [{ key: 'xyz' }, { key: 'abc' }]
array.sort
combines the functionality of both Array.prototype.sort()
and Ember.computed.sort
array1: Ember.A(['xyz', 'abc']),
array2: Ember.A([{ key: 'abc' }, { key: 'xyz' }]),
value1: array.sort('array1'), // ['abc', 'xyz']
value2: array.sort('array2', ['key:desc']), // [{ key: 'xyz' }, { key: 'abc' }]
value3: array.sort('array2', (a, b) => a.key < b.key), // [{ key: 'xyz' }, { key: 'abc' }]
array.uniqBy
wraps Ember.Array.uniqBy
, allows composing
array: Ember.A([{ test: 1 }, { test: 2 }, { test: 2 }]),
key: 'test',
value: array.uniqBy('array', 'key') // [{ test: 1 }, { test: 2 }]
array.uniq
wraps Ember.Array.uniq
, allows composing
array: Ember.A([1, 2, 2]),
value: array.uniq('array') // [1, 2]
array.without
wraps Ember.Enumerable.without
, allows composing
array: Ember.A([1, 2, 3]),
referenceValue: 3,
value1: array.without('array', 'referenceValue'), // [1, 2]
value2: array.without('array', 2), // [1, 3]
value3: array.without('array', array.objectAt(1)) // [1, 3]
bool
same as Ember.computed.bool
, but allows composing
source1: null,
source2: 'my value 1',
source3: { source: 'source3' },
value1: bool('source1'), // false
value2: bool('source2'), // true
value3: bool('source3'), // true
collect
same as Ember.computed.collect
, but allows composing
source1: 'my value 1',
source2: 'my value 2',
value: collect('source1', collect('source2')) // ['my value 1', ['my value 2']]
conditional
implements the ternary operator, allows composing
condition1: true,
condition2: false,
expr1: 'my value 1',
expr2: 'my value 2',
value1: conditional('condition1', 'expr1', 'expr2'), // 'my value 1'
value2: conditional('condition2', 'expr1', 'expr2'), // 'my value 2'
value3: conditional(or('condition1', 'condition2'), raw('my value 1'), raw('my value 2')) // 'my value 1'
defaultTrue
true if source is undefined
source1: undefined,
source2: false,
source3: 'my value',
value1: defaultTrue('source1'), // true
value2: defaultTrue('source2'), // false
value3: defaultTrue('source3') // 'my value'
difference
subtracts numbers
source1: 3,
source2: 2,
source3: 1,
value1: difference('source1', 'source2', 'source3'), // 0
value2: difference('source1', collect('source2', 'source3')) // 2
divide
alias for quotient
eq
alias for equal
equal
like Ember.computed.equal
, but uses dependent properties on both sides. allows N number of arguments.
source1: 'my value',
source2: 'my other value',
source3: 'my value',
value1: equal('source1', 'source2'), // false
value2: equal('source1', 'source3'), // true
value3: equal('source1', 'source2', 'source3') // false
getBy
get a variable property name from an object
key: 'modelProperty',
model: {
modelProperty: 'my value'
},
value1: getBy('model', 'key'), // 'my value'
value2: getBy('model', raw('modelProperty')) // 'my value'
gt
like Ember.computed.gt
, but uses dependent properties on both sides
and allows composing
source1: 1,
source2: 2,
source3: 1,
value1: gt('source1', 'source2'), // false
value2: gt('source1', 'source3'), // false
value3: gt('source2', 'source3') // true
gte
like Ember.computed.gte
, but uses dependent properties on both sides
and allows composing
source1: 1,
source2: 2,
source3: 1,
value1: gte('source1', 'source2'), // false
value2: gte('source1', 'source3'), // true
value3: gte('source2', 'source3') // true
hash
build a hash out of computed properties, allows composing
source1: 'my value 1',
source2: 'my value 2',
value1: hash({
prop1: 'source1',
prop2: hash({
prop: 'source2'
})
}), // { prop1: 'my value 1', prop2: { prop: 'my value 2' } }
// you can also build the hash using property key names
value2: hash('source1', 'source2'), // { source1: 'my value 1', source2: 'my value 2' }
// or you can mix and match, the result will be merged
value3: hash('source1', { prop2: 'source2' }) // { source1: 'my value 1', prop2: 'my value 2' }
isEmpty
wraps Ember.isEmpty
sourceString1: '',
sourceString2: 'foobar',
sourceArray1: [],
sourceArray2: [1, 2, 3],
sourceObject1: {},
sourceObject2: { size: 0 },
valueString1: isEmpty('sourceString1'), // true
valueString2: isEmpty('sourceString2'), // false
valueArray1: isEmpty('sourceArray1'), // true
valueArray2: isEmpty('sourceArray2'), // false
valueObject1: isEmpty('sourceObject1'), // false
valueObject2: isEmpty('sourceObject2'), // true
valueObject1: isEmpty(collect(1, 2)), // false
valueObject1: isEmpty([]), // true
instanceOf
wraps instanceof
operator
key1: {},
key2: false,
key3: '',
value1: instanceOf('key1', Object), // true
value2: instanceOf(or('key2', 'key3'), String) // true
lt
like Ember.computed.lt
, but uses dependent properties on both sides
and allows composing
source1: 1,
source2: 2,
source3: 1,
value1: lt('source1', 'source2'), // true
value2: lt('source1', 'source3'), // false
value3: lt('source2', 'source3') // false
lte
like Ember.computed.lte
, but uses dependent properties on both sides
and allows composing
source1: 1,
source2: 2,
source3: 1,
value1: lte('source1', 'source2'), // true
value2: lte('source1', 'source3'), // true
value3: lte('source2', 'source3') // false
math
exposes all Math
functions
source1: 2.2,
source2: 2.7,
value1: math.ceil('source1'), // 3
value2: math.floor(sum('source1', 'source2')) // 4
mod
the modulus operator
number1: 123,
number2: 45,
example: mod('number1', 'number2'), // 33
composingExample: mod(sum('number1', 'number2'), 39) // 12
multiply
alias for product
nand
applies logical NAND
operation
sourceTrue: true,
sourceFalse: false,
value1: nand('sourceFalse', 'sourceFalse', 'sourceFalse'), // true
value2: nand('sourceFalse', 'sourceTrue', 'sourceFalse'), // true
value3: nand('sourceTrue', 'sourceTrue', 'sourceTrue') // false
neq
alias for notEqual
nor
applies logical NOR
operation
sourceTrue: true,
sourceFalse: false,
value1: nor('sourceFalse', 'sourceFalse', 'sourceFalse'), // true
value2: nor('sourceFalse', 'sourceTrue', 'sourceFalse'), // false
value3: nor('sourceTrue', 'sourceTrue', 'sourceTrue') // false
not
same as Ember.computed.not
, but allows composing
source1: true,
source2: false,
value1: not('source1'), // false
value2: not(and('source1', 'source2')) // true
notEmpty
negation of isEmpty
sourceString1: '',
sourceString2: foobar,
sourceArray1: [],
sourceArray2: [1, 2, 3],
sourceObject1: {},
sourceObject2: { size: 0 },
valueString1: notEmpty('sourceString1'), // false
valueString2: notEmpty('sourceString2'), // true
valueArray1: notEmpty('sourceArray1'), // false
valueArray2: notEmpty('sourceArray2'), // true
valueObject1: notEmpty('sourceObject1'), // true
valueObject2: notEmpty('sourceObject2'), // false
valueObject1: notEmpty(collect(1, 2)), // true
valueObject1: notEmpty([]) // false
notEqual
the inverse of equal
, allows composing
source1: 'my value',
source2: 'my other value',
source3: 'my value',
value1: notEqual('source1', 'source2'), // true
value2: notEqual('source1', 'source3'), // false
value3: notEqual('source1', 'source2', 'source3') // true
number
wraps Number
, allows composing
prop: true,
example: number('prop'), // 1
composingExample: sum(collect(8, number('prop'))) // 9
or
same as Ember.computed.or
, but allows composing
source1: true,
source2: false,
source3: true,
value1: or('source1', 'source2', 'source3'), // true
value2: or(not('source1'), 'source2', not('source3')) // false
parseFloat
wraps parseFloat
, allows composing
string1: '12.34',
string2: '12',
string3: '34',
example: parseFloat('string1'), // 12.34
composingExample: parseFloat(tag`${'string2'}.${'string3'}`) // 12.34
parseInt
wraps parseInt
, allows composing
string: '123',
example: parseInt('string'), // 123
composingExample: parseInt(substr('string', 1), 8) // 19
product
multiplies numbers
source1: 1,
source2: 2,
source3: 3,
value1: product('source1', 'source2', 'source3'), // 6
value2: product('source1', collect('source2', 'source3')) // 6
promise.all
combines promises using RSVP.all
promise1: computed(function() {
return RSVP.resolve('value1');
}),
promise2: computed(function() {
return RSVP.resolve('value2');
}),
promise: promise.all('promise1', 'promise2') // resolves to ['value1', 'value2']
promise.array
wraps a promise in the equivalent of DS.PromiseArray
(ArrayProxy
and PromiseProxyMixin
)
productsPromise: computed(function() {
return this.store.findAll('product');
}),
products: promise.array('productsPromise')
can also wrap a computed property
products: promise.array(computed(function() {
return this.store.findAll('product');
}))
promise.hash
combines promises using RSVP.hash
promise1: computed(function() {
return RSVP.resolve('value1');
}),
promise2: computed(function() {
return RSVP.resolve('value2');
}),
promise: promise.hash('promise1', 'promise2') // resolves to { promise1: 'value1', promise2: 'value2' }
promise.object
wraps a promise in the equivalent of DS.PromiseObject
(ObjectProxy
and PromiseProxyMixin
)
productPromise: computed(function() {
return this.store.findRecord('product', 1);
}),
product: promise.object('productPromise')
can also wrap a computed property
product: promise.object(computed(function() {
return this.store.findRecord('product', 1);
}))
promise.resolve
wraps a value in an RSVP.resolve
key1: 'my value',
promise1: promise.resolve('key1'), // a resolved promise if you need it
key2: computed(function() {
return this.store.findRecord('user');
}),
promise2: promise.resolve(conditional('someBool', 'key1', 'key2')) // resolve an object if you don't know if it is a promise or not
promise.then
calls .then()
on a promise and then .get
on the result
key: 'firstName',
userPromise: computed(function() {
return this.store.findRecord('user'); // { firstName: 'Mary' }
}),
firstName: promise.then('userPromise', 'key') // 'Mary'
quotient
divides numbers
source1: 3,
source2: 2,
source3: 1,
value1: quotient('source1', 'source2', 'source3'), // 1.5
value2: quotient('source1', collect('source2', 'source3')) // 1.5
string.camelize
wraps Ember.String.camelize
, allows composing
originalValue: 'test-string',
newValue: string.camelize('originalValue') // 'testString'
string.capitalize
wraps Ember.String.capitalize
, allows composing
originalValue: 'test string',
newValue: string.capitalize('originalValue') // 'Test string'
string.classify
wraps Ember.String.classify
, allows composing
originalValue: 'test string',
newValue: string.classify('originalValue') // 'TestString'
string.dasherize
wraps Ember.String.dasherize
, allows composing
originalValue: 'TestString',
newValue: string.dasherize('originalValue') // 'test-string'
string.decamelize
wraps Ember.String.decamelize
, allows composing
originalValue: 'TestString',
newValue: string.decamelize('originalValue') // 'test_string'
string.escapeExpression
wraps Ember.Handlebars.Utils.escapeExpression
, allows composing
originalValue: '<input>',
newValue: string.escapeExpression('originalValue') // '<input>'
string.htmlSafe
wraps Ember.String.htmlSafe
, allows composing
originalValue: '<input>',
newValue: string.htmlSafe('originalValue') // will not be escaped
string.indexOf
wraps String.prototype.indexOf()
, allows composing
string: '121',
value: '1',
example: string.indexOf('string', 'value'), // 0
composingExample: string.indexOf(substr('string', 1), raw('1')) // 1
string.isHtmlSafe
wraps Ember.String.isHTMLSafe
, allows composing
source1: '<input>',
source2: string.htmlSafe('<input>'),
value1: string.isHtmlSafe('source1'), // false
value2: string.isHtmlSafe('source2') // true
string.lastIndexOf
wraps String.prototype.lastIndexOf()
, allows composing
string: '121',
value: '1',
example: string.lastIndexOf('string', 'value'), // 2
composingExample: string.lastIndexOf(substr('string', 0, 2), raw('1')) // 0
string.length
wraps String.prototype.length
, allows composing
string1: 'abc',
string2: 'xyz',
example: string.length('string1'), // 3
composingExample: string.length(tag`${'string1'}${'string2'}`) // 6
string.match
wraps String.prototype.match
, allows composing
string1: 'abc',
string2: 'xyz',
regex1: /abc/,
regex2: /xyz/,
example: string.match('string1', 'regex1'), // ['abc']
example: string.match('string1', 'regex2'), // null
composingExample: string.match(tag`${'string1'}${'string2'}`, 'regex2') // ['xyz']
string.replace
wraps String.prototype.replace
, allows composing
string: 'abc',
substr: 'bc',
newSubstr: 'cb',
value1: string.replace('string', 'substr', 'newSubstr'), // 'acb'
value2: string.replace('string', 'substr', string.toUpper('newSubstr')) // 'aCB'
string.split
wraps String.prototype.split
, allows composing
source: 'val1,val2',
key: ',',
value1: string.split('source', 'key'), // ['val1', 'val2']
value2: string.split('source', raw(',')) // ['val1', 'val2']
string.substr
wraps String.prototype.substr()
, allows composing
string1: 'abcxyz',
string2: 'abc',
string3: 'xyz',
example: string.substr('string1', 2, 2), // 'cx'
composingExample: string.substr(tag`${'string2'}${'string3'}`, 2, 2) // 'cx'
string.substring
wraps String.prototype.substring()
, allows composing
string1: 'abcxyz',
string2: 'abc',
string3: 'xyz',
example: string.substring('string1', 2, 4), // 'cx'
composingExample: string.substring(tag`${'string2'}${'string3'}`, 2, 4) // 'cx'
string.titleize
capitalizes words, allows composing
originalValue: 'james mcAvoy',
newValue: string.titleize('originalValue') // 'James Mcavoy'
string.toLower
wraps String.prototype.toLowerCase()
, allows composing
originalValue: 'TestString',
newValue: string.toLower('originalValue') // 'teststring'
string.toUpper
wraps String.prototype.toUpperCase()
, allows composing
originalValue: 'TestString',
newValue: string.toUpper('originalValue') // 'TESTSTRING'
string.trim
wraps String.prototype.trim()
, allows composing
originalValue: ' TestString ',
newValue: string.trim('originalValue') // 'TestString'
string.underscore
wraps Ember.String.underscore
, allows composing
originalValue: 'TestString',
newValue: string.underscore('originalValue') // 'test_string'
subtract
alias for difference
sum
adds numbers
source1: 1,
source2: 2,
source3: 3,
value1: sum('source1', 'source2', 'source3'), // 6
value2: sum('source1', collect('source2', 'source3')) // 6
tag
use a tagged template literal as a computed macro, allows composing
source: 'two',
value1: tag`one ${'source'} three`, // 'one two three'
value2: tag`one ${toUpper('source')} three` // 'one TWO three'
toStr
calls toString
with args on whatever you provide
key1: {},
key2: 253,
key3: 254,
value1: toStr('key1'), // '[object Object]'
value2: toStr(math.max('key2', 'key3'), 16) // 'fe'
toString
alias for toStr
The toString
name conflicts with window.toString
and breaks Babel, which means you need to do something like this:
import { toString as toStr } from 'ember-awesome-macros';
That's why we provide the toStr
alias.
typeOf
wraps typeOf
operator
key1: {},
key2: false,
key3: '',
value1: typeOf('key1'), // 'object'
value2: typeOf(or('key2', 'key3')) // 'string'
unless
macro version of {{unless}}
and the inverse of conditional
, allows composing
condition1: false,
condition2: true,
expr1: 'my value 1',
expr2: 'my value 2',
value1: unless('condition1', 'expr1', 'expr2'), // 'my value 1'
value2: unless('condition2', 'expr1', 'expr2'), // 'my value 2'
value3: unless(and('condition1', 'condition2'), raw('my value 1'), raw('my value 2')) // 'my value 1'
xnor
applies logical XNOR
operation
sourceTrue: true,
sourceFalse: false,
value1: xnor('sourceFalse', 'sourceFalse', 'sourceFalse'), // true
value2: xnor('sourceFalse', 'sourceTrue', 'sourceFalse'), // false
value3: xnor('sourceTrue', 'sourceTrue', 'sourceTrue') // true
xor
applies logical XOR
operation
sourceTrue: true,
sourceFalse: false,
value1: xor('sourceFalse', 'sourceFalse', 'sourceFalse'), // false
value2: xor('sourceFalse', 'sourceTrue', 'sourceFalse'), // true
value3: xor('sourceTrue', 'sourceTrue', 'sourceTrue') // false
Contributing
See the Contributing guide for details.
License
This project is licensed under the MIT License.