{"_id":"@charles_lindecker/img-convertor","_rev":"2-03bf7b9a602888a8c70aab60c51521ed","name":"@charles_lindecker/img-convertor","dist-tags":{"latest":"1.0.1"},"versions":{"1.0.0":{"name":"@charles_lindecker/img-convertor","version":"1.0.0","keywords":["image","converter","resize","webp","breakpoints","cli","sharp","responsive"],"author":{"name":"Charles Lindecker","email":"charles.lindecker@outlook.fr"},"license":"MIT","_id":"@charles_lindecker/img-convertor@1.0.0","maintainers":[{"name":"charles_lindecker","email":"charles.lindecker@outlook.fr"}],"homepage":"https://github.com/LINDECKER-Charles/Web-Image-Formateur#readme","bugs":{"url":"https://github.com/LINDECKER-Charles/Web-Image-Formateur/issues"},"bin":{"img-convertor":"bin/img-convertor.js"},"dist":{"shasum":"b1135fcfa55653b67358e27589665373009da798","tarball":"https://registry.npmjs.org/@charles_lindecker/img-convertor/-/img-convertor-1.0.0.tgz","fileCount":80,"integrity":"sha512-Hxjdf7O97TXFFuXGYknpIrtWQnTWDKnQ5sjNg4r6pc61+JQenxlh8eGyreRdhCl3cHx4+XiLto2XUtmQeM1VIw==","signatures":[{"sig":"MEUCIE+m+1xzy+isT/kE16MFh/l9yARDNBonCaUlAwv+qz8oAiEA5Ci/4AiGW+N51PlurAchobAJIF2Ye63/RMX1yyOmZ9M=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":135670},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=18.17"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"81824faedd4f579f5597be2c19b847bf2a811b09","scripts":{"ci":"npm run typecheck && npm run test && npm run build","dev":"node --loader tsx/esm src/cli/index.ts","test":"vitest run","build":"tsc -p tsconfig.json","clean":"node -e \"import('node:fs').then(fs=>fs.rmSync('dist',{recursive:true,force:true}))\"","start":"node bin/img-convertor.js","prebuild":"npm run clean","typecheck":"tsc --noEmit","test:watch":"vitest","test:coverage":"vitest run --coverage","prepublishOnly":"npm run build"},"_npmUser":{"name":"charles_lindecker","email":"charles.lindecker@outlook.fr"},"repository":{"url":"git+https://github.com/LINDECKER-Charles/Web-Image-Formateur.git","type":"git"},"_npmVersion":"11.7.0","description":"Fast image converter and responsive breakpoint resizer with an interactive console and a professional CLI.","directories":{},"_nodeVersion":"22.16.0","dependencies":{"sharp":"^0.33.5","commander":"^12.1.0","picocolors":"^1.1.1","@inquirer/prompts":"^7.2.0"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.19.2","vitest":"^2.1.8","typescript":"^5.7.2","@types/node":"^22.10.0","@vitest/coverage-v8":"^2.1.8"},"_npmOperationalInternal":{"tmp":"tmp/img-convertor_1.0.0_1776722096207_0.86144689883353","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@charles_lindecker/img-convertor","version":"1.0.1","description":"Fast image converter and responsive breakpoint resizer with an interactive console and a professional CLI.","author":{"name":"Charles Lindecker","email":"charles.lindecker@outlook.fr"},"license":"MIT","type":"module","engines":{"node":">=18.17"},"main":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"bin":{"img-convertor":"bin/img-convertor.js"},"scripts":{"build":"tsc -p tsconfig.json","clean":"node -e \"import('node:fs').then(fs=>fs.rmSync('dist',{recursive:true,force:true}))\"","prebuild":"npm run clean","dev":"node --loader tsx/esm src/cli/index.ts","start":"node bin/img-convertor.js","prepublishOnly":"npm run build","typecheck":"tsc --noEmit","test":"vitest run","test:watch":"vitest","test:coverage":"vitest run --coverage","ci":"npm run typecheck && npm run test && npm run build"},"keywords":["image","converter","resize","webp","breakpoints","cli","sharp","responsive"],"dependencies":{"@inquirer/prompts":"^7.2.0","commander":"^12.1.0","picocolors":"^1.1.1","sharp":"^0.33.5"},"devDependencies":{"@types/node":"^22.10.0","@vitest/coverage-v8":"^2.1.8","tsx":"^4.19.2","typescript":"^5.7.2","vitest":"^2.1.8"},"repository":{"type":"git","url":"git+https://github.com/LINDECKER-Charles/Web-Image-Formateur.git"},"gitHead":"6b44711be6b8091c12100c51bd12e93f863fb927","_id":"@charles_lindecker/img-convertor@1.0.1","bugs":{"url":"https://github.com/LINDECKER-Charles/Web-Image-Formateur/issues"},"homepage":"https://github.com/LINDECKER-Charles/Web-Image-Formateur#readme","_nodeVersion":"22.16.0","_npmVersion":"11.7.0","dist":{"integrity":"sha512-/9Sza1Ri2gGg3+Du8pkjvIkzFxJAfvC6SuZMD5CH8qJS8/xm1EOUMHpoIp5jYjN9irUpeGcXeN7g5MTitJvESQ==","shasum":"770496b8af3e68b35c88e7a4125010c9ed2c347a","tarball":"https://registry.npmjs.org/@charles_lindecker/img-convertor/-/img-convertor-1.0.1.tgz","fileCount":80,"unpackedSize":140284,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQD456TKEa+S+tpmZ1eaORs57vrGgFC0IXd+Sz5eAn+MfgIgUfd82Lve7lZ37hFnhRT6GXrnfGWYQhRHDYUbmEO4aoc="}]},"_npmUser":{"name":"charles_lindecker","email":"charles.lindecker@outlook.fr"},"directories":{},"maintainers":[{"name":"charles_lindecker","email":"charles.lindecker@outlook.fr"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/img-convertor_1.0.1_1776726342647_0.013111506809737605"},"_hasShrinkwrap":false}},"time":{"created":"2026-04-20T21:54:56.106Z","modified":"2026-04-20T23:05:42.896Z","1.0.0":"2026-04-20T21:54:56.352Z","1.0.1":"2026-04-20T23:05:42.793Z"},"bugs":{"url":"https://github.com/LINDECKER-Charles/Web-Image-Formateur/issues"},"author":{"name":"Charles Lindecker","email":"charles.lindecker@outlook.fr"},"license":"MIT","homepage":"https://github.com/LINDECKER-Charles/Web-Image-Formateur#readme","keywords":["image","converter","resize","webp","breakpoints","cli","sharp","responsive"],"repository":{"type":"git","url":"git+https://github.com/LINDECKER-Charles/Web-Image-Formateur.git"},"description":"Fast image converter and responsive breakpoint resizer with an interactive console and a professional CLI.","maintainers":[{"name":"charles_lindecker","email":"charles.lindecker@outlook.fr"}],"readme":"# img-convertor\n\n[![CI](https://img.shields.io/github/actions/workflow/status/LINDECKER-Charles/Web-Image-Formateur/ci.yml?branch=main&label=CI&logo=github)](https://github.com/LINDECKER-Charles/Web-Image-Formateur/actions/workflows/ci.yml)\n[![tests](https://img.shields.io/badge/tests-80%20passed-brightgreen?logo=vitest&logoColor=white)](#testing)\n[![coverage](https://img.shields.io/badge/coverage-100%25-brightgreen?logo=vitest&logoColor=white)](#testing)\n[![node](https://img.shields.io/badge/node-%E2%89%A518.17-brightgreen?logo=node.js&logoColor=white)](https://nodejs.org/)\n[![npm version](https://img.shields.io/npm/v/@charles_lindecker/img-convertor.svg?logo=npm)](https://www.npmjs.com/package/@charles_lindecker/img-convertor)\n[![license](https://img.shields.io/badge/license-MIT-blue)](./LICENSE)\n\nA fast image converter and responsive breakpoint resizer for the web.\nShips with a polished **CLI** *and* an **interactive console** — pick your flow.\n\n```bash\nnpm i -g @charles_lindecker/img-convertor\nimg-convertor res-conv --input ./assets -r --format webp --quality 80\n```\n\n---\n\n## Quick start\n\n```bash\n# 1. Install globally\nnpm i -g @charles_lindecker/img-convertor\n\n# 2. Convert every image in the current folder to WEBP (recursive)\nimg-convertor convert -r --format webp\n\n# 3. Or launch the guided interactive console\nimg-convertor\n```\n\nThat's it. `img-convertor` writes the outputs next to each source file.\n\n---\n\n## Install\n\n> Requires **Node.js ≥ 18.17**.\n\n```bash\n# Global CLI (recommended for day-to-day use)\nnpm i -g @charles_lindecker/img-convertor\n\n# Or as a project dev-dependency\nnpm i -D @charles_lindecker/img-convertor\n\n# Ad-hoc with npx (no install)\nnpx img-convertor --help\n```\n\n---\n\n## Usage\n\nThe CLI exposes three commands plus a `config` command for persistent defaults.\nRun **without arguments** at any time to open the interactive console.\n\n```text\nimg-convertor <command> [options]\n\nCommands\n  convert      Convert images to another format.\n  resize       Generate responsive breakpoint variants.\n  res-conv     Resize + re-encode in a single pass.\n  config       Inspect or update persistent defaults.\n  interactive  Open the interactive console.\n```\n\n### 1. Convert — change image format\n\nRe-encodes every source image into a target format, preserving dimensions.\n\n```bash\n# Convert a single file to WEBP\nimg-convertor convert --input ./hero.png --format webp --quality 85\n\n# Convert the whole ./assets tree to AVIF\nimg-convertor convert --input ./assets -r --format avif --quality 70\n\n# Same but implicit input = current directory\nimg-convertor convert -r --format webp\n```\n\nOutput is written next to the source: `hero.png` → `hero.webp`.\n\n### 2. Resize — generate responsive breakpoints\n\nProduces one variant per breakpoint, skipping any breakpoint larger than the\nsource width (no upscaling). Aspect ratio is preserved.\n\n```bash\n# Default breakpoints\nimg-convertor resize --input ./hero.png\n\n# Custom breakpoints\nimg-convertor resize --input ./hero.png --breakpoint 320,640,1024,1920\n\n# Whole directory, recursively\nimg-convertor resize --input ./assets -r --breakpoint 480,960,1440\n```\n\nFile naming: `hero.png` → `320x180_hero.png`, `640x360_hero.png`, …\n\n### 3. Res-conv — resize *and* convert in one pass\n\nThe combo workflow: resize to each breakpoint **and** re-encode into the\ntarget format. This is the command you want for shipping web assets.\n\n```bash\nimg-convertor res-conv \\\n  --input ./assets -r \\\n  --format webp \\\n  --breakpoint 320,640,1024,1920 \\\n  --quality 80\n```\n\nOutput: `320x180_hero.webp`, `640x360_hero.webp`, …\n\n### 4. Interactive mode\n\nNo flags? Just run the binary:\n\n```bash\nimg-convertor\n```\n\nA guided console walks you through command selection, input path, breakpoints,\nformat, and quality — with your saved defaults pre-filled.\n\n### 5. Persistent defaults — the `config` command\n\nInstead of retyping `--quality`, `--breakpoint`, or `--format` on every run,\npersist your preferred defaults. They are used as fallbacks when a flag is\nomitted; explicit flags always win.\n\n```bash\nimg-convertor config set quality 80\nimg-convertor config set format avif\n\nimg-convertor config list      # show current values + source (user/default)\nimg-convertor config get quality\nimg-convertor config unset quality\nimg-convertor config reset     # wipe the whole config file\nimg-convertor config path      # print the config file path\n```\n\n### 6. Breakpoint presets — `config preset`\n\nKeep several named breakpoint lists and switch between them without retyping.\n\n```bash\nimg-convertor config preset add mobile  \"320,640\"\nimg-convertor config preset add retina  \"480,960,1440\"\nimg-convertor config preset add print   \"1200,2400,3600\"\n\nimg-convertor config preset list        # all presets, the default is highlighted\nimg-convertor config preset use retina  # mark \"retina\" as the default\nimg-convertor config preset clear-default\nimg-convertor config preset remove mobile\n```\n\nOnce a preset is marked as default, every `resize` / `res-conv` invocation\nuses it when `--breakpoint` is omitted. `config list` shows the active preset\nnext to the resolved breakpoint list.\n\n**Save on the fly.** In the interactive console, if you type a custom list of\nbreakpoints during an operation, you're offered to save it as a preset and\noptionally make it the new default — so you only ever type a list once.\n\n**Manage interactively.** The interactive main menu has a `Settings` entry\nthat lists, adds, removes, and selects presets without leaving the console.\n\nThe config file lives at `~/.img-convertor/config.json` (cross-platform).\nSet `IMG_CONVERTOR_CONFIG_DIR` to relocate it (useful for CI, sandboxed runs,\nor non-standard home directories).\n\n---\n\n## CLI reference\n\n### Common options\n\n| Flag                   | Default                     | Description                                                   |\n| ---------------------- | --------------------------- | ------------------------------------------------------------- |\n| `--input <path>`       | current working directory   | File or directory to process.                                 |\n| `-r, --recursive`      | `false`                     | Recurse into subdirectories (directory input only).           |\n| `--format <fmt>`       | `webp`                      | `webp` \\| `jpeg` \\| `jpg` \\| `png` \\| `avif`.                 |\n| `--quality <0-100>`    | `85`                        | Encoder quality.                                              |\n| `--breakpoint <list>`  | built-in defaults           | Comma-separated widths, e.g. `320,640,1024`.                  |\n\nDefault breakpoints: `24, 40, 80, 160, 320, 640, 768, 1024, 1280, 1536`.\n\n### Applies-to matrix\n\n| Flag           | `convert` | `resize` | `res-conv` |\n| -------------- | :-------: | :------: | :--------: |\n| `--input`      |     ✓     |    ✓     |     ✓      |\n| `-r`           |     ✓     |    ✓     |     ✓      |\n| `--format`     |     ✓     |    —     |     ✓      |\n| `--quality`    |     ✓     |    ✓     |     ✓      |\n| `--breakpoint` |     —     |    ✓     |     ✓      |\n\n---\n\n## Programmatic API\n\nEverything the CLI does is exposed as plain functions — useful for build\nscripts, asset pipelines, or hooking into your own tooling.\n\n```ts\nimport {\n  discoverImages,\n  runConvert,\n  runResize,\n  runResizeConvert,\n  resolveDefaults,\n  saveSettings,\n} from '@charles_lindecker/img-convertor';\n\nconst files = await discoverImages({ input: './assets', recursive: true });\n\nawait runResizeConvert({\n  files,\n  format: 'webp',\n  breakpoints: [320, 640, 1024, 1920],\n  quality: 80,\n  onProgress: (r) => console.log(r.source, '→', r.outputs.length, 'variants'),\n});\n```\n\nSee [`src/index.ts`](./src/index.ts) for the full public surface.\n\n---\n\n## Project structure\n\n```\n.\n├── bin/\n│   └── img-convertor.js       # CLI shim (shebang) → dist/cli/index.js\n├── src/\n│   ├── cli/\n│   │   ├── index.ts           # commander program builder + entrypoint\n│   │   ├── options.ts         # shared option definitions (user-default aware)\n│   │   ├── helpers.ts         # input resolution + TTY confirmation\n│   │   └── commands/\n│   │       ├── convert.ts\n│   │       ├── resize.ts\n│   │       ├── res-conv.ts\n│   │       └── config.ts\n│   ├── core/                  # pure logic — no I/O coupling to the CLI\n│   │   ├── config.ts          # supported formats, built-in defaults\n│   │   ├── types.ts           # public TS types\n│   │   ├── discover.ts        # file & directory walker\n│   │   ├── converter.ts       # single-file sharp encoder\n│   │   ├── resizer.ts         # single-file breakpoint generator\n│   │   ├── pipeline.ts        # batch runners + onProgress hook\n│   │   └── settings.ts        # persistent user config (env-overridable)\n│   ├── interactive/\n│   │   └── index.ts           # @inquirer/prompts console flow\n│   ├── ui/\n│   │   └── logger.ts          # colored output + per-file reporting\n│   ├── utils/\n│   │   ├── breakpoints.ts     # parsing, clamping, validation\n│   │   └── formats.ts         # format normalization + sharp mapping\n│   └── index.ts               # programmatic API\n├── tests/                     # vitest suite (mirrors src/ layout)\n├── archive/\n│   └── python/                # legacy Python implementation (read-only)\n├── .github/workflows/ci.yml   # typecheck + test + build matrix\n├── package.json\n├── tsconfig.json\n└── vitest.config.ts\n```\n\n**Design notes**\n\n- `core/` is pure — no `commander`, no `@inquirer/prompts`, no `picocolors`.\n  The CLI and the interactive mode are two UIs wired on top of the same\n  pipeline. Testing and embedding the library stay trivial.\n- `settings.ts` reads/writes `~/.img-convertor/config.json` and honors\n  `IMG_CONVERTOR_CONFIG_DIR` for sandboxed runs.\n- Encoder options (WEBP `effort`, JPEG `mozjpeg`, PNG `compressionLevel`) are\n  centralized in `converter.ts::pipeline()` so format-specific tuning lives in\n  one place.\n\n---\n\n## Development\n\n```bash\nnpm install\nnpm run dev -- convert --input ./samples --format webp   # run from TS\nnpm run build                                             # tsc → dist/\nnpm run typecheck                                         # no-emit check\nnpm run ci                                                # typecheck + test + build\n```\n\n---\n\n## Testing\n\nTest runner: [**vitest**](https://vitest.dev/). Coverage provider: `v8`.\n\n```bash\nnpm test                # single run (what CI runs)\nnpm run test:watch      # watch mode\nnpm run test:coverage   # generates ./coverage/lcov.info\n```\n\nImage-heavy tests generate their fixtures on the fly with `sharp` (no binary\nblobs in the repo). Settings tests isolate their config file via the\n`IMG_CONVERTOR_CONFIG_DIR` env var.\n\n### Current status — 80 tests · 100% coverage\n\n```\nFile             | % Stmts | % Branch | % Funcs | % Lines\n-----------------|---------|----------|---------|--------\nAll files        |   100   |   100    |   100   |   100\n```\n\n| Test file                         | Tests | Covers                                             |\n| --------------------------------- | :---: | -------------------------------------------------- |\n| `tests/utils/breakpoints.test.ts` |  12   | `parseBreakpoints`, `clampQuality`                 |\n| `tests/utils/formats.test.ts`     |  11   | `normalizeFormat`, `extensionFor`, `sharpFormat`   |\n| `tests/core/discover.test.ts`     |   7   | File/dir discovery, recursion, extension filter, POSIX FIFO |\n| `tests/core/converter.test.ts`    |  12   | Format conversion (webp/jpeg/png/avif), destinations, quality |\n| `tests/core/resizer.test.ts`      |   4   | Breakpoint variants, aspect ratio, no-upscale      |\n| `tests/core/pipeline.test.ts`     |   6   | Batch convert / resize / res-conv + error + progress |\n| `tests/core/settings.test.ts`     |  28   | Persistent defaults, presets, validation, env override |\n\nOne test is `skipIf(win32)` (POSIX FIFO) — it runs on the Linux and macOS CI\nmatrix.\n\n---\n\n## Continuous integration\n\nGitHub Actions runs `typecheck → test → build` on every push and PR:\n\n- Linux (Node 18, 20, 22, 24)\n- Windows (Node 22)\n- macOS (Node 22)\n\nA separate `coverage` job runs on Node 22 and uploads the `lcov` report as a\nbuild artifact. See [`.github/workflows/ci.yml`](./.github/workflows/ci.yml).\n\n---\n\n## Legacy\n\nThis package is a full rewrite of the original Python `dm-console-manager`\nimage module on top of Node.js + [`sharp`](https://sharp.pixelplumbing.com/).\nThe legacy Python source is kept under [`archive/python`](./archive/python)\nfor reference — it is not shipped with the npm package.\n\n---\n\n## License\n\n[MIT](./LICENSE) © Charles Lindecker\n","readmeFilename":"README.md"}