npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

formatarc

v0.4.0

Published

Convert JSON, YAML, CSV, Markdown, HTML, and PDF from the terminal, and check Qiita / Zenn article compatibility. Browser-based version at formatarc.com.

Downloads

245

Readme

formatarc

Convert JSON, YAML, CSV, Markdown, HTML, and PDF from the terminal, and check whether a Qiita or Zenn article survives the move to the other platform — your data never leaves your machine. No config, no telemetry, no upload.

npm version license: MIT npm downloads

Web version → formatarc.com — the same conversions, 100% in your browser, no signup.

Why formatarc?

Most "online JSON / YAML / CSV converters" send the data you paste to a server. In November 2025, security firm watchTowr disclosed that two popular formatter sites (jsonformatter.org and codebeautify.org) had publicly exposed over 80,000 saved submissions (5 GB+) through a predictable "Recent Links" URL — including Active Directory credentials, cloud access keys, private keys, CI/CD secrets, JWTs, and full AWS Secrets Manager exports from government, banking, healthcare, and aerospace organizations. (watchTowr report)

formatarc is built so that can't happen. The CLI runs entirely on your machine, and the web version runs entirely in your browser — no upload, no logging, no telemetry, no account.

It is not only paste-to-a-server sites, either: in early 2026, a widely used JSON formatter browser extension was reported (on Hacker News and dev.to) to add third-party tracking and checkout-page injection after moving to a closed-source model — a reminder that an installed extension can change behaviour through an automatic update. Background on both risks: are online converters safe? and picking a JSON formatter Chrome extension by privacy and permissions.

| | formatarc CLI | formatarc web | Typical online converter | jq / yq / pandoc | |---|:---:|:---:|:---:|:---:| | Data stays local | ✅ | ✅ | ❌ | ✅ | | No signup / no upload | ✅ | ✅ | ⚠️ | ✅ | | JSON + YAML + CSV + Markdown + HTML in one tool | ✅ | ✅ | ⚠️ | ❌ | | Works offline | ✅ | after first load | ❌ | ✅ | | Single install | ✅ | n/a | n/a | ❌ |

JSON formatter comparison: privacy and breach history

A field-by-field comparison of the most common ways to format JSON in 2026. Sources for the breach column are linked below — paste-to-a-server sites have a verifiable incident history that local CLIs and browser-side tools structurally cannot.

| Tool | Type | Data stays local | Open source | Multi-format | Public breach (2024–2026) | |---|---|:---:|:---:|---|---| | formatarc (CLI) | CLI / npm | ✅ | ✅ MIT | JSON, YAML, CSV, Markdown, HTML | n/a — no server, no storage | | formatarc.com | Web (browser-side) | ✅ | ✅ MIT | JSON, YAML, CSV, Markdown, HTML | n/a — no server, no storage | | jsonformatter.org | Web (paste-to-server) | ❌ pasted JSON sent to server | ❌ | JSON-focused | ⚠️ Nov 2025 — 80,000+ saved submissions (5 GB+) exposed via predictable "Recent Links" URL (watchTowr) | | codebeautify.org | Web (paste-to-server) | ❌ pasted data sent to server | ❌ | multi-format | ⚠️ Nov 2025 — same watchTowr disclosure | | jsonlint.com | Web (paste-to-server) | ❌ pasted JSON sent to server | ❌ | JSON only | no public incident known to date | | jq | CLI | ✅ runs locally | ✅ MIT | JSON only | n/a | | prettier | CLI / npm | ✅ runs locally | ✅ MIT | code formatter (JSON, JS, TS, etc.) | n/a |

The takeaway is mechanical: if a tool sends your data to a third-party server, the breach surface is non-zero regardless of intent. CLIs and browser-side tools have no such surface to leak.

Install

npm install -g formatarc

Or run directly with npx:

npx formatarc json-format '{"a":1}'

Usage

formatarc <tool> [input or file]
cat file | formatarc <tool>

Tools

| Command | Description | |---------|-------------| | json-format | Pretty-print JSON | | yaml-to-json | Convert YAML to JSON | | json-to-yaml | Convert JSON to YAML | | csv-to-json | Convert CSV (with header row) to JSON | | json-to-csv | Convert JSON objects to CSV (nested keys are flattened) | | csv-to-markdown | Convert CSV to a Markdown (GFM) table | | markdown-to-csv | Convert Markdown (GFM) tables to CSV | | markdown-to-html | Convert Markdown to HTML | | html-to-markdown | Convert HTML to Markdown | | pdf-to-markdown | Extract the text of a PDF as Markdown | | qiita-to-zenn | Check a Qiita article for Zenn compatibility | | zenn-to-qiita | Check a Zenn article for Qiita compatibility |

About pdf-to-markdown

PDF is the one tool here that reads a file rather than text, and the one with real limits. They are worth knowing before you pipe it into anything:

  • Works on PDFs that contain text. A scanned PDF stores each page as an image with no text layer, so it cannot be converted. The command says so and exits non-zero instead of guessing.
  • Tables can come out misaligned. Most PDFs do not store a table as a table — the structure has to be inferred from lines and text positions. When a PDF contains tables, the command prints a note on stderr. Check the result against the original.
  • Formulas are not supported.
  • When the text layer cannot be read reliably (some CJK CFF fonts, where the extractor mistakes Adobe-Japan1 CIDs for Unicode codepoints), it falls back to plain text extraction and tells you on stderr. Headings and tables are not generated in that case.

Notes go to stderr, so formatarc pdf-to-markdown in.pdf > out.md still gives you clean Markdown.

About qiita-to-zenn / zenn-to-qiita

These two do not convert an article and hand it back as done. They report every syntax difference and convert only the ones that convert without losing meaning, because most of them do not: of the 74 differences in the rule table, 37 convert deterministically, 14 need a decision only the author can make, and 23 have no counterpart at all. The table was compiled by surveying both platforms on 2026-08-04 and is shared with the web version, which lists the same counts: formatarc.com/en/qiita-zenn-compat.

The trap worth naming: Zenn renders Markdown with html: false, so raw HTML that Qiita accepts — <details>, <img width>, <dl> — reaches the reader as escaped tags. Nothing throws. The article just looks broken after it is published. 21 rules are that shape, which is why the report exists at all.

The converted Markdown goes to stdout and the report to stderr, so formatarc qiita-to-zenn article.md > converted.md gives you a clean article and leaves the report on screen.

Examples

Format JSON:

formatarc json-format '{"name":"FormatArc","tools":["json","yaml","csv"]}'
{
  "name": "FormatArc",
  "tools": [
    "json",
    "yaml",
    "csv"
  ]
}

Convert a YAML file to JSON:

formatarc yaml-to-json config.yaml

Pipe from curl:

curl -s https://api.example.com/data | formatarc json-format

Convert CSV from stdin:

cat users.csv | formatarc csv-to-json

Convert JSON to CSV (nested objects become dotted column names):

cat users.json | formatarc json-to-csv

Convert CSV to a Markdown table:

cat users.csv | formatarc csv-to-markdown

Pull the tables out of a Markdown document as CSV:

cat report.md | formatarc markdown-to-csv

Render Markdown as HTML:

cat README.md | formatarc markdown-to-html > README.html

Strip HTML to Markdown (handy for piping web pages into LLMs):

curl -s https://example.com | formatarc html-to-markdown

Extract the text of a PDF as Markdown:

formatarc pdf-to-markdown report.pdf
formatarc pdf-to-markdown report.pdf > report.md
cat report.pdf | formatarc pdf-to-markdown

Check a Qiita article before moving it to Zenn:

formatarc qiita-to-zenn article.md > zenn-draft.md

Validate data in CI and git hooks

Every command exits 0 on success and 1 on failure, writing the result to stdout and any error to stderr. Errors are line-numbered, so a broken file points you straight at the problem instead of a cryptic parser dump:

$ echo '{"a":1,}' | formatarc json-format
Invalid JSON: remove the trailing comma on line 1.
$ echo $?
1

That makes it a drop-in validator for pipelines and pre-commit hooks — and, like everything else here, the data never leaves the runner.

Fail a GitHub Actions build on malformed JSON or YAML:

- name: Validate config files
  run: |
    npx formatarc json-format config.json > /dev/null
    npx formatarc yaml-to-json .github/settings.yaml > /dev/null

Gate a cross-posting pipeline on article compatibility. qiita-to-zenn and zenn-to-qiita exit 1 when the article carries anything that breaks silently, needs a decision, or has no counterpart on the other platform, and 0 when every difference converted losslessly:

- name: Check the article survives the move to Zenn
  run: npx formatarc qiita-to-zenn public/my-article.md > /dev/null

Block a commit that stages invalid JSON (.git/hooks/pre-commit):

#!/bin/sh
for f in $(git diff --cached --name-only --diff-filter=ACM | grep '\.json$'); do
  npx formatarc json-format "$f" > /dev/null || { echo "Invalid JSON in $f"; exit 1; }
done

Programmatic API

import { convert } from "formatarc";

const result = convert("json-format", '{"a":1}');
console.log(result.output);
// {
//   "a": 1
// }

convert(tool, input)

Returns { output: string, error: string }.

  • output — the converted result (empty string on error)
  • error — error message (empty string on success)

convertPdf(bytes)

PDF input is binary, so it does not go through convert(). Returns a promise.

It ships from formatarc/pdf rather than the package root: the implementation imports node:fs and friends, and re-exporting it from the root broke bundlers targeting the browser (the Chrome extension builds from this same package).

import { convertPdf, type PdfResult, type PdfRoute } from "formatarc/pdf";
import { readFileSync } from "node:fs";

const result = await convertPdf(new Uint8Array(readFileSync("report.pdf")));
if (result.error) throw new Error(result.error);
if (result.route === "refused") {
  // scanned PDF — no text layer, OCR would be required
}
console.log(result.markdown);
  • route — "inspector" (normal), "fallback" (text-only, the text layer was unreliable), or "refused" (scanned PDF, nothing was converted)
  • hasTables — the PDF contains tables, so the result needs checking
  • pageCount, ocrPages, pdfType, error

analyzeQiitaZenn(input, direction, locale)

Ships from formatarc/qiita-zenn — it carries the rule table, which the string conversions have no reason to load.

import { analyzeQiitaZenn } from "formatarc/qiita-zenn";

const result = analyzeQiitaZenn(markdown, "qiita-to-zenn", "en");
console.log(result.output);   // the converted article
console.log(result.findings); // every difference, with line numbers
console.log(result.counts);   // { total, breaksSilently, deterministic, lossy, unsupported }
  • direction — "qiita-to-zenn" or "zenn-to-qiita"
  • locale — "en" or "ja"; picks the language of the findings
  • a fourth argument takes the author's decisions ({ [ruleId]: optionValue }). Without it, differences that need a decision are reported but left unconverted

Web Version

For a browser-based experience with no signup and no data upload:

formatarc.com

  • JSON Formatter, YAML ↔ JSON, CSV ↔ JSON
  • CSV ↔ Markdown, Markdown ↔ HTML, PDF → Markdown
  • Qiita / Zenn compatibility check
  • Runs entirely in the browser
  • Multilingual (English, Japanese, Spanish, Portuguese, Korean, Chinese)

There is also a Chrome extension for popup and right-click conversion — same browser-side processing, no upload.

Related projects by the same author

The CLI shares conversion logic and design goals with two sister projects, all under the same "data never leaves your machine" promise:

Companion reads on the privacy axis:

License

MIT