Skip to content

Commit

Permalink
feat(compat): implement unescape (#874)
Browse files Browse the repository at this point in the history
  • Loading branch information
D-Sketon authored Dec 8, 2024
1 parent f32d375 commit fad6457
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 0 deletions.
10 changes: 10 additions & 0 deletions benchmarks/performance/unescape.bench.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { bench, describe } from 'vitest';
import { unescape as unescapeToolkit_ } from 'es-toolkit';
import { unescape as unescapeCompatToolkit_ } from 'es-toolkit/compat';
import { unescape as unescapeLodash_ } from 'lodash';

const unescapeToolkit = unescapeToolkit_;
const unescapeCompatToolkit = unescapeCompatToolkit_;
const unescapeLodash = unescapeLodash_;

const longString = 'fred, barney, & pebbles'.repeat(50);
Expand All @@ -12,6 +14,10 @@ describe('unescape', () => {
unescapeToolkit('fred, barney, & pebbles');
});

bench('es-toolkit/compat/unescape', () => {
unescapeCompatToolkit('fred, barney, & pebbles');
});

bench('lodash/unescape', () => {
unescapeLodash('fred, barney, & pebbles');
});
Expand All @@ -22,6 +28,10 @@ describe('unescape/long', () => {
unescapeToolkit(longString);
});

bench('es-toolkit/compat/unescape - long string', () => {
unescapeCompatToolkit(longString);
});

bench('lodash/unescape long string', () => {
unescapeLodash(longString);
});
Expand Down
1 change: 1 addition & 0 deletions src/compat/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ export { toUpper } from './string/toUpper.ts';
export { trim } from './string/trim.ts';
export { trimEnd } from './string/trimEnd.ts';
export { trimStart } from './string/trimStart.ts';
export { unescape } from './string/unescape.ts';
export { upperCase } from './string/upperCase.ts';
export { upperFirst } from './string/upperFirst.ts';
export { words } from './string/words.ts';
Expand Down
51 changes: 51 additions & 0 deletions src/compat/string/unescape.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { describe, expect, it } from 'vitest';
import { escape } from './escape';
import { unescape } from './unescape';
import { map } from '../array/map';
import { stubString } from '../util/stubString';

describe('unescape', () => {
let escaped = '&<>"'/';
let unescaped = '&<>"\'/';

escaped += escaped;
unescaped += unescaped;

it('should unescape entities in order', () => {
expect(unescape('&amp;lt;')).toBe('&lt;');
});

it('should unescape the proper entities', () => {
expect(unescape(escaped)).toBe(unescaped);
});

it('should handle strings with nothing to unescape', () => {
expect(unescape('abc')).toBe('abc');
});

it('should unescape the same characters escaped by `_.escape`', () => {
expect(unescape(escape(unescaped))).toBe(unescaped);
});

it('should handle leading zeros in html entities', () => {
expect(unescape('&#39;')).toBe("'");
expect(unescape('&#039;')).toBe("'");
expect(unescape('&#000039;')).toBe("'");
});

['&#96;', '&#x2F;'].forEach(entity => {
it(`should not unescape the "${entity}" entity`, () => {
expect(unescape(entity)).toBe(entity);
});
});

it('should return an empty string for empty values', () => {
// eslint-disable-next-line no-sparse-arrays
const values = [, null, undefined, ''];
const expected = map(values, stubString);

const actual = map(values, (value, index) => (index ? unescape(value as any) : unescape()));

expect(actual).toEqual(expected);
});
});
19 changes: 19 additions & 0 deletions src/compat/string/unescape.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { unescape as unescapeToolkit } from '../../string/unescape.ts';
import { toString } from '../util/toString.ts';

/**
* Converts the HTML entities `&amp;`, `&lt;`, `&gt;`, `&quot;`, and `&#39;` in `str` to their corresponding characters.
* It is the inverse of `escape`.
*
* @param {string} str The string to unescape.
* @returns {string} Returns the unescaped string.
*
* @example
* unescape('This is a &lt;div&gt; element.'); // returns 'This is a <div> element.'
* unescape('This is a &quot;quote&quot;'); // returns 'This is a "quote"'
* unescape('This is a &#39;quote&#39;'); // returns 'This is a 'quote''
* unescape('This is a &amp; symbol'); // returns 'This is a & symbol'
*/
export function unescape(str?: string): string {
return unescapeToolkit(toString(str));
}

0 comments on commit fad6457

Please sign in to comment.