@rip-lang/api 0.7.3 → 0.7.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/api.rip +1 -1
- package/middleware.rip +72 -1
- package/package.json +1 -1
package/api.rip
CHANGED
|
@@ -590,6 +590,6 @@ export read = (keyOrTag = null, tagOrMiss = null, missOrNil = null) ->
|
|
|
590
590
|
return miss?() if typeof miss is 'function'
|
|
591
591
|
throw new Error "Missing required field: #{key}"
|
|
592
592
|
else
|
|
593
|
-
return
|
|
593
|
+
return if typeof miss is 'function' then miss?() else miss
|
|
594
594
|
|
|
595
595
|
v
|
package/middleware.rip
CHANGED
|
@@ -3,13 +3,14 @@
|
|
|
3
3
|
# ==============================================================================
|
|
4
4
|
#
|
|
5
5
|
# Usage:
|
|
6
|
-
# import { cors, logger, compress, sessions } from '@rip-lang/api/middleware'
|
|
6
|
+
# import { cors, logger, compress, sessions, prettyJson } from '@rip-lang/api/middleware'
|
|
7
7
|
# import { session } from '@rip-lang/api'
|
|
8
8
|
#
|
|
9
9
|
# use logger()
|
|
10
10
|
# use cors origin: 'https://myapp.com'
|
|
11
11
|
# use compress()
|
|
12
12
|
# use sessions()
|
|
13
|
+
# use prettyJson # Pretty JSON for iOS mobile browsers
|
|
13
14
|
#
|
|
14
15
|
# before ->
|
|
15
16
|
# session.userId = 123 # Works anywhere via AsyncLocalStorage
|
|
@@ -390,3 +391,73 @@ export bodyLimit = (opts = {}) ->
|
|
|
390
391
|
return c.json { error: message }, 413
|
|
391
392
|
|
|
392
393
|
await next()
|
|
394
|
+
|
|
395
|
+
# ==============================================================================
|
|
396
|
+
# prettyJson — Pretty JSON for iOS Mobile Browsers
|
|
397
|
+
# ==============================================================================
|
|
398
|
+
#
|
|
399
|
+
# Renders JSON as syntax-highlighted HTML for iOS mobile browsers.
|
|
400
|
+
# Solves the iOS Safari/Chrome "download" footer issue when viewing JSON.
|
|
401
|
+
#
|
|
402
|
+
# Usage:
|
|
403
|
+
# use prettyJson
|
|
404
|
+
#
|
|
405
|
+
# Only activates when:
|
|
406
|
+
# 1. Request is from iOS (iPhone/iPad)
|
|
407
|
+
# 2. Browser is directly viewing (Accept: text/html, not API call)
|
|
408
|
+
#
|
|
409
|
+
|
|
410
|
+
export prettyJson = (c, next) ->
|
|
411
|
+
originalJson = c.json.bind(c)
|
|
412
|
+
|
|
413
|
+
c.json = (data, status = 200, headers = {}) ->
|
|
414
|
+
if _shouldRenderHtmlJson(c.req.raw)
|
|
415
|
+
return _renderHtmlJson(data, status)
|
|
416
|
+
originalJson(data, status, headers)
|
|
417
|
+
|
|
418
|
+
next!()
|
|
419
|
+
|
|
420
|
+
_shouldRenderHtmlJson = (req) ->
|
|
421
|
+
ua = req.headers.get('user-agent') or ''
|
|
422
|
+
accept = req.headers.get('accept') or ''
|
|
423
|
+
dest = req.headers.get('sec-fetch-dest') or ''
|
|
424
|
+
|
|
425
|
+
isIOS = /iPhone|iPad|iPod/i.test(ua)
|
|
426
|
+
acceptsHtml = accept.includes('text/html')
|
|
427
|
+
isNavigation = dest is 'document' or (acceptsHtml and not accept.startsWith('application/json'))
|
|
428
|
+
|
|
429
|
+
isIOS and isNavigation
|
|
430
|
+
|
|
431
|
+
_renderHtmlJson = (data, status) ->
|
|
432
|
+
json = JSON.stringify(data, null, 2)
|
|
433
|
+
|
|
434
|
+
# HTML escape then syntax highlight
|
|
435
|
+
escaped = json
|
|
436
|
+
.replace(/&/g, '&')
|
|
437
|
+
.replace(/</g, '<')
|
|
438
|
+
.replace(/>/g, '>')
|
|
439
|
+
|
|
440
|
+
highlighted = escaped
|
|
441
|
+
.replace(/"([^"]+)":/g, '<span class="k">"$1"</span>:')
|
|
442
|
+
.replace(/: "([^"]*)"/g, ': <span class="s">"$1"</span>')
|
|
443
|
+
.replace(/: (-?\d+\.?\d*)/g, ': <span class="n">$1</span>')
|
|
444
|
+
.replace(/: (true|false)/g, ': <span class="b">$1</span>')
|
|
445
|
+
.replace(/: (null)/g, ': <span class="b">$1</span>')
|
|
446
|
+
|
|
447
|
+
html = """<!DOCTYPE html>
|
|
448
|
+
<html><head>
|
|
449
|
+
<meta charset="utf-8">
|
|
450
|
+
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
451
|
+
<title>JSON</title>
|
|
452
|
+
<style>
|
|
453
|
+
*{box-sizing:border-box}
|
|
454
|
+
body{font:14px/1.5 ui-monospace,monospace;background:#1a1a2e;color:#e0e0e0;margin:0;padding:16px}
|
|
455
|
+
pre{margin:0;white-space:pre-wrap;word-break:break-word}
|
|
456
|
+
.k{color:#82aaff}.s{color:#c3e88d}.n{color:#f78c6c}.b{color:#89ddff}
|
|
457
|
+
</style>
|
|
458
|
+
</head><body><pre>#{highlighted}</pre></body></html>"""
|
|
459
|
+
|
|
460
|
+
new Response html, {
|
|
461
|
+
status: status
|
|
462
|
+
headers: new Headers({ 'content-type': 'text/html; charset=utf-8' })
|
|
463
|
+
}
|