Skip to content

Instantly share code, notes, and snippets.

@marcoslhc
Last active February 3, 2018 19:39
Show Gist options
  • Save marcoslhc/ceeb9f61d9cc3fd774fac358df292ef2 to your computer and use it in GitHub Desktop.
Save marcoslhc/ceeb9f61d9cc3fd774fac358df292ef2 to your computer and use it in GitHub Desktop.
const compose =
(...funcs) => arg => funcs.reduceRight((composed, f) => f(composed), arg);
const filterReduce =
predicate => reducer => (accum, value) => (predicate(value)) ? reducer(accum, value) : accum;
const mapReduce =
morphism => reducer => (accum, value) => reducer(accum, morphism(value));
const transduce =
(predicate, morphism) => reducer => (accum, value) => (predicate(value)) ? reducer(accum, morphism(value)) : accum;
const ingest =
(accum, value) => accum.concat(value);
function ClassList(unwrapFn) {
this.getClasses = unwrapFn;
return this;
}
// Let's make it a "pointed functor"
ClassList.of = function(classes) {
return new ClassList(() => {
return classes;
});
};
// And is a Functor after all. It should map
ClassList.prototype.map = function(fn) {
return ClassList.of(fn(this.getClasses()));
};
ClassList.prototype.reduce = function (reducer, initialValue) {
return ClassList.of(this.getClasses().reduce(reducer, initialValue));
}
// Notice how we can define "filter" by reducing the previous array
// into a new array with only the values that satisfies the predicate
ClassList.prototype.filter = function (predicate) {
return ClassList.of(this.getClasses()).reduce((newList, currentClass) => {
if (predicate(currentClass)) newList.push(currentClass);
return newList;
}, []);
}
// These are derivation and mostly for convenience
ClassList.prototype.mapFilter = function(predicate, fn) {
const reducer = transduce(predicate, fn)(ingest)
return ClassList.of(this.getClasses()).reduce(reducer, []);
};
ClassList.prototype.filterReduce = function (predicate, fn) {
const reducer = filterReduce(predicate)(fn);
return ClassList.of(this.getClasses()).reduce(reducer, []);
};
ClassList.prototype.concat = function (otherList) {
return ClassList.of(this.getClasses().concat(otherList.getClasses()));
}
ClassList.prototype.addClass = function (classes) {
const classesToAdd = Array.isArray(classes) ? classes
: [classes];
return ClassList.of(this.getClasses()).concat(ClassList.of(classesToAdd));
}
ClassList.prototype.removeClass = function (className) {
const predicate = (currentClass) => currentClass !== className;
return ClassList.of(this.getClasses()).filter(predicate)
}
ClassList.prototype.getString = function () {
return this.getClasses.join(' ');
}
const getSelectedClass =
classRegex => classString => classRegex.test(classString);
const addClassModifier =
className => (classString) => classString.concat('--').concat(className);
ClassList.of([
'btn__background--solarized',
'btn__text--solarized',
'btn__overlay--solarized',
'btn__icon',
'btn__placeholder'
]).reduce(
transduce(
getSelectedClass(/--solarized/),
addClassModifier('active')
)(ingest),
[]).getClasses();
// [
// "btn__background--solarized--active",
// "btn__text--solarized--active",
// "btn__overlay--solarized--active"
// ];
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment