Repository: styleguidist/react-styleguidist
Pull request #1384 (2019-06-15 00:01:08)

Fix section pages if section name has inappropriate symbols
If you have a forward slash in your section name, the pagePerSection links are all broken,
resulting in "Page not found".

For example:
  pagePerSection links break when section name includes a "/", like `name: '@foo/components'`

The solution is just to encode a name in the getUrl and then correctly
decode it in the router hash logic.

iss: https://github.com/styleguidist/react-styleguidist/issues/1332

![Fix for pagePerSection links break when section name includes a  :](https://user-images.githubusercontent.com/5443359/59544341-ab282500-8f19-11e9-91c7-c75b608e3d04.gif)



codecov-io: # [Codecov](https://codecov.io/gh/styleguidist/react-styleguidist/pull/1384?src=pr&el=h1) Report
> Merging [#1384](https://codecov.io/gh/styleguidist/react-styleguidist/pull/1384?src=pr&el=desc) into [master](https://codecov.io/gh/styleguidist/react-styleguidist/commit/5ff72d8c82d11ce70c6449a77343e2cc5462c037?src=pr&el=desc) will **increase** coverage by `<.01%`.
> The diff coverage is `100%`.

| [Impacted Files](https://codecov.io/gh/styleguidist/react-styleguidist/pull/1384?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [src/client/utils/handleHash.js](https://codecov.io/gh/styleguidist/react-styleguidist/pull/1384/diff?src=pr&el=tree#diff-c3JjL2NsaWVudC91dGlscy9oYW5kbGVIYXNoLmpz) | `96.15% <100%> (ø)` | :arrow_up: |
| [src/client/utils/getUrl.js](https://codecov.io/gh/styleguidist/react-styleguidist/pull/1384/diff?src=pr&el=tree#diff-c3JjL2NsaWVudC91dGlscy9nZXRVcmwuanM=) | `96.15% <100%> (+0.15%)` | :arrow_up: |


Patch:
diff --git a/src/client/utils/getUrl.js b/src/client/utils/getUrl.js
index fbb6ce7a..fa0b6d80 100644
--- a/src/client/utils/getUrl.js
+++ b/src/client/utils/getUrl.js
@@ -29,15 +29,17 @@ export default function getUrl(
 		url += '?nochrome';
 	}
 
+	const encodedName = encodeURIComponent(name);
+
 	if (anchor) {
 		url += `#${slug}`;
 	} else if (isolated || nochrome) {
-		url += `#!/${name}`;
+		url += `#!/${encodedName}`;
 	}
 
 	if (hashPath) {
 		if (!id) {
-			hashPath = [...hashPath, name];
+			hashPath = [...hashPath, encodedName];
 		}
 		url += `#/${hashPath.join('/')}`;
 	}
diff --git a/src/client/utils/handleHash.js b/src/client/utils/handleHash.js
index 57b1c62b..b7b9d1f5 100644
--- a/src/client/utils/handleHash.js
+++ b/src/client/utils/handleHash.js
@@ -51,7 +51,9 @@ export const getHash = (hash, prependHash) => {
  * @return {Array.<string>}
  */
 export const getHashAsArray = (hash, prependHash) => {
-	return getHash(hash, prependHash).split(separator);
+	return trimParams(trimHash(hash, prependHash))
+		.split(separator)
+		.map(decodeURIComponent);
 };
 
 /**


Test patch:
diff --git a/src/client/utils/__tests__/getUrl.spec.js b/src/client/utils/__tests__/getUrl.spec.js
index 1c37af52..e47f4038 100644
--- a/src/client/utils/__tests__/getUrl.spec.js
+++ b/src/client/utils/__tests__/getUrl.spec.js
@@ -69,6 +69,11 @@ describe('getUrl', () => {
 		expect(result).toBe('/styleguide/#/Documentation/FooBar');
 	});
 
+	it('should return a route path with encoded name if name has inappropriate symbols', () => {
+		const result = getUrl({ name: '@foo/components', slug, hashPath: ['Documentation'] }, loc);
+		expect(result).toBe('/styleguide/#/Documentation/%40foo%2Fcomponents');
+	});
+
 	it('should return a route path with a param id=foobar', () => {
 		const result = getUrl({ name, slug, hashPath: ['Documentation'], id: true }, loc);
 		expect(result).toBe('/styleguide/#/Documentation?id=foobar');
diff --git a/src/client/utils/__tests__/handleHash.spec.js b/src/client/utils/__tests__/handleHash.spec.js
index 2cf138a0..6be00c34 100644
--- a/src/client/utils/__tests__/handleHash.spec.js
+++ b/src/client/utils/__tests__/handleHash.spec.js
@@ -44,6 +44,11 @@ describe('handleHash', () => {
 		expect(result).toEqual(['FooBar', 'Component']);
 	});
 
+	it('getHashAsArray should return array with an encoded component name', () => {
+		const result = getHashAsArray('#/Documentation/Files/%40foo%2Fcomponents', routeHash);
+		expect(result).toEqual(['Documentation', 'Files', '@foo/components']);
+	});
+
 	it('getHashAsArray should return array without params', () => {
 		const result = getHashAsArray('#/FooBar/Component?id=Example/Perfect', routeHash);
 		expect(result).toEqual(['FooBar', 'Component']);