Skip to content

Commit

Permalink
fix: fix diacritics and special unicode characters handling
Browse files Browse the repository at this point in the history
mi-neovici authored and cristinecula committed Aug 20, 2024
1 parent 310a078 commit e3c45c4
Showing 5 changed files with 95 additions and 16 deletions.
19 changes: 11 additions & 8 deletions src/cosmoz-tree.ts
Original file line number Diff line number Diff line change
@@ -148,7 +148,7 @@ export class Tree {
* @param {Boolean} options.firstHitOnly [false] (If the search should only return the first found node.)
* @param {Object} nodes [this._roots] (The nodes the search should be based on.)
*/
_searchNodes(
private _searchNodes(
propertyValue: string | undefined,
options: {
propertyName: string;
@@ -263,7 +263,7 @@ export class Tree {
.sort(_sortPathNodes)[0];
}

_getPathNodes(
private _getPathNodes(
pathLocator: string,
nodeObj: TreeData = this._treeData,
pathLocatorSeparator: string = this.pathLocatorSeparator,
@@ -279,7 +279,7 @@ export class Tree {
return nodes;
}

_pathToNodes(path: string[], nodes: TreeData, separator: string) {
private _pathToNodes(path: string[], nodes: TreeData, separator: string) {
let pathSegment = nodes;
return path.map((nodeKey: string, i: number) => {
// Get the nodes on the path
@@ -415,14 +415,14 @@ export class Tree {
* Checks if a node matches the search criteria.
* @returns {Boolean} True if node matches
* @param {node} node (The node the check should be based on.)
* @param {String} propertyValue (The value of the property the match should be based on. e.g. "Peter")
* @param {String} searchValue (The value of the property the match should be based on. e.g. "Peter")
* @param {Object} options (Comparison options)
* @param {String} options.propertyName (The name of the property the match should be based on. e.g. "name")
* @param {Boolean} options.exact [false] (If the search should be executed exact or fuzzy. true wouldn't match "Pet")
*/
nodeConformsSearch(
node: Node,
propertyValue: string | undefined,
searchValue: string | undefined,
options?: {
propertyName: string;
exact?: boolean;
@@ -439,14 +439,17 @@ export class Tree {
}

if (options?.exact) {
return property === propertyValue;
return property === searchValue;
}

if (propertyValue === undefined) {
if (searchValue === undefined) {
return false;
}

return property.toLowerCase().indexOf(propertyValue.toLowerCase()) > -1;
const normalizedPropertyValue = property.normalize('NFD').replace(/\p{Diacritic}/gu, '').toUpperCase();
const normalizedSearchValue = searchValue.normalize('NFD').replace(/\p{Diacritic}/gu, '').toUpperCase();

return normalizedPropertyValue.indexOf(normalizedSearchValue) > -1;
}

/**
9 changes: 9 additions & 0 deletions test/base-data.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { Tree } from '../src/cosmoz-tree';

export const treeBaseUrl = '/test/data';

export const treeFromJsonUrl = async (url: string, options = {}) => {
const json = await fetch(url).then((r) => r.json());

return new Tree(json, options);
};
11 changes: 3 additions & 8 deletions test/cosmoz-tree.test.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,11 @@
import { assert } from '@open-wc/testing';
import { Tree, Node } from '../src/cosmoz-tree';
import { treeBaseUrl, treeFromJsonUrl } from './base-data';

const treeBaseUrl = '/test/data',
basicTreeUrl = `${treeBaseUrl}/basicTree.json`,
const basicTreeUrl = `${treeBaseUrl}/basicTree.json`,
basicTreePlUrl = `${treeBaseUrl}/basicTreePL.json`,
multiRootTreeUrl = `${treeBaseUrl}/multiRootTree.json`,
missingAncestorTreeUrl = `${treeBaseUrl}/missingAncestorTree.json`,
treeFromJsonUrl = async (url: string, options = {}) => {
const json = await fetch(url).then((r) => r.json());

return new Tree(json, options);
};
missingAncestorTreeUrl = `${treeBaseUrl}/missingAncestorTree.json`;

suite('basic', () => {
let basicTree: Tree;
35 changes: 35 additions & 0 deletions test/data/diacriticsTree.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"1": {
"id": "11111111-1111-1111-1111-111111111111",
"name": "Root",
"pathLocator": "1",
"children": {
"2": {
"id": "167d1485-7d4f-4c7d-86cd-a4fb00f31245",
"name": "Node2",
"pathLocator": "1.2",
"children": {
"3": {
"id": "3a7654f1-e3e6-49c7-b6a8-a4fb00f31245",
"name": "Pétér",
"pathLocator": "1.2.3",
"children": {
"301": {
"id": "3a7654f1-e3e6-49c7-b6a8-a4fb00f31245",
"name": "Péter",
"pathLocator": "1.2.3.301",
"children": {}
}
}
}
}
},
"4": {
"id": "2b547550-b874-4228-9395-a4fb00f31245",
"name": "Michaél",
"pathLocator": "1.4",
"children": {}
}
}
}
}
37 changes: 37 additions & 0 deletions test/diacritics.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { treeBaseUrl, treeFromJsonUrl } from './base-data';
import { Tree } from '../src/cosmoz-tree';
import { assert } from '@open-wc/testing';

const diacriticsTreeUrl = `${treeBaseUrl}/diacriticsTree.json`;

suite('diacritics', () => {
let diacriticsTree: Tree;

suiteSetup(async () => {
diacriticsTree = await treeFromJsonUrl(diacriticsTreeUrl);
});

/**
* A pair of [value, exactMatches, nonExactMatches]
*/
const valuesToCheck = [
['Peter', 0, 2],
['Péter', 1, 2],
['Pétér', 1, 2],
['Michael', 0, 1],
['Michaél', 1, 1]
] as const;

valuesToCheck.forEach(([value, exactMatches, nonExactMatches]) => {
test(`should matter when doing an exact search (${value})`, () => {
const results = diacriticsTree.searchNodes(value, undefined, true, 'name');

assert.equal(results.length, exactMatches);
});

test(`should NOT matter when doing a non-exact search (${value})`, () => {
const results = diacriticsTree.searchNodes(value, undefined, false, 'name');
assert.equal(results.length, nonExactMatches);
});
})
});

0 comments on commit e3c45c4

Please sign in to comment.