/* global Tinycon:false, ansi_up:false */ window.App = (function app(window, document) { 'use strict'; /** * @type {Object} * @private */ var _socket; /** * @type {HTMLElement} * @private */ var _logContainer; /** * @type {HTMLElement} * @private */ var _filterInput; /** * @type {String} * @private */ var _filterValue = ''; /** * @type {HTMLElement} * @private */ var _pauseBtn; /** * @type {boolean} * @private */ var _isPaused = false; /** * @type {number} * @private */ var _skipCounter = 0; /** * @type {HTMLElement} * @private */ var _topbar; /** * @type {HTMLElement} * @private */ var _body; /** * @type {number} * @private */ var _linesLimit = Math.Infinity; /** * @type {number} * @private */ var _newLinesCount = 0; /** * @type {boolean} * @private */ var _isWindowFocused = true; /** * @type {object} * @private */ var _highlightConfig; /** * Hide element if doesn't contain filter value * * @param {Object} element * @private */ var _filterElement = function(elem) { var pattern = new RegExp(_filterValue, 'i'); var element = elem; if (pattern.test(element.textContent)) { element.style.display = ''; } else { element.style.display = 'none'; } }; /** * Filter logs based on _filterValue * * @function * @private */ var _filterLogs = function() { var collection = _logContainer.childNodes; var i = collection.length; if (i === 0) { return; } while (i) { _filterElement(collection[i - 1]); i -= 1; } window.scrollTo(0, document.body.scrollHeight); }; /** * Set _filterValue from URL parameter `filter` * * @function * @private */ var _setFilterValueFromURL = function(filterInput, uri) { var _url = new URL(uri); var _filterValueFromURL = _url.searchParams.get('filter'); if (typeof _filterValueFromURL !== 'undefined' && _filterValueFromURL !== null) { _filterValue = _filterValueFromURL; filterInput.value = _filterValue; // eslint-disable-line } }; /** * Set parameter `filter` in URL * * @function * @private */ var _setFilterParam = function(value, uri) { var _url = new URL(uri); var _params = new URLSearchParams(_url.search.slice(1)); if (value === '') { _params.delete('filter'); } else { _params.set('filter', value); } _url.search = _params.toString(); window.history.replaceState(null, document.title, _url.toString()); }; /** * @return void * @private */ var _faviconReset = function() { _newLinesCount = 0; Tinycon.setBubble(0); }; /** * @return void * @private */ var _updateFaviconCounter = function() { if (_isWindowFocused || _isPaused) { return; } if (_newLinesCount < 99) { _newLinesCount += 1; Tinycon.setBubble(_newLinesCount); } }; /** * @return String * @private */ var _highlightWord = function(line) { var output = line; if (_highlightConfig && _highlightConfig.words) { Object.keys(_highlightConfig.words).forEach((wordCheck) => { output = output.replace( wordCheck, '' + wordCheck + '' ); }); } if (_highlightConfig && _highlightConfig.wordsRegExClass) { Object.keys(_highlightConfig.wordsRegExClass).forEach((wordsRegExClassCheck) => { output = output.replace( new RegExp(wordsRegExClassCheck), '$&' ); }); } if (_highlightConfig && _highlightConfig.wordsRegExMatchClass) { Object.keys(_highlightConfig.wordsRegExMatchClass).forEach((wordsRegExMatchClassCheck) => { var regex = new RegExp(wordsRegExMatchClassCheck); if(regex.test(output)) { //console.log('PASSED: ' + output); var matched = output.match(regex)[1]; console.log(matched); output = output.replace( matched, '$&' ); } }); } return output; }; /** * @return HTMLElement * @private */ var _highlightLine = function(line, container) { if (_highlightConfig && _highlightConfig.lines) { Object.keys(_highlightConfig.lines).forEach((lineCheck) => { if (line.indexOf(lineCheck) !== -1) { container.setAttribute('style', _highlightConfig.lines[lineCheck]); } }); } return container; }; return { /** * Init socket.io communication and log container * * @param {Object} opts options */ init: function init(opts) { var self = this; // Elements _logContainer = opts.container; _filterInput = opts.filterInput; _filterInput.focus(); _pauseBtn = opts.pauseBtn; _topbar = opts.topbar; _body = opts.body; _setFilterValueFromURL(_filterInput, window.location.toString()); // Filter input bind _filterInput.addEventListener('keyup', function(e) { // ESC if (e.keyCode === 27) { this.value = ''; _filterValue = ''; } else { _filterValue = this.value; } _setFilterParam(_filterValue, window.location.toString()); _filterLogs(); }); // Pause button bind _pauseBtn.addEventListener('mouseup', function() { _isPaused = !_isPaused; if (_isPaused) { this.className += ' play'; } else { _skipCounter = 0; this.classList.remove('play'); } }); // Favicon counter bind window.addEventListener( 'blur', function() { _isWindowFocused = false; }, true ); window.addEventListener( 'focus', function() { _isWindowFocused = true; _faviconReset(); }, true ); // socket.io init _socket = opts.socket; _socket .on('options:lines', function(limit) { _linesLimit = limit; }) .on('options:hide-topbar', function() { _topbar.className += ' hide'; _body.className = 'no-topbar'; }) .on('options:no-indent', function() { _logContainer.className += ' no-indent'; }) .on('options:highlightConfig', function(highlightConfig) { _highlightConfig = highlightConfig; }) .on('line', function(line) { if (_isPaused) { _skipCounter += 1; self.log('==> SKIPED: ' + _skipCounter + ' <==', (_skipCounter > 1)); } else { self.log(line); } }); }, /** * Log data * * @param {string} data data to log */ log: function log(data, replace = false) { var wasScrolledBottom = window.innerHeight + window.scrollY >= document.body.offsetHeight; var div = document.createElement('div'); var p = document.createElement('p'); p.className = 'inner-line'; // convert ansi color codes to html && escape HTML tags data = ansi_up.escape_for_html(data); // eslint-disable-line data = ansi_up.ansi_to_html(data); // eslint-disable-line p.innerHTML = _highlightWord(data); div.className = 'line'; div = _highlightLine(data, div); div.addEventListener('click', function click() { if (this.className.indexOf('selected') === -1) { //this.className = 'line-selected'; this.classList.add("line-selected") } else { //this.className = 'line'; this.classList.remove("line-selected") } }); div.appendChild(p); _filterElement(div); if (replace) { _logContainer.replaceChild(div, _logContainer.lastChild); } else { _logContainer.appendChild(div); } if (_logContainer.children.length > _linesLimit) { _logContainer.removeChild(_logContainer.children[0]); } if (wasScrolledBottom) { window.scrollTo(0, document.body.scrollHeight); } _updateFaviconCounter(); } }; }(window, document));