I have written the below snippets before which may be useful to you.
// this function only check if the selection is spanned across the highlighted span
function shouldSelectText() {
    // http://stackoverflow.com/a/6056743/510577
    var sel = rangy.getSelection();
    if (sel.rangeCount) {
        var range = sel.getRangeAt(0);
        var nodes = range.getNodes([1], function(node) {
            return node.tagName.toLowerCase() == "span"; // only need to satisfy one of open / close "span" tag, so no need to use "containsNode"
        });
        return (nodes.length <= 0);
    }
    return false;
}
shouldSelectText in my case is invoked during - (BOOL)canPerformAction:(SEL)action withSender:(id)sender of the web view to check whether the webview should expand the highlight under selection.
// the return value indicates whether it is highlighted before
function selectHighlight() {
    var sel = rangy.getSelection();
    if (sel.rangeCount > 0) {
        // console.log("has selection!");
        if (_highlighter.getHighlightsInSelection().length <= 0) {
            return false; // do nothing if it is not highlighted before
        }
        // else the selection is highlighted, so we expand it to select the whole highlight
        window.requestAnimationFrame(function() {
            var range = rangy.createRange();
            range = _highlighter.getHighlightsInSelection()[0].getRange(); // use non-disclosed private API of rangy highlighter!
            sel.setSingleRange(range);
            _highlightUnderSelection = _highlighter.getIntersectingHighlights(rangy.getSelection().getAllRanges())[0]; // must be the first one
        });
        return true;
    }
    return false;
}
 
if shouldSelectText returns true, then you may use selectHighlight to expand the highlight under selection.
 
P.S. you need to make use of stringByEvaluatingJavaScriptFromString of UIWebView to call the above JS from the native side