From 1d1ce50c0fd74e162be4553de7844d7ecffa3fc7 Mon Sep 17 00:00:00 2001 From: tecfu Date: Sun, 20 Sep 2026 07:53:06 +0000 Subject: [PATCH] feat: split CLI into smartwrap-cli so core installs without yargs Closes #19. Library users who only need text wrapping no longer pull in yargs or the CLI binary. - smartwrap (root): core TypeScript library only (strip-ansi, wcwidth) - packages/smartwrap-cli: separate package with the smartwrap bin + yargs - Remove src/terminal-adapter.ts and bin field from the core package - README documents the install matrix Rebased onto master after the TypeScript rewrite (#25) and long-word perf fix (#26). --- README.md | 19 ++++++++--- package.json | 9 ++--- packages/smartwrap-cli/LICENSE | 19 +++++++++++ packages/smartwrap-cli/README.md | 22 +++++++++++++ packages/smartwrap-cli/package.json | 33 +++++++++++++++++++ .../smartwrap-cli/src/terminal-adapter.js | 23 ++++++------- scripts/write-package-jsons.js | 9 ----- 7 files changed, 102 insertions(+), 32 deletions(-) create mode 100644 packages/smartwrap-cli/LICENSE create mode 100644 packages/smartwrap-cli/README.md create mode 100644 packages/smartwrap-cli/package.json rename src/terminal-adapter.ts => packages/smartwrap-cli/src/terminal-adapter.js (78%) mode change 100644 => 100755 diff --git a/README.md b/README.md index 6f22adf..5f23ef1 100644 --- a/README.md +++ b/README.md @@ -4,20 +4,27 @@ Textwrap for JavaScript/Node.js, written in **TypeScript**. Correctly handles wide characters (宽字符) and emojis (😃). Optionally break words when wrapping strings. Preserves ANSI escape codes. -Ships compiled CommonJS + declaration files (`.d.ts`). +Ships compiled CommonJS + ESM + declaration files (`.d.ts`). ## Installation +**Library only** (no CLI, no `yargs`): + ```bash npm install smartwrap ``` -CLI (global): +**CLI** (separate package): ```bash -npm install -g smartwrap +npm install -g smartwrap-cli ``` +| Install | Package | Contents | +|---------|---------|----------| +| `npm install smartwrap` | **smartwrap** | Core library only | +| `npm install -g smartwrap-cli` | **smartwrap-cli** | `smartwrap` binary + yargs | + ## Usage ```ts @@ -76,12 +83,14 @@ npm test Source is pure TypeScript under `src/`. Published artifacts live in `dist/`. +The CLI lives in `packages/smartwrap-cli` and is published separately as `smartwrap-cli`. + ## Breaking changes in 3.0.0 - **Node.js ≥ 14** required. - Source rewritten in TypeScript; `main` / `types` point at `dist/`. -- Removed unused `grapheme-splitter` and the `array.prototype.flat` polyfill. -- See prior changelog notes on the modernize release for dependency cleanup details. +- CLI moved to the separate **`smartwrap-cli`** package (core no longer depends on `yargs`). +- Removed unused `grapheme-splitter`, `breakword`, and the `array.prototype.flat` polyfill. ## License diff --git a/package.json b/package.json index 8324c92..cb2ef89 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "smartwrap", "version": "3.0.0", - "description": "Textwrap for javascript/nodejs. Correctly handles wide characters (宽字符) and emojis (😃). Wraps strings with option to break on words.", + "description": "Textwrap for javascript/nodejs. Correctly handles wide characters (\u5bbd\u5b57\u7b26) and emojis (\ud83d\ude03). Wraps strings with option to break on words.", "main": "./dist/cjs/main.js", "module": "./dist/esm/main.js", "types": "./dist/cjs/main.d.ts", @@ -22,9 +22,6 @@ "engines": { "node": ">=14" }, - "bin": { - "smartwrap": "./dist/cjs/terminal-adapter.js" - }, "scripts": { "build": "npm run build:cjs && npm run build:esm && node scripts/write-package-jsons.js", "build:cjs": "tsc -p tsconfig.cjs.json", @@ -53,13 +50,11 @@ "license": "MIT", "dependencies": { "strip-ansi": "^6.0.1", - "wcwidth": "^1.0.1", - "yargs": "^17.7.2" + "wcwidth": "^1.0.1" }, "devDependencies": { "@types/node": "^18.19.0", "@types/strip-ansi": "^5.2.1", - "@types/yargs": "^17.0.33", "chai": "^4.3.10", "eslint": "^8.57.0", "mocha": "^10.7.3", diff --git a/packages/smartwrap-cli/LICENSE b/packages/smartwrap-cli/LICENSE new file mode 100644 index 0000000..d13cc4b --- /dev/null +++ b/packages/smartwrap-cli/LICENSE @@ -0,0 +1,19 @@ +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/packages/smartwrap-cli/README.md b/packages/smartwrap-cli/README.md new file mode 100644 index 0000000..921e691 --- /dev/null +++ b/packages/smartwrap-cli/README.md @@ -0,0 +1,22 @@ +# smartwrap-cli + +Command-line interface for [smartwrap](https://www.npmjs.com/package/smartwrap). + +## Install + +```bash +npm install -g smartwrap-cli +``` + +For library-only use (no CLI, no `yargs`), install [`smartwrap`](https://www.npmjs.com/package/smartwrap) instead. + +## Usage + +```bash +echo "somestring you want to wrap" | smartwrap --width=3 --paddingLeft=1 +smartwrap --help +``` + +## License + +MIT diff --git a/packages/smartwrap-cli/package.json b/packages/smartwrap-cli/package.json new file mode 100644 index 0000000..bc2f1c7 --- /dev/null +++ b/packages/smartwrap-cli/package.json @@ -0,0 +1,33 @@ +{ + "name": "smartwrap-cli", + "version": "3.0.0", + "description": "CLI for smartwrap — text wrapping with wide-character and emoji support", + "bin": { + "smartwrap": "src/terminal-adapter.js" + }, + "engines": { + "node": ">=14" + }, + "repository": { + "type": "git", + "url": "https://github.com/tecfu/smartwrap.git", + "directory": "packages/smartwrap-cli" + }, + "keywords": [ + "smartwrap", + "wordwrap", + "cli", + "terminal" + ], + "author": "tecfu", + "license": "MIT", + "dependencies": { + "smartwrap": "^3.0.0", + "yargs": "^17.7.2" + }, + "files": [ + "src/", + "LICENSE", + "README.md" + ] +} diff --git a/src/terminal-adapter.ts b/packages/smartwrap-cli/src/terminal-adapter.js old mode 100644 new mode 100755 similarity index 78% rename from src/terminal-adapter.ts rename to packages/smartwrap-cli/src/terminal-adapter.js index 10334a2..1d39452 --- a/src/terminal-adapter.ts +++ b/packages/smartwrap-cli/src/terminal-adapter.js @@ -1,6 +1,8 @@ #!/usr/bin/env node -import smartwrap, { type SmartwrapOptions } from './main' -import yargs from 'yargs' +'use strict' + +const smartwrap = require('smartwrap') +const yargs = require('yargs') const argv = yargs .option('breakword', { @@ -13,8 +15,8 @@ const argv = yargs describe: 'Placeholder for wide characters when minWidth < 2' }) .option('minWidth', { - choices: [1, 2] as const, - default: 2 as 1 | 2, + choices: [1, 2], + default: 2, describe: 'Minimum line width. Use 1 only if you are certain you are not using wide characters and want a 1-space column.' }) @@ -29,7 +31,7 @@ const argv = yargs type: 'number' }) .option('splitAt', { - default: [' ', '\t'] as string[], + default: [' ', '\t'], describe: 'Characters at which to split input' }) .option('trim', { @@ -42,7 +44,7 @@ const argv = yargs default: 10, describe: 'Set the line width of the output (in spaces)', demandOption: true, - coerce: (arg: string | number): number => { + coerce: (arg) => { const n = Number(arg) if (Number.isNaN(n)) { throw new Error('Invalid width specified.') @@ -54,7 +56,7 @@ const argv = yargs .alias('h', 'help') .parseSync() -const options: SmartwrapOptions = {} +const options = {} const keys = [ 'breakword', 'errorChar', @@ -64,18 +66,17 @@ const keys = [ 'splitAt', 'trim', 'width' -] as const +] for (const key of keys) { if (typeof argv[key] !== 'undefined') { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - ;(options as any)[key] = argv[key] + options[key] = argv[key] } } process.stdin.resume() process.stdin.setEncoding('utf8') -process.stdin.on('data', (chunk: string) => { +process.stdin.on('data', (chunk) => { const out = smartwrap(chunk, options) console.log(out) }) diff --git a/scripts/write-package-jsons.js b/scripts/write-package-jsons.js index 19ba158..a1b0977 100644 --- a/scripts/write-package-jsons.js +++ b/scripts/write-package-jsons.js @@ -30,14 +30,5 @@ if (fs.existsSync(cjsMain)) { } } -const bin = path.join('dist', 'cjs', 'terminal-adapter.js') -if (fs.existsSync(bin)) { - let content = fs.readFileSync(bin, 'utf8') - if (!content.startsWith('#!')) { - content = '#!/usr/bin/env node\n' + content - fs.writeFileSync(bin, content) - } - fs.chmodSync(bin, 0o755) -} console.log('Wrote dist package metadata and CJS interop')