Open
Description
This is a fancy, reactive string builder. It's used to define "components" as do-routines that yield string(s) which are all concated together to produce a chunk of HTML, which can then be shoved into the DOM. Since it's based on IOx, it can be set as dependent on other IOs/IOxs as inputs and reactively re-rendered on each update.
Example for how to use the utility:
// this could be an IOx which can have its value updated
// over time if desired
var id = IO.of(42);
doRender(whatever,[ id ])
// this step is just console.log()ing, but it could instead
// be pushing the HTML into a DOM element
.map(v => console.log("html",v))
.run({});
// here's a "component" -- you `yield` out string(s), or any
// monad that produces a string, and it concats them all.
//
// the nice thing is, other than the string concating, this
// is a full do-routine that can be async, do any monad/IO
// operations, etc, whatever you need to define your
// component's markup
function *whatever(context,id) {
yield `<div id="${id}">`;
for (let i = 0; i < 3; i++) {
yield `<span>${i}</span>`;
}
yield `</div>`;
}
And here's the candidate first implementation of doRender(..)
:
function doRender(gen,deps = [],...args) {
return IOx.do(runner,deps);
// ************************************
async function *runner(context,...depsVals) {
var htmlIO = IO.of("");
var it = gen(context,...depsVals,...args);
var res;
while (true) {
res = it.next(res);
if (isPromise(res)) {
res = await res;
}
else {
let done = res.done;
if (isMonad(res.value)) {
if (IO.is(res.value)) {
res = res.value.chain(concatIfString);
}
else if (Nothing.is(res.value)) {
return IO.of("");
}
else if (Either.is(res.value) || Maybe.is(res.value)) {
res = res.value.fold(IO.of,concatIfString);
}
else {
res = res.value.fold(concatIfString);
}
}
else {
res = concatIfString(res.value);
}
res = yield res;
if (done) {
return htmlIO.run(context);
}
}
}
// ************************************
function concatIfString(v) {
if (typeof v == "string") {
htmlIO = htmlIO.concat(IO.of(v));
return IO.of();
}
else {
return IO.of(v);
}
}
}
}