Skip to content

Commit ce57f7c

Browse files
committed
Add input from STDIN
Add option for input encoding
1 parent b0241b9 commit ce57f7c

File tree

7 files changed

+128
-38
lines changed

7 files changed

+128
-38
lines changed

.github/workflows/node.js.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ jobs:
1616

1717
strategy:
1818
matrix:
19-
node-version: [10.x, 12.x, 14.x]
19+
node-version: [10.x, 12.x, 14.x, 16.x]
2020

2121
steps:
2222
- uses: actions/checkout@v2

.npmignore

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,2 @@
11
test/
2-
.github
3-
.idea
2+
.github/

README.md

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,19 @@ This tool is basically a tiny wrapper around [js-yaml](https://github.com/nodeca
1818
Usage: yaml-sort [options]
1919
2020
Options:
21-
--input, -i The YAML file(s) which needs to be sorted [array] [required]
22-
--output, -o The YAML file to output sorted content to [string]
23-
--stdout, -s Output the proposed sort to STDOUT only [boolean] [default: false]
24-
--check, -k Check if the given file(s) is already sorted [boolean] [default: false]
25-
--indent, --id Indentation width to use (in spaces) [number] [default: 2]
26-
--lineWidth, -w Wrap line width [number] [default: 80]
27-
-h, --help Show help [boolean]
28-
--version Show version number [boolean]
21+
-i, --input The YAML file(s) which needs to be sorted [array] [default: "-"]
22+
-o, --output The YAML file to output sorted content to [string]
23+
-s, --stdout Output the proposed sort to STDOUT only [boolean] [default: false]
24+
-k, --check Check if the given file(s) is already sorted [boolean] [default: false]
25+
--indent, --id Indentation width to use (in spaces) [number] [default: 2]
26+
-e, --encoding Input encoding [choices: "ascii", "utf8", "utf16le"] [default: "utf8"]
27+
-w, --lineWidth Wrap line width [number] [default: 80]
28+
-h, --help Show help [boolean]
29+
--version Show version number [boolean]
2930
3031
Examples:
31-
yaml-sort --input config.yml Sorts alphabetically and overwrites the file config.yml.
32+
yaml-sort --input config.yml Sorts alphabetically and overwrites the file config.yml
3233
yaml-sort --input config.yml --lineWidth 100 --stdout Sorts the file config.yml and output result to STDOUT wrapped to 100 columns
33-
yaml-sort --input config.yml --indent 4 --output sorted.yml Indents with 4 spaces and outputs result to file sorted.yml.
34+
yaml-sort --input config.yml --indent 4 --output sorted.yml Indents with 4 spaces and outputs result to file sorted.yml
35+
cat config.yml | yaml-sort Sorts alphabetically from STDIN
3436
```

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "yaml-sort",
3-
"version": "1.1.1",
3+
"version": "1.2.0",
44
"description": "CLI tool to sort YAML files alphabetically",
55
"main": "yaml-sort.js",
66
"scripts": {

test/test-utf16le.yml

166 Bytes
Binary file not shown.

test/test.js

Lines changed: 78 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,31 @@ const test = require('tape')
66
const spawn = require('tape-spawn')
77
const opts = { cwd: __dirname }
88

9+
test('CLI --help', (t) => {
10+
const proc = spawn(t, '../yaml-sort.js -h', opts)
11+
proc.stdout.match(/^Usage:/)
12+
proc.stderr.match('')
13+
proc.exitCode(0)
14+
proc.end()
15+
})
16+
917
test('CLI w/o arg', (t) => {
1018
const proc = spawn(t, '../yaml-sort.js', opts)
19+
proc.stdout.match('')
1120
proc.exitCode(1)
12-
proc.stderr.match(/Missing required argument: input/)
21+
proc.end()
22+
})
23+
24+
test('CLI w/o arg (STDIN)', (t) => {
25+
const proc = spawn(t, 'cat test.yml | ../yaml-sort.js', opts)
26+
proc.exitCode(0)
27+
proc.stdout.match('a: Lorem ipsum dolor sit amet, consectetur adipiscing elit...\n' +
28+
'b:\n' +
29+
' b: 35\n' +
30+
' c:\n' +
31+
' d: false\n' +
32+
'\n')
33+
proc.stderr.match('')
1334
proc.end()
1435
})
1536

@@ -22,6 +43,7 @@ test('CLI w/ arg', (t) => {
2243
' c:\n' +
2344
' d: false\n' +
2445
'\n')
46+
proc.stderr.match('')
2547
proc.end()
2648
})
2749

@@ -36,6 +58,22 @@ test('CLI --output', (t) => {
3658
' b: 35\n' +
3759
' c:\n' +
3860
' d: false\n')
61+
proc.stderr.match('')
62+
proc.end()
63+
})
64+
65+
test('CLI --output (STDIN)', (t) => {
66+
const proc = spawn(t,
67+
'cat test.yml | ../yaml-sort.js --input - --output output.yml' +
68+
' && cat output.yml' +
69+
' && rm -f output.yml', opts)
70+
proc.exitCode(0)
71+
proc.stdout.match('a: Lorem ipsum dolor sit amet, consectetur adipiscing elit...\n' +
72+
'b:\n' +
73+
' b: 35\n' +
74+
' c:\n' +
75+
' d: false\n')
76+
proc.stderr.match('')
3977
proc.end()
4078
})
4179

@@ -48,6 +86,7 @@ test('CLI --indent', (t) => {
4886
' c:\n' +
4987
' d: false\n' +
5088
'\n')
89+
proc.stderr.match('')
5190
proc.end()
5291
})
5392

@@ -62,6 +101,7 @@ test('CLI --lineWidth', (t) => {
62101
' c:\n' +
63102
' d: false\n' +
64103
'\n')
104+
proc.stderr.match('')
65105
proc.end()
66106
})
67107

@@ -79,6 +119,24 @@ test('CLI --check SUCCESS', (t) => {
79119
'../yaml-sort.js --input sorted.yml --check', opts)
80120
proc.exitCode(0)
81121
proc.stdout.match('')
122+
proc.stderr.match('')
123+
proc.end()
124+
})
125+
126+
test('CLI --encoding FAIL', (t) => {
127+
const proc = spawn(t,
128+
'../yaml-sort.js --input test-utf16le.yml --stdout', opts)
129+
proc.exitCode(1)
130+
proc.stdout.match('')
131+
proc.stderr.match(/null byte is not allowed in input/)
132+
proc.end()
133+
})
134+
135+
test('CLI --encoding SUCCESS', (t) => {
136+
const proc = spawn(t,
137+
'../yaml-sort.js --input test-utf16le.yml --stdout --encoding utf16le', opts)
138+
proc.exitCode(0)
139+
proc.stderr.match('')
82140
proc.end()
83141
})
84142

@@ -89,5 +147,24 @@ test('CLI --lineWidth SUCCESS', (t) => {
89147
' && rm -f output.yml', opts)
90148
proc.exitCode(0)
91149
proc.stdout.match('')
150+
proc.stderr.match('')
151+
proc.end()
152+
})
153+
154+
test('CLI --output --stdout FAIL', (t) => {
155+
const proc = spawn(t,
156+
'../yaml-sort.js --input test.yml --stdout --output output.yml', opts)
157+
proc.exitCode(1)
158+
proc.stdout.match('')
159+
proc.stderr.match(/Arguments stdout and output are mutually exclusive/)
160+
proc.end()
161+
})
162+
163+
test('CLI --check --stdout FAIL', (t) => {
164+
const proc = spawn(t,
165+
'../yaml-sort.js --input test.yml --check --stdout', opts)
166+
proc.exitCode(1)
167+
proc.stdout.match('')
168+
proc.stderr.match(/Arguments check and stdout are mutually exclusive/)
92169
proc.end()
93170
})

yaml-sort.js

Lines changed: 35 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,26 @@
22

33
'use strict'
44

5-
const argv = require('yargs')
5+
const fs = require('fs')
6+
const yaml = require('js-yaml')
7+
const yargs = require('yargs')
8+
9+
const argv = yargs
610
.usage('Usage: $0 [options]')
7-
.example(
8-
'$0 --input config.yml',
9-
'Sorts alphabetically and overwrites the file config.yml'
10-
)
11-
.example(
12-
'$0 --input config.yml --lineWidth 100 --stdout',
13-
'Sorts the file config.yml and output result to STDOUT wrapped to 100 columns'
14-
)
15-
.example(
16-
'$0 --input config.yml --indent 4 --output sorted.yml',
17-
'Indents with 4 spaces and outputs result to file sorted.yml'
18-
)
11+
.example([
12+
['$0 --input config.yml',
13+
'Sorts alphabetically and overwrites the file config.yml'],
14+
['$0 --input config.yml --lineWidth 100 --stdout',
15+
'Sorts the file config.yml and output result to STDOUT wrapped to 100 columns'],
16+
['$0 --input config.yml --indent 4 --output sorted.yml',
17+
'Indents with 4 spaces and outputs result to file sorted.yml'],
18+
['cat config.yml | $0',
19+
'Sorts alphabetically from STDIN']
20+
])
1921
.option('input', {
2022
alias: 'i',
2123
describe: 'The YAML file(s) which needs to be sorted',
22-
demandOption: 'Please provide an input file',
24+
default: '-',
2325
string: true,
2426
array: true
2527
})
@@ -30,14 +32,14 @@ const argv = require('yargs')
3032
})
3133
.option('stdout', {
3234
alias: 's',
33-
default: false,
3435
describe: 'Output the proposed sort to STDOUT only',
36+
conflicts: 'output',
3537
boolean: true
3638
})
3739
.option('check', {
3840
alias: 'k',
39-
default: false,
4041
describe: 'Check if the given file(s) is already sorted',
42+
conflicts: ['output', 'stdout'],
4143
boolean: true
4244
})
4345
.option('indent', {
@@ -46,27 +48,36 @@ const argv = require('yargs')
4648
describe: 'Indentation width to use (in spaces)',
4749
number: true
4850
})
51+
.option('encoding', {
52+
alias: 'e',
53+
default: 'utf8',
54+
describe: 'Input encoding',
55+
choices: ['ascii', 'utf8', 'utf16le']
56+
})
4957
.option('lineWidth', {
5058
alias: 'w',
5159
default: 80,
5260
describe: 'Wrap line width',
5361
number: true
5462
})
55-
.demandOption(['input'])
5663
.help('h')
5764
.alias('h', 'help')
5865
.version()
5966
.wrap(null)
6067
.argv
6168

62-
const yaml = require('js-yaml')
63-
const fs = require('fs')
64-
6569
let success = true
6670

6771
argv.input.forEach((file) => {
6872
try {
69-
const content = fs.readFileSync(file, 'utf8')
73+
const isStdin = file === '-'
74+
75+
if (isStdin && process.stdin.isTTY) {
76+
yargs.showHelp()
77+
process.exit(22)
78+
}
79+
80+
const content = fs.readFileSync(isStdin ? process.stdin.fd : file, argv.encoding)
7081

7182
const sorted = yaml.dump(yaml.load(content), {
7283
sortKeys: true,
@@ -79,15 +90,16 @@ argv.input.forEach((file) => {
7990
success = false
8091
console.warn(`'${file}' is not sorted and/or formatted (indent, line width).`)
8192
}
82-
} else if (argv.stdout) {
93+
} else if (argv.stdout || (isStdin && !argv.output)) {
8394
console.log(sorted)
8495
} else {
8596
fs.writeFile(
8697
argv.output ? argv.output : file,
8798
sorted,
8899
(error) => {
89100
if (error) {
90-
return console.error(error)
101+
success = false
102+
console.error(error)
91103
}
92104
})
93105
}

0 commit comments

Comments
 (0)