Skip to content

Commit e62c6bb

Browse files
committed
chore: implement handle trailing slash
1 parent 58f6110 commit e62c6bb

File tree

5 files changed

+134
-1
lines changed

5 files changed

+134
-1
lines changed

gatsby-node.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ export const pluginOptionsSchema: GatsbyNode['pluginOptionsSchema'] = ({ Joi })
1919
}),
2020
),
2121
pathBlacklist: Joi.array().description('Omit certain path segments'),
22+
trailingSlash: Joi.string().valid('always', 'never', 'ignore').default('always'),
2223
});
2324
};
2425

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`translatePagePaths generatePageContextByPath should default to empty prefix 1`] = `
4+
{
5+
"locale": undefined,
6+
"prefix": undefined,
7+
}
8+
`;
9+
10+
exports[`translatePagePaths generatePageContextByPath should generate the page context by path 1`] = `
11+
{
12+
"locale": "en-US",
13+
"prefix": "en",
14+
}
15+
`;

src/utils/path.test.ts

Lines changed: 100 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,62 @@
11
import { PluginOptions } from 'gatsby';
2-
import { addLocalePrefix, parsePathPrefix, translatePagePaths, trimRightSlash, trimSlashes } from './path';
2+
import {
3+
addLocalePrefix,
4+
generatePageContextByPath,
5+
handleTrailingSlash,
6+
parsePathPrefix,
7+
translatePagePaths,
8+
trimRightSlash,
9+
trimSlashes,
10+
} from './path';
11+
12+
describe('handleTrailingSlash', () => {
13+
it('should leave trailing slahes, when the option is set to always', () => {
14+
const expectation = handleTrailingSlash('https://example.com/', 'always');
15+
expect(expectation).toBe('https://example.com/');
16+
});
17+
18+
it('should add trailing slahes, when the option is set to always', () => {
19+
const expectation = handleTrailingSlash('https://example.com', 'always');
20+
expect(expectation).toBe('https://example.com/');
21+
});
22+
23+
it('should remove trailing slahes, when the option is set to never', () => {
24+
const expectation = handleTrailingSlash('https://example.com/', 'never');
25+
expect(expectation).toBe('https://example.com');
26+
});
27+
28+
it('should not add trailing slahes, when the option is set to never', () => {
29+
const expectation = handleTrailingSlash('https://example.com', 'never');
30+
expect(expectation).toBe('https://example.com');
31+
});
32+
33+
it('should return root paths', () => {
34+
const expectation = handleTrailingSlash('/', 'never');
35+
expect(expectation).toBe('/');
36+
});
37+
38+
it('should return empty paths', () => {
39+
const expectation = handleTrailingSlash('', 'never');
40+
expect(expectation).toBe('');
41+
});
42+
43+
it('should return empty paths', () => {
44+
const expectation = handleTrailingSlash('', 'never');
45+
expect(expectation).toBe('');
46+
});
47+
48+
it('should return paths, when the option is set to ignore', () => {
49+
let expectation = handleTrailingSlash('https://example.com', 'ignore');
50+
expect(expectation).toBe('https://example.com');
51+
expectation = handleTrailingSlash('https://example.com/', 'ignore');
52+
expect(expectation).toBe('https://example.com/');
53+
});
54+
55+
it('should default to always', () => {
56+
const expectation = handleTrailingSlash('https://example.com');
57+
expect(expectation).toBe('https://example.com/');
58+
});
59+
});
360

461
describe('trimRightSlash', () => {
562
it('should trim the right slash', () => {
@@ -103,4 +160,46 @@ describe('translatePagePaths', () => {
103160
{ locale: 'zh-CN', path: '/zh/imprint' },
104161
]);
105162
});
163+
164+
describe('generatePageContextByPath', () => {
165+
const path = '/imprint';
166+
const options: PluginOptions = {
167+
defaultLocale: `en-US`,
168+
siteUrl: '',
169+
locales: [
170+
{
171+
locale: `en-US`,
172+
prefix: `en`,
173+
slugs: {},
174+
messages: {},
175+
},
176+
{
177+
locale: `de-CH`,
178+
prefix: `de`,
179+
slugs: {
180+
'/imprint': '/impressum',
181+
},
182+
messages: {},
183+
},
184+
{
185+
locale: `zh-CN`,
186+
prefix: `zh`,
187+
slugs: {},
188+
messages: {},
189+
},
190+
],
191+
plugins: [],
192+
};
193+
194+
it('should generate the page context by path', () => {
195+
const expectation = generatePageContextByPath(path, options);
196+
expect(expectation).toMatchSnapshot();
197+
});
198+
199+
it('should default to empty prefix', () => {
200+
const customOptions = { ...options, defaultLocale: 'fr-FR' };
201+
const expectation = generatePageContextByPath(path, customOptions);
202+
expect(expectation).toMatchSnapshot();
203+
});
204+
});
106205
});

src/utils/path.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,23 @@
11
import { posix as nodePath } from 'path';
22
import { PluginOptions } from 'gatsby';
33

4+
export const handleTrailingSlash = (path: string, trailingSlashOption: PluginOptions['trailingSlash'] = 'always') => {
5+
if (path === '/' || path.length < 1) {
6+
return path;
7+
}
8+
9+
const hasTrailingSlash = path.endsWith('/');
10+
11+
switch (trailingSlashOption) {
12+
case 'always':
13+
return hasTrailingSlash ? path : `${path}/`;
14+
case 'never':
15+
return hasTrailingSlash ? path.slice(0, -1) : path;
16+
default:
17+
return path;
18+
}
19+
};
20+
421
export const trimRightSlash = (path: string) => {
522
return path === '/' ? path : path.replace(/\/$/, '');
623
};

types.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,5 +39,6 @@ declare module 'gatsby' {
3939
pageBlacklist?: string[];
4040
}[];
4141
pathBlacklist?: string[];
42+
trailingSlash?: 'always' | 'never' | 'ignore';
4243
}
4344
}

0 commit comments

Comments
 (0)