Skip to content

Commit

Permalink
⏪ src: Revert change to use native String.prototype.normalize
Browse files Browse the repository at this point in the history
  • Loading branch information
motss committed May 2, 2019
1 parent 8978067 commit e0ded85
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 65 deletions.
32 changes: 14 additions & 18 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,30 +111,26 @@ export const diacritics: Diacritics[] = [
];
// tslint:enable:max-line-length

function nativeStringNormalize(s: string) {
/**
* NOTE: Normalizing accents/ diacritics in ES6.
* See https://bit.ly/2Cncgor for more info.
*/
return s.normalize('NFD').replace(/[\u0300-\u036f]/g, '');
}

function stringNormalize(s: string) {
const normalized = diacritics.filter(n => n.diacritics.test(s));
return !normalized.length ? s : normalized[0].letter;
}

export function normalizeSync(input?: string | null) {
if ('string' !== typeof(input)) {
throw new TypeError(`Expected 'input' to be of type string, but received '${input}'`);
}

const replaceDiacritics =
'function' === typeof(''.normalize) && 'aeo' === nativeStringNormalize('áèö') ?
(s: string) => nativeStringNormalize(s) : (s: string) => stringNormalize(s);

/**
* NOTE(motss): Due to the fact that this module should do what we expect it to be - normalize
* accents/ diacritics. However, some characters are not accented such as those from
* [Latin-1 Supplement](https://bit.ly/2vz1l7m). Also see a relevant
* [GH issue](https://bit.ly/2JbAmH0).
*
* Hence, to match the mental module of the users, `String.prototype.normalize` should not be used
* as such.
*/
return !input.length ?
input : input.replace(/(\S)/g, (_, p: string) => replaceDiacritics(p));
input :
input.replace(/(\S)/g, (_, s: string) => {
const normalized = diacritics.find(n => n.diacritics.test(s));
return null == normalized ? s : normalized.letter;
});
}

export async function normalize(input?: string | null) {
Expand Down
58 changes: 11 additions & 47 deletions src/test/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,6 @@ describe('normalize-diacritics', () => {
}
});

it(`throws error in 'replaceDiacritics'`, async () => {
const cachedFn = String.prototype.normalize;
String.prototype.normalize = () => { throw new Error('String#normalize is broken'); };

try {
await normalize('Réunion');
} catch (e) {
expect(e).toStrictEqual(new Error('String#normalize is broken'));
} finally {
String.prototype.normalize = cachedFn;
}
});

it(`throws when 'input' is 'undefined'`, async () => {
try {
await normalize();
Expand All @@ -36,29 +23,33 @@ describe('normalize-diacritics', () => {
});

describe('ok', () => {
it('normalizes strings', async () => {
it(`skips normalization for empty character`, async () => {
expect(await normalize('')).toStrictEqual('');
});

it('normalizes accented characters', async () => {
try {
const strs = [
'Åland Islands',
'Saint Barthélemy',
'Cocos (Keeling) Islands',
'Côte d\'Ivoire',
`Côte d'Ivoire`,
'Curaçao',
'Réunion',
];

expect(await normalize(strs[0])).toStrictEqual('Aland Islands');
expect(await normalize(strs[1])).toStrictEqual('Saint Barthelemy');
expect(await normalize(strs[2])).toStrictEqual('Cocos (Keeling) Islands');
expect(await normalize(strs[3])).toStrictEqual('Cote d\'Ivoire');
expect(await normalize(strs[3])).toStrictEqual(`Cote d'Ivoire`);
expect(await normalize(strs[4])).toStrictEqual('Curacao');
expect(await normalize(strs[5])).toStrictEqual('Reunion');
} catch (e) {
throw e;
}
});

it('normalizes string without using native function', async () => {
it('normalizes accented characters without using native function', async () => {
const cachedFn = String.prototype.normalize;
String.prototype.normalize = null!;

Expand All @@ -71,36 +62,9 @@ describe('normalize-diacritics', () => {
}
});

it('returns original character when no match found', async () => {
const cachedFilter = Array.prototype.filter;
const cachedFn = String.prototype.normalize;
Array.prototype.filter = () => [];
String.prototype.normalize = null!;

try {
expect(await normalize('Réunion')).toStrictEqual('Réunion');
} catch (e) {
throw e;
} finally {
Array.prototype.filter = cachedFilter;
String.prototype.normalize = cachedFn;
}
});

it('normalizes single-character string', async () => {
try {
expect(await normalize('ô')).toStrictEqual('o');
} catch (e) {
throw e;
}
});

it('returns empty string untouched', async () => {
try {
expect(await normalize('')).toStrictEqual('');
} catch (e) {
throw e;
}
it(`normalizes non-accented characters (Latin-1 Supplement)`, async () => {
expect(await normalize('tromsø')).toStrictEqual('tromso');
expect(await normalize('\u00d8')).toStrictEqual('O');
});

});
Expand Down

0 comments on commit e0ded85

Please sign in to comment.