UNPKG

4.49 kBPlain TextView Raw
1import { CliCommandDefinitionOption, CliValue, CliValueType, MriOpts } from './types';
2
3// tslint:disable-next-line:no-any
4export const isFunction = (f: any) => typeof f === 'function';
5
6// tslint:disable-next-line:no-any
7export const isRegExp = (r: any) => r instanceof RegExp;
8
9export const dashCase = (base: string) => base.replace(/([a-zA-Z])(?=[A-Z])/g, '$1-').toLowerCase();
10
11export const passedOptionsToNames = (passed: string[], options: CliCommandDefinitionOption[]) => {
12 return passed.map(f => {
13 const opt = options.find(o => {
14 return (o.flag && o.flag === f) || o.name === f;
15 });
16 return opt ? opt.name : f;
17 });
18};
19
20export const getOptionsMriOpts = (options: CliCommandDefinitionOption[] = []): MriOpts => {
21 const opts: MriOpts = {};
22
23 options.forEach(o => {
24 if (o.flag) {
25 opts.alias = opts.alias || {};
26 const flag = o.flag.replace(/-/g, '');
27 opts.alias[flag] = o.name;
28 }
29
30 const dashedName = dashCase(o.name);
31 if (dashedName !== o.name) {
32 opts.alias[dashedName] = o.name;
33 }
34
35 if (o.default) {
36 opts.default = opts.default || {};
37 opts.default[o.name] = o.default;
38 }
39
40 if (o.valueType) {
41 if (o.valueType === 'string') {
42 opts.string = opts.string || [];
43 (opts.string as string[]).push(o.name);
44 } else if (o.valueType === 'boolean') {
45 opts.boolean = opts.boolean || [];
46 (opts.boolean as string[]).push(o.name);
47 }
48 }
49 });
50
51 return opts;
52};
53
54// Not sure this is doing much..
55export const coerceCliValue = (value: CliValue, type: CliValueType = 'string'): CliValue => {
56 switch (type) {
57 case 'boolean':
58 return Boolean(value);
59 case 'number':
60 return value ? parseInt(value as string, 10) : value;
61 case 'string':
62 default:
63 return value;
64 }
65};
66
67const preserveCamelCase = val => {
68 let isLastCharLower = false;
69 let isLastCharUpper = false;
70 let isLastLastCharUpper = false;
71
72 for (let i = 0; i < val.length; i++) {
73 const character = val[i];
74
75 if (isLastCharLower && /[a-zA-Z]/.test(character) && character.toUpperCase() === character) {
76 val = val.slice(0, i) + '-' + val.slice(i);
77 isLastCharLower = false;
78 isLastLastCharUpper = isLastCharUpper;
79 isLastCharUpper = true;
80 i++;
81 } else if (
82 isLastCharUpper &&
83 isLastLastCharUpper &&
84 /[a-zA-Z]/.test(character) &&
85 character.toLowerCase() === character
86 ) {
87 val = val.slice(0, i - 1) + '-' + val.slice(i - 1);
88 isLastLastCharUpper = isLastCharUpper;
89 isLastCharUpper = false;
90 isLastCharLower = true;
91 } else {
92 isLastCharLower = character.toLowerCase() === character && character.toUpperCase() !== character;
93 isLastLastCharUpper = isLastCharUpper;
94 isLastCharUpper = character.toUpperCase() === character && character.toLowerCase() !== character;
95 }
96 }
97
98 return val;
99};
100
101export const camelCase = (input, options = { pascalCase: false }) => {
102 if (!(typeof input === 'string' || Array.isArray(input))) {
103 throw new TypeError('Expected the input to be `string | string[]`');
104 }
105
106 options = {
107 pascalCase: false,
108 ...options,
109 };
110
111 const postProcess = x => (options.pascalCase ? x.charAt(0).toUpperCase() + x.slice(1) : x);
112
113 if (Array.isArray(input)) {
114 input = input
115 .map(x => x.trim())
116 .filter(x => x.length)
117 .join('-');
118 } else {
119 input = input.trim();
120 }
121
122 if (input.length === 0) {
123 return '';
124 }
125
126 if (input.length === 1) {
127 return options.pascalCase ? input.toUpperCase() : input.toLowerCase();
128 }
129
130 const hasUpperCase = input !== input.toLowerCase();
131
132 if (hasUpperCase) {
133 input = preserveCamelCase(input);
134 }
135
136 input = input
137 .replace(/^[_.\- ]+/, '')
138 .toLowerCase()
139 .replace(/[_.\- ]+(\w|$)/g, (_, p1) => p1.toUpperCase())
140 .replace(/\d+(\w|$)/g, m => m.toUpperCase());
141
142 return postProcess(input);
143};