<commit_before>import $events from 'wee-events';
import { _doc, _win } from 'core/variables';
import { $copy, $extend, $isObject } from 'core/types';
import { $exec } from 'core/core';
import { $each, $parseHTML, $setRef } from 'core/dom';
import { $serializeForm } from 'dom/index';
import { supportsPushState } from './push-state';
import $fetch from 'wee-fetch';
import $ from 'wee-dom';
import { warn } from './warn';

let defaults = {
	bind: {
		click: 'a',
		submit: 'form'
	},
	context: 'document',
	fetch: $fetch.create(),
	partials: 'title,main',
	request: {
		method: 'get',
		responseType: 'text',
		headers: {
			'X-PJAX': 'true'
		}
	},
	replace: null
};
let settings = $copy(defaults);
let response = null;
let paused = false;

/**
 * Determine if path is valid for history navigation
 *
 * @param {HTMLElement} el
 * @param {string} [currentPath]
 * @returns {boolean}
 * @private
 */
function _isValid(el, currentPath) {
	// Link has no destination URL
	if (! el.href) { return false; }

	// Link opens a new browser window
	if (el.target === '_blank') { return false; }

	// Link is not absolute URL
	if (! /https?:/.test(el.href)) { return false; }

	// Link is a download
	if (el.hasAttribute('download')) { return false; }

	// Link is supposed to be ignored
	if (el.hasAttribute('data-static')) { return false; }

	// Link is external URL
	if (el.host && el.host !== location.host) { return false; }

	// Link is current page, but with a hash added
	if (el.hash && el.pathname === currentPath) { return false; }

	if (! currentPath) { return true; }

	// TODO: Remove whitelisting logic
	let exts = settings.extensions;
	let segs = currentPath.split('.');
	let ext;

	if (segs.length > 1) {
		ext = segs.pop().split(/#|\?/)[0];
	}

	// No file extension in URL or extension is whitelisted
	return ! ext || (exts && exts.indexOf(ext) > -1);
}

/**
 * Return current path
 *
 * @private
 * @param {object} [loc]
 * @returns {string}
 */
function _path(loc) {
	loc = loc || location;
	return loc.pathname + loc.search + loc.hash;
}

/**
 * Reset references and variables for a given selector
 *
 * @private
 * @param sel
 */
function _reset(sel) {
	response = null;
	$setRef(sel);
	// TODO: Uncomment when $setVar is added
	// $setVar(sel);

	pjax.bind(sel);
}

const pjax = {
	// Empty callback - will be defined by router.pjax
	onTrigger() {},

	/**
	 * Bind element events and form submit events to callback
	 *
	 * @param {($|HTMLElement|string)} [context=document]
	 */
	bind(context) {
		const events = settings.bind;
		context = context || settings.context;

		if (supportsPushState) {
			const keys = Object.keys(events);
			let i = 0;

			// Iterate through events to be bound
			for (; i < keys.length; i++) {
				const event = keys[i];
				const sel = events[event];

				$each(sel, el => {
					const evts = event.split(' ').map(val => {
							return val + '.pjax';
						}).join(' ');

					// Retrieve data-url off of element
					// Used if element is not <a> tag
					const loc = el.getAttribute('data-url');
					let destination = el;

					// Create <a> tag for validation of URL
					if (loc) {
						let attrs = el.attributes;
						let j = 0;
						let attr;

						destination = _doc.createElement('a');

						// Clone attributes from bound element to new a tag
						for (; j < attrs.length; j++) {
							attr = attrs[j];
							destination.setAttribute(attr.name, attr.value);
						}

						// Set URL
						destination.href = loc;
					}

					// Ensure the path exists and is local
					if (! evts || ! _isValid(destination)) {
						warn('PJAX: no events provided or invalid destination URL ' + destination.href);
						return;
					}

					// TODO: Make this reset optional so we can use 'bind' dynamically
					// Remove existing pjax events
					$events.off(el, '.pjax');

					// Bind designated events
					$events.on(el, evts, (e, el) => {
						if (paused) {
							warn('pjax has been paused - will not trigger navigation');
							return;
						}

						// Don't navigate with control keys
						if (e.metaKey || e.ctrlKey || e.shiftKey) { return; }

						// Don't navigate when preventDefault already called
						if (e.defaultPrevented) { return; }

						// Don't navigate on right click
						if (e.button !== undefined && e.button !== 0) { return; }

						let path = _path(destination);
<commit_msg>Prevent binding internal page links in pjax<commit_after>import $events from 'wee-events';
import { _doc, _win } from 'core/variables';
import { $copy, $extend, $isObject } from 'core/types';
import { $exec } from 'core/core';
import { $each, $parseHTML, $setRef } from 'core/dom';
import { $serializeForm } from 'dom/index';
import { supportsPushState } from './push-state';
import $fetch from 'wee-fetch';
import $ from 'wee-dom';
import { warn } from './warn';
import { parseLocation } from './location';

let defaults = {
	bind: {
		click: 'a',
		submit: 'form'
	},
	context: 'document',
	fetch: $fetch.create(),
	partials: 'title,main',
	request: {
		method: 'get',
		responseType: 'text',
		headers: {
			'X-PJAX': 'true'
		}
	},
	replace: null
};
let settings = $copy(defaults);
let response = null;
let paused = false;

/**
 * Determine if path is valid for history navigation
 *
 * @param {HTMLElement} el
 * @param {string} [currentPath]
 * @returns {boolean}
 * @private
 */
function _isValid(el, currentPath) {
	// Link has no destination URL
	if (! el.href) { return false; }

	// Link opens a new browser window
	if (el.target === '_blank') { return false; }

	// Link is not absolute URL
	if (! /https?:/.test(el.href)) { return false; }

	// Link is a download
	if (el.hasAttribute('download')) { return false; }

	// Link is supposed to be ignored
	if (el.hasAttribute('data-static')) { return false; }

	// Link is external URL
	if (el.host && el.host !== location.host) { return false; }

	// Link is current page, but with a hash added
	if (el.hash && el.pathname === currentPath) { return false; }

	return true;
}

/**
 * Return current path
 *
 * @private
 * @param {object} [loc]
 * @returns {string}
 */
function _path(loc) {
	loc = loc || location;
	return loc.pathname + loc.search + loc.hash;
}

/**
 * Reset references and variables for a given selector
 *
 * @private
 * @param sel
 */
function _reset(sel) {
	response = null;
	$setRef(sel);
	// TODO: Uncomment when $setVar is added
	// $setVar(sel);

	pjax.bind(sel);
}

const pjax = {
	// Empty callback - will be defined by router.pjax
	onTrigger() {},

	/**
	 * Bind element events and form submit events to callback
	 *
	 * @param {($|HTMLElement|string)} [context=document]
	 */
	bind(context) {
		const current = parseLocation();
		const events = settings.bind;
		context = context || settings.context;

		if (supportsPushState) {
			const keys = Object.keys(events);
			let i = 0;

			// Iterate through events to be bound
			for (; i < keys.length; i++) {
				const event = keys[i];
				const sel = events[event];

				$each(sel, el => {
					const evts = event.split(' ').map(val => {
							return val + '.pjax';
						}).join(' ');

					// Retrieve data-url off of element
					// Used if element is not <a> tag
					const loc = el.getAttribute('data-url');
					let destination = el;

					// Create <a> tag for validation of URL
					if (loc) {
						let attrs = el.attributes;
						let j = 0;
						let attr;

						destination = _doc.createElement('a');

						// Clone attributes from bound element to new a tag
						for (; j < attrs.length; j++) {
							attr = attrs[j];
							destination.setAttribute(attr.name, attr.value);
						}

						// Set URL
						destination.href = loc;
					}

					// Ensure the path exists and is local
					if (! evts || ! _isValid(destination, current.path)) {
						// TODO: Make this print as verbose only
						// warn('PJAX: no events provided or invalid destination URL ' + destination.href);
						return;
					}

					// TODO: Make this reset optional so we can use 'bind' dynamically
					// Remove existing pjax events
					$events.off(el, '.pjax');

					// Bind designated events
					$events.on(el, evts, e => {
						if (paused) {
							warn('pjax has been paused - will not trigger navigation');
							return;
						}

						// Don't navigate with control keys
						if (e.metaKey || e.ctrlKey || e.shiftKey) { return; }

						// Don't navigate when preventDefault already called
						if (e.defaultPrevented) { return; }

						// Don't navigate on right click
						if (e.button !== undefined && e.button !== 0) { return; }

						let path = _path(destination);

{'fraction_non_alphanumeric': 0.14821719878816128, 'fraction_numerical': 0.0010487065951992542, 'mean_word_length': 2.762823323103902, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 15, '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': '5411712', 'n_tokens_mistral': 3241, 'n_tokens_neox': 2729, 'n_words': 895}