<commit_before>(function(window, document, console, CodeMirror) {

  var slimwiki = window.slimwiki,
      editor,
      updatePreviewDelay = 1000,
      updatePreviewTimeout = null,
      updatePreviewRunning = false,
      previewIsDirty = false;


  function init() {
    editor = CodeMirror.fromTextArea(document.getElementById('editor'), {
      // Config see: https://codemirror.net/doc/manual.html
      mode: 'gfm',
      lineNumbers: false,
      lineWrapping: true,
      theme: 'railscasts'
    });

    editor.on('changes', onEditorChange);
  }

  function onEditorChange() {
    previewIsDirty = true;
    if (! updatePreviewRunning) {
      window.clearTimeout(updatePreviewTimeout);
      updatePreviewTimeout = window.setTimeout(function() {
        previewIsDirty = false;

        updatePreviewRunning = true;
        var start = new Date().getTime(),
            articleFilename = slimwiki.settings.articleFilename;
        callRpc('editor', 'saveArticle', [ articleFilename, editor.getValue() ], function(result, error) {
          updatePreviewRunning = false;

          if (error) {
            console.error('Saving article failed:', error);
          } else {
            document.getElementById('content').innerHTML = result;
            slimwiki.View.updateSyntaxHighlighting();
            console.log('Saved article in ' + (new Date().getTime() - start) + ' ms');
          }

          if (previewIsDirty) {
            onEditorChange();
          }
        })
      }, updatePreviewDelay);
    }
  }

  function callRpc(objectName, methodName, paramArray, done) {
    var request = new XMLHttpRequest(),
        requestJson;

    request.open('POST', 'rpc/' + objectName, true);
    request.onreadystatechange = function () {
      if (request.readyState == 4) {
        if (request.status != 200) {
          done(null, 'Request failed with status ' + request.status);
        } else {
          try {
            var responseJson = JSON.parse(request.responseText);
            if (responseJson.error) {
              done(null, 'Request failed on server-side: ' + responseJson.error.message);<commit_msg>Synchronizing scroll position of preview when editor is scrolled<commit_after>(function(window, document, console, CodeMirror) {

  var slimwiki = window.slimwiki,
      editor,
      updatePreviewDelay = 1000,
      updatePreviewTimeout = null,
      updatePreviewRunning = false,
      previewIsDirty = false;


  function init() {
    editor = CodeMirror.fromTextArea(document.getElementById('editor'), {
      // Config see: https://codemirror.net/doc/manual.html
      mode: 'gfm',
      lineNumbers: false,
      lineWrapping: true,
      theme: 'railscasts'
    });

    editor.on('changes', onEditorChange);
    editor.on('scroll', onEditorScroll)
  }

  function onEditorChange() {
    previewIsDirty = true;
    if (! updatePreviewRunning) {
      window.clearTimeout(updatePreviewTimeout);
      updatePreviewTimeout = window.setTimeout(function() {
        previewIsDirty = false;

        updatePreviewRunning = true;
        var start = new Date().getTime(),
            articleFilename = slimwiki.settings.articleFilename;
        callRpc('editor', 'saveArticle', [ articleFilename, editor.getValue() ], function(result, error) {
          updatePreviewRunning = false;

          if (error) {
            console.error('Saving article failed:', error);
          } else {
            document.getElementById('content').innerHTML = result;
            slimwiki.View.updateSyntaxHighlighting();
            console.log('Saved article in ' + (new Date().getTime() - start) + ' ms');
          }

          if (previewIsDirty) {
            onEditorChange();
          }
        })
      }, updatePreviewDelay);
    }
  }

  function onEditorScroll() {
    // Synchronize scroll position of preview when editor is scrolled
    var scrollInfo = editor.getScrollInfo(),
        scrollFactor = scrollInfo.top / (scrollInfo.height - scrollInfo.clientHeight),
        bodyElem = document.body;

    window.scrollTo(0, scrollFactor * (bodyElem.scrollHeight - bodyElem.clientHeight));
  }

  function callRpc(objectName, methodName, paramArray, done) {
    var request = new XMLHttpRequest(),
        requestJson;

    request.open('POST', 'rpc/' + objectName, true);
    request.onreadystatechange = function () {
      if (request.readyState == 4) {
        if (request.status != 200) {
          done(null, 'Request failed with status ' + request.status);
        } else {
          try {
            var responseJson = JSON.parse(request.responseText);
            if (responseJson.error) {
              done(null, 'Request failed on server-side: ' + responseJson.error.message);
{'fraction_non_alphanumeric': 0.11550666384599112, 'fraction_numerical': 0.0035963613285381847, 'mean_word_length': 2.5575620767494356, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2612324', 'n_tokens_mistral': 1302, 'n_tokens_neox': 1251, 'n_words': 277}