@rip-lang/server 1.4.3 → 1.4.4

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 CHANGED
@@ -5,14 +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
- # Default mode is run: HTML renders, images display.
9
- # Text files that can't run are shown with syntax highlighting.
8
+ # Single-click serves files natively (HTML renders, images display, etc.).
9
+ # Double-click (appends ?) shows syntax-highlighted source for text files.
10
+ # Markdown always renders. Directories show a listing with index file detection.
10
11
  # ==============================================================================
11
12
 
12
13
  import { use, start, notFound } from '@rip-lang/server'
13
14
  import { statSync } from 'node:fs'
14
15
  import { join, resolve, basename } from 'node:path'
15
- import { renderDirectoryListing, renderMarkdown, renderTextFile, isTextFile, serveRipHighlightGrammar, findIndexFile, INDEX_FILES } from './serving/static.rip'
16
+ import { renderDirectoryListing, renderMarkdown, renderTextFile, isTextFile, serveRipHighlightGrammar, findIndexFile } from './serving/static.rip'
16
17
 
17
18
  root = resolve(process.env.APP_BASE_DIR or process.cwd())
18
19
  rootSlash = root + '/'
@@ -23,8 +24,10 @@ notFound ->
23
24
  res = serveRipHighlightGrammar()
24
25
  return res if res
25
26
 
26
- reqPath = try decodeURIComponent(@req.path) catch then @req.path
27
+ url = new URL(@req.url)
28
+ reqPath = try decodeURIComponent(url.pathname) catch then url.pathname
27
29
  path = resolve(root, reqPath.slice(1))
30
+ viewSource = url.search is '?'
28
31
 
29
32
  unless path is root or path.startsWith(rootSlash)
30
33
  return new Response 'Not Found', { status: 404 }
@@ -37,11 +40,11 @@ notFound ->
37
40
  if stat.isFile()
38
41
  accept = @req.header('accept') or ''
39
42
  if accept.includes('text/html')
40
- if path.endsWith('.md')
43
+ if path.endsWith('.md') and not viewSource
41
44
  try
42
45
  html = renderMarkdown(path)
43
46
  return new Response html, { headers: { 'Content-Type': 'text/html; charset=UTF-8' } }
44
- if isTextFile(path) and not INDEX_FILES.includes(basename(path))
47
+ if viewSource and isTextFile(path)
45
48
  try
46
49
  html = renderTextFile(path)
47
50
  return new Response html, { headers: { 'Content-Type': 'text/html; charset=UTF-8' } }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rip-lang/server",
3
- "version": "1.4.3",
3
+ "version": "1.4.4",
4
4
  "description": "Bun-native content server: static sites, apps, HTTP proxy, and TCP/TLS passthrough",
5
5
  "type": "module",
6
6
  "main": "api.rip",
@@ -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)}();
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+'?'})}();
193
193
  </script>
194
194
  </body>
195
195
  </html>
@@ -376,10 +376,11 @@ export serveStaticRoute = (req, url, route) ->
376
376
  return new Response(html, { headers: { 'content-type': 'text/html; charset=UTF-8' } })
377
377
  if stat.isFile()
378
378
  if route.browse and acceptsHtml(req)
379
- if filePath.endsWith('.md')
379
+ viewSource = url.search is '?'
380
+ if filePath.endsWith('.md') and not viewSource
380
381
  html = renderMarkdown(filePath)
381
382
  return new Response(html, { headers: { 'content-type': 'text/html; charset=UTF-8' } })
382
- if isTextFile(filePath)
383
+ if viewSource and isTextFile(filePath)
383
384
  html = renderTextFile(filePath)
384
385
  return new Response(html, { headers: { 'content-type': 'text/html; charset=UTF-8' } })
385
386
  file = Bun.file(filePath)