<commit_before>$.Redactor.prototype.WoltLabPaste = function() {
	"use strict";
	
	return {
		init: function () {
			var clipboardData = null;
			var isKbd = false;
			
			// IE 11
			var isIe = (document.documentMode && typeof window.clipboardData === 'object');
			
			var pastedHtml = null, pastedPlainText = null;
			
			var mpInit = this.paste.init;
			this.paste.init = (function (e) {
				pastedPlainText = pastedHtml = null;
				
				var isCode = (this.opts.type === 'pre' || this.utils.isCurrentOrParent('pre'));
				isKbd = (!isCode && this.utils.isCurrentOrParent('kbd'));
				if (isCode || isKbd) {
					if (isIe) {
						clipboardData = window.clipboardData.getData('Text');
					}
					else {
						clipboardData = e.originalEvent.clipboardData.getData('text/plain');
					}
					
					var mpCleanEncodeEntities = this.clean.encodeEntities;
					this.clean.encodeEntities = (function(str) {
						// revert to original method
						this.clean.encodeEntities = mpCleanEncodeEntities;
						
						return WCF.String.escapeHTML(str);
					}).bind(this);
				}
				else if (!isIe) {
					var types = e.originalEvent.clipboardData.types;
					if (types.length === 1 && types[0] === 'text/plain') {
						var tmp = WCF.String.escapeHTML(e.originalEvent.clipboardData.getData('text/plain'));
						
						pastedPlainText = '';
						var lines = tmp.split("\n");
						if (lines.length === 1) {
							// paste single-line content as real plain text
							pastedPlainText = tmp;
						}
						else {
							// plain newline characters do not work out well, mimic HTML instead
							lines.forEach(function (line) {
								line = line.trim();
								if (line === '') line = '<br>';
								
								pastedPlainText += '<p>' + line + '</p>';
							});
						}
					}
					else if (types.indexOf('text/html') !== -1) {
						// handles all major browsers except iOS Safari which does not expose `text/html`,
						// but instead gives us `public.rtf` (which of course is completely useless)
						// https://bugs.webkit.org/show_bug.cgi?id=19893
						pastedHtml = e.originalEvent.clipboardData.getData('text/html');
						
						// remove document fragments
						if (pastedHtml.match(/^<html>[\s\S]*?<body>([\s\S]+)<\/body>\s*<\/html>$/)) {
							pastedHtml = RegExp.$1.replace(/^\s*(?:<!--StartFragment-->)(.+)(?:<!--EndFragment-->)?\s*$/, '$1');
						}
					}
				}
				
				if (pastedPlainText !== null || pastedHtml !== null) {
					e.preventDefault();
				}
				
				mpInit.call(this, e);
			}).bind(this);
			
			var mpCreatePasteBox = this.paste.createPasteBox;
			this.paste.createPasteBox = (function (pre) {
				if (pastedHtml === null && pastedPlainText === null) {
					mpCreatePasteBox.call(this, pre);
				}
				
				// do nothing
			}).bind(this);
			
			require(['Environment'], (function(Environment) {
				if (Environment.platform() === 'ios' && Environment.browser() === 'safari') {
					var mpAppendPasteBox = this.paste.appendPasteBox;
					this.paste.appendPasteBox = (function() {
						// iOS doesn't like `position: fixed` and font-sizes below 16px that much
						this.$pasteBox.css({
							fontSize: '16px',
							height: '1px',
							left: '1px',
							overflow: 'hidden',
							position: 'absolute',
							top: (~~(window.innerHeight / 4) + window.pageYOffset) + 'px',
							width: '1px'
						});
						
						mpAppendPasteBox.call(this);
					}).bind(this);
				}
			}).bind(this));
			
			var mpGetPasteBoxCode = this.paste.getPasteBoxCode;
			this.paste.getPasteBoxCode = (function (pre) {
				if (pastedHtml !== null || pastedPlainText !== null) {
					// prevent page scrolling
					this.tmpScrollTop = undefined;
					
					// DEBUG CODE TO VERIFY PASTE HANDLING -- REMOVE BEFORE RELEASE
					var box = elBySel('.redactor-box');
					var p = box.nextSibling;
					if (p === null || p.nodeName !== 'P') {
						p = elCreate('p');
						box.parentNode.insertBefore(p, box.nextSibling);
					}
					
					p.textContent = WCF.getUUID();
					
					return pastedHtml || pastedPlainText;
				}
				
				var returnValue = mpGetPasteBoxCode.call(this, pre);
				
				if (isKbd) {
					return clipboardData;
				}
				
				// use clipboard data if paste box is flawed or when
				// pasting in IE 11 where clipboard data is more reliable
				if (pre && (!returnValue || isIe)) {
					return clipboardData;
				}
				<commit_msg>Avoid timeout issue in Chrome on Android when pasting<commit_after>$.Redactor.prototype.WoltLabPaste = function() {
	"use strict";
	
	var _environment = null;
	
	return {
		init: function () {
			var clipboardData = null;
			var isKbd = false;
			
			// IE 11
			var isIe = (document.documentMode && typeof window.clipboardData === 'object');
			
			var pastedHtml = null, pastedPlainText = null;
			
			// special `init()` implementation for Chrome on Android which seems to have
			// some serious issues with `setTimeout()` during a `paste` event
			var mpInitChromeOnAndroid = (function (e) {
				this.rtePaste = true;
				var pre = !!(this.opts.type === 'pre' || this.utils.isCurrentOrParent('pre'));
				
				this.utils.saveScroll();
				this.selection.save();
				this.paste.createPasteBox(pre);
				
				var html = this.paste.getPasteBoxCode(pre);
				
				// buffer
				this.buffer.set();
				this.selection.restore();
				
				this.utils.restoreScroll();
				
				// paste info
				var data = this.clean.getCurrentType(html);
				
				// clean
				html = this.clean.onPaste(html, data);
				
				// callback
				var returned = this.core.callback('paste', html);
				html = (typeof returned === 'undefined') ? html : returned;
				
				this.paste.insert(html, data);
				this.rtePaste = false;
				
				// clean pre breaklines
				if (pre) this.clean.cleanPre();
			}).bind(this);
			
			var mpInit = this.paste.init;
			this.paste.init = (function (e) {
				pastedPlainText = pastedHtml = null;
				
				var isCode = (this.opts.type === 'pre' || this.utils.isCurrentOrParent('pre'));
				isKbd = (!isCode && this.utils.isCurrentOrParent('kbd'));
				if (isCode || isKbd) {
					if (isIe) {
						clipboardData = window.clipboardData.getData('Text');
					}
					else {
						clipboardData = e.originalEvent.clipboardData.getData('text/plain');
					}
					
					var mpCleanEncodeEntities = this.clean.encodeEntities;
					this.clean.encodeEntities = (function(str) {
						// revert to original method
						this.clean.encodeEntities = mpCleanEncodeEntities;
						
						return WCF.String.escapeHTML(str);
					}).bind(this);
				}
				else if (!isIe) {
					var types = e.originalEvent.clipboardData.types;
					if (types.length === 1 && types[0] === 'text/plain') {
						var tmp = WCF.String.escapeHTML(e.originalEvent.clipboardData.getData('text/plain'));
						
						pastedPlainText = '';
						var lines = tmp.split("\n");
						if (lines.length === 1) {
							// paste single-line content as real plain text
							pastedPlainText = tmp;
						}
						else {
							// plain newline characters do not work out well, mimic HTML instead
							lines.forEach(function (line) {
								line = line.trim();
								if (line === '') line = '<br>';
								
								pastedPlainText += '<p>' + line + '</p>';
							});
						}
					}
					else if (types.indexOf('text/html') !== -1) {
						// handles all major browsers except iOS Safari which does not expose `text/html`,
						// but instead gives us `public.rtf` (which of course is completely useless)
						// https://bugs.webkit.org/show_bug.cgi?id=19893
						pastedHtml = e.originalEvent.clipboardData.getData('text/html');
						
						// remove document fragments
						if (pastedHtml.match(/^<html>[\s\S]*?<body>([\s\S]+)<\/body>\s*<\/html>$/)) {
							pastedHtml = RegExp.$1.replace(/^\s*(?:<!--StartFragment-->)(.+)(?:<!--EndFragment-->)?\s*$/, '$1');
						}
					}
				}
				
				if (pastedPlainText !== null || pastedHtml !== null) {
					e.preventDefault();
				}
				
				if (_environment.platform() === 'android' && _environment.browser() === 'chrome') {
					mpInitChromeOnAndroid(e);
				}
				else {
					mpInit.call(this, e);
				}
			}).bind(this);
			
			require(['Environment'], (function(Environment) {
				_environment = Environment;
				
				if (_environment.platform() === 'ios') {
					var mpAppendPasteBox = this.paste.appendPasteBox;
					this.paste.appendPasteBox = (function() {
						// iOS doesn't like `position: fixed` and font-sizes below 16px that much
						this.$pasteBox.css({
							fontSize: '16px',
							height: '1px',
							left: '1px',
							overflow: 'hidden',
							position: 'absolute',
							top: (~~(window.innerHeight / 4) + window.pageYOffset) + 'px',
							width: '1px'
						});
						
						mpAppendPasteBox.call(this);
					}).bind(this);
				}
			}).bind(this));
			
			var mpCreatePasteBox = this.paste.createPasteBox;
			this.paste.createPasteBox = (function (pre) {
				if (pastedHtml === null && pastedPlainText === null) {
					mpCreatePasteBox.call(this, pre);
				}
				
				// do nothing
			}).bind(this);
			
			var mpGetPasteBoxCode = this.paste.getPasteBoxCode;
			this.paste.getPasteBoxCode = (function (pre) {
				if (pastedHtml !== null || pastedPlainText !== null) {
					// prevent page scrolling
					this.tmpScrollTop = undefined;
					
					// DEBUG CODE TO VERIFY PASTE HANDLING -- REMOVE BEFORE RELEASE
					var box = elBySel('.redactor-box');
					var p = box.nextSibling;
					if (p === null || p.nodeName !== 'P') {
						p = elCreate('p');
						box.parentNode.insertBefore(p, box.nextSibling);
					}
					
					p.textContent = WCF.getUUID();
					
					return pastedHtml || pastedPlainText;
				}
				
				var returnValue = mpGetPasteBoxCode.call(this, pre);
				
				if (isKbd) {
					return clipboardData;
				}
				
				// use clipboard data if paste box is flawed or when
				// pasting in IE 11 where clipboard data is more reliable
				if (pre && (!returnValue || isIe)) {
					return clipboardData;
				}
				
{'fraction_non_alphanumeric': 0.152291917973462, 'fraction_numerical': 0.004624045034177724, 'mean_word_length': 2.429507066528783, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 21, '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': '3228887', 'n_tokens_mistral': 4423, 'n_tokens_neox': 3145, 'n_words': 704}