<commit_before>app.directive('fill', function ($window, $timeout) {
	return {
		restrict: 'AC',
		link: function (scope, elem, attrs) {
			var options = scope.$eval(attrs.fill);
			var windowEl = angular.element($window);
			var el = angular.element(elem);
			var marginBottom = options.marginBottom || 0;

			windowEl.resize(function () {
				var fillHeight = $window.innerHeight - el.offset().top - marginBottom - 1;
				el.css({
					height: fillHeight + 'px',
					margin: 0
				});
			});
			$timeout(function () {
				windowEl.resize();
			}, 500);
		}
	};
});
app.directive('autoScroll', function ($timeout) {
	return {
		scope: {
			watching: '@autoScroll'
		},
		link: function (scope, elem) {
			var el = angular.element(elem);
			var firstTime = true;
			scope.$watch('watching', function () {
				// TODO why does height need a 1px tolerance?
				var currentScroll = el.prop('scrollHeight') - el.prop('scrollTop');
				if(firstTime || currentScroll == el.height() || currentScroll == el.height() + 1) {
					$timeout(function () {
						el.scrollTop(el.prop('scrollHeight'));
					}, firstTime ? 500 : 0);
					firstTime = false;
				}
			});
		}};
});
app.directive('bunkerInput', function($window, user) {
	return {
		scope: {
			text: '=bunkerInput'
		},
		link: function(scope, elem) {
			scope.$on('inputText', function(evt, text) {
				var append = scope.text.length ? ' ' : ''; // start with a space if message already started
				append += text + ' ';
				scope.text += append;
				angular.element(elem).focus();
			});

			// Handle user away notification
			var win = angular.element($window);
			win.bind('focus', function () {
				scope.$apply(function() {
					user.current.present = true;
					user.current.$save();
				});
			});
			win.bind('blur', function () {
				scope.$apply(function() {
					user.current.present = false;
					user.current.$save();
				});
			});
		}
	};
});
app.directive('bunkerMessage', function ($compile, emoticons) {
	return {
		template: '<span ng-bind-html="formatted"></span>',
		scope: {
			text: '@bunkerMessage'
		},
		link: function (scope, elem) {
			scope.$watch('text', function (text) {
				var formatted = text,
					replacedEmotes = {},
					replacedLinks = {};

				// Parse emoticons
				_.each(text.match(/:\w+:/g), function (emoticonText) {
					var knownEmoticon = _.find(emoticons.files, function (known) {
						return known.replace(/.\w+$/, '') == emoticonText.replace(/:/g, '');
					});
					if (knownEmoticon && !replacedEmotes[knownEmoticon]) {
						formatted = formatted.replace(new RegExp(emoticonText, 'g'),
								'<img class="emoticon" title="' + emoticonText + '" src="/assets/images/emoticons/' + knownEmoticon + '"/>');
						replacedEmotes[knownEmoticon] = true;
					}
				});

				// Parse links
				var attachedImage;
				_.each(text.match(/(http|ftp|https):\/\/[\w-]+(\.[\w-]+)+([\w.,@?^=%&amp;:\/~+#-]*[\w@?^=%&amp;\/~+#-])?/gi), function (link) {
					if (/\.(gif|png|jpg|jpeg)$/i.test(link) && !attachedImage) {
						// Image link
						attachedImage = angular.element('<div bunker-message-image="' + link + '"></div>');
					}

					if (!replacedLinks[link]) {
						formatted = formatted.replace(new RegExp(link, 'g'), '<a href="' + link + '" target="_blank">' + link + '</a>');<commit_msg>bold and italics (but not bold italics, p.s. I hate the first person to point this out)<commit_after>app.directive('fill', function ($window, $timeout) {
	return {
		restrict: 'AC',
		link: function (scope, elem, attrs) {
			var options = scope.$eval(attrs.fill);
			var windowEl = angular.element($window);
			var el = angular.element(elem);
			var marginBottom = options.marginBottom || 0;

			windowEl.resize(function () {
				var fillHeight = $window.innerHeight - el.offset().top - marginBottom - 1;
				el.css({
					height: fillHeight + 'px',
					margin: 0
				});
			});
			$timeout(function () {
				windowEl.resize();
			}, 500);
		}
	};
});
app.directive('autoScroll', function ($timeout) {
	return {
		scope: {
			watching: '@autoScroll'
		},
		link: function (scope, elem) {
			var el = angular.element(elem);
			var firstTime = true;
			scope.$watch('watching', function () {
				// TODO why does height need a 1px tolerance?
				var currentScroll = el.prop('scrollHeight') - el.prop('scrollTop');
				if(firstTime || currentScroll == el.height() || currentScroll == el.height() + 1) {
					$timeout(function () {
						el.scrollTop(el.prop('scrollHeight'));
					}, firstTime ? 500 : 0);
					firstTime = false;
				}
			});
		}};
});
app.directive('bunkerInput', function($window, user) {
	return {
		scope: {
			text: '=bunkerInput'
		},
		link: function(scope, elem) {
			scope.$on('inputText', function(evt, text) {
				var append = scope.text.length ? ' ' : ''; // start with a space if message already started
				append += text + ' ';
				scope.text += append;
				angular.element(elem).focus();
			});

			// Handle user away notification
			var win = angular.element($window);
			win.bind('focus', function () {
				scope.$apply(function() {
					user.current.present = true;
					user.current.$save();
				});
			});
			win.bind('blur', function () {
				scope.$apply(function() {
					user.current.present = false;
					user.current.$save();
				});
			});
		}
	};
});
app.directive('bunkerMessage', function ($compile, emoticons) {
	return {
		template: '<span ng-bind-html="formatted"></span>',
		scope: {
			text: '@bunkerMessage'
		},
		link: function (scope, elem) {
			scope.$watch('text', function (text) {
				var formatted = text,
					replacedEmotes = {},
					replacedLinks = {};

				// Parse bold
				_.each(text.match(/(\*[\w\s]+\*)/g), function (bold) {
					formatted = formatted.replace(bold, '<strong>' + bold.replace(/\*/g, '') + '</strong>');
				});

				// Parse italics
				_.each(text.match(/(_[\w\s]+_)/g), function (italics) {
					formatted = formatted.replace(italics, '<em>' + italics.replace(/_/g, '') + '</em>');
				});

				// Parse emoticons
				_.each(text.match(/:\w+:/g), function (emoticonText) {
					var knownEmoticon = _.find(emoticons.files, function (known) {
						return new RegExp(known.replace(/.\w+$/, ''), 'i').test(emoticonText.replace(/:/g, ''));
					});
					if (knownEmoticon && !replacedEmotes[knownEmoticon]) {
						formatted = formatted.replace(new RegExp(emoticonText, 'g'),
								'<img class="emoticon" title="' + emoticonText + '" src="/assets/images/emoticons/' + knownEmoticon + '"/>');
						replacedEmotes[knownEmoticon] = true;
					}
				});

				// Parse links
				var attachedImage;
				_.each(text.match(/(http|ftp|https):\/\/[\w-]+(\.[\w-]+)+([\w.,@?^=%&amp;:\/~+#-]*[\w@?^=%&amp;\/~+#-])?/gi), function (link) {
					if (/\.(gif|png|jpg|jpeg)$/i.test(link) && !attachedImage) {
						// Image link
						attachedImage = angular.element('<div bunker-message-image="' + link + '"></div>');
					}

					if (!replacedLinks[link]) {
						formatted = formatted.replace(new RegExp(link, 'g'), '<a href="' + link + '" target="_blank">' + link + '</a>');
{'fraction_non_alphanumeric': 0.2043743786393978, 'fraction_numerical': 0.0034086067319982955, 'mean_word_length': 3.0587896253602307, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 21, 'https://': 0, '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': '4868382', 'n_tokens_mistral': 2925, 'n_tokens_neox': 2338, 'n_words': 462}