D
DreamLake

Preview

JSONL Preview

JSONL (one JSON value per line, also called NDJSON) rendered as a virtualized list with click-to-expand detail.

Extensions: jsonl, ndjson

Format

Each line is a complete, independent JSON value. Whitespace inside a value is allowed (the value is one logical entity even if it spans visually), but the convention is one line per object.

{"ts": 0.000, "data": [0.0, -1.57, 0.0]}
{"ts": 0.010, "data": [0.0, -1.56, 0.01]}
{"ts": 0.020, "data": [0.01, -1.55, 0.01]}

This is the format used by every useSegment view's segment cache and by dreamlake-py for its track chunks.

Loading strategy

Fetch (with optional Range) → split on \n → parse each line lazily as the user scrolls. The split + parse path is streaming-aware: parsing a single line never requires holding the whole array in memory.

const text = await fetcher(url, ...).then(r => r.text())
const lines = text.split('\n').filter(Boolean)
// rows materialized on demand by the virtual list

Click-to-expand split panel

The list shows one row per line — a compact summary (first ~80 chars of the JSON). Clicking a row opens a side panel rendering the full value through a syntax-highlighted JSON view, with collapsible nested objects and arrays.

┌─ rows ─────────────────────┬─ detail ──────────────┐
│ {"ts": 0.000, "data": ...} │ {                     │
│ {"ts": 0.010, "data": ...} │   "ts": 0.010,        │
│ {"ts": 0.020, "data": ...} │   "data": [           │
│ {"ts": 0.030, "data": ...} │     0.0,              │
...-1.56,            │
│                            │     0.01
│                            │   ]                   │
│                            │ }                     │
└────────────────────────────┴───────────────────────┘

The detail panel is virtualized too — opening a 10 MB JSON object with 100k keys does not freeze the tab.

Virtual scrolling

Same approach as CSV: only visible rows are mounted. A 1M-line JSONL renders in ~30 ms.

Soft size limit

Default: 10 MB. Range fetch → drop incomplete trailing line → truncation banner.

<FilePreview url={url} limits={{ jsonlMaxBytes: 100 * 1024 * 1024 }} />

If a line fails to parse (malformed JSON), the row renders with a warning glyph and the original text. The previewer never crashes on bad input.

Live demo

Loading demo...
import { FilePreview } from '@vuer-ai/vuer-m3u/preview'

export function MyComponent() {
  return (
    <FilePreview url="/vuer-m3u-demo/preview/tabular/events.jsonl" />
  )
}

Cross-links