@nyaomaru/divider 1.7.3 → 1.8.0

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
@@ -130,6 +130,22 @@ const result = dividerLoop('abcdefghij', 3);
130
130
  // Supports flatten option for string[]
131
131
  const result2 = dividerLoop(['hello', 'world'], 2, { flatten: true });
132
132
  // ['he', 'll', 'ow', 'or', 'ld']
133
+
134
+ // You can also control where to start dividing using `startOffset`
135
+ const result3 = dividerLoop('abcdefghij', 3, { startOffset: 1 });
136
+ // ['abcd', 'efg', 'hij']
137
+
138
+ // Combine with flatten and trim
139
+ const result4 = dividerLoop([' hello ', 'world '], 2, {
140
+ flatten: true,
141
+ trim: true,
142
+ startOffset: 1,
143
+ });
144
+ // ['h', 'el', 'lo', 'wor', 'ld']
145
+
146
+ // Limit the number of chunks using maxChunks
147
+ const result5 = dividerLoop('abcdefghij', 3, { maxChunks: 2 });
148
+ // ['abc', 'defghij']
133
149
  ```
134
150
 
135
151
  ### 📌 `dividerNumberString()` Usage
@@ -150,22 +166,22 @@ const result3 = dividerNumberString(['abc123', '45z'], { flatten: true });
150
166
  // ['abc', '123', '45', 'z']
151
167
  ```
152
168
 
153
- ## 🎯 Options
169
+ ## 🎯 General Options
154
170
 
155
- | Option | Type | Default | Description |
156
- | -------------- | ----------| ------- | ------------------------------------------------------------------------- |
157
- | `flatten` | `boolean` | `false` | If `true`, the resulting nested arrays are flattened into a single array. |
158
- | `trim` | `boolean` | `false` | If `true`, trims whitespace from each divided segment. |
159
- | `excludeEmpty` | `boolean` | `false` | If `true`, removes empty strings or strings with only whitespace. |
171
+ | Option | Type | Default | Description |
172
+ | --------- | ------------------------------------ | -------- | ------------------------------------------------------------------------- |
173
+ | `flatten` | `boolean` | `false` | If `true`, the resulting nested arrays are flattened into a single array. |
174
+ | `trim` | `boolean` | `false` | If `true`, trims whitespace from each divided segment. |
175
+ | `exclude` | `'none' / 'empty' / 'whitespace'` | `'none'` | See detailed explanation below |
160
176
 
161
177
  ### `flatten` (default: `false`)
162
178
 
163
179
  ```ts
164
180
  const words = ['hello', 'world'];
165
- const result1 = divider(words, 2);
181
+ const result = divider(words, 2);
166
182
  // [['he', 'llo'], ['wo', 'rld']]
167
183
 
168
- const result2 = divider(words, 2, { flatten: true });
184
+ const result = divider(words, 2, { flatten: true });
169
185
  // ['he', 'llo', 'wo', 'rld']
170
186
  ```
171
187
 
@@ -175,28 +191,47 @@ const result2 = divider(words, 2, { flatten: true });
175
191
  const result = divider(' hello world ', 7, { trim: true });
176
192
  // ['hello', 'world']
177
193
 
178
- const result2 = divider([' a ', ' b c '], ' ', {
194
+ const result = divider([' a ', ' b c '], ' ', {
179
195
  flatten: true,
180
196
  trim: true,
181
197
  });
182
198
  // ['a', 'b', 'c']
183
199
  ```
184
200
 
185
- ### `excludeEmpty` (default: `false`)
201
+ ### `exclude` (default: `'none'`)
202
+
203
+ | Option | Description |
204
+ | -------------- | ------------------------------------------------------------------------ |
205
+ | `'none'` | Do not exclude any segments (all results are kept). |
206
+ | `'empty'` | Exclude empty strings (`''`). |
207
+ | `'whitespace'` | Exclude strings that contain only whitespace characters (e.g., `' '`). |
208
+
209
+ Control how segments like empty strings (`''`) or whitespace-only strings (`' '`) are handled.
186
210
 
187
211
  ```ts
188
- // Remove empty strings or strings with only spaces
189
- const result = divider('a, ,b', ',', { trim: true, excludeEmpty: true });
212
+ // Remove truly empty strings
213
+ const result = divider('a,,b', ',', { exclude: 'empty' });
190
214
  // ['a', 'b']
191
215
 
192
- const result2 = divider([' a ', ' ', ' b'], ' ', {
193
- flatten: true,
216
+ // Remove both empty and whitespace-only strings
217
+ const result = divider('a, ,b', ',', { exclude: 'whitespace' });
218
+ // ['a', 'b']
219
+
220
+ // You can combine with `trim` for clearer results
221
+ const result = divider('a, ,b', ',', {
194
222
  trim: true,
195
- excludeEmpty: true,
223
+ exclude: 'whitespace',
196
224
  });
197
225
  // ['a', 'b']
198
226
  ```
199
227
 
228
+ ## Special Options
229
+
230
+ | Option | Type | Default | Description |
231
+ | ------------- | -------- | ------- | ------------------------------------------------------------------------------------------------------- |
232
+ | `startOffset` | `number` | `0` | Starting index offset when dividing into chunks (only for `dividerLoop`) |
233
+ | `maxChunks` | `number` | `∞` | Maximum number of chunks allowed. Extra chunks are joined into the last chunk. (only for `dividerLoop`) |
234
+
200
235
  ## 💡 Features
201
236
 
202
237
  - 🧩 Flexible Division: Index-based and string-based separators
package/dist/index.cjs CHANGED
@@ -28,9 +28,6 @@ __export(index_exports, {
28
28
  });
29
29
  module.exports = __toCommonJS(index_exports);
30
30
 
31
- // src/utils/constants.ts
32
- var dividerOptionKeys = ["flatten", "trim", "excludeEmpty"];
33
-
34
31
  // src/utils/is.ts
35
32
  function isString(arg) {
36
33
  return typeof arg === "string";
@@ -40,7 +37,7 @@ function isNumber(arg) {
40
37
  }
41
38
  function isOptions(arg) {
42
39
  if (typeof arg !== "object" || arg === null) return false;
43
- return dividerOptionKeys.some((key) => key in arg);
40
+ return "flatten" in arg || "trim" in arg || "exclude" in arg;
44
41
  }
45
42
  function isEmptyArray(input) {
46
43
  return Array.isArray(input) && input.length === 0;
@@ -60,6 +57,12 @@ function isNestedStringArray(input) {
60
57
  function isWhitespaceOnly(s) {
61
58
  return s.trim() === "";
62
59
  }
60
+ function isEmptyString(s) {
61
+ return s === "";
62
+ }
63
+ function isNoneMode(mode) {
64
+ return mode === "none";
65
+ }
63
66
 
64
67
  // src/utils/regex.ts
65
68
  var regexCache = /* @__PURE__ */ new Map();
@@ -116,6 +119,13 @@ function ensureStringArray(input) {
116
119
  return isString(input) ? [input] : input;
117
120
  }
118
121
 
122
+ // src/utils/exclude-predicate.ts
123
+ var excludePredicateMap = {
124
+ none: () => true,
125
+ empty: (s) => !isEmptyString(s),
126
+ whitespace: (s) => !isWhitespaceOnly(s)
127
+ };
128
+
119
129
  // src/utils/option.ts
120
130
  function extractOptions(args) {
121
131
  const clonedArgs = [...args];
@@ -138,8 +148,15 @@ function applyDividerOptions(result, options) {
138
148
  if (options.flatten) {
139
149
  output = output.flat();
140
150
  }
141
- if (options.excludeEmpty) {
142
- output = isNestedStringArray(output) ? output.filter((arr) => arr.some((s) => !isWhitespaceOnly(s))) : output.filter((s) => !isWhitespaceOnly(s));
151
+ if (!isNoneMode(options.exclude)) {
152
+ const exclude = options.exclude ?? "none";
153
+ let shouldKeep = () => true;
154
+ if (exclude in excludePredicateMap) {
155
+ shouldKeep = excludePredicateMap[exclude];
156
+ }
157
+ const filterNested = (arr) => arr.map((row) => row.filter(shouldKeep)).filter((row) => row.length > 0);
158
+ const filterFlat = (arr) => arr.filter(shouldKeep);
159
+ output = isNestedStringArray(output) ? filterNested(output) : filterFlat(output);
143
160
  }
144
161
  return output;
145
162
  }
@@ -205,7 +222,17 @@ function dividerLoop(input, size, options) {
205
222
  console.warn("dividerLoop: chunk size must be a positive number");
206
223
  return [];
207
224
  }
208
- const applyChunking = (str) => divider(str, ...generateIndexes(str, size, options?.startOffset ?? 0));
225
+ const { startOffset = 0, maxChunks } = options ?? {};
226
+ const applyChunking = (str) => {
227
+ let chunks = divider(str, ...generateIndexes(str, size, startOffset));
228
+ const shouldTruncateChunks = isNumber(maxChunks) && maxChunks > 0 && chunks.length > maxChunks;
229
+ if (shouldTruncateChunks) {
230
+ const head = chunks.slice(0, maxChunks - 1);
231
+ const tail = chunks.slice(maxChunks - 1).join("");
232
+ chunks = [...head, tail];
233
+ }
234
+ return chunks;
235
+ };
209
236
  if (isString(input)) {
210
237
  const result2 = applyChunking(input);
211
238
  return applyDividerOptions(result2, options ?? {});
package/dist/index.d.cts CHANGED
@@ -1,10 +1,13 @@
1
- declare const dividerOptionKeys: readonly ["flatten", "trim", "excludeEmpty"];
2
-
3
- type DividerOptionKey = (typeof dividerOptionKeys)[number];
1
+ type DividerExcludeMode = 'none' | 'empty' | 'whitespace';
4
2
  type DividerResult<T extends string | string[]> = T extends string ? string[] : string[][];
5
- type DividerOptions = Partial<Record<DividerOptionKey, boolean>>;
3
+ type DividerOptions = {
4
+ flatten?: boolean;
5
+ trim?: boolean;
6
+ exclude?: DividerExcludeMode;
7
+ };
6
8
  type DividerLoopOptions = DividerOptions & {
7
9
  startOffset?: number;
10
+ maxChunks?: number;
8
11
  };
9
12
  type DividerSeparators = (number | string)[];
10
13
  type DividerArgs = DividerSeparators | [...DividerSeparators, DividerOptions];
@@ -19,4 +22,4 @@ declare function dividerLoop<T extends string | string[]>(input: T, size: number
19
22
 
20
23
  declare function dividerNumberString<T extends string | string[]>(input: T, options?: DividerOptions): DividerResult<T>;
21
24
 
22
- export { type DividerArgs, type DividerLoopOptions, type DividerOptionKey, type DividerOptions, type DividerResult, type DividerSeparators, divider, dividerFirst, dividerLast, dividerLoop, dividerNumberString };
25
+ export { type DividerArgs, type DividerExcludeMode, type DividerLoopOptions, type DividerOptions, type DividerResult, type DividerSeparators, divider, dividerFirst, dividerLast, dividerLoop, dividerNumberString };
package/dist/index.d.ts CHANGED
@@ -1,10 +1,13 @@
1
- declare const dividerOptionKeys: readonly ["flatten", "trim", "excludeEmpty"];
2
-
3
- type DividerOptionKey = (typeof dividerOptionKeys)[number];
1
+ type DividerExcludeMode = 'none' | 'empty' | 'whitespace';
4
2
  type DividerResult<T extends string | string[]> = T extends string ? string[] : string[][];
5
- type DividerOptions = Partial<Record<DividerOptionKey, boolean>>;
3
+ type DividerOptions = {
4
+ flatten?: boolean;
5
+ trim?: boolean;
6
+ exclude?: DividerExcludeMode;
7
+ };
6
8
  type DividerLoopOptions = DividerOptions & {
7
9
  startOffset?: number;
10
+ maxChunks?: number;
8
11
  };
9
12
  type DividerSeparators = (number | string)[];
10
13
  type DividerArgs = DividerSeparators | [...DividerSeparators, DividerOptions];
@@ -19,4 +22,4 @@ declare function dividerLoop<T extends string | string[]>(input: T, size: number
19
22
 
20
23
  declare function dividerNumberString<T extends string | string[]>(input: T, options?: DividerOptions): DividerResult<T>;
21
24
 
22
- export { type DividerArgs, type DividerLoopOptions, type DividerOptionKey, type DividerOptions, type DividerResult, type DividerSeparators, divider, dividerFirst, dividerLast, dividerLoop, dividerNumberString };
25
+ export { type DividerArgs, type DividerExcludeMode, type DividerLoopOptions, type DividerOptions, type DividerResult, type DividerSeparators, divider, dividerFirst, dividerLast, dividerLoop, dividerNumberString };
package/dist/index.js CHANGED
@@ -1,6 +1,3 @@
1
- // src/utils/constants.ts
2
- var dividerOptionKeys = ["flatten", "trim", "excludeEmpty"];
3
-
4
1
  // src/utils/is.ts
5
2
  function isString(arg) {
6
3
  return typeof arg === "string";
@@ -10,7 +7,7 @@ function isNumber(arg) {
10
7
  }
11
8
  function isOptions(arg) {
12
9
  if (typeof arg !== "object" || arg === null) return false;
13
- return dividerOptionKeys.some((key) => key in arg);
10
+ return "flatten" in arg || "trim" in arg || "exclude" in arg;
14
11
  }
15
12
  function isEmptyArray(input) {
16
13
  return Array.isArray(input) && input.length === 0;
@@ -30,6 +27,12 @@ function isNestedStringArray(input) {
30
27
  function isWhitespaceOnly(s) {
31
28
  return s.trim() === "";
32
29
  }
30
+ function isEmptyString(s) {
31
+ return s === "";
32
+ }
33
+ function isNoneMode(mode) {
34
+ return mode === "none";
35
+ }
33
36
 
34
37
  // src/utils/regex.ts
35
38
  var regexCache = /* @__PURE__ */ new Map();
@@ -86,6 +89,13 @@ function ensureStringArray(input) {
86
89
  return isString(input) ? [input] : input;
87
90
  }
88
91
 
92
+ // src/utils/exclude-predicate.ts
93
+ var excludePredicateMap = {
94
+ none: () => true,
95
+ empty: (s) => !isEmptyString(s),
96
+ whitespace: (s) => !isWhitespaceOnly(s)
97
+ };
98
+
89
99
  // src/utils/option.ts
90
100
  function extractOptions(args) {
91
101
  const clonedArgs = [...args];
@@ -108,8 +118,15 @@ function applyDividerOptions(result, options) {
108
118
  if (options.flatten) {
109
119
  output = output.flat();
110
120
  }
111
- if (options.excludeEmpty) {
112
- output = isNestedStringArray(output) ? output.filter((arr) => arr.some((s) => !isWhitespaceOnly(s))) : output.filter((s) => !isWhitespaceOnly(s));
121
+ if (!isNoneMode(options.exclude)) {
122
+ const exclude = options.exclude ?? "none";
123
+ let shouldKeep = () => true;
124
+ if (exclude in excludePredicateMap) {
125
+ shouldKeep = excludePredicateMap[exclude];
126
+ }
127
+ const filterNested = (arr) => arr.map((row) => row.filter(shouldKeep)).filter((row) => row.length > 0);
128
+ const filterFlat = (arr) => arr.filter(shouldKeep);
129
+ output = isNestedStringArray(output) ? filterNested(output) : filterFlat(output);
113
130
  }
114
131
  return output;
115
132
  }
@@ -175,7 +192,17 @@ function dividerLoop(input, size, options) {
175
192
  console.warn("dividerLoop: chunk size must be a positive number");
176
193
  return [];
177
194
  }
178
- const applyChunking = (str) => divider(str, ...generateIndexes(str, size, options?.startOffset ?? 0));
195
+ const { startOffset = 0, maxChunks } = options ?? {};
196
+ const applyChunking = (str) => {
197
+ let chunks = divider(str, ...generateIndexes(str, size, startOffset));
198
+ const shouldTruncateChunks = isNumber(maxChunks) && maxChunks > 0 && chunks.length > maxChunks;
199
+ if (shouldTruncateChunks) {
200
+ const head = chunks.slice(0, maxChunks - 1);
201
+ const tail = chunks.slice(maxChunks - 1).join("");
202
+ chunks = [...head, tail];
203
+ }
204
+ return chunks;
205
+ };
179
206
  if (isString(input)) {
180
207
  const result2 = applyChunking(input);
181
208
  return applyDividerOptions(result2, options ?? {});
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@nyaomaru/divider",
3
3
  "type": "module",
4
- "version": "1.7.3",
4
+ "version": "1.8.0",
5
5
  "description": "To divide string or string[] with a given separator",
6
6
  "main": "./dist/index.cjs",
7
7
  "module": "./dist/index.js",