API explorer can now do GET, has JSON syntax highlighting

Refs #1871
pull/1912/head
Simon Willison 2022-11-01 17:31:22 -07:00
rodzic 497290beaf
commit 0b166befc0
2 zmienionych plików z 103 dodań i 17 usunięć

Wyświetl plik

@ -0,0 +1,43 @@
/*
https://github.com/luyilin/json-format-highlight
From https://unpkg.com/json-format-highlight@1.0.1/dist/json-format-highlight.js
MIT Licensed
*/
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global.jsonFormatHighlight = factory());
}(this, (function () { 'use strict';
var defaultColors = {
keyColor: 'dimgray',
numberColor: 'lightskyblue',
stringColor: 'lightcoral',
trueColor: 'lightseagreen',
falseColor: '#f66578',
nullColor: 'cornflowerblue'
};
function index (json, colorOptions) {
if ( colorOptions === void 0 ) colorOptions = {};
if (!json) { return; }
if (typeof json !== 'string') {
json = JSON.stringify(json, null, 2);
}
var colors = Object.assign({}, defaultColors, colorOptions);
json = json.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
return json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+]?\d+)?)/g, function (match) {
var color = colors.numberColor;
if (/^"/.test(match)) {
color = /:$/.test(match) ? colors.keyColor : colors.stringColor;
} else {
color = /true/.test(match) ? colors.trueColor : /false/.test(match) ? colors.falseColor : /null/.test(match) ? colors.nullColor : color;
}
return ("<span style=\"color: " + color + "\">" + match + "</span>");
});
}
return index;
})));

Wyświetl plik

@ -2,6 +2,10 @@
{% block title %}API Explorer{% endblock %}
{% block extra_head %}
<script src="{{ base_url }}-/static/json-format-highlight-1.0.1.js"></script>
{% endblock %}
{% block content %}
<h1>API Explorer</h1>
@ -14,17 +18,30 @@
{% endfor %}
{% endif %}
<form method="post" id="api-explorer">
<div>
<label for="path">API path:</label>
<input type="text" id="path" name="path" value="/fixtures/searchable/-/insert" style="width: 60%">
</div>
<div style="margin: 0.5em 0">
<label for="apiJson" style="vertical-align: top">JSON:</label>
<textarea id="apiJson" name="json" style="width: 60%; height: 200px; font-family: monospace; font-size: 0.8em;"></textarea>
</div>
<p><button id="json-format" type="button">Format JSON</button> <input type="submit" value="POST"></p>
</form>
<details open style="border: 2px solid #ccc; border-bottom: none; padding: 0.5em">
<summary style="cursor: pointer;">GET</summary>
<form method="get" id="api-explorer-get" style="margin-top: 0.7em">
<div>
<label for="path">API path:</label>
<input type="text" id="path" name="path" value="/data/docs.json" style="width: 60%">
<input type="submit" value="GET">
</div>
</form>
</details>
<details style="border: 2px solid #ccc; padding: 0.5em">
<summary style="cursor: pointer">POST</summary>
<form method="post" id="api-explorer-post" style="margin-top: 0.7em">
<div>
<label for="path">API path:</label>
<input type="text" id="path" name="path" value="/data/docs/-/insert" style="width: 60%">
</div>
<div style="margin: 0.5em 0">
<label for="apiJson" style="vertical-align: top">JSON:</label>
<textarea id="apiJson" name="json" style="width: 60%; height: 200px; font-family: monospace; font-size: 0.8em;"></textarea>
</div>
<p><button id="json-format" type="button">Format JSON</button> <input type="submit" value="POST"></p>
</form>
</details>
<div id="output" style="display: none">
<h2>API response: HTTP <span id="response-status"></span></h2>
@ -36,7 +53,7 @@
<script>
document.querySelector('#json-format').addEventListener('click', (ev) => {
ev.preventDefault();
const json = document.querySelector('textarea[name="json"]').value;
let json = document.querySelector('textarea[name="json"]').value.trim();
try {
const parsed = JSON.parse(json);
document.querySelector('textarea[name="json"]').value = JSON.stringify(parsed, null, 2);
@ -44,14 +61,41 @@ document.querySelector('#json-format').addEventListener('click', (ev) => {
alert("Error parsing JSON: " + e);
}
});
var form = document.getElementById('api-explorer');
var postForm = document.getElementById('api-explorer-post');
var getForm = document.getElementById('api-explorer-get');
var output = document.getElementById('output');
form.addEventListener("submit", (ev) => {
var errorList = output.querySelector('.errors');
getForm.addEventListener("submit", (ev) => {
ev.preventDefault();
var formData = new FormData(form);
var formData = new FormData(getForm);
var path = formData.get('path');
fetch(path, {
method: 'GET',
headers: {
'Accept': 'application/json',
}
}).then((response) => {
output.style.display = 'block';
document.getElementById('response-status').textContent = response.status;
return response.json();
}).then((data) => {
output.querySelector('pre').innerHTML = jsonFormatHighlight(data);
errorList.style.display = 'none';
}).catch((error) => {
alert(error);
});
});
postForm.addEventListener("submit", (ev) => {
ev.preventDefault();
var formData = new FormData(postForm);
var json = formData.get('json');
var path = formData.get('path');
// Validate JSON
if (!json.length) {
json = '{}';
}
try {
var data = JSON.parse(json);
} catch (err) {
@ -69,7 +113,6 @@ form.addEventListener("submit", (ev) => {
document.getElementById('response-status').textContent = r.status;
return r.json();
}).then(data => {
var errorList = output.querySelector('.errors');
if (data.errors) {
errorList.style.display = 'block';
errorList.innerHTML = '';
@ -81,7 +124,7 @@ form.addEventListener("submit", (ev) => {
} else {
errorList.style.display = 'none';
}
output.querySelector('pre').innerText = JSON.stringify(data, null, 2);
output.querySelector('pre').innerHTML = jsonFormatHighlight(data);
output.style.display = 'block';
}).catch(err => {
alert("Error: " + err);