rhsTransformer: function setNoteIfEmpty()

in src/js/other-websites/fathom.js [1464:1570]


                           rhsTransformer: function setNoteIfEmpty(fact) {
                               // If note is explicitly set by the RHS, let it take
                               // precedence, even though that makes this entire LHS
                               // pointless.
                               if (fact.note === undefined) {
                                   fact.note = nearest;  // TODO: Wrap this in an object to make room to return distance later.
                               }
                               return fact;
                           }};
                }
            }
        }

        checkFact(fact) {
            // Barf if the fact doesn't set a type at least. It should be a *new* type or at least one that doesn't result in cycles, but we can't deduce that.
        }

        possibleTypeCombinations() {
            return [new NiceSet([this._a.guaranteedType()])];
        }

        typesMentioned() {
            return new NiceSet([this._a.guaranteedType(),
                                this._b.guaranteedType()]);
        }

        guaranteedType() {
            return this._a.guaranteedType();
        }
    }

    // The right-hand side of a rule


    const TYPE = 1;
    const NOTE = 2;
    const SCORE = 4;
    const ELEMENT = 8;
    const SUBFACTS = {
        type: TYPE,
        note: NOTE,
        score: SCORE,
        element: ELEMENT
    };

    /**
     * Expose the output of this rule's LHS as a "final result" to the surrounding
     * program. It will be available by calling :func:`~BoundRuleset.get` on the
     * ruleset and passing the key. You can run each node through a callback
     * function first by adding :func:`through()`, or you can run the entire set of
     * nodes through a callback function by adding :func:`allThrough()`.
     */
    function out(key) {
        return new OutwardRhs(key);
    }

    class InwardRhs {
        constructor(calls = [], max = Infinity, types) {
            this._calls = calls.slice();
            this._max = max;  // max score
            this._types = new NiceSet(types);  // empty set if unconstrained
        }

        /**
         * Declare that the maximum returned subscore is such and such,
         * which helps the optimizer plan efficiently. This doesn't force it to be
         * true; it merely throws an error at runtime if it isn't. To lift an
         * ``atMost`` constraint, call ``atMost()`` (with no args). The reason
         * ``atMost`` and ``typeIn`` apply until explicitly cleared is so that, if
         * someone used them for safety reasons on a lexically distant rule you are
         * extending, you won't stomp on their constraint and break their
         * invariants accidentally.
         */
        atMost(score) {
            return new this.constructor(this._calls, score, this._types);
        }

        _checkAtMost(fact) {
            if (fact.score !== undefined && fact.score > this._max) {
                throw new Error(`Score of ${fact.score} exceeds the declared atMost(${this._max}).`);
            }
        }

        /**
          * Determine any of type, note, score, and element using a callback. This
          * overrides any previous call to `props` and, depending on what
          * properties of the callback's return value are filled out, may override
          * the effects of other previous calls as well.
          *
          * The callback should return...
          *
          * * An optional :term:`subscore`
          * * A type (required on ``dom(...)`` rules, defaulting to the input one on
          *   ``type(...)`` rules)
          * * Optional notes
          * * An element, defaulting to the input one. Overriding the default
          *   enables a callback to walk around the tree and say things about nodes
          *   other than the input one.
          */
        props(callback) {
            function getSubfacts(fnode) {
                const subfacts = callback(fnode);
                // Filter the raw result down to okayed properties so callbacks
                // can't insert arbitrary keys (like conserveScore, which might
                // mess up the optimizer).
                for (let subfact in subfacts) {
                    if (!SUBFACTS.hasOwnProperty(subfact) || !(SUBFACTS[subfact] & getSubfacts.possibleSubfacts)) {