Repository navigation
v0.1.0
Change one import
npx tinyswaptinyswap finds js-yaml, yaml, yamljs, @std/yaml, json5, strip-json-comments, jsonc-parser, comment-json, jju, ini and @one-ini/wasm in your project, picks the subpath for the version you have installed, shows the diff, then rewrites the imports and swaps the dependencies. Or do it by hand:
- import yaml from "js-yaml";
+ import yaml from "tinyaml/js-yaml";
- import JSON5 from "json5";
+ import JSON5 from "tinyjson5/json5";
- import ini from "ini";
+ import ini from "tinyini/ini";The calls, options, output and errors stay the same.
What you get
| You use | Switch to | Size, gzip | Parses | Stringifies |
|---|---|---|---|---|
| yaml | tinyaml/yaml |
29.8 → 16.9 KiB | 12.0× faster | 2.8× faster |
| js-yaml 4 | tinyaml/js-yaml |
14.4 → 11.6 KiB | 1.6× faster | 1.7× faster |
| json5 2.2.3 | tinyjson5/json5 |
7.5 → 3.2 KiB | 7.4× faster | 4.7× faster |
| comment-json 4.6.2 | tinyjson5/comment-json |
35.3 → 18.2 KiB | 1.8× faster | 1.3× faster |
| @one-ini/wasm 0.2.1 | tinyini/one-ini |
36.0 → 1.7 KiB | 12.4× faster | — |
| ini 7.0.0 | tinyini/ini |
1.6 → 1.5 KiB | 1.8× faster | 2.9× faster |
Writing new code? The root tinyaml API is 7.7 KiB. It parses 18.7× faster than yaml, stringifies 12.9× faster, and gets all 373 yaml-test-suite cases with an expected result right. js-yaml, yaml, yamljs and @std/yaml each get some wrong.
The full table lists all 18 drop-ins. Measured on an Apple M4 with Node 26.13.0.
How we know they match
A drop-in only helps if nothing breaks. Each one passes the original library's own test suite and is fuzzed against the original: a million inputs per subpath for tinyjson5 and tinyini, and thousands per subpath for tinyaml. Each one also covers the edges, from errors and warnings to getters, proxies and sloppy-mode writes. Every known difference is listed in that package's README, along with bugs in the original that tiny doesn't copy.
Typed config imports
All three parsers are TypeScript 7.1 content mappers. Register one in tsconfig.json, and an import config from "./config.yaml" (or .json5, .jsonc, .ini) is typed the way a .json import is. A typo in a key becomes a type error, and a syntax error shows up at its line and column.
A YAML linter
tinyaml-lint catches YAML that other readers load differently, such as no as a boolean or 2026-11-01 as a date. It runs from the CLI, as a library (tinyaml/linter), as an ESLint plugin (tinyaml/eslint) and as a Vite Doctor extension (tinyaml/doctor).
Install
pnpm add tinyaml tinyjson5 tinyiniEach package is published on its own, so install only what you use. Docs at tiny.onmax.me.
👉 Changelog
🚀 Enhancements
- type .yaml, .json5, .jsonc and .ini imports with TypeScript 7.1 content mappers (#18)
- add tinymigrate, a wizard that moves a project to the drop-ins (#15)
- add a YAML linter and a Vite Doctor extension (#6)
- tinyjson5: add tinyjson5/jju, a drop-in for jju 1.4.0 (
ae4853f) - tinyjson5: add tinyjson5/comment-json, a drop-in for comment-json 4.6.2 (
3c1dd49) - tinyjson5: add tinyjson5/jsonc-parser, a drop-in for jsonc-parser 3.3.1 (
76c48ba) - tinyjson5: add drop-ins for strip-json-comments 2, 3 and 5 (
0e9401e) - tinyjson5: add tinyjson5/json5-v1, a drop-in for json5 1.0.2 (
553025e) - tinyjson5: give the root json5 3's rules and a strict jsonc option (
787ee99) - tinyini: add tinyini/one-ini and tinyini/one-ini-v0.1 (
74e11b1) - tinyini: add tinyini/ini-v1 and tinyini/ini-v2 from the shared core (
10c6206) - tinyini: give the root its own INI API, without ini's legacy (
2f34e60) - add drop-in entries for js-yaml 4 and 5, yaml, yamljs and @std/yaml (
a69764c) - add tinyaml, a YAML loader and dumper with js-yaml JSON_SCHEMA semantics (
ed8e6b4)
🔥 Performance
- tinyjson5/jsonc-parser: look for control characters in the string itself, not with a regex that reruns at each line (
c654727) - tinyjson5/jju: make jju's silent writes with one sloppy-mode function, not Reflect (
d1101d9)
🩹 Fixes
- remove five more quadratic paths, close the twelfth review's findings, and list the bugs tinyaml doesn't copy (
1b909b5) - read byte order marks and warnings in linear time, and close the eleventh review's findings (
ed604d1) - close the tenth review's findings (
9452614) - close the ninth review's findings (
23797f4) - close the seventh review's findings (
e4bc01e) - tinyaml/js-yaml-v5: build the null limit without a chained type assertion (
ce8f288) - close the fifth and sixth reviews' findings, and make the linter use the parser (
c5c516c) - tinyjson5/jsonc-parser: build the enums, error names and format comparison without built-ins jsonc-parser doesn't call (
0ae91ee) - tinyjson5/comment-json: keep the faster paths only with this realm's Array, String and Object prototypes (
9e7e675) - tinyjson5/jsonc-parser: read characters as jsonc-parser does in string errors and comment lookahead, and document sliced token values (
6478451) - tinyini: check each package specifier loads its own mode, and read typed-array lengths across realms (
8212df6) - tinyini: probe each bundle's mode behaviour, compare other one-ini builds by version field only, and match boxed strings and shadowed typed-array lengths (
a21b2cd) - tinyini: keep one-ini's working data out of arrays, read root arrays as JSON does, and reject invalid fuzz counts (
ae6c212) - tinyini: build the one-ini AST after parsing, as serde does, and stop root arrays at their first length (
84707df) - tinyini: fail the oracle scripts on a broken harness, and match toJSON, inherited AST names and the glue's length read (
d663ec0) - tinyjson5/comment-json: restore an outer stringify's cache, throw the engine's TypeError, check constructors before reading them, convert odd keys at each lookup (
0e95043) - tinyjson5/jsonc-parser: scan strings a character at a time as jsonc-parser does, without a fast path that reads some twice (
80b2607) - tinyjson5/comment-json: read Symbol.for at each comment lookup as comment-json does, and bind only a call whose name and length are data (
8980d5c) - close the fourth review's findings, and find yaml's second document where yaml does (
7332668) - tinyjson5/comment-json: split comment keys with the captured string built-ins, step aside when the global Symbol changes, and keep undefined as a prop (
0623075) - tinyjson5/comment-json: read every built-in from globalThis's descriptors and probe it on private receivers; look up comments by prefix and prop (
44681e4) - tinyjson5/comment-json: check each kept built-in does its own job, not another's of the same name (
883ecc6) - tinyjson5/comment-json: know the engine's own built-ins by name, and read them without running getters (
f20c101) - tinyjson5: typecheck without fetched fixtures, and run CommonJS originals' own tests on Node 22 (
e2eef3a) - tinyjson5/comment-json: take the faster paths only with the engine's own built-ins (
60db330) - tinyjson5/comment-json: read comments without the array and map methods a program can patch (
5721823) - tinyjson5/comment-json: read comments once only while Symbol.for is the native one (
d46968c) - tinyjson5/comment-json: read comments once only on the standard prototype chain (
8b911f2) - tinyjson5: make every write in the ported sloppy-mode functions fail silently as there (
0751ca3) - tinyjson5/comment-json: keep array-timsort's class strict (
a28e031) - tinyjson5/comment-json: write to the array array-timsort sorts as its sloppy-mode code does (
8b41c1d) - tinyjson5/comment-json: write parsed values as sloppy mode does, and drop the comment cache when stringify throws (
0c7b27d) - tinyjson5: assign to primitives as sloppy mode does, and need Node 22.12 (
c32abbf) - tinyjson5: keep comment-json's sloppy-mode writes, and jju's Node assert (
0fcfbcb) - tinyjson5: keep jju's sloppy-mode writes, its option reads and its call types, and declare jsonc-parser's enums as enums (
c8fbd17) - tinyjson5/jsonc-parser: type its enums as enums, and keep its formatter's tables and its scanner's bounds (
f28096b) - tinyjson5: convert the text before setting a call's state, and iterate v1 replacer lists as Babel does (
efdb8c5) - tinyjson5/json5-v1: throw where json5 1.0.2's strict-mode delete throws (
678ab4c) - tinyjson5: make each original's reads, in its order, for hooks, getters and proxies (
7f9c4f3) - tinyjson5: hold every entry to its own original, and check every mode file's exports (
cd81e5f) - tinyini: follow ini's read order, pass toJSON its key, and make every test gate fail on a broken harness (
c17fc21) - tinyini: read options and values as often as ini does, match odd one-ini lengths, and run one-ini's own tests (
b58b90e) - tinyini: measure each entry's default export, isolate old ini versions, and cover every export (
c3fe038) - docs: show the generated drop-in table on the home page, since #11 removed drop-ins.svg (
87d317b) - close the gaps the third review found (
7df325f) - close the gaps the second review found in round one's fixes (
d34dd36) - follow the spec in more corners of the root, and match each original on more options, tags and errors (
c12097e) - tinyjson5: keep a property the reviver can't delete, as json5 does (
3f70b8a) - match js-yaml 4, js-yaml 5, @std/yaml and yaml errors and warnings more closely (
9ea7b62) - match js-yaml 4, js-yaml 5, yaml, yamljs and @std/yaml on more inputs (
6dbcc9c)
💅 Refactors
- tinyswap: rename tinymigrate to tinyswap, since npm blocks tinymigrate as too close to tiny-migrate (#21)
- tinyini: call the typed-array length getter through Reflect.get, not an unbound reference (
1b52b25) - tinyjson5: move the parser and stringifier into a shared core with one build per mode (
51e9e9e) - tinyini: shrink the root so it stays the smallest entry (
1e25df9) - tinyini: move the parser into a shared core with per-mode builds, and add tinyini/ini (
036730d) - shrink every entry with a build mode per library and less duplicated code (
0136e59)
📖 Documentation
- document the tinyswap codemod (#12)
- add bundle sizes to the package overview (#22)
- show typed imports, the linter and Vite Doctor at the top of their sections (#19)
- tinyini: measure the size of parse alone on the M4 (
ac89989) - draw 🤏 as Noto Emoji does, whole and unmirrored in the banners (#17)
- tinyini: measure size, speed and stack depth on the M4, and rewrite the website's pages for the root and subpaths (
11eade0) - one Copy page button with a menu for View as Markdown, ChatGPT, and Claude (#14)
- import swaps in tabs, and plain wording across the website (#16)
- rebrand around the 🤏 emoji: logo, favicons, hero, banners and charts (#13)
- tinyjson5: list the bugs tinyjson5 doesn't copy, and the M4 speed of every operation from scripts/speed-table.ts (
3b9a87b) - measure every drop-in on the M4, count all 18 in the root banner, and say strip-json-comments' time is for stripping (
dfcd37b) - tinyini: list the bugs the originals have and tinyini doesn't, and drop the ini 3–4 Windows line-ending note (
dd0a414) - tinyjson5: introduce the root's differences from json5 2 without saying all follow JSON (
5a595ee) - tinyjson5: say stringify looks for toJSON5 and toJSON on every value but null and undefined, as json5 does (
8449fe2) - tinyjson5: say stringify runs toJSON5, toJSON, the replacer and its BigInt check as JSON.stringify does (
8b8036c) - tinyjson5: say how stringify looks up toJSON5 and toJSON (
7282940) - tinyjson5: a trailing comma ends each object or array written with a member (
2c720de) - tinyjson5: describe the reviver as json5 3 calls it, and when space adds trailing commas (
6db9b2b) - tinyjson5: describe space as it works, and the reviver without describing JSON.parse's context (
f75f50c) - tinyjson5: say any truthy jsonc turns the mode on (
e389c20) - tinyjson5: say the reviver gets no context argument, and quote takes null for its default (
6e660d3) - tinyjson5: align the getting-started option table (
8d3d7bf) - tinyjson5: say bigint takes null as false (
a8fbb90) - tinyjson5: list the fields jju's assertion error keeps off Node (
34ceb7b) - tinyjson5: say require() loads the subpaths, which fuzz options are picked at random, and that throwing stringify calls match by error (
ca0f9e3) - tinyjson5: say which numbers bigint makes BigInts, which comments end at a line break, and that the ports keep their tokenizers (
2659522) - tinyjson5: point the banners at tinyjson5/json5, call strip-json-comments' timings stripping, and count fuzz seeds apart from edits (
fd7ce58) - tinyini: document every subpath, its differences and how it's checked, and add its rows to the drop-in tables (
ddba103) - point json5 users at tinyjson5/json5, and give the tinyjson5 card its measured size and speed (
1f9adb6) - tinyjson5: rewrite the website's pages for the root and subpaths, measure again, and correct the jju test count and the tsconfig's lines (
f054376) - tinyjson5: measure the drop-ins again after the speed and fidelity fixes, and update the size tables (
f0766ed) - tinyjson5: the speed of every operation next to its original, and say substring and fromCharCode are called otherwise in jsonc-parser (
49a8d40) - tinyaml: list the linter pages in the sidebar, and link the rules to the website (
d98f352) - tinyjson5: measure each subpath next to its original, and say where each package was measured (
b08fdcc) - record tinyjson5's root next to its drop-ins, for its size badge (
6b08c26) - give each tinyjson5 subpath a drop-in row, with stringify optional for parse-only libraries (
d2188e1) - restructure the READMEs, and generate their badges and drop-in tables with automd (#11)
- add the tiny website at tiny.onmax.me (#10)
- add a family logo, favicon, banners and one drop-in chart for the root README (#9)
- lead the README with the size, speed and drop-in numbers (
a8aecf9) - add a logo and redraw the banner (
b2f4edc)
📦 Build
- docs: Nuxt 5 nightly, @vite-hub/content, and the Worker config in nuxt.config.ts (
6c65371)
🏡 Chore
- tinyjson5: ship the licenses of the code the subpaths port (
08252c9) - tinyini: benchmark every entry, from the built dist (
fc590f2) - tinyini: add scripts/versions.ts, which fuzzes each ini version against the next (
c4bd92c) - turn the repository into a pnpm workspace for tinyaml, tinyjson5 and tinyini (#8)
- turn the repository into a pnpm workspace for tinyaml, tinyjson5 and tinyini (
17efe0a) - import tinyini into packages/tinyini (
f33e1c8) - import tinyjson5 into packages/tinyjson5 (
c3e4080) - move tinyaml into packages/tinyaml (
8f60c57) - add Pullfrog review through CLIProxy (#5)
✅ Tests
- tinyswap: expect the version range tinyswap writes, not latest (#24)
- tinyaml: compare n with 8n in the scaling tests, with room for a busy CI runner (
c971605) - tinyaml: warm up and take the best of five in the scaling tests (
49f774d) - tinyjson5: fuzz jju's legacy option too, and count the benchmark tsconfig's lines right (
863b9da) - remove redundant proof and strengthen test guards (#7)
🤖 CI
- install without git hooks, so the packages' vp config prepare scripts don't race for .git/config (
15ea32e) - publish a preview package for every commit on main (
7381331)
🎉 New Contributors
- Max (@onmax)
❤️ Contributors
- Max (@onmax)

