utilitish 0.0.8 → 0.0.9

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
@@ -3,3 +3,63 @@
3
3
  Ce projet est distribué sous licence [GPL v3](https://www.gnu.org/licenses/gpl-3.0.html) © 2025 Donovan Ferreira.
4
4
 
5
5
  Ceci est une petite librairie qui ajoute plusieurs méthodes au prototype JavaScript.
6
+
7
+ ## Configuration Slugify
8
+
9
+ La méthode `slugify()` peut être personnalisée pour répondre à vos besoins spécifiques. Consultez la JSDoc dans votre IDE pour voir tous les exemples disponibles.
10
+
11
+ ### Configuration globale
12
+
13
+ Vous pouvez définir une configuration globale qui s'appliquera à tous les appels `slugify()` :
14
+
15
+ ```typescript
16
+ import { setSlugifyConfig } from 'utilitish';
17
+
18
+ // Configuration pour remplacer les symboles de genre
19
+ setSlugifyConfig({
20
+ customReplacements: {
21
+ '♀': 'feminin',
22
+ '♂': 'masculin',
23
+ },
24
+ separator: '_',
25
+ });
26
+
27
+ 'Test ♀'.slugify(); // "test_feminin"
28
+ 'User♂@domain.com'.slugify(); // "user_masculin_at_domain_com"
29
+ ```
30
+
31
+ ### Configuration par appel
32
+
33
+ Vous pouvez aussi passer une configuration spécifique à chaque appel :
34
+
35
+ ```typescript
36
+ // Utilise la config globale
37
+ 'Hello World'.slugify(); // "hello-world"
38
+
39
+ // Override la config pour cet appel
40
+ 'Hello World'.slugify({ separator: '_' }); // "hello_world"
41
+ ```
42
+
43
+ ### Options de configuration
44
+
45
+ - **`customReplacements`**: Remplacer des caractères spécifiques (ex: "♀" → "feminin")
46
+ - **`separator`**: Caractère de séparation (défaut: "-")
47
+ - **`lowercase`**: Convertir en minuscules (défaut: true)
48
+ - **`removeAccents`**: Supprimer les accents (défaut: true)
49
+ - **`allowedChars`**: Regex des caractères autorisés (défaut: /[a-zA-Z0-9]/)
50
+ - **`maxLength`**: Longueur maximale du slug
51
+ - **`transformers`**: Fonctions de transformation personnalisées
52
+
53
+ ### Gestion de la configuration
54
+
55
+ ```typescript
56
+ import { getSlugifyConfig, resetSlugifyConfig } from 'utilitish';
57
+
58
+ // Obtenir la config actuelle
59
+ const currentConfig = getSlugifyConfig();
60
+
61
+ // Réinitialiser aux valeurs par défaut
62
+ resetSlugifyConfig();
63
+ ```
64
+
65
+ Pour plus d'exemples et cas d'usage avancés, consultez les JSDoc intégrées dans votre IDE.
@@ -47,7 +47,7 @@ declare global {
47
47
  * - Returns 0 for empty arrays regardless of type
48
48
  */
49
49
  sum(this: number[]): number;
50
- sum(this: T[], selector?: Selector<T, number>): number;
50
+ sum(this: T[], selector: Selector<T, number>): number;
51
51
  /**
52
52
  * Returns a new array with only unique elements based on strict equality (===).
53
53
  * Preserves order of first occurrence.
@@ -187,7 +187,8 @@ declare global {
187
187
  * - Returns new array; does not mutate original
188
188
  * - Empty arrays return empty array
189
189
  */
190
- sortAsc(this: T[], selector?: Selector<T, number | string>): T[];
190
+ sortAsc(this: (number | string)[]): T[];
191
+ sortAsc(this: T[], selector: Selector<T, number | string>): T[];
191
192
  /**
192
193
  * Returns a new sorted copy of the array in descending order.
193
194
  * Creates a new array without modifying the original.
@@ -210,7 +211,8 @@ declare global {
210
211
  * - Returns new array; does not mutate original
211
212
  * - Empty arrays return empty array
212
213
  */
213
- sortDesc(this: T[], selector?: Selector<T, number | string>): T[];
214
+ sortDesc(this: (number | string)[]): T[];
215
+ sortDesc(this: T[], selector: Selector<T, number | string>): T[];
214
216
  /**
215
217
  * Swaps the elements at two indices within the array.
216
218
  * Modifies the array in place and returns the array itself (for chaining).
@@ -121,8 +121,26 @@ const logic_utils_1 = require("../utils/logic.utils");
121
121
  return map;
122
122
  });
123
123
  (0, core_utils_1.defineIfNotExists)(Array.prototype, 'toObject', function (keySelector, valueSelector) {
124
- const map = this.toMap(keySelector, valueSelector);
125
- return (0, logic_utils_1.mapToObject)(map);
124
+ let entries;
125
+ if (!keySelector && this.length && this.every((item) => Array.isArray(item) && item.length === 2)) {
126
+ entries = this;
127
+ }
128
+ else {
129
+ const getKey = (0, core_utils_1.resolveSelector)(keySelector, (_, index) => index);
130
+ const getValue = (0, core_utils_1.resolveSelector)(valueSelector, (item) => item);
131
+ entries = this.map((item, index) => [getKey(item, index), getValue(item)]);
132
+ }
133
+ // Validate keys
134
+ for (const [key] of entries) {
135
+ if (key === null || key === undefined) {
136
+ throw new TypeError(`Invalid key: key cannot be null or undefined. Key received: ${String(key)}`);
137
+ }
138
+ const keyType = typeof key;
139
+ if (keyType !== 'string' && keyType !== 'number' && keyType !== 'symbol') {
140
+ throw new TypeError(`Invalid key type: keys must be string, number, or symbol, received ${keyType}. Key value: ${String(key)}`);
141
+ }
142
+ }
143
+ return Object.fromEntries(entries);
126
144
  });
127
145
  (0, core_utils_1.defineIfNotExists)(Array.prototype, 'toSet', function (selector) {
128
146
  const getValue = (0, core_utils_1.resolveSelector)(selector, (item) => item);
package/dist/index.d.ts CHANGED
@@ -4,3 +4,4 @@ import './map/map-prototype';
4
4
  import './object/object-prototype';
5
5
  import './set/set-prototype';
6
6
  import './string/string-prototype';
7
+ export { getSlugifyConfig, resetSlugifyConfig, setSlugifyConfig, type SlugifyConfig } from './utils/slugify.config';
package/dist/index.js CHANGED
@@ -1,8 +1,14 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.setSlugifyConfig = exports.resetSlugifyConfig = exports.getSlugifyConfig = void 0;
3
4
  require("./array/array-constructor");
4
5
  require("./array/array-prototype");
5
6
  require("./map/map-prototype");
6
7
  require("./object/object-prototype");
7
8
  require("./set/set-prototype");
8
9
  require("./string/string-prototype");
10
+ // Export slugify configuration functions
11
+ var slugify_config_1 = require("./utils/slugify.config");
12
+ Object.defineProperty(exports, "getSlugifyConfig", { enumerable: true, get: function () { return slugify_config_1.getSlugifyConfig; } });
13
+ Object.defineProperty(exports, "resetSlugifyConfig", { enumerable: true, get: function () { return slugify_config_1.resetSlugifyConfig; } });
14
+ Object.defineProperty(exports, "setSlugifyConfig", { enumerable: true, get: function () { return slugify_config_1.setSlugifyConfig; } });
@@ -1,7 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const core_utils_1 = require("../utils/core.utils");
4
- const logic_utils_1 = require("../utils/logic.utils");
5
4
  /**
6
5
  * @see Map.prototype.toList
7
6
  */
@@ -34,7 +33,17 @@ const logic_utils_1 = require("../utils/logic.utils");
34
33
  * @see Map.prototype.toObject
35
34
  */
36
35
  (0, core_utils_1.defineIfNotExists)(Map.prototype, 'toObject', function () {
37
- return (0, logic_utils_1.mapToObject)(this);
36
+ const entries = Array.from(this.entries());
37
+ for (const [key] of entries) {
38
+ if (key === null || key === undefined) {
39
+ throw new TypeError(`Invalid key: key cannot be null or undefined. Key received: ${String(key)}`);
40
+ }
41
+ const keyType = typeof key;
42
+ if (keyType !== 'string' && keyType !== 'number' && keyType !== 'symbol') {
43
+ throw new TypeError(`Invalid key type: keys must be string, number, or symbol, received ${keyType}. Key value: ${String(key)}`);
44
+ }
45
+ }
46
+ return Object.fromEntries(entries);
38
47
  });
39
48
  /**
40
49
  * @see Map.prototype.ensureArray
@@ -1,3 +1,4 @@
1
+ import { SlugifyConfig } from '../utils/slugify.config';
1
2
  declare global {
2
3
  interface String {
3
4
  /**
@@ -137,24 +138,61 @@ declare global {
137
138
  /**
138
139
  * Converts the string into a URL-friendly slug format.
139
140
  * Combines normalization, lowercasing, whitespace handling, and special character removal.
141
+ * Can be customized using global configuration or per-call options.
140
142
  *
141
143
  * @this {string} The string to slugify
144
+ * @param {SlugifyConfig} [config] - Optional configuration to override global settings
142
145
  * @returns {string} A URL-safe slug version of the string
143
146
  *
144
147
  * @example
148
+ * // Basic usage (default config)
145
149
  * 'Hello World'.slugify(); // 'hello-world'
146
150
  * 'Héllo Wørld'.slugify(); // 'hello-world'
147
151
  * 'Hello World!!!'.slugify(); // 'hello-world'
148
152
  *
153
+ * @example
154
+ * // Custom replacements
155
+ * 'Test ♀'.slugify({ customReplacements: { "♀": "feminin" } }); // 'test-feminin'
156
+ * 'User♂@domain.com'.slugify({ customReplacements: { "♂": "masculin", "@": "at" } }); // 'usermasculinatdomain-com'
157
+ *
158
+ * @example
159
+ * // Custom separator
160
+ * 'Hello World'.slugify({ separator: "_" }); // 'hello_world'
161
+ * 'Hello World'.slugify({ separator: "--" }); // 'hello--world'
162
+ *
163
+ * @example
164
+ * // Preserve accents
165
+ * 'Éléphant'.slugify({ removeAccents: false }); // 'éléphant'
166
+ *
167
+ * @example
168
+ * // Disable lowercasing
169
+ * 'Hello World'.slugify({ lowercase: false }); // 'Hello-World'
170
+ *
171
+ * @example
172
+ * // Max length
173
+ * 'Very long string'.slugify({ maxLength: 8 }); // 'very-lon'
174
+ *
175
+ * @example
176
+ * // Custom transformers
177
+ * 'hello world'.slugify({
178
+ * transformers: [(str) => str.replace(/world/g, 'universe')]
179
+ * }); // 'hello-universe'
180
+ *
149
181
  * @remarks
150
- * - Normalizes Unicode characters (NFD decomposition)
151
- * - Removes accents and diacritical marks
152
- * - Converts to lowercase
153
- * - Replaces spaces and special characters with hyphens
154
- * - Removes leading/trailing hyphens
155
- * - Collapses multiple consecutive hyphens into one
182
+ * - Uses global configuration by default (see setSlugifyConfig)
183
+ * - Normalizes Unicode characters (NFD decomposition) by default
184
+ * - Removes accents and diacritical marks by default
185
+ * - Converts to lowercase by default
186
+ * - Replaces spaces and special characters with separator (hyphen by default)
187
+ * - Removes leading/trailing separators
188
+ * - Collapses multiple consecutive separators into one
189
+ *
190
+ * @see setSlugifyConfig
191
+ * @see getSlugifyConfig
192
+ * @see resetSlugifyConfig
156
193
  */
157
194
  slugify(): string;
195
+ slugify(config: SlugifyConfig): string;
158
196
  /**
159
197
  * Replaces a substring between `start` and `end` indices with a given string.
160
198
  * Provides precise control over which portion of the string to replace.
@@ -178,4 +216,3 @@ declare global {
178
216
  replaceRange(start: number, end: number, replaceString?: string): string;
179
217
  }
180
218
  }
181
- export {};
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const core_utils_1 = require("../utils/core.utils");
4
+ const slugify_utils_1 = require("../utils/slugify.utils");
4
5
  /**
5
6
  * @see String.prototype.splitWords
6
7
  */
@@ -61,12 +62,8 @@ const core_utils_1 = require("../utils/core.utils");
61
62
  /**
62
63
  * @see String.prototype.slugify
63
64
  */
64
- (0, core_utils_1.defineIfNotExists)(String.prototype, 'slugify', function () {
65
- return this.normalize('NFD')
66
- .replace(/[̀-ͯ]/g, '')
67
- .replace(/[^a-zA-Z0-9]+/g, '-')
68
- .replace(/^-+|-+$/g, '')
69
- .toLowerCase();
65
+ (0, core_utils_1.defineIfNotExists)(String.prototype, 'slugify', function (config) {
66
+ return (0, slugify_utils_1.slugifyString)(this, config);
70
67
  });
71
68
  /**
72
69
  * @see String.prototype.capitalize
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  require("../string/string-prototype");
4
+ const slugify_config_1 = require("../utils/slugify.config");
4
5
  describe('String.prototype', () => {
5
6
  describe('capitalize()', () => {
6
7
  it('should capitalize the first character', () => {
@@ -67,11 +68,80 @@ describe('String.prototype', () => {
67
68
  });
68
69
  });
69
70
  describe('slugify()', () => {
70
- it('should slugify a string', () => {
71
+ beforeEach(() => {
72
+ (0, slugify_config_1.resetSlugifyConfig)(); // Reset to defaults before each test
73
+ });
74
+ it('should slugify a string with default config', () => {
71
75
  expect('Hello World!'.slugify()).toBe('hello-world');
72
76
  expect("Éléphant à l'été".slugify()).toBe('elephant-a-l-ete');
73
77
  expect(' --Hello__World-- '.slugify()).toBe('hello-world');
74
78
  });
79
+ describe('custom replacements', () => {
80
+ it('should apply custom replacements per call', () => {
81
+ expect('Test ♀'.slugify({ customReplacements: { '♀': 'feminin' } })).toBe('test-feminin');
82
+ expect('User♂@domain.com'.slugify({ customReplacements: { '♂': 'masculin', '@': 'at' } })).toBe('usermasculinatdomain-com');
83
+ });
84
+ it('should handle special regex characters in replacements', () => {
85
+ expect('Test [bracket]'.slugify({ customReplacements: { '[': 'left', ']': 'right' } })).toBe('test-leftbracketright');
86
+ });
87
+ });
88
+ describe('separator customization', () => {
89
+ it('should use custom separator globally', () => {
90
+ (0, slugify_config_1.setSlugifyConfig)({ separator: '_' });
91
+ expect('Hello World'.slugify()).toBe('hello_world');
92
+ expect('Test String'.slugify()).toBe('test_string');
93
+ });
94
+ it('should use custom separator per call', () => {
95
+ expect('Hello World'.slugify({ separator: '_' })).toBe('hello_world');
96
+ expect('Test String'.slugify({ separator: '__' })).toBe('test__string');
97
+ });
98
+ });
99
+ describe('case transformation', () => {
100
+ it('should respect lowercase setting globally', () => {
101
+ (0, slugify_config_1.setSlugifyConfig)({ lowercase: false });
102
+ expect('Hello World'.slugify()).toBe('Hello-World');
103
+ });
104
+ it('should respect lowercase setting per call', () => {
105
+ expect('Hello World'.slugify({ lowercase: false })).toBe('Hello-World');
106
+ });
107
+ });
108
+ describe('accent removal', () => {
109
+ it('should respect removeAccents setting per call', () => {
110
+ expect('Éléphant'.slugify({ removeAccents: false })).toBe('éléphant');
111
+ });
112
+ });
113
+ describe('allowed characters', () => {
114
+ it('should use custom allowed characters', () => {
115
+ expect('Hello123!@#'.slugify({ allowedChars: /[a-zA-Z0-9_]/ })).toBe('hello123');
116
+ });
117
+ });
118
+ describe('max length', () => {
119
+ it('should truncate to max length', () => {
120
+ expect('very-long-string-here'.slugify({ maxLength: 10 })).toBe('very-long');
121
+ expect('short'.slugify({ maxLength: 10 })).toBe('short');
122
+ });
123
+ it('should remove trailing separator after truncation', () => {
124
+ expect('hello-world-test'.slugify({ maxLength: 8 })).toBe('hello-wo');
125
+ });
126
+ });
127
+ describe('custom transformers', () => {
128
+ it('should apply custom transformers', () => {
129
+ const config = {
130
+ transformers: [
131
+ (str) => str.replace(/test/g, 'example'),
132
+ (str) => str.toUpperCase(),
133
+ ],
134
+ lowercase: false,
135
+ };
136
+ expect('this is a test'.slugify(config)).toBe('THIS-IS-A-EXAMPLE');
137
+ });
138
+ });
139
+ describe('configuration merging', () => {
140
+ it('should merge global and local config correctly', () => {
141
+ // Local config should override global defaults
142
+ expect('Test ♀'.slugify({ separator: '_', customReplacements: { '♀': 'female' } })).toBe('test_female');
143
+ });
144
+ });
75
145
  });
76
146
  describe('replaceRange()', () => {
77
147
  it('should replace a single character at the given index', () => {
@@ -1,3 +1,2 @@
1
1
  import { Selector } from './core.utils';
2
- export declare function mapToObject<K extends PropertyKey, V>(map: Map<K, V>): Record<K, V>;
3
2
  export declare function sortBy<T>(arr: T[], direction: 'asc' | 'desc', selector?: Selector<T, number | string>): T[];
@@ -1,24 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.mapToObject = mapToObject;
4
3
  exports.sortBy = sortBy;
5
4
  const core_utils_1 = require("./core.utils");
6
- function mapToObject(map) {
7
- const obj = {};
8
- for (const [key, value] of map) {
9
- // Validate that key is not null or undefined
10
- if (key === null || key === undefined) {
11
- throw new TypeError(`Invalid key: key cannot be null or undefined. Key received: ${String(key)}`);
12
- }
13
- const keyType = typeof key;
14
- // Only allow string, number, or symbol
15
- if (keyType !== 'string' && keyType !== 'number' && keyType !== 'symbol') {
16
- throw new TypeError(`Invalid key type: keys must be string, number, or symbol, received ${keyType}. Key value: ${String(key)}`);
17
- }
18
- obj[key] = value;
19
- }
20
- return obj;
21
- }
22
5
  function sortBy(arr, direction, selector) {
23
6
  if (arr.length === 0)
24
7
  return arr.slice();
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Configuration types and interfaces for the slugify functionality.
3
+ * Provides comprehensive customization options for URL slug generation.
4
+ */
5
+ export interface SlugifyConfig {
6
+ /**
7
+ * Custom character replacements applied before other transformations.
8
+ * Useful for replacing special symbols with words or other characters.
9
+ *
10
+ * @example
11
+ * { "♀": "feminin", "♂": "masculin", "@": "at" }
12
+ */
13
+ customReplacements?: Record<string, string>;
14
+ /**
15
+ * Character used to separate words in the slug.
16
+ * @default "-"
17
+ */
18
+ separator?: string;
19
+ /**
20
+ * Whether to convert the result to lowercase.
21
+ * @default true
22
+ */
23
+ lowercase?: boolean;
24
+ /**
25
+ * Whether to remove accents and diacritical marks.
26
+ * @default true
27
+ */
28
+ removeAccents?: boolean;
29
+ /**
30
+ * Regular expression pattern for characters to keep.
31
+ * Characters not matching this pattern will be replaced with the separator.
32
+ * @default "/[a-zA-Z0-9]/"
33
+ */
34
+ allowedChars?: RegExp;
35
+ /**
36
+ * Maximum length of the resulting slug (excluding separator trimming).
37
+ * If exceeded, the slug will be truncated.
38
+ * @default undefined (no limit)
39
+ */
40
+ maxLength?: number;
41
+ /**
42
+ * Custom transformation functions applied in order.
43
+ * Each function receives the current string state and should return the transformed string.
44
+ *
45
+ * @example
46
+ * [(str) => str.replace(/custom-pattern/g, 'replacement')]
47
+ */
48
+ transformers?: Array<(str: string) => string>;
49
+ }
50
+ /**
51
+ * Default configuration for slugify operations.
52
+ * Provides sensible defaults that can be overridden by users.
53
+ */
54
+ export declare const defaultSlugifyConfig: SlugifyConfig;
55
+ /**
56
+ * Sets the global slugify configuration that will be used by default.
57
+ * Merges the provided config with the existing global config.
58
+ *
59
+ * @param config - Partial configuration object to merge with current global config
60
+ *
61
+ * @example
62
+ * setSlugifyConfig({
63
+ * customReplacements: { "♀": "feminin", "♂": "masculin" },
64
+ * separator: "_"
65
+ * });
66
+ */
67
+ export declare function setSlugifyConfig(config: SlugifyConfig): void;
68
+ /**
69
+ * Gets the current global slugify configuration.
70
+ * Returns a copy to prevent external mutations.
71
+ *
72
+ * @returns Current global configuration object
73
+ */
74
+ export declare function getSlugifyConfig(): SlugifyConfig;
75
+ /**
76
+ * Resets the global slugify configuration to default values.
77
+ */
78
+ export declare function resetSlugifyConfig(): void;
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ /**
3
+ * Configuration types and interfaces for the slugify functionality.
4
+ * Provides comprehensive customization options for URL slug generation.
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.defaultSlugifyConfig = void 0;
8
+ exports.setSlugifyConfig = setSlugifyConfig;
9
+ exports.getSlugifyConfig = getSlugifyConfig;
10
+ exports.resetSlugifyConfig = resetSlugifyConfig;
11
+ /**
12
+ * Default configuration for slugify operations.
13
+ * Provides sensible defaults that can be overridden by users.
14
+ */
15
+ exports.defaultSlugifyConfig = {
16
+ customReplacements: {},
17
+ separator: '-',
18
+ lowercase: true,
19
+ removeAccents: true,
20
+ allowedChars: undefined, // Will be determined dynamically based on removeAccents
21
+ maxLength: undefined,
22
+ transformers: [],
23
+ };
24
+ /**
25
+ * Global configuration instance that can be modified by users.
26
+ * Starts with default values but can be updated via setSlugifyConfig().
27
+ */
28
+ let globalSlugifyConfig = { ...exports.defaultSlugifyConfig };
29
+ /**
30
+ * Sets the global slugify configuration that will be used by default.
31
+ * Merges the provided config with the existing global config.
32
+ *
33
+ * @param config - Partial configuration object to merge with current global config
34
+ *
35
+ * @example
36
+ * setSlugifyConfig({
37
+ * customReplacements: { "♀": "feminin", "♂": "masculin" },
38
+ * separator: "_"
39
+ * });
40
+ */
41
+ function setSlugifyConfig(config) {
42
+ globalSlugifyConfig = { ...globalSlugifyConfig, ...config };
43
+ }
44
+ /**
45
+ * Gets the current global slugify configuration.
46
+ * Returns a copy to prevent external mutations.
47
+ *
48
+ * @returns Current global configuration object
49
+ */
50
+ function getSlugifyConfig() {
51
+ return { ...globalSlugifyConfig };
52
+ }
53
+ /**
54
+ * Resets the global slugify configuration to default values.
55
+ */
56
+ function resetSlugifyConfig() {
57
+ globalSlugifyConfig = { ...exports.defaultSlugifyConfig };
58
+ }
@@ -0,0 +1,10 @@
1
+ import { SlugifyConfig } from './slugify.config';
2
+ /**
3
+ * Applies slugify transformations to a string based on the provided configuration.
4
+ * This is the core logic for converting strings to URL-friendly slugs.
5
+ *
6
+ * @param str - The input string to slugify
7
+ * @param config - Configuration object (uses global config if not provided)
8
+ * @returns The slugified string
9
+ */
10
+ export declare function slugifyString(str: string, config?: SlugifyConfig): string;
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.slugifyString = slugifyString;
4
+ const slugify_config_1 = require("./slugify.config");
5
+ /**
6
+ * Applies slugify transformations to a string based on the provided configuration.
7
+ * This is the core logic for converting strings to URL-friendly slugs.
8
+ *
9
+ * @param str - The input string to slugify
10
+ * @param config - Configuration object (uses global config if not provided)
11
+ * @returns The slugified string
12
+ */
13
+ function slugifyString(str, config) {
14
+ // Merge provided config with global config
15
+ const finalConfig = { ...(0, slugify_config_1.getSlugifyConfig)(), ...config };
16
+ let result = str;
17
+ // 1. Apply custom replacements first
18
+ if (finalConfig.customReplacements && Object.keys(finalConfig.customReplacements).length > 0) {
19
+ for (const [pattern, replacement] of Object.entries(finalConfig.customReplacements)) {
20
+ // Escape special regex characters in the pattern
21
+ const escapedPattern = pattern.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
22
+ result = result.replace(new RegExp(escapedPattern, 'g'), replacement);
23
+ }
24
+ }
25
+ // 2. Apply custom transformers
26
+ if (finalConfig.transformers && finalConfig.transformers.length > 0) {
27
+ for (const transformer of finalConfig.transformers) {
28
+ result = transformer(result);
29
+ }
30
+ }
31
+ // 3. Remove accents if configured
32
+ if (finalConfig.removeAccents) {
33
+ result = result.normalize('NFD').replace(/[̀-ͯ]/g, '');
34
+ }
35
+ // 4. Replace non-allowed characters with separator
36
+ const separator = finalConfig.separator || '-';
37
+ // Determine allowed characters based on removeAccents setting
38
+ const defaultAllowedChars = finalConfig.removeAccents ? /[a-zA-Z0-9]/ : /[a-zA-Z0-9\u00C0-\u017F]/; // Include accented Latin characters if accents are preserved
39
+ const allowedRegex = finalConfig.allowedChars || defaultAllowedChars;
40
+ const allowedPattern = allowedRegex.source;
41
+ // Extract the character class content (remove surrounding brackets if present)
42
+ const charClass = allowedPattern.startsWith('[') && allowedPattern.endsWith(']') ? allowedPattern.slice(1, -1) : allowedPattern;
43
+ result = result.replace(new RegExp(`[^${charClass}]+`, 'g'), separator);
44
+ // 5. Remove leading/trailing separators
45
+ result = result.replace(new RegExp(`^${separator}+|${separator}+$`, 'g'), '');
46
+ // 6. Convert to lowercase if configured
47
+ if (finalConfig.lowercase) {
48
+ result = result.toLowerCase();
49
+ }
50
+ // 7. Apply max length if configured
51
+ if (finalConfig.maxLength && finalConfig.maxLength > 0) {
52
+ result = result.slice(0, finalConfig.maxLength);
53
+ // Remove trailing separator after truncation
54
+ result = result.replace(new RegExp(`${separator}$`), '');
55
+ }
56
+ // 8. Collapse multiple consecutive separators
57
+ result = result.replace(new RegExp(`${separator}+`, 'g'), separator);
58
+ return result;
59
+ }
package/package.json CHANGED
@@ -1,6 +1,14 @@
1
1
  {
2
2
  "name": "utilitish",
3
- "version": "0.0.8",
3
+ "version": "0.0.9",
4
+ "repository": {
5
+ "type": "git",
6
+ "url": "git+https://github.com/FDonovan12/utilitish.git"
7
+ },
8
+ "publishConfig": {
9
+ "access": "public",
10
+ "provenance": false
11
+ },
4
12
  "description": "",
5
13
  "main": "dist/index.js",
6
14
  "types": "dist/index.d.ts",