Repository: styleguidist/react-styleguidist
Pull request #1509 (2020-01-03 13:17:43)

fix:(isolation mode issue) issue #1492
issue link: https://github.com/styleguidist/react-styleguidist/issues/1492

This issue occurred because of the fix that have been made in version 10.0.1 for the issue: https://github.com/styleguidist/react-styleguidist/issues/1454

Hashed Url example: the "#button" in the url is an example of Hashed Url...it gets appended after clicking the Button component in the side-Navbar...
<img width="1440" alt="Screenshot 2020-01-03 at 6 14 45 PM" src="https://user-images.githubusercontent.com/21274438/71724136-2967fc80-2e55-11ea-9a6e-39c9d16d21e2.png">

After the issue #1454 was resolved...it was taking the hashed url token in the isolated page(which opens after clicking the fullscreen icon) url as you can see below

after clicking the fullscreen icon we got results like this!
<img width="973" alt="pageNotFound(1)" src="https://user-images.githubusercontent.com/21274438/71724438-54068500-2e56-11ea-80c8-736a9591db60.png">

so this was the issue which is resolved by doing a simple check i.e. we are verifying if the currentHash that we are getting in the 'buildIsolatedOrNoChromeFragment()' function is a hashedUrl("#button") or a Section-Url("#/Components")...

we just checked the first character after the '#' in the currentHash string if it matches the hashedUrlpattern then we are neglecting the extra currentHashPath...

now as you can see below we removed the "/button" from the url...it is working fine..
<img width="1440" alt="pageFound" src="https://user-images.githubusercontent.com/21274438/71725180-050e1f00-2e59-11ea-921c-e471a6be3df0.png">


we have written a test case for that as you can check...!
and also the issue mentioned in #1454 is also working fine...







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

| [Impacted Files](https://codecov.io/gh/styleguidist/react-styleguidist/pull/1509?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [src/client/utils/getUrl.ts](https://codecov.io/gh/styleguidist/react-styleguidist/pull/1509/diff?src=pr&el=tree#diff-c3JjL2NsaWVudC91dGlscy9nZXRVcmwudHM=) | `92.5% <100%> (+0.83%)` | :arrow_up: |


Patch:
diff --git a/src/client/rsg-components/Props/renderDefault.tsx b/src/client/rsg-components/Props/renderDefault.tsx
index 180d0e0d..13f07529 100644
--- a/src/client/rsg-components/Props/renderDefault.tsx
+++ b/src/client/rsg-components/Props/renderDefault.tsx
@@ -9,18 +9,19 @@ export default function renderDefault(prop: PropDescriptorWithFlow): React.React
 	// Workaround for issue https://github.com/reactjs/react-docgen/issues/221
 	// If prop has defaultValue it can not be required
 	if (prop.defaultValue) {
+		const defaultValueString = showSpaces(unquote(String(prop.defaultValue.value)));
 		if (prop.type || prop.flowType) {
 			const propName = prop.type ? prop.type.name : prop.flowType && prop.flowType.type;
 
 			if (defaultValueBlacklist.indexOf(prop.defaultValue.value) > -1) {
-				return <Code>{showSpaces(unquote(prop.defaultValue.value))}</Code>;
+				return <Code>{defaultValueString}</Code>;
 			} else if (propName === 'func' || propName === 'function') {
 				return (
 					<Text
 						size="small"
 						color="light"
 						underlined
-						title={showSpaces(unquote(prop.defaultValue.value))}
+						title={defaultValueString}
 					>
 						Function
 					</Text>
@@ -50,7 +51,7 @@ export default function renderDefault(prop: PropDescriptorWithFlow): React.React
 			}
 		}
 
-		return <Code>{showSpaces(unquote(prop.defaultValue.value))}</Code>;
+		return <Code>{defaultValueString}</Code>;
 	} else if (prop.required) {
 		return (
 			<Text size="small" color="light">
diff --git a/src/client/utils/getUrl.ts b/src/client/utils/getUrl.ts
index 076a4b78..4d30174d 100644
--- a/src/client/utils/getUrl.ts
+++ b/src/client/utils/getUrl.ts
@@ -1,3 +1,24 @@
+/* Returns the HashPath to be included in the isolated page view url */
+function getCurrentHashPath(stripFragment:RegExp,stripTrailingSlash:RegExp,currentHash: string):string {
+
+	/*This pattern matches urls like http://hostname.com/#button etc.,
+	these urls are generated when we click on a component in the side nav-bar.
+	This will verify whether the first character after the '#' symbol is an alphanumeric char or "_".
+	this pattern used to validate the components names.*/
+	const hashUrlPattern = /^#[a-zA-Z0-9_]/; // Ex. matches "#button","#1button","#_button"
+
+	/* This pattern matches "#!/" string pattern in the 'currentHash' const
+	this url pattern is used to show isolated page view mode in this project. */
+	const isolatedPageViewUrlPattern = /^#!\//; // Ex. matches "#!/button"  
+
+	if (hashUrlPattern.test(currentHash)) {
+		return '';
+	} else {
+		return (currentHash && !isolatedPageViewUrlPattern.test(currentHash)) ?
+			 currentHash.replace(stripFragment, '').replace(stripTrailingSlash, '') + '/' : '';
+	}
+}
+
 /**
  * Gets the URL fragment for an isolated or nochrome link.
  *
@@ -14,11 +35,8 @@ function buildIsolatedOrNoChromeFragment({
 }): string {
 	const stripFragment = /^#\/?/;
 	const stripTrailingSlash = /\/$/;
-	const currentHashPath =
-		// skip if we are already using `#!/`
-		currentHash && !currentHash.includes('#!/')
-			? currentHash.replace(stripFragment, '').replace(stripTrailingSlash, '') + '/'
-			: '';
+
+	const currentHashPath = getCurrentHashPath(stripFragment,stripTrailingSlash,currentHash);
 	return `#!/${currentHashPath}${encodedName}`;
 }
 


Test patch:
diff --git a/src/client/utils/__tests__/getUrl.spec.ts b/src/client/utils/__tests__/getUrl.spec.ts
index 327bb352..53cb4bdf 100644
--- a/src/client/utils/__tests__/getUrl.spec.ts
+++ b/src/client/utils/__tests__/getUrl.spec.ts
@@ -6,6 +6,11 @@ describe('getUrl', () => {
 		pathname: '/styleguide/',
 		hash: '#/Components',
 	};
+	const locHashedURL = {
+		origin: 'http://example.com',
+		pathname: '/styleguide/',
+		hash: '#button',
+	}
 	const name = 'FooBar';
 	const slug = 'foobar';
 
@@ -44,6 +49,11 @@ describe('getUrl', () => {
 		expect(result).toBe('/styleguide/#!/Components/FooBar/3');
 	});
 
+	it('should return an isolated example for a HashedURL', () => {
+		const result = getUrl({ name, slug, example: 0, isolated: true }, locHashedURL);
+		expect(result).toBe('/styleguide/#!/FooBar/0');
+	});
+
 	it('should return an isolated example=0 URL', () => {
 		const result = getUrl({ name, slug, example: 0, isolated: true }, loc);
 		expect(result).toBe('/styleguide/#!/Components/FooBar/0');