Skip to content

Commit b8e386e

Browse files
authored
Add a default formatter option (#43)
* add a default formatter option * update default humanize function * add test case * version bump
1 parent 7523a38 commit b8e386e

File tree

3 files changed

+29
-5
lines changed

3 files changed

+29
-5
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "use-react-router-breadcrumbs",
3-
"version": "3.0.2",
3+
"version": "3.1.0",
44
"description": "A hook for displaying and setting breadcrumbs for react router",
55
"main": "dist/cjs/index.js",
66
"module": "dist/es/index.js",

src/index.test.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -529,6 +529,23 @@ describe('use-react-router-breadcrumbs', () => {
529529
expect(breadcrumbs).toBe('One');
530530
});
531531
});
532+
533+
describe('defaultFormatter', () => {
534+
it('should be used if a breadcrumb is not provided for a specific path', () => {
535+
const routes = [
536+
{ path: '/one', breadcrumb: 'One' },
537+
{ path: '/one/two' },
538+
{ path: '/one/two/three_four' },
539+
];
540+
const { breadcrumbs } = render({
541+
pathname: '/one/two/three_four',
542+
routes,
543+
options: { defaultFormatter: (breadcrumb) => breadcrumb.replace(/two/g, 'changed') },
544+
});
545+
546+
expect(breadcrumbs).toBe('Home / One / changed / three_four');
547+
});
548+
});
532549
});
533550

534551
describe('Invalid route object', () => {

src/index.tsx

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ type Location = ReturnType<typeof useLocation>;
3131
export interface Options {
3232
disableDefaults?: boolean;
3333
excludePaths?: string[];
34+
defaultFormatter?: (str: string) => string
3435
}
3536

3637
export interface BreadcrumbMatch<ParamKey extends string = string> {
@@ -197,9 +198,9 @@ const NO_BREADCRUMB = Symbol('NO_BREADCRUMB');
197198
* we used to use the humanize-string package, but it added a lot of bundle
198199
* size and issues with compilation. This 4-liner seems to cover most cases.
199200
*/
200-
const humanize = (str: string): string => str
201+
export const humanize = (str: string): string => str
201202
.replace(/^[\s_]+|[\s_]+$/g, '')
202-
.replace(/[_\s]+/g, ' ')
203+
.replace(/[-_\s]+/g, ' ')
203204
.replace(/^[a-z]/, (m) => m.toUpperCase());
204205

205206
/**
@@ -242,10 +243,12 @@ const getDefaultBreadcrumb = ({
242243
currentSection,
243244
location,
244245
pathSection,
246+
defaultFormatter,
245247
}: {
246248
currentSection: string;
247249
location: Location;
248250
pathSection: string;
251+
defaultFormatter?: (str: string) => string
249252
}): BreadcrumbData => {
250253
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
251254
const match = matchPath(
@@ -257,7 +260,7 @@ const getDefaultBreadcrumb = ({
257260
)!;
258261

259262
return render({
260-
breadcrumb: humanize(currentSection),
263+
breadcrumb: defaultFormatter ? defaultFormatter(currentSection) : humanize(currentSection),
261264
match,
262265
location,
263266
});
@@ -271,13 +274,15 @@ const getBreadcrumbMatch = ({
271274
currentSection,
272275
disableDefaults,
273276
excludePaths,
277+
defaultFormatter,
274278
location,
275279
pathSection,
276280
branches,
277281
}: {
278282
currentSection: string;
279283
disableDefaults?: boolean;
280284
excludePaths?: string[];
285+
defaultFormatter?: (str: string) => string
281286
location: Location;
282287
pathSection: string;
283288
branches: BreadcrumbsRouteBranch[];
@@ -342,7 +347,8 @@ const getBreadcrumbMatch = ({
342347
// Although we have a match, the user may be passing their react-router config object
343348
// which we support. The route config object may not have a `breadcrumb` param specified.
344349
// If this is the case, we should provide a default via `humanize`.
345-
breadcrumb: userProvidedBreadcrumb || humanize(currentSection),
350+
breadcrumb: userProvidedBreadcrumb
351+
|| (defaultFormatter ? defaultFormatter(currentSection) : humanize(currentSection)),
346352
match: { ...match, route },
347353
location,
348354
props,
@@ -368,6 +374,7 @@ const getBreadcrumbMatch = ({
368374
// include a "Home" breadcrumb by default (can be overrode or disabled in config).
369375
currentSection: pathSection === '/' ? 'Home' : currentSection,
370376
location,
377+
defaultFormatter,
371378
});
372379
};
373380

0 commit comments

Comments
 (0)