diff --git a/frontend/src/app/shared/components/header-project-select/header-project-select.component.ts b/frontend/src/app/shared/components/header-project-select/header-project-select.component.ts index a91c8b3f444f..6e9e55feaf47 100644 --- a/frontend/src/app/shared/components/header-project-select/header-project-select.component.ts +++ b/frontend/src/app/shared/components/header-project-select/header-project-select.component.ts @@ -46,7 +46,6 @@ import { ApiV3Filter } from 'core-app/shared/helpers/api-v3/api-v3-filter-builde import { IHALCollection } from 'core-app/core/apiv3/types/hal-collection.type'; import { ConfigurationService } from 'core-app/core/config/configuration.service'; - @Component({ selector: 'opce-header-project-select', templateUrl: './header-project-select.component.html', @@ -75,7 +74,11 @@ export class OpHeaderProjectSelectComponent extends UntilDestroyedMixin { .filter( (project) => { if (searchText.length) { - const matches = project.name.toLowerCase().includes(searchText.toLowerCase()); + // Decompose accented letters such as é or ligatures ff or supertexts ² into basic letters + // and their accents, additionally remove the accents to make the search accent insensitive. + const normalizedProjectName = project.name.normalize('NFKD').replace(/[\u0300-\u036f]/g, ''); + const normalizedSearchText = searchText.normalize('NFKD').replace(/[\u0300-\u036f]/g, ''); + const matches = normalizedProjectName.toLowerCase().includes(normalizedSearchText.toLowerCase()); if (!matches) { return false; diff --git a/frontend/src/app/shared/components/project-include/project-include.component.ts b/frontend/src/app/shared/components/project-include/project-include.component.ts index 6a3b9f1d4fa3..91012c3c4299 100644 --- a/frontend/src/app/shared/components/project-include/project-include.component.ts +++ b/frontend/src/app/shared/components/project-include/project-include.component.ts @@ -176,8 +176,12 @@ export class OpProjectIncludeComponent extends UntilDestroyedMixin implements On .filter( (project) => { if (searchText.length) { - const matches = project.name.toLowerCase().includes(searchText.toLowerCase()); - + // Decompose accented letters such as é or ligatures ff or supertexts ² into basic letters + // and their accents, additionally remove the accents to make the search accent insensitive. + // Where is this being rendered? TODO: Make highlighting work + const normalizedProjectName = project.name.normalize('NFKD').replace(/[\u0300-\u036f]/g, ''); + const normalizedSearchText = searchText.normalize('NFKD').replace(/[\u0300-\u036f]/g, ''); + const matches = normalizedProjectName.toLowerCase().includes(normalizedSearchText.toLowerCase()); if (!matches) { return false; } diff --git a/spec/features/projects/project_autocomplete_spec.rb b/spec/features/projects/project_autocomplete_spec.rb index b43ddf283869..09d24750267f 100644 --- a/spec/features/projects/project_autocomplete_spec.rb +++ b/spec/features/projects/project_autocomplete_spec.rb @@ -62,12 +62,12 @@ "Very long project name with term at the END", "INK14 - Foo", "INK15 - Bar", - "INK16 - Baz" + "INK16 - Baz", + "Prójéct with accents ligatures ff and supertexts ²" ] names.map do |name| - identifier = name.gsub(/[ -]+/, "-").downcase - + identifier = name.gsub(/[ -]+/, "-").downcase.unicode_normalize(:nfkd).gsub(/\p{M}/, "") create(:project, name:, identifier:) end end @@ -150,6 +150,15 @@ top_menu.expect_no_result "INK14 - Foo" top_menu.expect_no_result "INK16 - Baz" + top_menu.search "Project with" + top_menu.expect_result "Prójéct with accents ligatures ff and supertexts ²" + + top_menu.search "ff" # Searching for ff should return the ligature ff + top_menu.expect_result "Prójéct with accents ligatures ff and supertexts ²" + + top_menu.search "²" + top_menu.expect_result "Prójéct with accents ligatures ff and supertexts ²" + # Visit a project top_menu.search_and_select "