UNPKG

3.63 kBPlain TextView Raw
1#!/usr/bin/env node
2(function() {
3
4 var fs = require('fs');
5 var he = require('../he.js');
6 var strings = process.argv.splice(2);
7 var stdin = process.stdin;
8 var data;
9 var timeout;
10 var action;
11 var options = {};
12 var log = console.log;
13
14 var main = function() {
15 var option = strings[0];
16 var count = 0;
17
18 if (/^(?:-h|--help|undefined)$/.test(option)) {
19 log(
20 'he v%s - https://mths.be/he',
21 he.version
22 );
23 log([
24 '\nUsage:\n',
25 '\the [--escape] string',
26 '\the [--encode] [--use-named-refs] [--everything] [--allow-unsafe] [--decimal] string',
27 '\the [--decode] [--attribute] [--strict] string',
28 '\the [-v | --version]',
29 '\the [-h | --help]',
30 '\nExamples:\n',
31 '\the --escape \\<img\\ src\\=\\\'x\\\'\\ onerror\\=\\"prompt\\(1\\)\\"\\>',
32 '\techo \'&copy; &#x1D306;\' | he --decode'
33 ].join('\n'));
34 return process.exit(option ? 0 : 1);
35 }
36
37 if (/^(?:-v|--version)$/.test(option)) {
38 log('v%s', he.version);
39 return process.exit(0);
40 }
41
42 strings.forEach(function(string) {
43 // Process options
44 if (string == '--escape') {
45 action = 'escape';
46 return;
47 }
48 if (string == '--encode') {
49 action = 'encode';
50 return;
51 }
52 if (string == '--use-named-refs') {
53 action = 'encode';
54 options.useNamedReferences = true;
55 return;
56 }
57 if (string == '--everything') {
58 action = 'encode';
59 options.encodeEverything = true;
60 return;
61 }
62 if (string == '--allow-unsafe') {
63 action = 'encode';
64 options.allowUnsafeSymbols = true;
65 return;
66 }
67 if (string == '--decimal') {
68 action = 'encode';
69 options.decimal = true;
70 return;
71 }
72 if (string == '--decode') {
73 action = 'decode';
74 return;
75 }
76 if (string == '--attribute') {
77 action = 'decode';
78 options.isAttributeValue = true;
79 return;
80 }
81 if (string == '--strict') {
82 action = 'decode';
83 options.strict = true;
84 return;
85 }
86 // Process string(s)
87 var result;
88 if (!action) {
89 log('Error: he requires at least one option and a string argument.');
90 log('Try `he --help` for more information.');
91 return process.exit(1);
92 }
93 try {
94 result = he[action](string, options);
95 log(result);
96 count++;
97 } catch(error) {
98 log(error.message + '\n');
99 log('Error: failed to %s.', action);
100 log('If you think this is a bug in he, please report it:');
101 log('https://github.com/mathiasbynens/he/issues/new');
102 log(
103 '\nStack trace using he@%s:\n',
104 he.version
105 );
106 log(error.stack);
107 return process.exit(1);
108 }
109 });
110 if (!count) {
111 log('Error: he requires a string argument.');
112 log('Try `he --help` for more information.');
113 return process.exit(1);
114 }
115 // Return with exit status 0 outside of the `forEach` loop, in case
116 // multiple strings were passed in.
117 return process.exit(0);
118 };
119
120 if (stdin.isTTY) {
121 // handle shell arguments
122 main();
123 } else {
124 // Either the script is called from within a non-TTY context, or `stdin`
125 // content is being piped in.
126 if (!process.stdout.isTTY) {
127 // The script was called from a non-TTY context. This is a rather uncommon
128 // use case we don’t actively support. However, we don’t want the script
129 // to wait forever in such cases, so…
130 timeout = setTimeout(function() {
131 // …if no piped data arrived after a whole minute, handle shell
132 // arguments instead.
133 main();
134 }, 60000);
135 }
136 data = '';
137 stdin.on('data', function(chunk) {
138 clearTimeout(timeout);
139 data += chunk;
140 });
141 stdin.on('end', function() {
142 strings.push(data.trim());
143 main();
144 });
145 stdin.resume();
146 }
147
148}());