UNPKG

4.5 kBPlain TextView Raw
1import { CliCommandDefinitionOption, MriOpts, CliValue, CliValueType } 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 (<string[]>opts.string).push(o.name);
44 } else if (o.valueType === 'boolean') {
45 opts.boolean = opts.boolean || [];
46 (<string[]>opts.boolean).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 break;
60 case 'number':
61 return value ? parseInt(value as string) : value;
62 case 'string':
63 default:
64 return value;
65 }
66};
67
68const preserveCamelCase = val => {
69 let isLastCharLower = false;
70 let isLastCharUpper = false;
71 let isLastLastCharUpper = false;
72
73 for (let i = 0; i < val.length; i++) {
74 const character = val[i];
75
76 if (isLastCharLower && /[a-zA-Z]/.test(character) && character.toUpperCase() === character) {
77 val = val.slice(0, i) + '-' + val.slice(i);
78 isLastCharLower = false;
79 isLastLastCharUpper = isLastCharUpper;
80 isLastCharUpper = true;
81 i++;
82 } else if (
83 isLastCharUpper &&
84 isLastLastCharUpper &&
85 /[a-zA-Z]/.test(character) &&
86 character.toLowerCase() === character
87 ) {
88 val = val.slice(0, i - 1) + '-' + val.slice(i - 1);
89 isLastLastCharUpper = isLastCharUpper;
90 isLastCharUpper = false;
91 isLastCharLower = true;
92 } else {
93 isLastCharLower = character.toLowerCase() === character && character.toUpperCase() !== character;
94 isLastLastCharUpper = isLastCharUpper;
95 isLastCharUpper = character.toUpperCase() === character && character.toLowerCase() !== character;
96 }
97 }
98
99 return val;
100};
101
102export const camelCase = (input, options = { pascalCase: false }) => {
103 if (!(typeof input === 'string' || Array.isArray(input))) {
104 throw new TypeError('Expected the input to be `string | string[]`');
105 }
106
107 options = {
108 pascalCase: false,
109 ...options
110 };
111
112 const postProcess = x => (options.pascalCase ? x.charAt(0).toUpperCase() + x.slice(1) : x);
113
114 if (Array.isArray(input)) {
115 input = input
116 .map(x => x.trim())
117 .filter(x => x.length)
118 .join('-');
119 } else {
120 input = input.trim();
121 }
122
123 if (input.length === 0) {
124 return '';
125 }
126
127 if (input.length === 1) {
128 return options.pascalCase ? input.toUpperCase() : input.toLowerCase();
129 }
130
131 const hasUpperCase = input !== input.toLowerCase();
132
133 if (hasUpperCase) {
134 input = preserveCamelCase(input);
135 }
136
137 input = input
138 .replace(/^[_.\- ]+/, '')
139 .toLowerCase()
140 .replace(/[_.\- ]+(\w|$)/g, (_, p1) => p1.toUpperCase())
141 .replace(/\d+(\w|$)/g, m => m.toUpperCase());
142
143 return postProcess(input);
144};