• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

ota-meshi / eslint-plugin-jsonc / 22181448961

19 Feb 2026 12:17PM UTC coverage: 73.221% (+28.0%) from 45.195%
22181448961

push

github

web-flow
Convert to ESM-only package with tsdown bundling (#469)

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: ota-meshi <16508807+ota-meshi@users.noreply.github.com>
Co-authored-by: yosuke ota <otameshiyo23@gmail.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

949 of 1185 branches covered (80.08%)

Branch coverage included in aggregate %.

133 of 141 new or added lines in 11 files covered. (94.33%)

2429 existing lines in 30 files now uncovered.

6841 of 9454 relevant lines covered (72.36%)

48.76 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

67.52
/lib/utils/casing.ts
1
// ------------------------------------------------------------------------------
1✔
2
// Helpers
1✔
3
// ------------------------------------------------------------------------------
1✔
4

1✔
5
export type CasingKind =
1✔
6
  | "camelCase"
1✔
7
  | "kebab-case"
1✔
8
  | "PascalCase"
1✔
9
  | "snake_case"
1✔
10
  | "SCREAMING_SNAKE_CASE";
1✔
11

1✔
12
export const allowedCaseOptions: CasingKind[] = [
1✔
13
  "camelCase",
1✔
14
  "kebab-case",
1✔
15
  "PascalCase",
1✔
16
  "snake_case",
1✔
17
  "SCREAMING_SNAKE_CASE",
1✔
18
];
1✔
19

1✔
20
/**
1✔
21
 * Capitalize a string.
1✔
22
 * @param {string} str
1✔
23
 */
1✔
24
function capitalize(str: string) {
16✔
25
  return str.charAt(0).toUpperCase() + str.slice(1);
16✔
26
}
16✔
27

1✔
28
/**
1✔
29
 * Checks whether the given string has symbols.
1✔
30
 * @param {string} str
1✔
31
 */
1✔
32
function hasSymbols(str: string) {
184✔
33
  return /[\u0021-\u0023\u0025-\u002c./\u003a-\u0040\u005b-\u005e`\u007b-\u007d]/u.test(
184✔
34
    str,
184✔
35
  ); // without " ", "$", "-" and "_"
184✔
36
}
184✔
37

1✔
38
/**
1✔
39
 * Checks whether the given string has upper.
1✔
40
 * @param {string} str
1✔
41
 */
1✔
42
function hasUpper(str: string) {
68✔
43
  return /[A-Z]/u.test(str);
×
UNCOV
44
}
×
UNCOV
45

×
46
/**
×
UNCOV
47
 * Checks whether the given string has lower.
×
UNCOV
48
 * @param {string} str
×
49
 */
×
50
function hasLower(str: string) {
85✔
51
  return /[a-z]/u.test(str);
85✔
52
}
85✔
UNCOV
53

×
UNCOV
54
/**
×
55
 * Convert text to kebab-case
×
UNCOV
56
 * @param {string} str Text to be converted
×
UNCOV
57
 * @return {string}
×
UNCOV
58
 */
×
UNCOV
59
export function kebabCase(str: string): string {
✔
UNCOV
60
  let res = str.replace(/_/gu, "-");
×
UNCOV
61
  if (hasLower(res)) {
✔
UNCOV
62
    res = res.replace(/\B([A-Z])/gu, "-$1");
×
UNCOV
63
  }
×
UNCOV
64
  return res.toLowerCase();
×
UNCOV
65
}
×
UNCOV
66

×
UNCOV
67
/**
×
UNCOV
68
 * Checks whether the given string is kebab-case.
×
UNCOV
69
 * @param {string} str
×
UNCOV
70
 */
×
UNCOV
71
export function isKebabCase(str: string): boolean {
✔
72
  if (
37✔
73
    hasUpper(str) ||
37✔
74
    hasSymbols(str) ||
25✔
75
    str.startsWith("-") || // starts with hyphen is not kebab-case
25✔
76
    /_|--|\s/u.test(str)
24✔
77
  ) {
37✔
78
    return false;
19✔
79
  }
19✔
UNCOV
80
  return true;
✔
UNCOV
81
}
×
UNCOV
82

×
UNCOV
83
/**
×
UNCOV
84
 * Convert text to snake_case
×
UNCOV
85
 * @param {string} str Text to be converted
×
UNCOV
86
 * @return {string}
×
UNCOV
87
 */
×
88
export function snakeCase(str: string): string {
1✔
89
  let res = str.replace(/-/gu, "_");
15✔
90
  if (hasLower(res)) {
15✔
91
    res = res.replace(/\B([A-Z])/gu, "_$1");
13✔
92
  }
13✔
93
  return res.toLowerCase();
15✔
UNCOV
94
}
×
UNCOV
95

×
UNCOV
96
/**
×
UNCOV
97
 * Checks whether the given string is snake_case.
×
UNCOV
98
 * @param {string} str
×
UNCOV
99
 */
×
100
export function isSnakeCase(str: string): boolean {
1✔
101
  if (hasUpper(str) || hasSymbols(str) || /-|__|\s/u.test(str)) {
31✔
102
    return false;
14✔
103
  }
14✔
104
  return true;
31✔
105
}
31✔
106

1✔
107
/**
1✔
108
 * Convert text to SCREAMING_SNAKE_CASE
1✔
109
 * @param {string} str Text to be converted
1✔
110
 * @return {string}
1✔
111
 */
1✔
112
export function screamingSnakeCase(str: string): string {
1✔
113
  let res = str.replace(/-/gu, "_");
10✔
114
  if (hasLower(res)) {
10✔
UNCOV
115
    res = res.replace(/\B([A-Z])/gu, "_$1");
×
UNCOV
116
  }
×
UNCOV
117
  return res.toUpperCase();
×
UNCOV
118
}
×
UNCOV
119

×
UNCOV
120
/**
×
UNCOV
121
 * Checks whether the given string is SCREAMING_SNAKE_CASE.
×
UNCOV
122
 * @param {string} str
×
UNCOV
123
 */
×
UNCOV
124
export function isScreamingSnakeCase(str: string): boolean {
✔
125
  if (hasLower(str) || hasSymbols(str) || /-|__|\s/u.test(str)) {
24✔
126
    return false;
14✔
127
  }
14✔
128
  return true;
24✔
129
}
24✔
130

1✔
131
/**
1✔
132
 * Convert text to camelCase
1✔
133
 * @param {string} str Text to be converted
1✔
134
 * @return {string} Converted string
1✔
135
 */
1✔
136
export function camelCase(str: string): string {
1✔
137
  if (isPascalCase(str)) {
32✔
138
    return str.charAt(0).toLowerCase() + str.slice(1);
12✔
139
  }
12✔
140
  let s = str;
32✔
141
  if (!hasLower(s)) {
32✔
142
    s = s.toLowerCase();
2✔
143
  }
2✔
144
  return s.replace(/[-_](\w)/gu, (_, c) => (c ? c.toUpperCase() : ""));
32!
145
}
32✔
146

1✔
147
/**
1✔
148
 * Checks whether the given string is camelCase.
1✔
149
 * @param {string} str
1✔
150
 */
1✔
151
export function isCamelCase(str: string): boolean {
1✔
152
  if (
62✔
153
    hasSymbols(str) ||
62✔
154
    /^[A-Z]/u.test(str) ||
60✔
155
    /[\s\-_]/u.test(str) // kebab or snake or space
41✔
UNCOV
156
  ) {
✔
UNCOV
157
    return false;
×
UNCOV
158
  }
×
UNCOV
159
  return true;
✔
UNCOV
160
}
×
UNCOV
161

×
UNCOV
162
/**
×
UNCOV
163
 * Convert text to PascalCase
×
UNCOV
164
 * @param {string} str Text to be converted
×
UNCOV
165
 * @return {string} Converted string
×
UNCOV
166
 */
×
167
export function pascalCase(str: string): string {
1✔
168
  return capitalize(camelCase(str));
16✔
169
}
16✔
170

1✔
171
/**
1✔
172
 * Checks whether the given string is PascalCase.
1✔
173
 * @param {string} str
1✔
174
 */
1✔
175
export function isPascalCase(str: string): boolean {
1✔
176
  if (
65✔
177
    hasSymbols(str) ||
65✔
178
    /^[a-z]/u.test(str) ||
65✔
179
    /[\s\-_]/u.test(str) // kebab or snake or space
41✔
180
  ) {
65✔
181
    return false;
36✔
UNCOV
182
  }
×
UNCOV
183
  return true;
✔
UNCOV
184
}
×
UNCOV
185

×
UNCOV
186
const convertersMap = {
×
UNCOV
187
  "kebab-case": kebabCase,
×
UNCOV
188
  snake_case: snakeCase,
×
UNCOV
189
  SCREAMING_SNAKE_CASE: screamingSnakeCase,
×
UNCOV
190
  camelCase,
×
UNCOV
191
  PascalCase: pascalCase,
×
192
};
1✔
193

1✔
194
const checkersMap = {
1✔
195
  "kebab-case": isKebabCase,
1✔
196
  snake_case: isSnakeCase,
1✔
197
  SCREAMING_SNAKE_CASE: isScreamingSnakeCase,
1✔
UNCOV
198
  camelCase: isCamelCase,
×
UNCOV
199
  PascalCase: isPascalCase,
×
UNCOV
200
};
×
UNCOV
201

×
UNCOV
202
/**
×
UNCOV
203
 * Return case checker
×
UNCOV
204
 * @param name type of checker to return ('camelCase', 'kebab-case', 'PascalCase')
×
UNCOV
205
 */
×
206
export function getChecker(name: CasingKind): (str: string) => boolean {
1✔
207
  return checkersMap[name] || isPascalCase;
31!
208
}
31✔
209

1✔
210
/**
1✔
211
 * Return case converter
1✔
212
 * @param name type of converter to return
1✔
213
 */
1✔
214
export function getConverter(name: CasingKind): (str: string) => string {
1✔
215
  return convertersMap[name] || pascalCase;
5!
216
}
5✔
217

1✔
218
/**
1✔
219
 * Return case exact converter.
1✔
220
 * If the converted result is not the correct case, the original value is returned.
1✔
221
 * @param name type of converter to return ('camelCase', 'kebab-case', 'PascalCase')
1✔
222
 */
1✔
223
export function getExactConverter(name: CasingKind): (str: string) => string {
1✔
UNCOV
224
  const converter = getConverter(name);
×
UNCOV
225
  const checker = getChecker(name);
×
UNCOV
226
  return (str: string) => {
×
UNCOV
227
    const result = converter(str);
×
UNCOV
228
    return checker(result) ? result : str; /* cannot convert */
×
UNCOV
229
  };
×
UNCOV
230
}
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc