Mercurial > piecrust2
view piecrust/resources/server/piecrust-debug-info.js @ 750:377f4b626e74 2.0.0rc1
cm: Regenerate the CHANGELOG.
author | Ludovic Chabant <ludovic@chabant.com> |
---|---|
date | Thu, 09 Jun 2016 22:35:18 -0700 |
parents | 93b656f0af54 |
children | 8d5b8a3dca02 |
line wrap: on
line source
/////////////////////////////////////////////////////////////////////////////// // PieCrust debug info and features // // This stuff is injected by PieCrust's preview server and shouldn't show up // in production. It should all be self-contained in this one file. /////////////////////////////////////////////////////////////////////////////// var eventSource = new EventSource("/__piecrust_debug/pipeline_status"); if (eventSource != null) { eventSource.onerror = function(e) { console.log("Error with SSE, closing.", e); eventSource.close(); }; eventSource.addEventListener('ping', function(e) { }); eventSource.addEventListener('pipeline_success', function(e) { var obj = JSON.parse(e.data); console.log("Got pipeline success", obj); // Check which assets were processed, and whether they are referenced // by the current page for the usual use-cases. for (var i = 0; i < obj.assets.length; ++i) { a = obj.assets[i]; if (assetReloader.reloadAsset(a)) { notification.flashSuccess("Reloaded " + a); } } }); eventSource.addEventListener('pipeline_error', function(e) { var obj = JSON.parse(e.data); console.log("Got pipeline error", obj); var outer = document.createElement('div'); outer.style = 'padding: 1em;'; for (var i = 0; i < obj.assets.length; ++i) { var item = obj.assets[i]; var markup = ( '<p>Error processing: <span style="font-family: monospace;">' + item.path + '</span></p>\n' + '<ul>'); for (var j = 0; j < item.errors.length; ++j) { markup += ( '<li style="font-family: monospace;">' + item.errors[j] + '</li>\n'); } markup += '</ul>\n'; var entry = document.createElement('div'); entry.innerHTML = markup; outer.appendChild(entry); } var placeholder = document.getElementById('piecrust-debug-info-pipeline-status'); placeholder.appendChild(outer); }); } /////////////////////////////////////////////////////////////////////////////// NotificationArea = function() { var area = document.createElement('div'); area.id = 'piecrust-debug-notifications'; area.className = 'piecrust-debug-notifications'; document.querySelector('body').appendChild(area); this._area = area; this._lastId = 0; }; NotificationArea.prototype.flashSuccess = function(msg) { this.flashMessage(msg, 'success'); }; NotificationArea.prototype.flashError = function(msg) { this.flashMessage(msg, 'error'); }; NotificationArea.prototype.flashMessage = function(msg, css_class) { this._lastId += 1; var thisId = this._lastId; this._area.insertAdjacentHTML( 'afterbegin', '<div id="piecrust-debug-notification-msg' + thisId + '" ' + 'class="piecrust-debug-notification ' + 'piecrust-debug-notification-' + css_class + '">' + msg + '</div>'); window.setTimeout(this._discardNotification, 2000, thisId); }; NotificationArea.prototype._discardNotification = function(noteId) { var added = document.querySelector('#piecrust-debug-notification-msg' + noteId); added.remove(); }; /////////////////////////////////////////////////////////////////////////////// function _get_extension(name) { var ext = null; var dotIdx = name.lastIndexOf('.'); if (dotIdx > 0) ext = name.substr(dotIdx + 1); return ext; } function _get_basename(name) { var filename = name; var slashIdx = name.lastIndexOf('/'); if (slashIdx > 0) filename = name.substr(slashIdx + 1); return filename; } var _regex_cache_bust = /\?\d+$/; function _is_path_match(path1, path2) { path1 = path1.replace(_regex_cache_bust, ''); console.log("Matching:", path1, path2) return path1.endsWith(path2); }; function _add_cache_bust(path, cache_bust) { path = path.replace(_regex_cache_bust, ''); return path + cache_bust; } /////////////////////////////////////////////////////////////////////////////// AssetReloader = function() { this._imgExts = ['jpg', 'jpeg', 'png', 'gif', 'svg']; this._imgReloader = new ImageReloader(); this._cssReloader = new CssReloader(); }; AssetReloader.prototype.reloadAsset = function(name) { var ext = _get_extension(name); var filename = _get_basename(name); if (ext == 'css') { return this._cssReloader.reloadStylesheet(filename); } if (this._imgExts.indexOf(ext) >= 0) { return this._imgReloader.reloadImage(filename); } console.log("Don't know how to reload", filename); return false; }; /////////////////////////////////////////////////////////////////////////////// CssReloader = function() { }; CssReloader.prototype.reloadStylesheet = function(name) { var result = false; var sheets = document.styleSheets; var cacheBust = '?' + new Date().getTime(); for (var i = 0; i < sheets.length; ++i) { var sheet = sheets[i]; if (_is_path_match(sheet.href, name)) { sheet.ownerNode.href = _add_cache_bust(sheet.href, cacheBust); result = true; } } return result; }; /////////////////////////////////////////////////////////////////////////////// ImageReloader = function() { this._imgStyles = [ { selector: 'background', styleNames: ['backgroundImage'] }, ]; this._regexCssUrl = /\burl\s*\(([^)]+)\)/; }; ImageReloader.prototype.reloadImage = function(name) { var result = false; var imgs = document.images; var cacheBust = '?' + new Date().getTime(); for (var i = 0; i < imgs.length; ++i) { var img = imgs[i]; if (_is_path_match(img.src, name)) { img.src = _add_cache_bust(img.src, cacheBust); result = true; } } for (var i = 0; i < this._imgStyles.length; ++i) { var imgInfo = this._imgStyles[i]; var domImgs = document.querySelectorAll( "[style*=" + imgInfo.selector + "]"); for (var j = 0; j < domImgs.length; ++j) { var img = domImgs[j]; result |= this._reloadStyleImage(img.style, imgInfo.styleNames, name, cacheBust); } } for (var i = 0; i < document.styleSheets.length; ++i) { var styleSheet = document.styleSheets[i]; result |= this._reloadStylesheetImage(styleSheet, name, cacheBust); } return result; }; ImageReloader.prototype._reloadStyleImage = function(style, styleNames, path, cacheBust) { var result = false; for (var i = 0; i < styleNames.length; ++i) { var value = style[styleNames[i]]; if ((typeof value) == 'string') { m = this._regexCssUrl.exec(value); if (m != null) { var m_clean = m[1].replace(/^['"]/, ''); m_clean = m_clean.replace(/['"]$/, ''); if (_is_path_match(m_clean, path)) { m_clean = _add_cache_bust(m_clean, cacheBust); style[styleNames[i]] = 'url("' + m_clean + '")'; result = true; } } } } return result; }; ImageReloader.prototype._reloadStylesheetImage = function(styleSheet, path, cacheBust) { try { var rules = styleSheet.cssRules; } catch (e) { // Things like remote CSS stylesheets (e.g. a Google Fonts ones) // will triger a SecurityException here, so just ignore that. return; } var result = false; for (var i = 0; i < rules.length; ++i) { var rule = rules[i]; switch (rule.type) { case CSSRule.IMPORT_RULE: result |= this._reloadStylesheetImage(rule.styleSheet, path, cacheBust); break; case CSSRule.MEDIA_RULE: result |= this._reloadStylesheetImage(rule, path, cacheBust); break; case CSSRule.STYLE_RULE: for (var j = 0; j < this._imgStyles.length; ++j) { var imgInfo = this._imgStyles[j]; result |= this._reloadStyleImage( rule.style, imgInfo.styleNames, path, cacheBust); } break; } } return result; }; /////////////////////////////////////////////////////////////////////////////// function toggleDebugInfo() { var info = document.querySelector('.piecrust-debug-info'); if (info.classList.contains('piecrust-debug-info-unloaded')) { loadDebugInfo(); info.classList.remove('piecrust-debug-info-unloaded'); } if (this.innerHTML == '[+]') { this.innerHTML = '[-]'; info.style = ""; } else { this.innerHTML = '[+]'; info.style = "display: none;"; } } function loadDebugInfo() { var xmlHttp = new XMLHttpRequest(); xmlHttp.onreadystatechange = function() { if (xmlHttp.readyState == XMLHttpRequest.DONE) { var info = document.querySelector('.piecrust-debug-info'); if(xmlHttp.status == 200) { info.innerHTML = xmlHttp.responseText; } else if(xmlHttp.status == 400) { info.innerHTML = "Error fetching debug info."; } else { info.innerHTML = "Unknown error."; } } } var pageUrl = window.location.pathname; xmlHttp.open("GET", "/__piecrust_debug/debug_info?page=" + pageUrl, true); xmlHttp.send(); } /////////////////////////////////////////////////////////////////////////////// var notification = new NotificationArea(); var assetReloader = new AssetReloader(); window.onload = function() { var cacheBust = '?' + new Date().getTime(); var style = document.createElement('link'); style.rel = 'stylesheet'; style.type = 'text/css'; style.href = '/__piecrust_static/piecrust-debug-info.css' + cacheBust; document.head.appendChild(style); var expander = document.querySelector('.piecrust-debug-expander'); expander.onclick = toggleDebugInfo; }; window.onbeforeunload = function(e) { if (eventSource != null) eventSource.close(); };