From 4dc2cc4d8d24737f995dbb3d81bbfc93f02267ab Mon Sep 17 00:00:00 2001 From: jholdstock Date: Mon, 26 Jun 2023 14:26:48 +0100 Subject: [PATCH] webapi: Use raw whitespace to format JSON. No need to manually construct HTML in this formatting func, it can simply deal with whitespace and then use
 tags to display.

Add some tests to validate behaviour.
---
 webapi/formatting.go                       | 14 +++---
 webapi/formatting_test.go                  | 51 ++++++++++++++++++++++
 webapi/public/css/vspd.css                 |  6 +++
 webapi/templates/ticket-search-result.html |  8 ++--
 4 files changed, 69 insertions(+), 10 deletions(-)
 create mode 100644 webapi/formatting_test.go

diff --git a/webapi/formatting.go b/webapi/formatting.go
index 9b42a57..de6b10d 100644
--- a/webapi/formatting.go
+++ b/webapi/formatting.go
@@ -4,7 +4,6 @@ import (
 	"bytes"
 	"encoding/json"
 	"fmt"
-	"html/template"
 	"strings"
 	"time"
 
@@ -40,16 +39,19 @@ func stripWss(input string) string {
 	return input
 }
 
-func indentJSON(log slog.Logger) func(string) template.HTML {
-	return func(input string) template.HTML {
+// indentJSON returns a func which uses whitespace to format a provided JSON
+// string. If the parameter is invalid JSON, an error will be logged and the
+// param will be returned unaltered.
+func indentJSON(log slog.Logger) func(string) string {
+	return func(input string) string {
 		var indented bytes.Buffer
-		err := json.Indent(&indented, []byte(input), "
", "    ") + err := json.Indent(&indented, []byte(input), "", " ") if err != nil { log.Errorf("Failed to indent JSON: %w", err) - return template.HTML(input) + return input } - return template.HTML(indented.String()) + return indented.String() } } diff --git a/webapi/formatting_test.go b/webapi/formatting_test.go new file mode 100644 index 0000000..589c375 --- /dev/null +++ b/webapi/formatting_test.go @@ -0,0 +1,51 @@ +package webapi + +import ( + "testing" + + "github.com/decred/slog" +) + +func TestIndentJSON(t *testing.T) { + t.Parallel() + + // Get the actual invokable func by passing a noop logger. + indentJSONFunc := indentJSON(slog.Disabled) + + tests := map[string]struct { + input string + expected string + }{ + "nothing": { + input: "", + expected: "", + }, + "empty": { + input: "{}", + expected: "{}", + }, + "one line JSON": { + input: "{\"key\":\"value\"}", + expected: "{\n \"key\": \"value\"\n}", + }, + "nested JSON": { + input: "{\"key\":{\"key2\":\"value\"}}", + expected: "{\n \"key\": {\n \"key2\": \"value\"\n }\n}", + }, + "invalid JSON": { + input: "this is not valid json", + expected: "this is not valid json", + }, + } + + for testName, test := range tests { + test := test + t.Run(testName, func(t *testing.T) { + t.Parallel() + actual := indentJSONFunc(test.input) + if actual != test.expected { + t.Fatalf("expected %q, got %q", test.expected, actual) + } + }) + } +} diff --git a/webapi/public/css/vspd.css b/webapi/public/css/vspd.css index f5b3cd0..4ccb6f3 100644 --- a/webapi/public/css/vspd.css +++ b/webapi/public/css/vspd.css @@ -158,6 +158,12 @@ footer .code { font-size: 12px; } +#ticket-table pre { + color: #3D5873; + font-size: 12px; + white-space: pre-wrap; +} + .vsp-status { padding: 10px; } diff --git a/webapi/templates/ticket-search-result.html b/webapi/templates/ticket-search-result.html index c687c13..5fc8479 100644 --- a/webapi/templates/ticket-search-result.html +++ b/webapi/templates/ticket-search-result.html @@ -128,7 +128,7 @@ - + @@ -136,7 +136,7 @@ - + @@ -172,7 +172,7 @@
Request{{ indentJSON $value.Request }}
{{ indentJSON $value.Request }}
Request
Signature
Response{{ indentJSON $value.Response }}
{{ indentJSON $value.Response }}
Response
Signature
- + @@ -180,7 +180,7 @@ - +
Request{{ indentJSON .AltSignAddrData.Req }}
{{ indentJSON .AltSignAddrData.Req }}
Request
Signature
Response{{ indentJSON .AltSignAddrData.Resp }}
{{ indentJSON .AltSignAddrData.Resp }}
Response
Signature