<commit_before>

(function() {
  var FALSE, HOVER, KEY;
  MathJax.Hub.Register.StartupHook("MathEvents Ready",function () {
    FALSE = MathJax.Extension.MathEvents.Event.False;
    HOVER = MathJax.Extension.MathEvents.Hover;
    KEY = MathJax.Extension.MathEvents.Event.KEY;
  });
  var Explorer = MathJax.Extension.Explorer = {
    enriched: [],
    active: [],
    speechDiv: null,
    Register: function(jax, id, script) {
      if (jax.enriched) {
        Explorer.enriched.push(jax);
      };
    },
    AddEvents: function() {
      for (var i = 0, jax; jax = Explorer.enriched[i]; i++) {
        // This is costly! Can I do this also from the script?
        var frame = document.getElementById(jax.inputID + '-Frame');
        if (frame) {
          Explorer.AddEvent(frame);
          Explorer.active.push(jax);
        }
      }
      if (Explorer.enriched.length !== Explorer.active.length) {
          MathJax.Hub.Queue(["AddEvents", Explorer]);
      }
    },
    AddEvent: function(element) {
      element.onkeydown = Explorer.Keydown;
    },
    Keydown: function (event) {
      if (event.keyCode === KEY.SPACE) {
        var math = event.target;
        if (event.shiftKey) {
          Explorer.AddSpeech(math);
          var speechNode = math.querySelector('span[data-semantic-speech]');
          Explorer.Speak(speechNode.getAttribute('data-semantic-speech'));
        } else {
          MathJax.Extension.MathEvents.Event.ContextMenu(event, math);
        }
      } else if (event.keyCode === KEY.ESCAPE) {
        Explorer.RemoveSpeech();
      }
      FALSE(event);
    },
    AddSpeech: function(math) {
      if (!Explorer.speechDiv) {
        Explorer.speechDiv = MathJax.HTML.addElement(
          document.body, "div", {className:"MathJax_SpeechOutput",
                                 style: {fontSize: '1px', color: '#FFFFFF'}});
        Explorer.speechDiv.setAttribute('aria-live', 'assertive');
      }
    },
    RemoveSpeech: function() {
      if (Explorer.speechDiv) {
        Explorer.speechDiv.parentNode.removeChild(Explorer.speechDiv);
      }
      Explorer.speechDiv = null;
    },
    Speak: function(speech) {
      Explorer.speechDiv.textContent = speech;
    },
    GetRoot: function(math) {
      var speechNodes = math.querySelectorAll('span[data-semantic-speech]');
      var parent = speechNodes.find(function(x) {
          return !x.hasAttribute('data-semantic-parent');});
    }
  };
  
  MathJax.Hub.postInputHooks.Add(["Register", Explorer], 200);

  MathJax.Hub.Register.MessageHook("End Math",
                                   ["AddEvents", MathJax.Extension.Explorer]);

})();
<commit_msg>Finds the correct root element for speech generation.<commit_after>

(function() {
  var FALSE, KEY;
  MathJax.Hub.Register.StartupHook("MathEvents Ready",function () {
    FALSE = MathJax.Extension.MathEvents.Event.False;
    KEY = MathJax.Extension.MathEvents.Event.KEY;
  });

  var Explorer = MathJax.Extension.Explorer = {
    enriched: [],
    active: [],
    speechDiv: null,
    //
    // Collates all enriched jaxs.
    //
    Register: function(jax, id, script) {
      if (jax.enriched) {
        Explorer.enriched.push(jax);
      };
    },
    //
    // Adds key events to each enriched jax.
    //
    AddEvents: function() {
      for (var i = 0, jax; jax = Explorer.enriched[i]; i++) {
        // This is costly! Can I do this also by walking back from script?
        var frame = document.getElementById(jax.inputID + '-Frame');
        if (frame) {
          Explorer.AddEvent(frame);
          Explorer.active.push(jax);
        }
      }
      if (Explorer.enriched.length !== Explorer.active.length) {
        MathJax.Hub.Queue(["AddEvents", Explorer]);
      }
    },
    //
    // Adds a single key event.
    //
    AddEvent: function(element) {
      element.onkeydown = Explorer.Keydown;
    },
    // 
    // Event execution on keydown. Subsumes the same method of MathEvents.
    //
    Keydown: function (event) {
      if (event.keyCode === KEY.SPACE) {
        var math = event.target;
        if (event.shiftKey) {
          Explorer.AddSpeech(math);
          var speechNode = Explorer.GetRoot(math);
          Explorer.Speak(speechNode.getAttribute('data-semantic-speech'));
        } else {
          MathJax.Extension.MathEvents.Event.ContextMenu(event, math);
        }
      } else if (event.keyCode === KEY.ESCAPE) {
        Explorer.RemoveSpeech();
      }
      FALSE(event);
    },
    //
    // Adds the speech div.
    //
    AddSpeech: function(math) {
      if (!Explorer.speechDiv) {
        Explorer.speechDiv = MathJax.HTML.addElement(
          document.body, "div", {className:"MathJax_SpeechOutput",
                                 style: {fontSize: '1px', color: '#FFFFFF'}});
        Explorer.speechDiv.setAttribute('aria-live', 'assertive');
      }
    },
    //
    // Removes the speech div.
    //
    RemoveSpeech: function() {
      if (Explorer.speechDiv) {
        Explorer.speechDiv.parentNode.removeChild(Explorer.speechDiv);
      }
      Explorer.speechDiv = null;
    },
    //
    // Speaks a string by poking it into the speech div.
    //
    Speak: function(speech) {
      Explorer.speechDiv.textContent = speech;
    },
    //
    //
    //
    GetRoot: function(math) {
      var speechNodes = math.querySelectorAll('span[data-semantic-speech]');
      for (var i = 0, speechNode; speechNode = speechNodes[i]; i++) {
        if (!speechNode.hasAttribute('data-semantic-parent')) {
          return speechNode;
        }
      }
      return speechNodes[0];
    }
  };
  
  MathJax.Hub.postInputHooks.Add(["Register", Explorer], 200);

  MathJax.Hub.Register.MessageHook("End Math",
                                   ["AddEvents", MathJax.Extension.Explorer]);

})();

{'fraction_non_alphanumeric': 0.1404416839199448, 'fraction_numerical': 0.002070393374741201, 'mean_word_length': 2.2169811320754715, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5430089', 'n_tokens_mistral': 1867, 'n_tokens_neox': 1793, 'n_words': 329}