Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 22 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,28 @@ this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm

## [Unreleased]

Nothing yet.
### Added
- JSON Formatter: a Tree view alongside the text output. It shows the same
document the text does, with sorted keys and expanded embedded JSON, as a
collapsible tree. Only the rows on screen are rendered, so large documents
scroll smoothly. It opens a couple of levels deep, and has Expand all /
Collapse all and full keyboard navigation (arrow keys, Home/End, Enter).
- JSON Formatter: copy the selected tree node's path as an RFC 6901 pointer
(`/items/0/id`), a dot path (`items[0].id`) or a jq path (`.items[0].id`).
- JSON Formatter: embedded JSON strings can be expanded one field at a time.
A field nested inside another payload unlocks once its parent is expanded.
- JSON Formatter: auto-fixes for almost-JSON. It strips a JSONP wrapper, the
`)]}'` prefix, a byte-order mark and comments; converts single quotes;
quotes bare keys; and removes trailing commas. Apply them in place, or
review the change side by side in Diff first.
- JSON Formatter: lossless mode. When a document has numbers JavaScript
cannot hold exactly, like `12345678901234567890`, format and minify keep
them digit for digit instead of rounding them. This includes numbers inside
expanded embedded JSON.

### Fixed
- JSON Formatter: with "Expand embedded JSON" on, a key named `__proto__`
was silently dropped from the output. It is now kept like any other key.

## [0.3.0] — 2026-09-25

Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"@codemirror/merge": "6.12.2",
"@codemirror/state": "6.7.5",
"@codemirror/view": "6.43.12",
"@tanstack/react-virtual": "3.14.12",
"change-case": "5.4.4",
"clsx": "2.1.1",
"cmdk": "1.1.1",
Expand Down
20 changes: 20 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 30 additions & 0 deletions src/lib/persist/handoff.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { TOOLS_BY_SLUG, type ToolSlug } from '@/lib/registry'
import { readIdb, writeIdb } from './idb'
import { readLocal, writeLocal } from './store'

/**
* Seed another tool's saved state before navigating to it -- e.g. the JSON
* tool opening its auto-fix preview in Diff.
*
* The patch is merged over whatever the target has stored, and `useToolState`
* merges that over the tool's own defaults on mount, so the caller only names
* the fields it means to set and never needs the target's module (importing it
* would pull that tool's chunk into the caller's).
*
* Resolves false for a `store: 'none'` tool (there is nowhere to put it) or a
* failed write, so the caller can stay put instead of opening an empty tool.
*/
export async function handOff<T extends object>(slug: ToolSlug, patch: Partial<T>): Promise<boolean> {
const tool = TOOLS_BY_SLUG[slug]
const version = tool.stateVersion

if (tool.store.kind === 'idb') {
const current = (await readIdb<T>(slug, version)) ?? {}
return writeIdb(slug, version, { ...current, ...patch })
}
if (tool.store.kind === 'local') {
const current = readLocal<T>(slug, version) ?? {}
return writeLocal(slug, version, { ...current, ...patch }) === 'ok'
}
return false
}
Loading
Loading