Skip to content
nguyenkduyworkPublic

About

No description, website, or topics provided.

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

omnitool

CI License: MIT Node TypeScript

Everyday file tools — merge PDFs, convert and resize images, zip, hash, compare two versions of a file, and reformat data — that run entirely inside your browser tab.

No file you open ever leaves your device. There is no server. Every operation runs in a Web Worker on your own machine, and the app makes no network calls at runtime: no uploads, no analytics, no telemetry, no CDN fetches. Open your browser's network tab and it stays empty. Disconnect from the internet after the page loads and every tool keeps working.

Use it online

https://nguyenkduywork.github.io/omnitool/

Nothing to install and nothing to sign up for. Open the page and drop a file on it.

  • Install it as an app. A service worker precaches the app shell, so your browser will offer to install omnitool from the address bar. Once installed it runs in its own window and works offline.
  • It works offline after the first visit. Tool code is cached the first time you use each tool; a reload with the network off keeps working.
  • Every tool has its own address. …/#/pdf-merge is bookmarkable and shareable, and the back button moves between a tool and the catalogue. Files are never in the URL, so a link you share opens the tool empty — it can never carry your data.

Using it

Two ways in, both first-class:

  • Drop files first. Drag them anywhere in the window, paste with Ctrl/Cmd+V, or use Choose files. The tool list narrows to what can actually run on them.
  • Pick a tool first. Choose from the catalogue and bring the files after — the tool tells you what it needs rather than refusing. Tools that need no files at all, like the QR code generator, just open and run.

Ctrl/Cmd+K searches the tools. The file tray is reorderable, which matters for merging — drag a row, use its arrow buttons, or focus a row and press the arrow keys. With several files loaded, Arrange files sorts naturally by name (2 before 10), sorts by size, or reverses the order. Undo restores the last ordering change, including a drag or keyboard move. Adding or removing files clears that order snapshot.

Removing a file or choosing Remove all files shows a separate Undo notice in the file tray. It restores the most recent removal, with the original files and order. There is no timer; adding, removing, reordering, or replacing files again clears that snapshot, as does dismissing the notice or reloading. Undo is paused while a tool runs. Only the files are restored; custom editor changes and cleared results are not recovered.

Search understands common task names such as compress PDF, combine PDF, and unzip. Resize shows only the controls for the selected mode, with guidance on preserving proportions. Resize also shows each image's original and output dimensions before running. Quick presets halve both dimensions or fit the longest edge to 1080 or 1920 pixels. Don’t enlarge smaller images caps each dimension at its original size; files that need no size change are returned byte for byte. Dimension previews are read once per file and shown in groups of 20 for large batches. Gzip, TAR, JSON formatting and contact-sheet options also hide controls that do not apply to the current mode, keeping your values when you switch back.

Settings you edit in standard option panels are remembered while this tab stays open. Reset restores the tool's defaults for the current files; reloading starts fresh. File-derived defaults remain automatic until you edit them. Visual editors keep their own file-specific state.

After a run, choose Use this result… or Use all results… to open the output in another compatible file tool. Review its settings before running. This replaces the tray without changing files on disk; Undo restores the previous tray and order. Undo holds one handoff and is cleared when you add, remove, or reorder files or dismiss the notice. Compare text owns its sources separately and is not a handoff destination.

Click an image result to open a larger preview with pixel dimensions, Fit or percentage zoom, and previous/next navigation. Download from the viewer or press Esc to return to the result card. When converting a transparent image to JPEG, choose a white (default) or black background; PNG and WebP keep their transparency.

Fully keyboard operable, with visible focus rings, aria-live announcements, and WCAG AA contrast in both light and dark themes — covered by tests, not just intent.

The tools

PDF

Tool What it does
Merge PDFs Combine several PDFs into one, in file-tray order
Split PDF One file per page, or by page range (1-3,7,9-)
Organize pages Reorder, rotate, and delete pages on a visual page board
Shrink PDF Re-encodes images inside the PDF; reports real before/after bytes
PDF to images Rasterise every page to PNG or JPEG at a chosen DPI
Images to PDF One image per page, in file-tray order
Clean PDF metadata Strip the author, dates, and XMP a PDF carries — without touching a page
Extract images Pull the pictures embedded in a PDF back out as image files

Images

Tool What it does
Convert image PNG, JPEG, WebP, or AVIF (see Limitations)
Resize image By exact dimensions or by percentage, with optional aspect lock
Compress image Re-encode at a lower quality, same format
Crop image Draw a crop box on a visual editor, in the image's own pixels
Rotate image Turn in 90° steps, mirror left-to-right or top-to-bottom, with a live preview
Strip metadata Remove EXIF, GPS, XMP and comments — without re-encoding
Merge into a sheet Arrange several images into one contact sheet
Watermark image Stamp a line of text over an image, in a corner or tiled diagonally

Data & text

Tool What it does
Create ZIP Bundle the dropped files into one archive
Extract ZIP Unpack every file from a ZIP archive
Create TAR Bundle into one .tar, or a gzipped .tar.gz
Extract TAR Unpack a .tar or .tar.gz, long names and pax included
Gzip Compress to .gz, or decompress one back to bytes
Split file Cut any file into fixed-size .partNNN pieces
Join file parts Put the pieces back together, checking the sequence
Hash files SHA-256, SHA-1, SHA-512, or MD5
Base64 Encode files to Base64 text, or decode back to bytes
CSV ⇄ JSON Convert between CSV and JSON, with quoted-field and CRLF handling
Format JSON Pretty-print or minify
Generate QR code Turn text or a URL into a QR code, PNG or SVG
Clean up text Sort, deduplicate, trim, and normalise the lines of a text file
Compare text Show what changed between two versions of a text or code file, down to the word — from two files, or from text you paste

Run it locally

Prerequisites: Node.js 20 or newer, and npm. Nothing else — no database, no API keys, no environment configuration.

git clone https://github.com/nguyenkduywork/omnitool.git
cd omnitool
npm install
npm run dev

Then open the URL it prints (http://localhost:5173 by default).

To check a production build instead:

npm run build
npm run preview

Commands

Command What it does
npm run dev Start the dev server with hot reload
npm run build Production build to dist/
npm run preview Serve the production build locally
npm run typecheck tsc --noEmit, strict mode
npm run lint ESLint, including the import-boundary rules
npm test Unit tests — Node plus headless Chromium
npm run test:e2e Playwright, against a real production build
npm run contrast Check every colour pairing against WCAG AA, both themes
npm run size Verify the initial-load size budget
npm run bench Re-run the performance measurements
npm run make-fixtures Regenerate the binary test fixtures

Before opening a pull request, run the same gate CI runs:

npm run typecheck && npm run lint && npm test && npm run build && npm run size && npm run test:e2e

Playwright needs its browsers once: npx playwright install --with-deps chromium. If another local app uses port 4173, set OMNITOOL_TEST_PORT to a free port before running the end-to-end checks.

Requirements

A current version of Chrome, Edge, Firefox, or Safari. omnitool uses standard evergreen browser APIs — Web Workers, OffscreenCanvas, createImageBitmap, and a service worker — with no browser-specific code paths. CI runs the full suite against headless Chromium on every change, so that combination is the most exhaustively verified.

Limitations

Behaviour worth knowing before you rely on it. See docs/known-issues.md for open engineering items.

  • AVIF export does not work in any browser today. Canvas silently returns a PNG when asked for AVIF, so omnitool probes the real encoder at startup and disables the option with the reason shown, rather than handing you PNG bytes named .avif.

  • Shrink PDF re-encodes images, and only some of them. It targets 8-bit RGB and grayscale JPEG images inside the PDF. JPEG 2000, CCITT, JBIG2, CMYK and stencil masks are left alone, so a PDF dominated by fonts or vectors will barely move. It never claims a reduction it did not achieve — if the result would be larger, you get the original back.

  • Resize, Compress, Crop, Rotate and Watermark re-encode the image. A quarter turn costs a little quality, and the quality slider is what it costs; PNG output ignores it because PNG is lossless. Formats the browser can decode but not encode — GIF, BMP, TIFF, SVG — come back as PNG, and the filename changes with them. Resize keeps the original file when Don’t enlarge smaller images is on and no dimension changes, including any metadata and animation that file already contains.

  • Strip metadata covers JPEG, PNG and WebP only. Those are the containers whose metadata can be cut without touching a pixel. Anything else is refused by name rather than quietly re-encoded. The ICC colour profile is kept unless you ask for it too.

  • Clean PDF metadata is not redaction. It empties the document's Info dictionary and purges XMP, then sweeps what it unlinked. It does not touch page content: text, images and their EXIF, annotations, form values, attachments and bookmarks all survive. A PDF with your name printed on page one still has your name on page one.

  • A watermark is a label, not a lock. It paints text into the pixels, so it can be cropped off or painted over. It marks provenance, it does not protect anything.

  • Compare text owns two independent sources. Paste text, open a UTF-8 file, or explicitly choose empty text on either side. Inputs sit side by side on wide screens and use source tabs on phones. Review supports automatic, split, and unified layouts; line, word, and grapheme detail; wrapping; literal Find; change navigation; and expandable context. Swap, Clear, and Undo retain source state while the tab stays open. Sources stay in memory and are never uploaded or saved as drafts.

  • Comparison has explicit limits and fallbacks. Up to 10 MiB of decoded UTF-8 and 200,000 display lines combined are supported. Background workers compute the comparison; bounded pages let you reach every change. Larger sources require Compare now. File sources over 250,000 UTF-16 units or 5,000 line terminators start with a bounded preview; full native editing is an explicit action that can pause the browser. Editing CRLF or CR files normalizes endings to LF, with a warning before editing. Untouched sources retain their original endings and BOM. Detail falls back to line highlighting above 2,000 characters per line. Moved blocks appear as deletion and insertion; unrelated files can produce a disclosed wholesale replacement.

  • Review rules and exact patches serve different purposes. Ignore whitespace trims lines and collapses spaces/tabs; Ignore case affects the review. Ending and BOM differences remain explicit metadata. Reports and copied summaries follow the selected scope, context, detail, and rules. Exact patches retain raw BOM and line-ending bytes, including differences hidden by review rules. Reports, summaries, and patches are capped at 32 MiB. The tool never writes either source file back. See the reproducible Text Diff benchmarks for measured performance and coverage.

  • Clean up text sorts in code-unit order, not your locale's — uppercase before lowercase, digits before letters, like sort under LC_ALL=C. It reads UTF-8 only.

  • Extract images gets the pictures out, not every picture. JPEG streams come out byte for byte and raw pixels are wrapped losslessly in PNG. JPEG 2000, fax formats, indexed palettes, stencil masks and predictor-encoded data are skipped and named in the report with the reason.

  • A batch with one bad file costs a re-run. An op can only signal failure by throwing, so the worker drops the bad input and re-runs on what is left in order to report the good outputs honestly. Cost is roughly (bad files + 1) × the work.

Deployment

CI runs on every push and pull request: typecheck, lint, colour contrast, unit and browser tests, production build, size budget, and the full end-to-end suite.

Publishing to GitHub Pages happens automatically once CI passes on main — deliberately gated on CI rather than on the push itself, so a commit CI is about to fail never reaches the live site. You can also re-deploy the current main by hand from Actions → Deploy → Run workflow. vite.config.ts sets base: './', so the build is host-agnostic and Pages serves dist/ as-is.

Contributing

See CONTRIBUTING.md for the import-boundary rules, the per-tool test requirements, the size budget, and how performance claims are measured.

License

MIT — see LICENSE.

About

No description, website, or topics provided.

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages