JSFiddle - React, Tailwind, and code Playground

HTML

<h3>X is 
<u data-bind='if: x'>True</u>
<u data-bind='ifnot: x'>False</u>
    <button data-bind='click: function () { x(!x()) }'>Toggle</button>

</h3>


<h1>Element - Element</h1>

<div data-bind='if: x'>IF X</div>
<div data-bind='else'>ELSE</div>

<h1>Element - Comment</h1>

<div data-bind='if: x'>IF X</div>
<!-- ko else -->ELSE
<!-- /ko -->

<h1>[ifnot] Element - Element</h1>

<div data-bind='ifnot: x'>NOT X</div>
<div data-bind='else'>ELSE (X)</div>

<h1>Comment - Element</h1>

<!-- ko if: x -->IF X
<!-- /ko -->
<div data-bind='else'>ELSE

</div>

<h1>Comment - Comment</h1>

<!-- ko if: x -->IF X
<!-- /ko -->
<!-- ko else: -->ELSE
<!-- /ko -->

<h1> Comments (nested) - Comment</h1>
<!-- ko if: x -->
IF X (<!-- ko text: "" + x() --><!-- /ko -->)
<!-- /ko -->
<!-- ko else -->
ELSE
<!-- /ko -->

<h1> Foreach (empty) - Else</h1>
<!-- ko foreach: [] -->
  Don't see me!
<!-- /ko -->
<!-- ko else -->
List is empty
<!-- /ko -->

<h1> Foreach ([1,2,3]) - Else</h1>
<!-- ko foreach: [1,2,3] -->
    <em data-bind='text: $data'></em>
<!-- /ko -->
<!-- ko else -->
    Don't see me!
<!-- /ko -->

<h1> Foreach (ko.obs(undefined)) - Else</h1>
<!-- ko foreach: ko.observable(undefined) -->
  Undefined.
<!-- /ko -->
<!-- ko else -->
  List is empty
<!-- /ko -->

CSS

body {
    padding: 8px 2em;
}
h1 {
    font-size: 1em;
    border-bottom: 1px solid #AAA;
}

JavaScript

/*

       For a plugin based upon this fiddle:
       https://github.com/brianmhunt/knockout-else

 */


// Re. https://github.com/knockout/knockout/issues/962
// See knockout virtualElements
function startsCommentBinding(node) {
    return (node.textContent || node.innerText)
        .match(/^(<!--)?\s*ko\s+[\s\S]+/);
}

function endsCommentBinding(node) {
    return (node.textContent || node.innerText)
        .match(/^(<!--)?\s*\/ko/);
}

function getBindingConditional(node, bindingContext) {
    var conditional;
    var bindings = ko.bindingProvider.instance.getBindings(node, bindingContext);
    if (!bindings) {
        return
    } else if (conditional = bindings['if']) {
        return ko.pureComputed(function () {
            return !ko.unwrap(conditional)
        });
    } else if (conditional = bindings['ifnot']) {
        return ko.pureComputed(function () {
            return ko.unwrap(conditional)
        });
    } else if (conditional = bindings['foreach']) {
        return ko.pureComputed(function () {
            var conResult = ko.unwrap(conditional);
            return !conResult || conResult.length === 0;
        });
    }
    return
}

function prevVirtualNode(node) {
    var depth = 0;
    do {
        if (node.nodeType === 8) {
            if (startsCommentBinding(node)) {
                if (--depth == 0) {
                    return node;
                }
            } else if (endsCommentBinding(node)) {
                depth++;
            }
        }
    } while (node = node.previousSibling);
    return;
}

function getPrecedingConditional(element, bindingContext) {
    var prevSib = element;
    do {
        prevSib = prevSib.previousSibling;
    } while (prevSib && [1, 8].indexOf(prevSib.nodeType) === -1);
    if (!prevSib) {
        throw new Error("Unmatched conditionals!");
        return;
    }
    if (prevSib.nodeType == 1) {
        return getBindingConditional(prevSib, bindingContext);
    } else if (prevSib.nodeType == 8) {
...