diff --git a/README.md b/README.md index 9f9cfb1..805c4f0 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ A community-driven collection of software development terms with explanations in multiple languages. Perfect for building developer tools, documentation sites, educational content and much more. -**[Browse All Terms](https://kyco.github.io/dev-dict/)** · **[Documentation](https://kyco.github.io/dev-dict/docs)** +**[Docs](https://kyco.github.io/dev-dict/docs)** · **[Browse All Terms](https://kyco.github.io/dev-dict/)** ## Installation @@ -33,7 +33,7 @@ dictionary.forEach(term => { }) ``` -For detailed API documentation, code examples, and more, visit the **[Documentation](https://kyco.github.io/dev-dict/docs)**. +For detailed API documentation, code examples, and more, visit the **[documentation](https://kyco.github.io/dev-dict/docs)**. ## Supported Languages @@ -47,7 +47,7 @@ Want to add a language? See [CONTRIBUTING.md](./CONTRIBUTING.md#adding-a-new-lan ## Contributing -Contributions welcome! Add terms, provide translations, fix errors, or suggest improvements. +Contributions welcome! Add terms, provide translations, fix errors or suggest improvements. See [CONTRIBUTING.md](./CONTRIBUTING.md) for details. diff --git a/demo/src/pages/HomePage.tsx b/demo/src/pages/HomePage.tsx index 07f881d..f8fae39 100644 --- a/demo/src/pages/HomePage.tsx +++ b/demo/src/pages/HomePage.tsx @@ -7,6 +7,7 @@ import { TermCard } from '~/components/TermCard' import { FILTER_OPTIONS, LANGUAGES } from '~/shared/constants' import { useAppContext } from '~/shared/context/AppContext' import { filterTerms } from '~/shared/utils/filterUtils' +import { sortTermsByName } from '~/shared/utils/sortUtils' import { getTermCompleteness } from '~/shared/utils/termUtils' import { terms } from 'dev-dict' import { getTags, getTerms, getTypes } from 'dev-dict/utils' @@ -49,7 +50,7 @@ export function HomePage({ searchQuery, onSearchChange, completeness, onComplete ) const filteredTerms = useMemo(() => { - return filterTerms(dictionary, { + const filtered = filterTerms(dictionary, { searchQuery, selectedTypes, selectedTags, @@ -59,7 +60,8 @@ export function HomePage({ searchQuery, onSearchChange, completeness, onComplete return { baselineComplete: comp.baselineComplete, fullPercentage: comp.fullPercentage } }, }) - }, [dictionary, searchQuery, selectedTypes, selectedTags, completeness]) + return filtered.sort((a, b) => sortTermsByName(a, b, lang)) + }, [dictionary, searchQuery, selectedTypes, selectedTags, completeness, lang]) const rowCount = Math.ceil(filteredTerms.length / columns) diff --git a/demo/src/pages/StatusPage.tsx b/demo/src/pages/StatusPage.tsx index 81ea972..f25d6ae 100644 --- a/demo/src/pages/StatusPage.tsx +++ b/demo/src/pages/StatusPage.tsx @@ -2,6 +2,7 @@ import { Link } from '@tanstack/react-router' import { Dropdown } from '~/components/Dropdown' import { StatusIcon } from '~/components/StatusIcon' import { FILTER_OPTIONS, getGithubEditUrl, SORT_OPTIONS } from '~/shared/constants' +import { sortTermsByName } from '~/shared/utils/sortUtils' import { getTermCompleteness } from '~/shared/utils/termUtils' import { terms } from 'dev-dict' import { getTerms } from 'dev-dict/utils' @@ -60,9 +61,9 @@ export function StatusPage({ searchQuery, onSearchChange }: StatusPageProps) { } if (sortBy === 'name') { - result = [...result].sort((a, b) => a.name.localeCompare(b.name)) + result = [...result].sort((a, b) => sortTermsByName(a, b)) } else { - result = [...result].sort((a, b) => a.fullPercentage - b.fullPercentage || a.name.localeCompare(b.name)) + result = [...result].sort((a, b) => a.fullPercentage - b.fullPercentage || sortTermsByName(a, b)) } return result diff --git a/demo/src/shared/utils/sortUtils.ts b/demo/src/shared/utils/sortUtils.ts new file mode 100644 index 0000000..74c7f92 --- /dev/null +++ b/demo/src/shared/utils/sortUtils.ts @@ -0,0 +1,34 @@ +/** + * Custom sort function that ensures terms starting with special characters + * (like ".NET") appear first in their alphabetical group. + * + * For example, ".NET" will appear first under "N", before "NestJS". + */ +export function sortTermsByName(a: { name: string }, b: { name: string }, locale = 'en-US'): number { + const aHasSpecialPrefix = /^[^a-zA-Z0-9]/.test(a.name) + const bHasSpecialPrefix = /^[^a-zA-Z0-9]/.test(b.name) + + // Remove leading non-alphanumeric characters for primary comparison + const aClean = a.name.replace(/^[^a-zA-Z0-9]+/, '') + const bClean = b.name.replace(/^[^a-zA-Z0-9]+/, '') + + // Get first letter (case-insensitive) for grouping + const aFirstLetter = aClean.charAt(0).toLowerCase() + const bFirstLetter = bClean.charAt(0).toLowerCase() + + // If they're in different letter groups, sort by letter + if (aFirstLetter !== bFirstLetter) { + return aClean.localeCompare(bClean, locale) + } + + // Same letter group: items with special prefixes come first + if (aHasSpecialPrefix && !bHasSpecialPrefix) { + return -1 + } + if (!aHasSpecialPrefix && bHasSpecialPrefix) { + return 1 + } + + // Both have or both don't have special prefixes: sort normally + return a.name.localeCompare(b.name, locale) +}