I have an object of css rules which can have any or none of the following properties:
{ 'font-style': '…',
'font-variant': '…',
'font-weight': '…',
'text-decoration': '…',
'vertical-align': '…' }
The next step is to build up a css string that is applied to an input, e.g.:
style({'text-decoration': 'underline'}, 'foo');
//=> '<span style="text-decoration:underline">foo</span>'
However if the rules
object does not contain any of the above five css rule, the input is returned as is:
style({}, 'foo'); //=> 'foo'
As you can see this is not rocket science but care must be taken so as to not apply an empty css string or include extra stuff that we don't need.
I did come up with a solution using ramda.js which I was quite happy with until I decided to dive deeper into Monads.
I was impressed with the amount of code I have been able to remove by using a few Monadic principles.
const {curry} = require('ramda');
const {Maybe} = require('monet');
const css = (attrs, key) =>
attrs[key] ?
Maybe.of(`${key}:${attrs[key]};`) :
Maybe.of('');
const style = curry((va, td, fw, fv, fs, input) =>
va || td || fw || fv || fs ?
`<span style="${va}${td}${fw}${fv}${fs}">${input}</span>` : input);
module.exports = curry((attrs, input) =>
Maybe.of(input)
.ap(css('font-style', attrs)
.ap(css('font-variant', attrs)
.ap(css('font-weight', attrs)
.ap(css('text-decoration', attrs)
.ap(css('vertical-align', attrs)
.map(style))))))
.some());
I'm happy with this but I can't help thinking that all these nested ap
are some sort of callbacks hell in disguise. Perhaps there's a better way which I am not aware of?
Question: is there a better way to combine multiple Maybe
monads?