Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: Page per section upgraded with page not found #993

Merged
merged 15 commits into from
Jul 2, 2018

Conversation

rafaesc
Copy link
Collaborator

@rafaesc rafaesc commented May 25, 2018

This PR is a feature of this issue:
#892

And started with this branch
#989

Also added a page not found
image

@codecov-io
Copy link

codecov-io commented May 25, 2018

Codecov Report

Merging #993 into master will decrease coverage by 0.04%.
The diff coverage is 97.53%.

Impacted Files Coverage Δ
...omponents/ComponentsList/ComponentsListRenderer.js 100% <ø> (ø) ⬆️
src/utils/getPageTitle.js 100% <100%> (ø) ⬆️
src/rsg-components/slots/index.js 100% <100%> (ø) ⬆️
...rc/rsg-components/SectionHeading/SectionHeading.js 100% <100%> (ø) ⬆️
src/utils/filterComponentsInSectionsByExactName.js 100% <100%> (ø) ⬆️
src/rsg-components/Examples/Examples.js 100% <100%> (ø) ⬆️
...rc/rsg-components/ComponentsList/ComponentsList.js 100% <100%> (ø) ⬆️
src/rsg-components/Playground/Playground.js 93.54% <100%> (+0.69%) ⬆️
.../rsg-components/TableOfContents/TableOfContents.js 95% <100%> (+0.88%) ⬆️
scripts/schemas/config.js 88.4% <100%> (+0.9%) ⬆️
... and 15 more

@sapegin sapegin requested a review from okonet May 27, 2018 16:41
Copy link
Member

@sapegin sapegin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

Can we close #989 then?

src/index.js Outdated
@@ -10,8 +10,20 @@ let codeRevision = 0;

/** Scrolls to origin when current window location hash points to an isolated view. */
const scrollToOrigin = () => {
if (window.location.hash.indexOf('#!/') === 0) {
window.scrollTo(0, 0);
const hash = window.location.hash;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code needs a lot of comments, meaningful variable names and splitting into multiple functions with meaningful names. It's impossible to understand what it does.

root: {
maxWidth,
margin: [[0, 'auto']],
padding: space[4],
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This padding creates extra whitespace, that is visible on the screenshot.

text={`
# 404

## Sorry, this page isn't available
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

# Page not found would be enough instead of both headings.


## Sorry, this page isn't available

The link you followed may be broken, or the page may have been removed
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add . at the end ;-)

@@ -6,14 +6,15 @@ import Para from 'rsg-components/Para';
import Slot from 'rsg-components/Slot';
import PlaygroundRenderer from 'rsg-components/Playground/PlaygroundRenderer';
import { EXAMPLE_TAB_CODE_EDITOR } from '../slots';
import { DisplayModes } from '../../consts';
import { DisplayModes, ExampleMode } from '../../consts';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DisplayModes, but ExampleMode. Was that intentional?

const index = parseInt(tokens[1], 10);
const shouldIsolate = hash.substr(0, 3) === '#!/';
if (shouldIsolate || hash.substr(0, 2) === '#/') {
const path = hash.replace(/\?id=[^]*/, '');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is very fragile, what if there will be &id=? It will also remove all parameters after id.

const shouldIsolate = hash.substr(0, 3) === '#!/';
if (shouldIsolate || hash.substr(0, 2) === '#/') {
const path = hash.replace(/\?id=[^]*/, '');
const tokens = path
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can split the first part at the very beginning with a regexp and avoid all substr calls and magic numbers.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I’m wondering why not introduce a routing solution to the project? It would simplify thing a lot since we won’t need parse location ourselves I guess.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@okonet Like history js?, but its possible that it necessary migrate several things.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we need a router like React Router because we render a single component in any case except welcome screen. But using a library to parse URLs could be a good idea to avoid hard-to-read string operations and regexps.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I agree complete router might be an overkill but let’s not do parsing ourselves

if (hash.substr(0, 3) === '#!/') {
const tokens = hash.substr(3).split('/');
const index = parseInt(tokens[1], 10);
const shouldIsolate = hash.substr(0, 3) === '#!/';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function also needs splitting and comments.

} else if (displayMode === DisplayModes.section) {
return `${sections[0].name} — ${baseTitle}`;
if (displayMode === DisplayModes.notFound) {
return 'Error 404 - ' + baseTitle;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Error 404 → Page not found

displayMode = DisplayModes.component;
let filteredSections;
if (pagePerSection) {
tokens.forEach((tokenName, index) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is happening here?

Copy link
Member

@okonet okonet left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with all Artem’s comments

@rafaesc
Copy link
Collaborator Author

rafaesc commented May 29, 2018

@sapegin @okonet I added a new file to handle the hash.

https://github.com/styleguidist/react-styleguidist/blob/ad5b8b2cf0cf6e4f17f4af34cd3031fc284f992e/src/utils/handleHash.js

You can see the tests.

https://github.com/styleguidist/react-styleguidist/blob/ad5b8b2cf0cf6e4f17f4af34cd3031fc284f992e/src/utils/__tests__/handleHash.spec.js

And his implementation here

export default function getInfoFromHash(hash) {
const shouldIsolate = hasInHash(hash, '#!/');
if (shouldIsolate || hasInHash(hash, '#/')) {
const hashArray = getHashAsArray(hash, shouldIsolate ? '#!/' : '#/');
const index = parseInt(hashArray[hashArray.length - 1], 10);
return {
isolate: shouldIsolate,
hashArray: hashArray.filter(filterNumbers),
targetName: hashArray[0],
targetIndex: isNaN(index) ? undefined : index,
};
}
return {};

/** Scrolls to origin when current window location hash points to an isolated view. */
const scrollToOrigin = () => {
const hash = window.location.hash;
if (hasInHash(hash, '#/') || hasInHash(hash, '#!/')) {
const element = document.scrollingElement || document.documentElement; // cross-browsers
/** Extracts the id param of hash */
const idHashParam = getParameterByName(hash, 'id');
let scrollTop = 0;
if (idHashParam) {
// Searches the node with the same id
const idElement = document.getElementById(idHashParam);
if (idElement && idElement.offsetTop) {
scrollTop = idElement.offsetTop;
}
}
/** Scroll to node or page top */
element.scrollTop = scrollTop;
}
};

@sapegin
Copy link
Member

sapegin commented May 30, 2018

I still think we should try something like https://github.com/unshiftio/url-parse instead of doing this manually.

@rafaesc
Copy link
Collaborator Author

rafaesc commented May 31, 2018

@sapegin I was thinking where use url-parse but I am not sure if we really need it because url-parse doesn't have a method to get the pages of hash and our router is something particular.

I found path-to-regexp, it seems useful but it is more useful to set an URL with params
https://github.com/pillarjs/path-to-regexp/blob/master/Readme.md#compile-reverse-path-to-regexp

Then found hasher, it's a good library because you can customized the pretend hash and you can get the router as array, but it has a strong dependency with location.hash, so it needs to integrate the router with the library when we only need an util.

So I had decided to adapt the part of hasher that we need in handleHash file, it doesn't have a strong dependency, easy to test and isn't necessary a big migration.

What do you think?

@okonet
Copy link
Member

okonet commented Jun 2, 2018

Reach Router is tiny so I’m wondering if we should try using it. It should simply a lot of code imo. https://mobile.twitter.com/ryanflorence/status/1002959657235722240

@sapegin
Copy link
Member

sapegin commented Jun 3, 2018

If it really simplify code (keep in mind that we’re rendering the same component with different props depending on the URL), then I’m fine with it. But we’ll still need something to parse query strings.

@okonet
Copy link
Member

okonet commented Jun 3, 2018

Let’s try router in a separate PR and finish this one. Do we have a conclusion?

@sapegin
Copy link
Member

sapegin commented Jun 3, 2018

Yup, let’s keep this PR as is, the code is isolated at least ;-/

@rafaesc
Copy link
Collaborator Author

rafaesc commented Jun 3, 2018

@sapegin @okonet thanks!

I will add documentation

@rafaesc
Copy link
Collaborator Author

rafaesc commented Jun 6, 2018

@sapegin it's strange that Travis told that there is an error when I only modified Markdown files.

@sapegin
Copy link
Member

sapegin commented Jun 6, 2018

Restart usually helps, any CI can fail for many reasons not related to code changes ;-)

@rafaesc
Copy link
Collaborator Author

rafaesc commented Jun 6, 2018

Yes, yesterday I restarted twice and it had the same result

Opening Cypress...
A configuration option you have supplied has been renamed.
Please rename videoRecording to video

maybe I have to send another change to work fine, please @sapegin review my changes in docs.

@sapegin
Copy link
Member

sapegin commented Jun 7, 2018

That should be fixed in master already.

@@ -282,6 +292,47 @@ module.exports = {
}
```

You can set the number of subpages of each section by adding`sectionDepth` in each first level section.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand what that means ;-(

@@ -48,12 +51,19 @@ function processSection(section, config) {
}
content = requireIt(`!!${examplesLoader}!${contentAbsolutePath}`);
}
sectionDepth =
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs some explanation: what is happening here? What is firstDepth?

src/index.js Outdated
const hash = window.location.hash;
if (hasInHash(hash, '#/') || hasInHash(hash, '#!/')) {
const element = document.scrollingElement || document.documentElement; // cross-browsers
/** Extracts the id param of hash */
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please don't use block comments instead of inline comments, also add an empty line before a comment to separate code paragraphs.

src/index.js Outdated
window.scrollTo(0, 0);
const hash = window.location.hash;
if (hasInHash(hash, '#/') || hasInHash(hash, '#!/')) {
const element = document.scrollingElement || document.documentElement; // cross-browsers
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What this line is doing? What this comment means? Which browsers? Worth extracting to a method with a meaningful name.

} else if (displayMode === DisplayModes.section) {
return `${sections[0].name} — ${baseTitle}`;
if (displayMode === DisplayModes.notFound) {
return 'Error 404 - Page not found';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just “Page not found", I think I've mentioned this before.


if (pagePerSection) {
// Try to filter each section for depth of each hash ["Documentation", "Files", "Button"]
// When sectionDepth is major of 0, their children should be filtered
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What “major of 0” means?

if (!sections.length) {
displayMode = DisplayModes.notFound;
}
// The targetName takes the last of hashArray
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment is repeating the code, but doesn't explain it.

) {
let url = pathname;

if (takeHash) {
url += hash.replace(/\?id=[^]*/, '');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've mentioned before that this is very destructive regexp, it will cause issues.

const separator = '/';
const hashValRegexp = /(.*)\?/;

function escapeRegExp(str) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use escapeRegExp from Lodash.

@@ -0,0 +1,73 @@
const defaultPrependHash = '#/';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This fine needs a huge “HACK” comment explaining that this is a temporary solution.

@rafaesc
Copy link
Collaborator Author

rafaesc commented Jun 22, 2018

It seems that there still is the bug when Travis tries to validate the branch, however, the PR was passed by Travis.

@@ -292,7 +292,7 @@ module.exports = {
}
```

You can set the number of subpages of each section by adding`sectionDepth` in each first level section.
If you want to isolate section's children as single pages, you can set up it adding `sectionDepth` in each section. Where `sectionDepth` it is the number of depth of routes that it will have each section.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can set up it adding sectionDepth in each section… → add the sectionDepth parameter to a section, where the value is the number of section levels that will be shown as single pages?

Though I’m still not 100% sure I understand now it works ;-/

}
]
}
```

For default `sectionDepth`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be removed or finished?

src/index.js Outdated
let scrollTop = 0;

if (idHashParam) {
// Searches the node with the same id
// Searches the node with the same id and takes his offsetTop
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment repeats the code but doesn't explain the intent.

@sapegin
Copy link
Member

sapegin commented Jun 24, 2018

Yeah, that's weird. I don't understand the difference between push and pr anyway ;-/

I think the code is fine now, just a few docs tweaks left.

@sapegin
Copy link
Member

sapegin commented Jul 1, 2018

Could you please merge master? Is there anything else left or we can make 7.1 release with this?

@rafaesc
Copy link
Collaborator Author

rafaesc commented Jul 1, 2018

@sapegin I think there is no more, I am going to solve the conflict with the master branch

@rafaesc rafaesc merged commit aa34bfe into master Jul 2, 2018
@sapegin
Copy link
Member

sapegin commented Jul 2, 2018

Merging this to maser wasn't a good idea, I'm going to revert it.

@rafaesc
Copy link
Collaborator Author

rafaesc commented Jul 2, 2018

Apologies I thought you mean that, tell me if I can help in any way

@sapegin
Copy link
Member

sapegin commented Jul 2, 2018

Maybe I wasn't clear enough, I meant to merge master into your branch to resolve merge conflicts.

I've reverted the merge now, but you will need to open a new PR I think (renaming the branch and opening a new PR should work).

P. S. You can try to make a new release if you want, there are some docs about the process. Let me know if that's something you'd like to do ;-)

@rafaesc
Copy link
Collaborator Author

rafaesc commented Jul 2, 2018

Perfect, thanks!

I will work it :)

@sapegin sapegin added this to the 7.1.0 milestone Jul 2, 2018
@sapegin
Copy link
Member

sapegin commented Jul 2, 2018

Ping me if you have any questions, there's a milestone for the next release.

@sapegin sapegin removed this from the 7.1.0 milestone Jul 6, 2018
@styleguidist-bot
Copy link
Collaborator

🎉 This PR is included in version 7.1.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants