@rip-lang/server 1.4.6 → 1.4.8
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/browse.rip +6 -13
- package/package.json +1 -1
- package/serving/static.rip +16 -8
package/browse.rip
CHANGED
|
@@ -5,15 +5,15 @@
|
|
|
5
5
|
# Built-in file browser when no index.rip or index.ts exists in the target
|
|
6
6
|
# directory. Activated automatically by `rip server` when no app entry is found.
|
|
7
7
|
#
|
|
8
|
-
#
|
|
9
|
-
#
|
|
10
|
-
#
|
|
8
|
+
# Text files get syntax-highlighted by default. HTML files render natively
|
|
9
|
+
# (double-click adds ?view to see source). Markdown renders. Binary files
|
|
10
|
+
# (images, PDFs) serve natively. Directories show a listing.
|
|
11
11
|
# ==============================================================================
|
|
12
12
|
|
|
13
13
|
import { use, start, notFound } from '@rip-lang/server'
|
|
14
14
|
import { statSync } from 'node:fs'
|
|
15
15
|
import { join, resolve, basename } from 'node:path'
|
|
16
|
-
import { renderDirectoryListing,
|
|
16
|
+
import { renderDirectoryListing, serveBrowseFile, serveRipHighlightGrammar, findIndexFile } from './serving/static.rip'
|
|
17
17
|
|
|
18
18
|
root = resolve(process.env.APP_BASE_DIR or process.cwd())
|
|
19
19
|
rootSlash = root + '/'
|
|
@@ -27,7 +27,6 @@ notFound ->
|
|
|
27
27
|
url = new URL(@req.url)
|
|
28
28
|
reqPath = try decodeURIComponent(url.pathname) catch then url.pathname
|
|
29
29
|
path = resolve(root, reqPath.slice(1))
|
|
30
|
-
viewSource = url.search is '?view'
|
|
31
30
|
|
|
32
31
|
unless path is root or path.startsWith(rootSlash)
|
|
33
32
|
return new Response 'Not Found', { status: 404 }
|
|
@@ -40,14 +39,8 @@ notFound ->
|
|
|
40
39
|
if stat.isFile()
|
|
41
40
|
accept = @req.header('accept') or ''
|
|
42
41
|
if accept.includes('text/html')
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
html = renderMarkdown(path)
|
|
46
|
-
return new Response html, { headers: { 'Content-Type': 'text/html; charset=UTF-8' } }
|
|
47
|
-
if viewSource and isTextFile(path)
|
|
48
|
-
try
|
|
49
|
-
html = renderTextFile(path)
|
|
50
|
-
return new Response html, { headers: { 'Content-Type': 'text/html; charset=UTF-8' } }
|
|
42
|
+
res = serveBrowseFile(path, url)
|
|
43
|
+
return res if res
|
|
51
44
|
return @send path
|
|
52
45
|
|
|
53
46
|
if stat.isDirectory()
|
package/package.json
CHANGED
package/serving/static.rip
CHANGED
|
@@ -189,7 +189,7 @@ export renderDirectoryListing = (reqPath, fsPath, rootName) ->
|
|
|
189
189
|
</table>
|
|
190
190
|
</div></div>
|
|
191
191
|
<script>
|
|
192
|
-
!function(){var p,c,ox=14,oy=14;function mk(){if(p)return p;p=document.createElement('div');p.className='pop';p.innerHTML='<div class="pop-b"></div>';document.body.appendChild(p);return p}function show(a,e){var s=a.dataset.src;if(!s)return;var el=mk(),b=el.firstChild;b.innerHTML='';var img=new Image();img.src=s;b.appendChild(img);c=a;el.classList.add('on');place(e.clientX,e.clientY)}function hide(){c=null;if(p)p.classList.remove('on')}function place(x,y){if(!p)return;var r=p.getBoundingClientRect(),m=12,l=x+ox,t=y+oy;if(l+r.width>innerWidth-m)l=x-r.width-ox;if(t+r.height>innerHeight-m)t=innerHeight-r.height-m;if(l<m)l=m;if(t<m)t=m;p.style.left=l+'px';p.style.top=t+'px'}document.addEventListener('mouseover',function(e){var a=e.target.closest('[data-pv]');if(a)show(a,e)});document.addEventListener('mousemove',function(e){if(c)place(e.clientX,e.clientY)});document.addEventListener('mouseout',function(e){var a=e.target.closest('[data-pv]');if(a&&a===c)hide()});document.addEventListener('scroll',hide,{passive:true});document.addEventListener('keydown',function(e){if(e.key==='Escape')hide()});window.addEventListener('blur',hide);var dt=0;document.addEventListener('click',function(e){var a=e.target.closest('td.nm a');if(!a)return;var h=a.getAttribute('href');if(!h||h.endsWith('/'))return;e.preventDefault();clearTimeout(dt);dt=setTimeout(function(){location.href=h},250)});document.addEventListener('dblclick',function(e){var a=e.target.closest('td.nm a');if(!a)return;var h=a.getAttribute('href');if(!h||h.endsWith('/'))return;e.preventDefault();clearTimeout(dt);location.href=h+'?view'})}();
|
|
192
|
+
!function(){var p,c,ox=14,oy=14;function mk(){if(p)return p;p=document.createElement('div');p.className='pop';p.innerHTML='<div class="pop-b"></div>';document.body.appendChild(p);return p}function show(a,e){var s=a.dataset.src;if(!s)return;var el=mk(),b=el.firstChild;b.innerHTML='';var img=new Image();img.src=s;b.appendChild(img);c=a;el.classList.add('on');place(e.clientX,e.clientY)}function hide(){c=null;if(p)p.classList.remove('on')}function place(x,y){if(!p)return;var r=p.getBoundingClientRect(),m=12,l=x+ox,t=y+oy;if(l+r.width>innerWidth-m)l=x-r.width-ox;if(t+r.height>innerHeight-m)t=innerHeight-r.height-m;if(l<m)l=m;if(t<m)t=m;p.style.left=l+'px';p.style.top=t+'px'}document.addEventListener('mouseover',function(e){var a=e.target.closest('[data-pv]');if(a)show(a,e)});document.addEventListener('mousemove',function(e){if(c)place(e.clientX,e.clientY)});document.addEventListener('mouseout',function(e){var a=e.target.closest('[data-pv]');if(a&&a===c)hide()});document.addEventListener('scroll',hide,{passive:true});document.addEventListener('keydown',function(e){if(e.key==='Escape')hide()});window.addEventListener('blur',hide);var dt=0,hx=/\.html?$/i;document.addEventListener('click',function(e){var a=e.target.closest('td.nm a');if(!a)return;var h=a.getAttribute('href');if(!h||h.endsWith('/'))return;if(!hx.test(h))return;e.preventDefault();clearTimeout(dt);dt=setTimeout(function(){location.href=h},250)});document.addEventListener('dblclick',function(e){var a=e.target.closest('td.nm a');if(!a)return;var h=a.getAttribute('href');if(!h||h.endsWith('/'))return;if(!hx.test(h))return;e.preventDefault();clearTimeout(dt);location.href=h+'?view'})}();
|
|
193
193
|
</script>
|
|
194
194
|
</body>
|
|
195
195
|
</html>
|
|
@@ -319,6 +319,19 @@ export renderTextFile = (filePath) ->
|
|
|
319
319
|
</html>
|
|
320
320
|
"""
|
|
321
321
|
|
|
322
|
+
# --- Browse file response (shared by browse.rip and serveStaticRoute) ---
|
|
323
|
+
|
|
324
|
+
export serveBrowseFile = (filePath, url) ->
|
|
325
|
+
viewSource = url.search is '?view'
|
|
326
|
+
isHtml = filePath.endsWith('.html') or filePath.endsWith('.htm')
|
|
327
|
+
if filePath.endsWith('.md') and not viewSource
|
|
328
|
+
html = renderMarkdown(filePath)
|
|
329
|
+
return new Response(html, { headers: { 'content-type': 'text/html; charset=UTF-8' } })
|
|
330
|
+
if isTextFile(filePath) and (viewSource or not isHtml)
|
|
331
|
+
html = renderTextFile(filePath)
|
|
332
|
+
return new Response(html, { headers: { 'content-type': 'text/html; charset=UTF-8' } })
|
|
333
|
+
null
|
|
334
|
+
|
|
322
335
|
# --- Static file serving ---
|
|
323
336
|
|
|
324
337
|
export INDEX_FILES = ['index.html', 'index.rip', 'index.ts', 'index.tsx', 'index.jsx', 'index.js']
|
|
@@ -376,13 +389,8 @@ export serveStaticRoute = (req, url, route) ->
|
|
|
376
389
|
return new Response(html, { headers: { 'content-type': 'text/html; charset=UTF-8' } })
|
|
377
390
|
if stat.isFile()
|
|
378
391
|
if route.browse and acceptsHtml(req)
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
html = renderMarkdown(filePath)
|
|
382
|
-
return new Response(html, { headers: { 'content-type': 'text/html; charset=UTF-8' } })
|
|
383
|
-
if viewSource and isTextFile(filePath)
|
|
384
|
-
html = renderTextFile(filePath)
|
|
385
|
-
return new Response(html, { headers: { 'content-type': 'text/html; charset=UTF-8' } })
|
|
392
|
+
res = serveBrowseFile(filePath, url)
|
|
393
|
+
return res if res
|
|
386
394
|
file = Bun.file(filePath)
|
|
387
395
|
return new Response(file, { headers: { 'content-type': mimeType(filePath) } })
|
|
388
396
|
|