Skip to content

Commit

Permalink
Change from sprintf() for templating to a Mustache MVP
Browse files Browse the repository at this point in the history
  • Loading branch information
thekid committed Jun 9, 2024
1 parent 4df76c4 commit ca7d4fd
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 27 deletions.
54 changes: 34 additions & 20 deletions src/main/php/xp/web/dev/Console.class.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php namespace xp\web\dev;

use Throwable as Any;
use Closure, Throwable as Any;
use lang\Throwable;
use web\{Error, Filter};

Expand All @@ -22,20 +22,21 @@ public function __construct($name= 'xp/web/dev/console') {
}

/**
* Creates HTML table rows
* Transforms template
*
* @param [:var] $headers
* @param string $template
* @param [:var] $context
* @return string
*/
private function rows($headers) {
$r= '';
foreach ($headers as $name => $value) {
$r.= '<tr>
<td class="name">'.htmlspecialchars($name).'</td>
<td class="value">'.htmlspecialchars(implode(', ', $value)).'</td>
</tr>';
}
return $r;
private function transform($template, $context) {
return preg_replace_callback(
'/\{\{([^ }]+) ?([^}]+)?\}\}/',
function($m) use($context) {
$value= $context[$m[1]] ?? '';
return $value instanceof Closure ? $value($context[$m[2]] ?? '') : htmlspecialchars($value);
},
$template
);
}

/**
Expand All @@ -53,23 +54,36 @@ public function filter($req, $res, $invocation) {
yield from $invocation->proceed($req, $res->streaming(function($res, $length) use($capture) {
return $capture->length($length);
}));

$kind= 'Debug';
$debug= ob_get_clean();
if (0 === strlen($debug)) return $capture->drain($res);
} catch (Any $e) {
$kind= 'Error';
$res->answer($e instanceof Error ? $e->status() : 500);
$debug= ob_get_clean()."\n".Throwable::wrap($e)->toString();
} finally {
$capture->end($res);
}

$console= sprintf(
typeof($this)->getClassLoader()->getResource($this->template),
htmlspecialchars($debug),
$capture->status,
htmlspecialchars($capture->message),
$this->rows($capture->headers),
htmlspecialchars($capture->bytes)
);
$console= $this->transform(typeof($this)->getClassLoader()->getResource($this->template), [
'kind' => $kind,
'debug' => $debug,
'status' => $capture->status,
'message' => $capture->message,
'headers' => $capture->headers,
'contents' => $capture->bytes,
'#rows' => function($headers) {
$r= '';
foreach ($headers as $name => $value) {
$r.= '<tr>
<td class="name">'.htmlspecialchars($name).'</td>
<td class="value">'.htmlspecialchars(implode(', ', $value)).'</td>
</tr>';
}
return $r;
}
]);
$target= $res->output()->stream(strlen($console));
try {
$target->begin(200, 'Debug', [
Expand Down
14 changes: 7 additions & 7 deletions src/main/php/xp/web/dev/console.html
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<title>Debug</title>
<title>{{kind}}</title>
<style type="text/css">
body { font-family: "Segoe UI",Arial,Helvetica; background-color: rgb(27, 43, 52); color: rgb(205, 211, 222); }
#content { margin: 2em; }
h1 img { float: left; margin-right: 0.5em; }
h1 #code { padding: 0.1em 0.5em; background-color: rgb(102, 153, 204); color: white; border-radius: 0.1em; }
h1 #code { padding: 0.1em 0.5em; background-color: rgb(102, 153, 204); color: white; border-radius: 0.1em; text-transform: uppercase; }
#debug { border: 1px dotted rgb(205, 211, 222); overflow: hidden; padding: 0.5em; font-size: 13px; }
button.clip { float: right; }
h2 #status { color: rgb(102, 153, 204); }
Expand All @@ -23,19 +23,19 @@
<h1>
<img width="59" height="48" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADsAAAAwCAYAAACv4gJwAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAAEeSURBVGhD7ZdNCsIwEEaj1/AILvUCHsStuPIwrsStB/EEnkmTkoESMklq85/vgQwFS+frm2npZrc/fsUgbHUdAoTtFYTtFW/Y0+3RVHXBvnrUye/7VR+1g6tvvGdDRqJmuP6HMmsNG7qvJSYgtC/b/6xj3OKDac6iB5TPLBl9XQ5Tzcn5+Zmqrz+YjWGW7nZKzGvBrIbrP+p7Vt19+tFxCbj+o5tVY0ajpmqJwFnMKkyzOfbZJItZsjo3W4JsZmsg287WAMxKYBZmGwJmJUOZxfcszFrgdiMloX3B7BqzIZB9136H7OESYFaSzCwZ/YcY14bZ1DtbAq5/a9hesY6xYs3OlcTVNxuWxoBObqW61g9j3CsI2ysI2ysDhRXiB5CuA+ASNuP/AAAAAElFTkSuQmCC" alt="Debug"/>

<span id="code">DEBUG</span>
<span id="code">{{kind}}</span>
</h1>
<div id="debug">
<button class="clip" title="Copy to clipboard" onclick="clip(document.getElementById('output').innerText); flash(document.getElementById('debug'))">📋</button>
<pre id="output">%1$s</pre>
<pre id="output">{{debug}}</pre>
</div>

<!-- Original HTTP response -->
<h2>HTTP/1.1 <span id="status">%2$d %3$s</span></h2>
<h2>HTTP/1.1 <span id="status">{{status}} {{message}}</span></h2>
<table id="headers">
%4$s
{{#rows headers}}
</table>
<pre id="body">%5$s</pre>
<pre id="body">{{content}}</pre>
</div>
<script type="text/javascript">
function clip(text) {
Expand Down

0 comments on commit ca7d4fd

Please sign in to comment.