├── .npmrc ├── .gitignore ├── .travis.yml ├── LICENSE ├── package.json ├── README.md ├── align.js └── test └── align.js /.npmrc: -------------------------------------------------------------------------------- 1 | package-lock=false 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | /node_modules 3 | .#* 4 | /.nyc_output 5 | /coverage 6 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | sudo: false 3 | node_js: 4 | - "12" 5 | - "14" 6 | - "16" 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015, Rebecca Turner 2 | 3 | Permission to use, copy, modify, and/or distribute this software for any 4 | purpose with or without fee is hereby granted, provided that the above 5 | copyright notice and this permission notice appear in all copies. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wide-align", 3 | "version": "1.1.5", 4 | "description": "A wide-character aware text alignment function for use on the console or with fixed width fonts.", 5 | "main": "align.js", 6 | "scripts": { 7 | "test": "tap --coverage test/*.js" 8 | }, 9 | "keywords": [ 10 | "wide", 11 | "double", 12 | "unicode", 13 | "cjkv", 14 | "pad", 15 | "align" 16 | ], 17 | "author": "Rebecca Turner (http://re-becca.org/)", 18 | "license": "ISC", 19 | "repository": { 20 | "type": "git", 21 | "url": "https://github.com/iarna/wide-align" 22 | }, 23 | "//": "But not version 5 of string-width, as that's ESM only", 24 | "dependencies": { 25 | "string-width": "^1.0.2 || 2 || 3 || 4" 26 | }, 27 | "devDependencies": { 28 | "tap": "*" 29 | }, 30 | "files": [ 31 | "align.js" 32 | ] 33 | } 34 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | wide-align 2 | ---------- 3 | 4 | A wide-character aware text alignment function for use in terminals / on the 5 | console. 6 | 7 | ### Usage 8 | 9 | ``` 10 | var align = require('wide-align') 11 | 12 | // Note that if you view this on a unicode console, all of the slashes are 13 | // aligned. This is because on a console, all narrow characters are 14 | // an en wide and all wide characters are an em. In browsers, this isn't 15 | // held to and wide characters like "古" can be less than two narrow 16 | // characters even with a fixed width font. 17 | 18 | console.log(align.center('abc', 10)) // ' abc ' 19 | console.log(align.center('古古古', 10)) // ' 古古古 ' 20 | console.log(align.left('abc', 10)) // 'abc ' 21 | console.log(align.left('古古古', 10)) // '古古古 ' 22 | console.log(align.right('abc', 10)) // ' abc' 23 | console.log(align.right('古古古', 10)) // ' 古古古' 24 | ``` 25 | 26 | ### Functions 27 | 28 | #### `align.center(str, length)` → `str` 29 | 30 | Returns *str* with spaces added to both sides such that that it is *length* 31 | chars long and centered in the spaces. 32 | 33 | #### `align.left(str, length)` → `str` 34 | 35 | Returns *str* with spaces to the right such that it is *length* chars long. 36 | 37 | ### `align.right(str, length)` → `str` 38 | 39 | Returns *str* with spaces to the left such that it is *length* chars long. 40 | 41 | ### Origins 42 | 43 | These functions were originally taken from 44 | [cliui](https://npmjs.com/package/cliui). Changes include switching to the 45 | MUCH faster pad generation function from 46 | [lodash](https://npmjs.com/package/lodash), making center alignment pad 47 | both sides and adding left alignment. 48 | -------------------------------------------------------------------------------- /align.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | var stringWidth = require('string-width') 3 | 4 | exports.center = alignCenter 5 | exports.left = alignLeft 6 | exports.right = alignRight 7 | 8 | // lodash's way of generating pad characters. 9 | 10 | function createPadding (width) { 11 | var result = '' 12 | var string = ' ' 13 | var n = width 14 | do { 15 | if (n % 2) { 16 | result += string; 17 | } 18 | n = Math.floor(n / 2); 19 | string += string; 20 | } while (n); 21 | 22 | return result; 23 | } 24 | 25 | function alignLeft (str, width) { 26 | var trimmed = str.trimRight() 27 | if (trimmed.length === 0 && str.length >= width) return str 28 | var padding = '' 29 | var strWidth = stringWidth(trimmed) 30 | 31 | if (strWidth < width) { 32 | padding = createPadding(width - strWidth) 33 | } 34 | 35 | return trimmed + padding 36 | } 37 | 38 | function alignRight (str, width) { 39 | var trimmed = str.trimLeft() 40 | if (trimmed.length === 0 && str.length >= width) return str 41 | var padding = '' 42 | var strWidth = stringWidth(trimmed) 43 | 44 | if (strWidth < width) { 45 | padding = createPadding(width - strWidth) 46 | } 47 | 48 | return padding + trimmed 49 | } 50 | 51 | function alignCenter (str, width) { 52 | var trimmed = str.trim() 53 | if (trimmed.length === 0 && str.length >= width) return str 54 | var padLeft = '' 55 | var padRight = '' 56 | var strWidth = stringWidth(trimmed) 57 | 58 | if (strWidth < width) { 59 | var padLeftBy = parseInt((width - strWidth) / 2, 10) 60 | padLeft = createPadding(padLeftBy) 61 | padRight = createPadding(width - (strWidth + padLeftBy)) 62 | } 63 | 64 | return padLeft + trimmed + padRight 65 | } 66 | -------------------------------------------------------------------------------- /test/align.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | var test = require('tap').test 3 | var align = require('..') 4 | 5 | test('align', function (t) { 6 | t.is(align.center('abc', 10), ' abc ', 'center narrow') 7 | t.is(align.center('古古古', 10), ' 古古古 ', 'center wide') 8 | t.is(align.left('abc', 10), 'abc ', 'left narrow') 9 | t.is(align.left('古古古', 10), '古古古 ', 'left wide') 10 | t.is(align.right('abc', 10), ' abc', 'right narrow') 11 | t.is(align.right('古古古', 10), ' 古古古', 'right wide') 12 | 13 | t.is(align.center('abc', 2), 'abc', 'center narrow overflow') 14 | t.is(align.center('古古古', 4), '古古古', 'center wide overflow') 15 | t.is(align.left('abc', 2), 'abc', 'left narrow overflow') 16 | t.is(align.left('古古古', 4), '古古古', 'left wide overflow') 17 | t.is(align.right('abc', 2), 'abc', 'right narrow overflow') 18 | t.is(align.right('古古古', 4), '古古古', 'right wide overflow') 19 | 20 | t.is(align.left('', 5), ' ', 'left align nothing') 21 | t.is(align.center('', 5), ' ', 'center align nothing') 22 | t.is(align.right('', 5), ' ', 'right align nothing') 23 | 24 | t.is(align.left(' ', 5), ' ', 'left align whitespace') 25 | t.is(align.center(' ', 5), ' ', 'center align whitespace') 26 | t.is(align.right(' ', 5), ' ', 'right align whitespace') 27 | 28 | t.is(align.left(' ', 2), ' ', 'left align whitespace overflow') 29 | t.is(align.center(' ', 2), ' ', 'center align whitespace overflow') 30 | t.is(align.right(' ', 2), ' ', 'right align whitespace overflow') 31 | 32 | t.is(align.left(' x ', 10), ' x ', 'left align whitespace mix') 33 | t.is(align.center(' x ', 10), ' x ', 'center align whitespace mix') 34 | t.is(align.right(' x ', 10), ' x ', 'right align whitespace mix') 35 | 36 | t.end() 37 | }) 38 | --------------------------------------------------------------------------------