simple-merge-class-names 2.0.4 → 3.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -11,7 +11,11 @@ A straightforward utility for merging CSS class names in `React + Tailwind` and
11
11
  - [Workflow To Minimize Typing Strain](#workflow-to-minimize-typing-strain)
12
12
 
13
13
  - [Argument Handling](#argument-handling)
14
+
14
15
  - [Breaking Changes From Version 1.X.X](#breaking-changes-from-version-1xx)
16
+
17
+ - [Console Warning for Invalid Arguments](#console-warning-for-invalid-arguments)
18
+
15
19
  - [Testing](#testing)
16
20
  - [Source Code](#source-code)
17
21
  - [Misc.](#misc)
@@ -103,6 +107,18 @@ function MyComponent() {
103
107
 
104
108
  In pervious versions, arguments that were not strings were implicitly converted to strings by the JavaScript engine.
105
109
 
110
+ ### Console Warning for Invalid Arguments
111
+
112
+ Invalid arguments are not silently ignored, as they may indicate a deeper issue. A single warning is logged to the developer console whenever these arguments are passed and ignored.
113
+
114
+ Example output:
115
+
116
+ ```plaintext
117
+ [mergeClassNames] Warning: invalid arguments were provided and were ignored:
118
+ - Expected all arguments to be strings, but got 4 non-string values: [(1/4): (undefined) of type "undefined", (2/4): (test) of type "object", (3/4): ([object Object]) of type "object", (4/4): (null) of type "object"].
119
+ - Expected 0 empty strings, but got 2.
120
+ ```
121
+
106
122
  ## Testing
107
123
 
108
124
  This project uses `Vitest` as the test runner for fast, modern testing.
@@ -129,20 +145,34 @@ pnpm test:watch
129
145
 
130
146
  const isTypeString = (val) => typeof val === "string";
131
147
 
132
- const isNotEmptyString = (val) => val !== "";
148
+ const isNonEmptyString = (val) => val !== "";
149
+
150
+ const partition = (array, keepPredicate) => {
151
+ const keep = [];
152
+ const ignore = [];
153
+ for (const element of array) {
154
+ (keepPredicate(element) ? keep : ignore).push(element);
155
+ }
156
+ return [keep, ignore];
157
+ };
133
158
 
134
159
  export const mergeClassNames = (...args) => {
135
- const space = "\x20"; // " "; ASCII code for single space character;
160
+ const space = "\x20"; // ASCII code for a single space character (" "), decimal 32
136
161
 
137
- const stringsOnly = args.filter((val) => isTypeString(val));
162
+ const [strings, nonStrings] = partition(args, isTypeString);
138
163
 
139
- const trimmed = stringsOnly.map((val) => val.trim());
164
+ const trimmed = strings.map((val) => val.trim());
140
165
 
141
- const nonEmpty = trimmed.filter((val) => isNotEmptyString(val));
166
+ const [nonEmptyStrings, emptyStrings] = partition(
167
+ trimmed,
168
+ isNonEmptyString
169
+ );
142
170
 
143
- const className = nonEmpty.join(space);
144
- return className;
145
- };
171
+ const className = nonEmptyStrings.join(space);
172
+
173
+ /* Don't silently ignore invalid input, explicitly disclose them as it indicate a bigger problem */
174
+ const warn = [];
175
+ /* ... */
146
176
  ```
147
177
 
148
178
  ## Misc.
@@ -1 +1 @@
1
- export declare const mergeClassNames: (...args: unknown[]) => string;
1
+ export declare const mergeClassNames: (...args: string[]) => string;
@@ -39,17 +39,65 @@
39
39
 
40
40
  const isTypeString = (val) => typeof val === "string";
41
41
 
42
- const isNotEmptyString = (val) => val !== "";
42
+ const isNonEmptyString = (val) => val !== "";
43
+
44
+ const partition = (array, keepPredicate) => {
45
+ const keep = [];
46
+ const ignore = [];
47
+ for (const element of array) {
48
+ (keepPredicate(element) ? keep : ignore).push(element);
49
+ }
50
+ return [keep, ignore];
51
+ };
43
52
 
44
53
  export const mergeClassNames = (...args) => {
45
- const space = "\x20"; // " "; ASCII code for single space character;
54
+ const space = "\x20"; // ASCII code for a single space character (" "), decimal 32
55
+
56
+ const [strings, nonStrings] = partition(args, isTypeString);
57
+
58
+ const trimmed = strings.map((val) => val.trim());
59
+
60
+ const [nonEmptyStrings, emptyStrings] = partition(
61
+ trimmed,
62
+ isNonEmptyString
63
+ );
64
+
65
+ const className = nonEmptyStrings.join(space);
66
+
67
+ /* Don't silently ignore invalid input, explicitly disclose them as it indicate a bigger problem */
68
+ const warn = [];
69
+
70
+ /* "Expected all arguments to be strings ..." */
71
+ if (nonStrings.length > 0) {
72
+ const join = ", ";
73
+ const count = nonStrings.length;
74
+ const formatGotArray = (element, index) =>
75
+ `(${index + 1}/${count}): (${element}) of type "${typeof element}"`;
76
+ const message = nonStrings.map(formatGotArray).join(join);
77
+
78
+ warn.push(
79
+ `Expected all arguments to be strings, but got ${count} non-string values: [${message}].`
80
+ );
81
+ }
46
82
 
47
- const stringsOnly = args.filter((val) => isTypeString(val));
83
+ /* "Expected 0 empty strings ..." */
84
+ if (nonEmptyStrings.length > 0) {
85
+ const count = emptyStrings.length;
86
+ warn.push(`Expected 0 empty strings, but got ${count}.`);
87
+ }
48
88
 
49
- const trimmed = stringsOnly.map((val) => val.trim());
89
+ /* Full Warn Message */
90
+ if (warn.length > 0) {
91
+ const newline = "\n";
92
+ const prefix = "\t" + "- ";
93
+ const message = warn.map((text) => `${prefix}${text}`).join(newline);
50
94
 
51
- const nonEmpty = trimmed.filter((val) => isNotEmptyString(val));
95
+ console.warn(
96
+ "[mergeClassNames] Warning: invalid arguments were provided and were ignored:",
97
+ newline,
98
+ message
99
+ );
100
+ }
52
101
 
53
- const className = nonEmpty.join(space);
54
102
  return className;
55
103
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "simple-merge-class-names",
3
- "version": "2.0.4",
3
+ "version": "3.0.1",
4
4
  "description": "A straightforward utility for merging CSS class names in React + Tailwind and JavaScript projects.",
5
5
  "exports": {
6
6
  ".": {