Skip to content

Commit

Permalink
add request/context headers and clean up some things
Browse files Browse the repository at this point in the history
  • Loading branch information
mindplay-dk committed Jan 14, 2019
1 parent 87c5be8 commit 0199176
Show file tree
Hide file tree
Showing 6 changed files with 207 additions and 70 deletions.
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,12 @@ If you haven't worked on a Chrome extension before, [start here](https://develop
Please submit pull-requests *without* the compiled `.js` files checked-in - we'll rebuild
the compiled source upon accepting your PR and/or publishing a release.

#### Icons

Icons were lifted from Devtools [here](https://github.com/ChromeDevTools/devtools-frontend/blob/master/front_end/Images/smallIcons.png) -
if you need more, extract them using [MethodDraw](https://editor.method.ac/), compress them
with [SVGOMG](https://jakearchibald.github.io/svgomg/), and [URL-encode](https://yoksel.github.io/url-encoder/) them.

### Roadmap

This is an early version - here are some of the features we'd like to add:
Expand Down
24 changes: 5 additions & 19 deletions chrome-extension/log.js

Large diffs are not rendered by default.

37 changes: 36 additions & 1 deletion chrome-extension/panel.css
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ body {
overflow-y: auto;
}

[class^="icon-"] {
.icon {
display: inline-block;
width: 10px;
height: 10px;
Expand All @@ -55,6 +55,41 @@ body {
background-image: url("data:image/svg+xml,%3Csvg width='10' height='10' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100' preserveAspectRatio='xMidYMid' class='lds-rolling' style='background:0 0'%3E%3Ccircle cx='50' cy='50' fill='none' stroke='%23757ed1' stroke-width='15' r='40' stroke-dasharray='188.49555921538757 64.83185307179586' transform='rotate(275.327 50 50)'%3E%3CanimateTransform attributeName='transform' type='rotate' calcMode='linear' values='0 50 50;360 50 50' keyTimes='0;1' dur='0.5s' begin='0s' repeatCount='indefinite'/%3E%3C/circle%3E%3C/svg%3E");
}

.icon-error {
background-image: url("data:image/svg+xml,%3Csvg width='10' height='10' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'%3E%3Cdefs%3E%3ClinearGradient id='a'%3E%3Cstop offset='0' stop-color='%23d7687d'/%3E%3Cstop offset='1' stop-color='%23b21402'/%3E%3C/linearGradient%3E%3ClinearGradient y1='1' x1='.5' xlink:href='%23a' x2='.5' id='b'/%3E%3C/defs%3E%3Cpath fill='none' d='M-1-1h12v12H-1z'/%3E%3Cg%3E%3Cpath fill='url(%23b)' d='M5 0C2.24 0 0 2.24 0 5s2.24 5 5 5 5-2.24 5-5-2.24-5-5-5'/%3E%3Cpath fill='%23eb3941' d='M.36 5C.36 7.56 2.44 9.64 5 9.64c2.56 0 4.64-2.08 4.64-4.64C9.64 2.44 7.56.36 5 .36 2.44.36.36 2.44.36 5'/%3E%3Cpath stroke='%23fff' d='M3 3l4 4M7 3L3 7'/%3E%3C/g%3E%3C/svg%3E");
}

.icon-check {
background-image: url("data:image/svg+xml,%3Csvg width='10' height='10' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='none' d='M-1-1h12v12H-1z'/%3E%3Cg%3E%3Cpath fill='none' d='M17.601-2.913h16.232v16.232H17.601V-2.913z'/%3E%3Cpath fill-rule='evenodd' d='M1.11 5.556L0 6.667 3.334 10 10 3.334 8.89 2.223 3.333 7.778 1.11 5.556z'/%3E%3C/g%3E%3C/svg%3E");
}

.header {
display: flex;
padding: 4px 4px 3px 4px;
background-color: var(--toolbar-bg-color);
border-bottom: var(--divider-border);
}

.header--error {
color: #753737;
}

.header__icon {
width: 15px;
}

.header__title {
flex: 1 1;
font-weight: bold;
}

.header__source {
display: inline-block;
float: right;
color: #555;
margin-left: 20px;
}

/*
TODO add filter input
Expand Down
82 changes: 66 additions & 16 deletions chrome-extension/panel.js

Large diffs are not rendered by default.

31 changes: 13 additions & 18 deletions src/log.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,29 @@
// This module implements backwards compatibility with ChromeLogger data.
/**
* This module implements backwards compatibility with ChromeLogger data, by rendering
* a console-like HTML page on the client-side.
*/

/**
* This loosely defines ChromeLogger's "packed" log-data format
*/
export interface Log {
version: string;
columns: string[];
rows: Array<any>;
}

/**
* We normalize ChromeLogger's "packed" format to this format
*/
interface Row {
log: any;
type: "log" | "info" | "warn" | "error" | "group" | "groupEnd" | "groupCollapsed" | "table";
backtrace: string | undefined;
}

/**
* These are the available icons defined in the CSS
*/
type Icon = "info" | "warning" | "error" | "collapse" | undefined;

/**
Expand Down Expand Up @@ -47,23 +59,6 @@ export function renderLog(log: Log): string {
<html>
<head>
<style>
/**
* Icons lifted from devtools here:
*
* https://github.com/ChromeDevTools/devtools-frontend/blob/master/front_end/Images/smallIcons.png
*
* If you need more, extract them using MethodDraw:
*
* https://editor.method.ac/
*
* Then compress them:
*
* https://jakearchibald.github.io/svgomg/
*
* And URL-encode them:
*
* https://yoksel.github.io/url-encoder/
*/
pre {
margin: 0;
Expand Down
97 changes: 81 additions & 16 deletions src/panel.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import { renderLog, Log } from "./log.js";
import { Request, Response } from "har-format";

type Icon = "spinner" | "error" | "check" | undefined;

/**
* This custom element allows us to isolate server-side log pages in a shadow-root.
*/
class LogEntry extends HTMLElement {
private shadow: ShadowRoot;

Expand Down Expand Up @@ -31,6 +36,13 @@ customElements.define("log-entry", LogEntry);

const $content = document.body.querySelector<HTMLElement>("[data-content]")!;

panel.onNavigation = url => {
console.log("ON NAVIGATION", url);

// TODO add "Preserve Log" option (similar to the "Network" tab)
$content.innerHTML = "";
};

panel.onRequest = transaction => {
console.log("ON REQUEST", transaction);

Expand All @@ -41,36 +53,89 @@ customElements.define("log-entry", LogEntry);
const request = (transaction as any).request as Request;
const response = (transaction as any).response as Response;

const title = `${request.method} ${request.url} [${response.status} ${response.statusText}]`;

for (let header of response.headers) {
const name = header.name.toLowerCase();

if (name === "x-chromelogger-data") {
try {
const log = JSON.parse(atob(header.value));
console.log("PARSE LOG", log);

appendContent(Promise.resolve(renderLog(log as Log)));
} catch (e) {
console.error(e);
}
appendLog(title, "X-ChromeLogger-Data", new Promise(resolve => {
try {
const log = JSON.parse(atob(header.value));

console.log("PARSED CHROME-LOGGER HEADER", log);

resolve(renderLog(log as Log));
} catch (error) {
throw `Error parsing X-ChromeLogger-Data header (${error})`;
}
}));
}
}
}

panel.onNavigation = url => {
console.log("ON NAVIGATION", url);
/**
* Append a log document to the "Server Log" panel
*/
function appendLog(title: string, source: string, documentPromise: Promise<string>) {
const header = appendHeader("spinner", title, source);

$content.innerHTML = "";
const el = document.createElement("log-entry") as LogEntry;

appendContent(Promise.resolve(`<h1>${url}</h1>`));
};
$content.appendChild(el);

function appendContent(html: Promise<string>) {
const el = document.createElement("log-entry") as LogEntry;
documentPromise
.then(html => {
el.setHTML(html);

header.setIcon("check");
})
.catch(error => {
el.setHTML(`<pre style="color:red; padding-left:20px;">${html(error)}</pre>`);

header.setIcon("error");
});
}

/**
* Create a header with an icon, title and source of the request
*/
function appendHeader(icon: Icon, title: string, source: string) {
const el = document.createElement("div");

el.innerHTML = (`
<div class="header ${icon ? `header--${icon}` : ``}">
<div class="header__icon">${
icon ? `<span class="icon"></span>` : ``
}</div>
<div class="header__title">${html(title)}</div>
<div class="header__source">${html(source)}</div>
</div>`
);

$content.appendChild(el);

html.then(html => el.setHTML(html));
function setIcon(icon: Icon) {
el.querySelector(".icon")!.className = `icon icon-${icon}`;
};

setIcon(icon);

return {
setIcon
};
}

/**
* Escape plain text as HTML
*/
function html(str: string | null | undefined): string {
return (str || '')
.replace(/&/g, '&amp;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&#39;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;');
}

})(window as PanelWindow);
Expand Down

0 comments on commit 0199176

Please sign in to comment.