Format JSON examples with proper indentation and syntax highlighting
This commit is contained in:
parent
2dc42a6cb7
commit
0a4f921fd9
2 changed files with 203 additions and 112 deletions
|
|
@ -243,3 +243,54 @@
|
|||
.historical-dot-marker {
|
||||
z-index: 15 !important;
|
||||
}
|
||||
|
||||
/* JSON syntax highlighting for API docs */
|
||||
.json-key {
|
||||
color: #7c3aed;
|
||||
}
|
||||
|
||||
.json-string {
|
||||
color: #059669;
|
||||
}
|
||||
|
||||
.json-number {
|
||||
color: #d97706;
|
||||
}
|
||||
|
||||
.json-boolean {
|
||||
color: #dc2626;
|
||||
}
|
||||
|
||||
.json-null {
|
||||
color: #6b7280;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.json-punc {
|
||||
color: #6b7280;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .json-key {
|
||||
color: #a78bfa;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .json-string {
|
||||
color: #34d399;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .json-number {
|
||||
color: #fbbf24;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .json-boolean {
|
||||
color: #f87171;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .json-null {
|
||||
color: #9ca3af;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .json-punc {
|
||||
color: #9ca3af;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -208,6 +208,151 @@ defmodule AprsmeWeb.ApiDocsLive do
|
|||
|
||||
defp sanitize_raw_packet(raw_packet), do: raw_packet
|
||||
|
||||
defp highlight_json(text) do
|
||||
highlighted =
|
||||
Regex.replace(
|
||||
~r/(?<!\\)("(?:[^"\\]|\\.)*")(?=\s*:)|(?<!\\)("(?:[^"\\]|\\.)*")|(\btrue\b|\bfalse\b)|(\bnull\b)|(-?\b\d+(?:\.\d+)?(?:[eE][+-]?\d+)?)/,
|
||||
text,
|
||||
fn
|
||||
_, key, "", "", "", "" ->
|
||||
~s(<span class="json-key">#{key}</span>)
|
||||
|
||||
_, "", str, "", "", "" ->
|
||||
~s(<span class="json-string">#{str}</span>)
|
||||
|
||||
_, "", "", bool, "", "" ->
|
||||
~s(<span class="json-boolean">#{bool}</span>)
|
||||
|
||||
_, "", "", "", null, "" ->
|
||||
~s(<span class="json-null">#{null}</span>)
|
||||
|
||||
_, "", "", "", "", num ->
|
||||
~s(<span class="json-number">#{num}</span>)
|
||||
end
|
||||
)
|
||||
|
||||
Regex.replace(~r/[{}[\]\:,]/, highlighted, ~s(<span class="json-punc">\\0</span>))
|
||||
end
|
||||
|
||||
defp callsign_success_json, do: ~s|{
|
||||
"data": {
|
||||
"id": "d7249877-d4a6-45c2-b314-2a8a355d2566",
|
||||
"callsign": "N0CALL-9",
|
||||
"base_callsign": "N0CALL",
|
||||
"ssid": "9",
|
||||
"sender": "N0CALL-9",
|
||||
"destination": "APRS",
|
||||
"path": "WIDE1-1,WIDE2-1",
|
||||
"data_type": "position",
|
||||
"information_field": "!4740.00N/12200.00W>Mobile Station",
|
||||
"raw_packet": "N0CALL-9>APRS,WIDE1-1,WIDE2-1:!4740.00N/12200.00W>Mobile Station",
|
||||
"received_at": "2024-01-15T10:30:45Z",
|
||||
"region": "US-West",
|
||||
"position": {
|
||||
"latitude": 47.666667,
|
||||
"longitude": -122.0,
|
||||
"course": 90,
|
||||
"speed": 35.5,
|
||||
"altitude": 152.4
|
||||
},
|
||||
"symbol": {
|
||||
"code": ">",
|
||||
"table_id": "/"
|
||||
},
|
||||
"comment": "Mobile Station",
|
||||
"timestamp": null,
|
||||
"aprs_messaging": false,
|
||||
"weather": null,
|
||||
"equipment": {
|
||||
"device_identifier": "APK004",
|
||||
"manufacturer": "Kenwood",
|
||||
"equipment_type": "TM-D710",
|
||||
"device_model": "TM-D710G",
|
||||
"device_vendor": "Kenwood",
|
||||
"device_class": "rig"
|
||||
},
|
||||
"message": null,
|
||||
"has_position": true,
|
||||
"inserted_at": "2024-01-15T10:30:45Z",
|
||||
"updated_at": "2024-01-15T10:30:45Z"
|
||||
}
|
||||
}|
|
||||
|
||||
defp callsign_not_found_json, do: ~s|{
|
||||
"data": null,
|
||||
"message": "No packets found for callsign N0CALL-9"
|
||||
}|
|
||||
|
||||
defp callsign_error_json, do: ~s|{
|
||||
"error": {
|
||||
"message": "Invalid callsign format",
|
||||
"code": "bad_request"
|
||||
}
|
||||
}|
|
||||
|
||||
defp weather_success_json, do: ~s|{
|
||||
"data": [
|
||||
{
|
||||
"callsign": "N0CALL-13",
|
||||
"base_callsign": "N0CALL",
|
||||
"position": {
|
||||
"lat": 37.7849,
|
||||
"lon": -122.4094
|
||||
},
|
||||
"distance_miles": 0.87,
|
||||
"weather": {
|
||||
"temperature": 72.5,
|
||||
"humidity": 65.0,
|
||||
"pressure": 1013.2,
|
||||
"wind_speed": 8.5,
|
||||
"wind_direction": 270,
|
||||
"wind_gust": 12.0,
|
||||
"rain_1h": 0.0,
|
||||
"rain_24h": 0.5,
|
||||
"rain_since_midnight": 0.3
|
||||
},
|
||||
"symbol": {
|
||||
"table_id": "/",
|
||||
"code": "_"
|
||||
},
|
||||
"comment": "Davis Vantage Pro2",
|
||||
"last_report": "2026-03-22T15:30:00Z"
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"count": 1,
|
||||
"params": {
|
||||
"latitude": 37.7749,
|
||||
"longitude": -122.4194,
|
||||
"radius_miles": 25.0,
|
||||
"hours": 6,
|
||||
"limit": 50
|
||||
}
|
||||
}
|
||||
}|
|
||||
|
||||
defp weather_empty_json, do: ~s|{
|
||||
"data": [],
|
||||
"meta": {
|
||||
"count": 0,
|
||||
"params": {
|
||||
"latitude": 0.0,
|
||||
"longitude": -180.0,
|
||||
"radius_miles": 10.0,
|
||||
"hours": 6,
|
||||
"limit": 50
|
||||
}
|
||||
}
|
||||
}|
|
||||
|
||||
defp weather_error_param_json, do: ~s|{
|
||||
"error": "Missing required parameter: lat"
|
||||
}|
|
||||
|
||||
defp weather_error_invalid_json, do: ~s|{
|
||||
"error": "Invalid latitude: must be a number between -90 and 90"
|
||||
}|
|
||||
|
||||
@impl true
|
||||
def render(assigns) do
|
||||
~H"""
|
||||
|
|
@ -339,67 +484,17 @@ defmodule AprsmeWeb.ApiDocsLive do
|
|||
|
||||
<h4 class="text-md font-medium mb-2">Success Response (200 OK)</h4>
|
||||
<div class="bg-gray-900 text-gray-100 dark:bg-gray-950 p-4 rounded-lg overflow-x-auto mb-4">
|
||||
<pre><code><%= raw ~s|{
|
||||
"data": {
|
||||
"id": "d7249877-d4a6-45c2-b314-2a8a355d2566",
|
||||
"callsign": "N0CALL-9",
|
||||
"base_callsign": "N0CALL",
|
||||
"ssid": "9",
|
||||
"sender": "N0CALL-9",
|
||||
"destination": "APRS",
|
||||
"path": "WIDE1-1,WIDE2-1",
|
||||
"data_type": "position",
|
||||
"information_field": "!4740.00N/12200.00W>Mobile Station",
|
||||
"raw_packet": "N0CALL-9>APRS,WIDE1-1,WIDE2-1:!4740.00N/12200.00W>Mobile Station",
|
||||
"received_at": "2024-01-15T10:30:45Z",
|
||||
"region": "US-West",
|
||||
"position": {
|
||||
"latitude": 47.666667,
|
||||
"longitude": -122.0,
|
||||
"course": 90,
|
||||
"speed": 35.5,
|
||||
"altitude": 152.4
|
||||
},
|
||||
"symbol": {
|
||||
"code": ">",
|
||||
"table_id": "/"
|
||||
},
|
||||
"comment": "Mobile Station",
|
||||
"timestamp": null,
|
||||
"aprs_messaging": false,
|
||||
"weather": null,
|
||||
"equipment": {
|
||||
"device_identifier": "APK004",
|
||||
"manufacturer": "Kenwood",
|
||||
"equipment_type": "TM-D710",
|
||||
"device_model": "TM-D710G",
|
||||
"device_vendor": "Kenwood",
|
||||
"device_class": "rig"
|
||||
},
|
||||
"message": null,
|
||||
"has_position": true,
|
||||
"inserted_at": "2024-01-15T10:30:45Z",
|
||||
"updated_at": "2024-01-15T10:30:45Z"
|
||||
}
|
||||
}| %></code></pre>
|
||||
<pre><code><%= raw highlight_json(callsign_success_json()) %></code></pre>
|
||||
</div>
|
||||
|
||||
<h4 class="text-md font-medium mb-2">Not Found Response (404)</h4>
|
||||
<div class="bg-gray-900 text-gray-100 dark:bg-gray-950 p-4 rounded-lg overflow-x-auto mb-4">
|
||||
<pre><code><%= raw ~s|{
|
||||
"data": null,
|
||||
"message": "No packets found for callsign N0CALL-9"
|
||||
}| %></code></pre>
|
||||
<pre><code><%= raw highlight_json(callsign_not_found_json()) %></code></pre>
|
||||
</div>
|
||||
|
||||
<h4 class="text-md font-medium mb-2">Error Response (400)</h4>
|
||||
<div class="bg-gray-900 text-gray-100 dark:bg-gray-950 p-4 rounded-lg overflow-x-auto">
|
||||
<pre><code><%= raw ~s|{
|
||||
"error": {
|
||||
"message": "Invalid callsign format",
|
||||
"code": "bad_request"
|
||||
}
|
||||
}| %></code></pre>
|
||||
<pre><code><%= raw highlight_json(callsign_error_json()) %></code></pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -512,77 +607,22 @@ defmodule AprsmeWeb.ApiDocsLive do
|
|||
|
||||
<h4 class="text-md font-medium mb-2">Success Response (200 OK)</h4>
|
||||
<div class="bg-gray-900 text-gray-100 dark:bg-gray-950 p-4 rounded-lg overflow-x-auto mb-4">
|
||||
<pre><code><%= raw ~s|{
|
||||
"data": [
|
||||
{
|
||||
"callsign": "N0CALL-13",
|
||||
"base_callsign": "N0CALL",
|
||||
"position": {
|
||||
"lat": 37.7849,
|
||||
"lon": -122.4094
|
||||
},
|
||||
"distance_miles": 0.87,
|
||||
"weather": {
|
||||
"temperature": 72.5,
|
||||
"humidity": 65.0,
|
||||
"pressure": 1013.2,
|
||||
"wind_speed": 8.5,
|
||||
"wind_direction": 270,
|
||||
"wind_gust": 12.0,
|
||||
"rain_1h": 0.0,
|
||||
"rain_24h": 0.5,
|
||||
"rain_since_midnight": 0.3
|
||||
},
|
||||
"symbol": {
|
||||
"table_id": "/",
|
||||
"code": "_"
|
||||
},
|
||||
"comment": "Davis Vantage Pro2",
|
||||
"last_report": "2026-03-22T15:30:00Z"
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"count": 1,
|
||||
"params": {
|
||||
"latitude": 37.7749,
|
||||
"longitude": -122.4194,
|
||||
"radius_miles": 25.0,
|
||||
"hours": 6,
|
||||
"limit": 50
|
||||
}
|
||||
}
|
||||
}| %></code></pre>
|
||||
<pre><code><%= raw highlight_json(weather_success_json()) %></code></pre>
|
||||
</div>
|
||||
|
||||
<h4 class="text-md font-medium mb-2">Empty Response (200 OK)</h4>
|
||||
<div class="bg-gray-900 text-gray-100 dark:bg-gray-950 p-4 rounded-lg overflow-x-auto mb-4">
|
||||
<pre><code><%= raw ~s|{
|
||||
"data": [],
|
||||
"meta": {
|
||||
"count": 0,
|
||||
"params": {
|
||||
"latitude": 0.0,
|
||||
"longitude": -180.0,
|
||||
"radius_miles": 10.0,
|
||||
"hours": 6,
|
||||
"limit": 50
|
||||
}
|
||||
}
|
||||
}| %></code></pre>
|
||||
<pre><code><%= raw highlight_json(weather_empty_json()) %></code></pre>
|
||||
</div>
|
||||
|
||||
<h4 class="text-md font-medium mb-2">Error Response (400 Bad Request)</h4>
|
||||
<div class="bg-gray-900 text-gray-100 dark:bg-gray-950 p-4 rounded-lg overflow-x-auto mb-4">
|
||||
<pre><code><%= raw ~s|{
|
||||
"error": "Missing required parameter: lat"
|
||||
}| %></code></pre>
|
||||
<pre><code><%= raw highlight_json(weather_error_param_json()) %></code></pre>
|
||||
</div>
|
||||
|
||||
<h4 class="text-md font-medium mb-2">Error Response (422 Unprocessable Entity)</h4>
|
||||
<div class="bg-gray-900 text-gray-100 dark:bg-gray-950 p-4 rounded-lg overflow-x-auto">
|
||||
<pre><code><%= raw ~s|{
|
||||
"error": "Invalid latitude: must be a number between -90 and 90"
|
||||
}| %></code></pre>
|
||||
<pre><code><%= raw highlight_json(weather_error_invalid_json()) %></code></pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue