diff --git a/src/accentFolding.js b/src/accentFolding.js
index bad52c3..d2a8e68 100644
--- a/src/accentFolding.js
+++ b/src/accentFolding.js
@@ -23,31 +23,47 @@ class AccentFolding {
}
replace(text) {
+ if (typeof text !== 'string') {
+ throw new TypeError('Input must be a string');
+ }
return [...text].map((char) => this.#accentMap.get(char) || char).join('');
}
highlightMatch(str, fragment, wrapTag = 'b') {
- if (!fragment) return str;
+ try {
+ if (!fragment) return str;
- const escapedFragment = fragment.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
- const strFolded = this.#fold(str).toLowerCase();
- const fragmentFolded = this.#fold(escapedFragment).toLowerCase();
+ if (typeof str !== 'string' || typeof fragment !== 'string') {
+ throw new TypeError('Both str and fragment must be strings');
+ }
- const re = new RegExp(fragmentFolded, 'g');
- let result = '';
- let lastIndex = 0;
- let hasMatch = false;
+ if (typeof wrapTag !== 'string') {
+ throw new TypeError('wrapTag must be a string');
+ }
- strFolded.replace(re, (match, index) => {
- hasMatch = true;
- result += this.#escapeHtml(str.slice(lastIndex, index));
- result += `<${wrapTag}>${this.#escapeHtml(str.slice(index, index + match.length))}${wrapTag}>`;
- lastIndex = index + match.length;
- });
+ const escapedFragment = fragment.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
+ const strFolded = this.#fold(str).toLowerCase();
+ const fragmentFolded = this.#fold(escapedFragment).toLowerCase();
- result += this.#escapeHtml(str.slice(lastIndex));
+ const re = new RegExp(fragmentFolded, 'g');
+ let result = '';
+ let lastIndex = 0;
+ let hasMatch = false;
- return hasMatch ? result : str;
+ strFolded.replace(re, (match, index) => {
+ hasMatch = true;
+ result += this.#escapeHtml(str.slice(lastIndex, index));
+ result += `<${wrapTag}>${this.#escapeHtml(str.slice(index, index + match.length))}${wrapTag}>`;
+ lastIndex = index + match.length;
+ });
+
+ result += this.#escapeHtml(str.slice(lastIndex));
+
+ return hasMatch ? result : str;
+ } catch (error) {
+ console.error('Error in highlightMatch:', error.message);
+ throw error; // Return original string if there's an error
+ }
}
#escapeHtml(unsafe) {
diff --git a/src/accentFolding.js.test.js b/src/accentFolding.js.test.js
index 6dd896c..61307eb 100644
--- a/src/accentFolding.js.test.js
+++ b/src/accentFolding.js.test.js
@@ -1,11 +1,38 @@
-import { expect, describe, it } from 'vitest';
+import { expect, describe, it, beforeEach } from 'vitest';
import AccentFolding from './accentFolding.js';
import accentMap from './accentMap.json';
describe('AccentFolding', () => {
- const accentFolder = new AccentFolding();
+ let accentFolder;
+
+ beforeEach(() => {
+ accentFolder = new AccentFolding();
+ });
describe('highlightMatch', () => {
+ it('should throw TypeError if str is not a string', () => {
+ expect(() => accentFolder.highlightMatch(123, 'test')).toThrow(TypeError);
+ expect(() => accentFolder.highlightMatch(123, 'test')).toThrow(
+ 'Both str and fragment must be strings'
+ );
+ });
+
+ it('should throw TypeError if fragment is not a string', () => {
+ expect(() => accentFolder.highlightMatch('test', 123)).toThrow(TypeError);
+ expect(() => accentFolder.highlightMatch('test', 123)).toThrow(
+ 'Both str and fragment must be strings'
+ );
+ });
+
+ it('should throw TypeError if wrapTag is not a string', () => {
+ expect(() => accentFolder.highlightMatch('test', 'es', 123)).toThrow(
+ TypeError
+ );
+ expect(() => accentFolder.highlightMatch('test', 'es', 123)).toThrow(
+ 'wrapTag must be a string'
+ );
+ });
+
it('should recognize simple accents', () => {
expect(accentFolder.highlightMatch('Fulanilo López', 'lo')).toBe(
'Fulanilo López'
@@ -63,6 +90,11 @@ describe('AccentFolding', () => {
});
describe('replace', () => {
+ it('should throw TypeError if input is not a string', () => {
+ expect(() => accentFolder.replace(123)).toThrow(TypeError);
+ expect(() => accentFolder.replace(123)).toThrow('Input must be a string');
+ });
+
it.each(Object.entries(accentMap))(
'should replace %s with %s',
(accentedChar, expectedChar) => {