1
0
mirror of https://github.com/chinchang/web-maker.git synced 2025-07-14 02:26:20 +02:00

add chrome like dev console! fixes #56

This commit is contained in:
Kushagra Gour
2017-05-07 16:59:47 +05:30
parent 5827cbe6c8
commit 88a49cd4c5
4 changed files with 261 additions and 4 deletions

View File

@ -101,6 +101,25 @@
</div>
<div class="demo-side" id="js-demo-side">
<iframe src="about://blank" frameborder="0" id="demo-frame"></iframe>
<div id="consoleEl" class="console">
<div id="consoleLogEl" class="console__log" class="code">
<div class="js-console__header code-wrap__header" title="Double click to toggle console">
<span class="code-wrap__header-label">Console</span>
<div class="code-wrap__header-right-options">
<a class="code-wrap__header-btn" title="Clear console" d-click="clearConsole">
<svg>
<use xlink:href="#cancel-icon"></use>
</svg>
</a>
<a class="code-wrap__header-btn code-wrap__collapse-btn" title="Toggle console" d-click="toggleConsole">
</a>
</div>
</div>
</div>
<div id="consolePromptEl" class="console__prompt">
<input type="" name="" class="full-width" style="background: none;border:0;">
</div>
</div>
</div>
</div>
<div class="footer">
@ -577,6 +596,11 @@
<path d="M8,5.14V19.14L19,12.14L8,5.14Z" />
</svg>
</symbol>
<symbol id="cancel-icon" viewBox="0 0 24 24">
<svg>
<path d="M12,2A10,10 0 0,1 22,12A10,10 0 0,1 12,22A10,10 0 0,1 2,12A10,10 0 0,1 12,2M12,4A8,8 0 0,0 4,12C4,13.85 4.63,15.55 5.68,16.91L16.91,5.68C15.55,4.63 13.85,4 12,4M12,20A8,8 0 0,0 20,12C20,10.15 19.37,8.45 18.32,7.09L7.09,18.32C8.45,19.37 10.15,20 12,20Z" />
</svg>
</symbol>
</svg>
<script src="lib/codemirror/lib/codemirror.js"></script>

174
src/screenlog.js Normal file
View File

@ -0,0 +1,174 @@
(function () {
var logEl,
isInitialized = false,
_console = {}; // backup console obj to contain references of overridden fns.
_options = {
bgColor: 'black',
logColor: 'lightgreen',
infoColor: 'blue',
warnColor: 'orange',
errorColor: 'red',
freeConsole: false,
css: '',
autoScroll: true,
proxyCallback: null,
noUi: false
};
function createElement(tag, css) {
var element = document.createElement(tag);
element.style.cssText = css;
return element;
}
function createPanel() {
var div = createElement('div', 'z-index:2147483647;font-family:Helvetica,Arial,sans-serif;font-size:10px;font-weight:bold;padding:5px;text-align:left;opacity:0.8;position:fixed;right:0;top:0;min-width:200px;max-height:50vh;overflow:auto;background:' + _options.bgColor + ';' + _options.css);
return div;
}
function genericLogger(color) {
return function() {
if (_options.proxyCallback) {
_options.proxyCallback.apply(null, arguments);
}
if (_options.noUi) { return; }
var el = createElement('div', 'line-height:18px;min-height:18px;background:' +
(logEl.children.length % 2 ? 'rgba(255,255,255,0.1)' : '') + ';color:' + color); // zebra lines
var val = [].slice.call(arguments).reduce(function(prev, arg) {
return prev + ' ' + (typeof arg === "object" ? JSON.stringify(arg) : arg);
}, '');
el.textContent = val;
logEl.appendChild(el);
// Scroll to last element, if autoScroll option is set.
if(_options.autoScroll) {
logEl.scrollTop = logEl.scrollHeight - logEl.clientHeight;
}
};
}
function clear() {
logEl.innerHTML = '';
}
function log() {
return genericLogger(_options.logColor).apply(null, arguments);
}
function info() {
return genericLogger(_options.infoColor).apply(null, arguments);
}
function warn() {
return genericLogger(_options.warnColor).apply(null, arguments);
}
function error() {
return genericLogger(_options.errorColor).apply(null, arguments);
}
function setOptions(options) {
for(var i in options)
if(options.hasOwnProperty(i) && _options.hasOwnProperty(i)) {
_options[i] = options[i];
}
}
function init(options) {
if (isInitialized) { return; }
isInitialized = true;
if(options) {
setOptions(options);
}
if (!_options.noUi) {
logEl = createPanel();
document.body.appendChild(logEl);
}
if (!_options.freeConsole) {
// Backup actual fns to keep it working together
_console.log = console.log;
_console.clear = console.clear;
_console.info = console.info;
_console.warn = console.warn;
_console.error = console.error;
console.log = originalFnCallDecorator(log, 'log');
console.clear = originalFnCallDecorator(clear, 'clear');
console.info = originalFnCallDecorator(info, 'info');
console.warn = originalFnCallDecorator(warn, 'warn');
console.error = originalFnCallDecorator(error, 'error');
}
}
function destroy() {
isInitialized = false;
console.log = _console.log;
console.clear = _console.clear;
console.info = _console.info;
console.warn = _console.warn;
console.error = _console.error;
logEl.remove();
}
/**
* Checking if isInitialized is set
*/
function checkInitialized() {
if (!isInitialized) {
throw 'You need to call `screenLog.init()` first.';
}
}
/**
* Decorator for checking if isInitialized is set
* @param {Function} fn Fn to decorate
* @return {Function} Decorated fn.
*/
function checkInitDecorator(fn) {
return function() {
checkInitialized();
return fn.apply(this, arguments);
};
}
/**
* Decorator for calling the original console's fn at the end of
* our overridden fn definitions.
* @param {Function} fn Fn to decorate
* @param {string} fn Name of original function
* @return {Function} Decorated fn.
*/
function originalFnCallDecorator(fn, fnName) {
return function() {
fn.apply(this, arguments);
if (typeof _console[fnName] === 'function') {
_console[fnName].apply(console, arguments);
}
};
}
window.addEventListener('error', function() {
genericLogger(_options.errorColor).call(null, arguments[0].error.stack);
});
// Public API
window.screenLog = {
init: init,
log: originalFnCallDecorator(checkInitDecorator(log), 'log'),
clear: originalFnCallDecorator(checkInitDecorator(clear), 'clear'),
info: originalFnCallDecorator(checkInitDecorator(clear), 'info'),
warn: originalFnCallDecorator(checkInitDecorator(warn), 'warn'),
error: originalFnCallDecorator(checkInitDecorator(error), 'error'),
destroy: checkInitDecorator(destroy)
};
})();
screenLog.init({
noUi: true,
proxyCallback: function () {
window.parent.onMessageFromConsole.apply(null, arguments);
}
});

View File

@ -5,7 +5,7 @@ addLibraryModal, addLibraryModal, notificationsBtn, notificationsModal, notifica
notificationsModal, notificationsBtn, codepenBtn, saveHtmlBtn, saveBtn, settingsBtn,
onboardModal, settingsModal, notificationsBtn, onboardShowInTabOptionBtn, editorThemeLinkTag,
onboardDontShowInTabOptionBtn, TextareaAutoComplete, savedItemCountEl, indentationSizeValueEl,
runBtn, searchInput
runBtn, searchInput, consoleEl, consoleLogEl
*/
/* eslint-disable no-extra-semi */
;(function (alertsService) {
@ -91,6 +91,7 @@ runBtn, searchInput
;
scope.cm = {};
scope.consoleCm;
scope.demoFrameDocument = frame.contentDocument || frame.contentWindow.document;
// Check all the code wrap if they are minimized or not
@ -734,6 +735,9 @@ runBtn, searchInput
+ '<body>\n' + html + '\n'
+ externalJs + '\n';
contents += '<script src="'
+ chrome.extension.getURL('screenlog.js') + '"></script>';
if (js) {
contents += '<script>\n' + js + '\n//# sourceURL=userscript.js';
} else {
@ -969,6 +973,17 @@ runBtn, searchInput
});
Inlet(scope.cm.js);
// Initialize codemirror in console
scope.consoleCm = CodeMirror(consoleLogEl, {
mode: 'javascript',
lineWrapping: true,
theme: 'monokai',
foldGutter: true,
readOnly: true,
viewportMargin: Infinity,
gutters: [ 'CodeMirror-foldgutter' ]
});
function openSettings() {
settingsModal.classList.toggle('is-modal-visible');
@ -1252,6 +1267,7 @@ runBtn, searchInput
scope.cm[type].setOption('keyMap', $('[data-setting=keymap]:checked').value);
scope.cm[type].refresh();
});
scope.consoleCm.setOption('theme', $('[data-setting=editorTheme]').value);
};
scope.onNewBtnClick = function () {
@ -1287,6 +1303,22 @@ runBtn, searchInput
trackEvent('ui', 'searchInputType');
};
scope.toggleConsole = function () {
consoleEl.classList.toggle('is-open');
};
scope.clearConsole = function () {
scope.consoleCm.setValue('');
};
window.onMessageFromConsole = function() {
[...arguments].forEach(function(arg) {
if (arg.indexOf && arg.indexOf('filesystem:chrome-extension') !== -1) {
arg = arg.replace(/filesystem:chrome-extension.*\.js:(\d+):(\d+)/g, 'script $1:$2');
}
scope.consoleCm.replaceRange('\n' + arg + ((arg + '').match(/\[object \w+\]/) ? JSON.stringify(arg) : '') + ' ', {line: Infinity});
});
}
function compileNodes() {
function attachListenerForEvent(eventName) {
@ -1505,6 +1537,9 @@ runBtn, searchInput
});
window.addEventListener('dblclick', function(e) {
var target = e.target;
if (target.classList.contains('js-console__header')) {
scope.toggleConsole();
}
if (target.classList.contains('js-code-wrap__header')) {
var codeWrapParent = target.parentElement;
toggleCodeWrapCollapse(codeWrapParent);

View File

@ -107,6 +107,7 @@ select, input[type="text"], input[type="number"], textarea {
top: 0; bottom: 0;
display: flex;
flex-direction: column;
overflow: hidden;
will-change: -webkit-filter;
transition: 0.10s ease 0.2s;
}
@ -201,9 +202,13 @@ select, input[type="text"], input[type="number"], textarea {
opacity: 0;
}
.code-wrap__header-btn {
display: inline-block;
vertical-align: top;
}
.code-wrap__header-btn,
.code-wrap__header-btn > svg {
width: 18px;
height: 18px;
display: inline-block;
}
.code-wrap__collapse-btn:before {
content: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" style="width:18px;height:18px" viewBox="0 0 24 24"><path fill="rgba(255,255,255,0.2)" d="M19.5,3.09L15,7.59V4H13V11H20V9H16.41L20.91,4.5L19.5,3.09M4,13V15H7.59L3.09,19.5L4.5,20.91L9,16.41V20H11V13H4Z" /></svg>');
@ -271,9 +276,10 @@ li.CodeMirror-hint-active {
.main-header,
.footer {
padding: 5px 10px;
background-color: rgba(0, 0, 0, 0.5);
background-color: rgb(18, 19, 27);
color: rgba(255, 255, 255, 0.45);
border-top: 1px solid rgba(255,255,255,0.14);
z-index: 1;
/*line-height: 20px;*/
}
.main-header {
@ -810,3 +816,21 @@ li.CodeMirror-hint-active {
.wobble {
animation-name: wobble;
}
.console {
background: var(--color-bg);
z-index: 1; /* bring above iframe */
position: absolute;
bottom: 0;
height: 30vh;
left: 0;
right: 0;
transform: translateY(calc(100% - 30px));
transition: transform 0.4s cubic-bezier(0.77,-0.1,0.13,0.9);
}
.console.is-open {
transform: translateY(0);
}
.console .Codemirror {
height: auto;
max-height: calc(100% - 50px);
}