<commit_before>// =============================================================================
// Boost.js | Router
// (c) Mathigon
// =============================================================================



/* global ga */
import { noop, run, zip, Evented } from '@mathigon/core';
import * as Ajax from './ajax';
import { Browser } from './browser';
import { $body } from './elements';


// -----------------------------------------------------------------------------
// Utilities

function getViewParams(url, view) {
  let match = view.regex.exec(url);
  if (match) {
    match.shift();
    return zip(view.params, match);
  } else {
    return null;
  }
}

// Prevent scroll restoration on popstate
if ('scrollRestoration' in history) history.scrollRestoration = 'manual';


// -----------------------------------------------------------------------------
// Browser History

const onPopState = (function () {
  let ready = false;

  if (document.readyState === 'complete') {
    ready = true;
  } else {
    window.addEventListener('load', function() {
      setTimeout(function() { ready = true; });
    });
  }

  return function(e) {
    if (ready && e.state) this.goToState(e.state);
  };
})();

function onLinkClick(e) {

  if (e.metaKey || e.ctrlKey || e.shiftKey) return;
  if (e.defaultPrevented) return;

  let el = e.target;
  while (el && 'A' !== el.nodeName) el = el.parentNode;
  if (!el || 'A' !== el.nodeName) return;

  // Check target
  if (el.target) return;

  // Different origin
  if (el.origin !== window.location.origin) return;

  // Ignore if tag has "download" attribute or rel="external" attribute
  if (el.hasAttribute('download') || el.getAttribute('rel') === 'external') return;

  // Check for mailto: in the href
  let link = el.getAttribute('href');
  if (link && link.indexOf('mailto:') > -1) return;

  let success = this.goTo(el.pathname + el.search, el.hash);
  if (success) e.preventDefault();
}


// -----------------------------------------------------------------------------
// Rendering and Navigation

function renderView(router, view, template, params) {
  router.$viewport.css('opacity', 0);

  setTimeout(() => {
    router.$viewport.removeChildren();
    $body.scrollTop = 0;
    router.$viewport.html = template;
    Browser.resize();
    Browser.replaceSvgImports();
    router.$viewport.css({ opacity: 1, 'pointer-events': 'all' });
    document.title = router.$viewport.$('title').text;
    router.initialise(router.$viewport, params);
    if (view.enter) view.enter(router.$viewport, params);
    router.trigger('afterChange');
  }, 350);
}

function loadView(router, view, params = {}, url = '') {
  router.$viewport.css({ opacity: 0.4, 'pointer-events': 'none' });
  let template = run(view.template, params) || Ajax.get(url);

  if (template.then) {
    template.then(response => renderView(router, view, response, params));
  } else {
    renderView(router, view, template, params);
  }
}


// -----------------------------------------------------------------------------
// Router Class

class _Router extends Evented {

  setup(options) {<commit_msg>Pass viewport element in Router 'afterChange' event.<commit_after>// =============================================================================
// Boost.js | Router
// (c) Mathigon
// =============================================================================



/* global ga */
import { noop, run, zip, Evented } from '@mathigon/core';
import * as Ajax from './ajax';
import { Browser } from './browser';
import { $body } from './elements';


// -----------------------------------------------------------------------------
// Utilities

function getViewParams(url, view) {
  let match = view.regex.exec(url);
  if (match) {
    match.shift();
    return zip(view.params, match);
  } else {
    return null;
  }
}

// Prevent scroll restoration on popstate
if ('scrollRestoration' in history) history.scrollRestoration = 'manual';


// -----------------------------------------------------------------------------
// Browser History

const onPopState = (function () {
  let ready = false;

  if (document.readyState === 'complete') {
    ready = true;
  } else {
    window.addEventListener('load', function() {
      setTimeout(function() { ready = true; });
    });
  }

  return function(e) {
    if (ready && e.state) this.goToState(e.state);
  };
})();

function onLinkClick(e) {

  if (e.metaKey || e.ctrlKey || e.shiftKey) return;
  if (e.defaultPrevented) return;

  let el = e.target;
  while (el && 'A' !== el.nodeName) el = el.parentNode;
  if (!el || 'A' !== el.nodeName) return;

  // Check target
  if (el.target) return;

  // Different origin
  if (el.origin !== window.location.origin) return;

  // Ignore if tag has "download" attribute or rel="external" attribute
  if (el.hasAttribute('download') || el.getAttribute('rel') === 'external') return;

  // Check for mailto: in the href
  let link = el.getAttribute('href');
  if (link && link.indexOf('mailto:') > -1) return;

  let success = this.goTo(el.pathname + el.search, el.hash);
  if (success) e.preventDefault();
}


// -----------------------------------------------------------------------------
// Rendering and Navigation

function renderView(router, view, template, params) {
  router.$viewport.css('opacity', 0);

  setTimeout(() => {
    router.$viewport.removeChildren();
    // TODO Remove all event listeners in $viewport, to avoid memory leaks.
    $body.scrollTop = 0;
    router.$viewport.html = template;
    Browser.resize();
    Browser.replaceSvgImports();
    router.$viewport.css({ opacity: 1, 'pointer-events': 'all' });
    document.title = router.$viewport.$('title').text;
    router.initialise(router.$viewport, params);
    if (view.enter) view.enter(router.$viewport, params);
    router.trigger('afterChange', {$viewport: router.$viewport});
  }, 350);
}

function loadView(router, view, params = {}, url = '') {
  router.$viewport.css({ opacity: 0.4, 'pointer-events': 'none' });
  let template = run(view.template, params) || Ajax.get(url);

  if (template.then) {
    template.then(response => renderView(router, view, response, params));
  } else {
    renderView(router, view, template, params);
  }
}


// -----------------------------------------------------------------------------
// Router Class

class _Router extends Evented {

  setup(options) {
{'fraction_non_alphanumeric': 0.2917709637046308, 'fraction_numerical': 0.002816020025031289, 'mean_word_length': 2.4407965554359525, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 9, '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': '2522417', 'n_tokens_mistral': 1848, 'n_tokens_neox': 1766, 'n_words': 453}