-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
Sort properties by 'required' and 'name' attributes #784
Conversation
Codecov Report
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! That looks useful.
I think we should do in on the backend though, in the props-loader somewhere. Ping me if you need help with finding the right place ;-)
@sapegin I'm not completely sure, but I guess it's not possible since |
I don't think there's a strict requirement to keep it as an object, but I'm afraid it may be too difficult to change now. |
import { unquote, getType, showSpaces } from './util'; | ||
|
||
// Test renderers with clean readable snapshot diffs | ||
// eslint-disable-next-line react/prop-types | ||
export default function ColumnsRenderer({ props }) { | ||
return ( | ||
<ul> | ||
{propsToArray(props).map((row, rowIdx) => ( | ||
{/* eslint-disable react/prop-types */} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure why react/prop-types
makes problems here. I've tried to add propTypes
for this component but had no success. Do you have an idea?
ColumnsRenderer.propTypes = {
props: PropTypes.array.isRequired,
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And it was already disabled: // eslint-disable-next-line react/prop-types
;-/ I guess because of the name props
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, I didn't notice that. 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's disable it for the whole file, it's a test anyway ;-)
@sapegin Changing how the props-loader works was a bit harder, but it's possible I guess. Please have another look. Since I don't know the code by heart I hope I have found every occurrence of props object vs. array, so please consider having another look into other components that are involved which I could have forgotten. |
@sapegin What do you think? Are there still changes necessary or are you fine with it? Current review status says that there are still requested changes. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Couple of small remarks, otherwise looks good. Thanks!
loaders/props-loader.js
Outdated
@@ -12,6 +12,18 @@ const consts = require('../scripts/consts'); | |||
|
|||
const ERROR_MISSING_DEFINITION = 'No suitable component definition found.'; | |||
|
|||
function sortProps(props) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function should be in a separate file with JSDocs comment, like other functions. Will be easier to test separately too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right. I've separated the function into an own file, added JSDocs and tests.
loaders/props-loader.js
Outdated
@@ -52,6 +64,10 @@ module.exports = function(source) { | |||
} | |||
|
|||
props = getProps(props, file); | |||
if (props.props) { | |||
const sortedProps = sortProps(props.props); | |||
props.props = sortedProps; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think props.props = sortProps(props.props);
would be enough here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's true. Done. 👍
import { unquote, getType, showSpaces } from './util'; | ||
|
||
// Test renderers with clean readable snapshot diffs | ||
// eslint-disable-next-line react/prop-types | ||
export default function ColumnsRenderer({ props }) { | ||
return ( | ||
<ul> | ||
{propsToArray(props).map((row, rowIdx) => ( | ||
{/* eslint-disable react/prop-types */} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's disable it for the whole file, it's a test anyway ;-)
@sapegin Alright, I've fixed all findings 👍 |
Can this be made optional? Props have different significance, and I personally sort/group them manually in the order of significance. For example, I would dislike having something like |
@n1313 I guess it could be made optional. In the props-loader we have access to the |
I'd suggest to make a more generic option to transform props with the default implementation that will sort them like in this PR. To disable sorting you could pass a function that does nothing. I don't really like the idea or an option that control sorting of props, that feels too specific. |
I've added my idea of how a generic function could look like. What are your opinions on that approach? |
The option of sorting props is valuable and useful, but I would personally prefer the default prop display behaviour to not change (especially if it is coming in with only a minor version bump). |
I'd like to collect more opinions, so far we're two against one ;-) @okonet @kof @SaraVieira @stepancar What do you think? |
@n1313 I understand your point, but I do not agree. The current implementation does not make any assumptions about the order of the properties. Eventually it uses the sorting of keys in an object, which is not standardised (see here). So this should change anyways to make it reliable - even if this had not been an issue so far. |
this sort by default makes sense, evtl optionally could be disabled, but I don't care right now about this, I hate manually decide what is more important and most of the time just put require stuff first. Btw this should be an eslint feature which also works with --fix |
Well, truth be told, I'm still sitting on v5.3.2 (because I couldn't get over the previous UI change that came in with a minor version bump and undoing that change is too much effort), so this change won't affect me at all. But if I was on v6, I would be pissed. |
One suggestion to validate users reaction could be to release a beta first and see if any one else has hard feelings about this change. In general prettier showed that good automated defaults are well accepted by the community. |
Btw. having this in eslint would completely solve the problem as you would shift this decision to the user. |
https://eslint.org/docs/rules/sort-keys exists, but it doesn't work with --fix :| |
eslint does not solve this problem, because eslint is a tool for structuring code. But it does not change the way how the underlying JavaScript engine interprets objects and how it sorts the keys. The only way to solve this problem is to use a data-structure with a guaranteed order, such as arrays. This PR tries to archive an order of the properties by transforming the object to an array of objects where a strict order is defined and uses this array for property rendering. So please keep this discussion focused. eslint does something completely different. The |
The let’s just do this and see if anyone else will complain. I believe this would be more useful for majority of the users and we have a way to disable this. We can’t make all users happy anyway. |
That's true. We could disable it by using To completely solve the problem and not rely on the pseudo-sorting of keys in an object we would have to change the way how |
docs/Configuration.md
Outdated
|
||
Type: `Function`, optional | ||
|
||
Function that transforms component properties. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
An example how to disable sorting and note that the default implementation sorts props would be nice.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea. I've improved the documentation. Please have another look.
What's the plan if someone else does complain? Roll back the release?
In my opinion it is important to note that current situation with props being unsorted is not a known source of unhappiness for any noticeable fraction of users of RSG (at the very least I am not aware of any issues or complaints about this in the repo). Many users are relying on current behaviour of RSG even though it is non-standard, and changing it will no doubt be a surprise to them. Please consider keeping current behaviour as default by shipping with |
We can always change the default value.
I did consider that and have made a decision, thanks for comments. |
docs/Configuration.md
Outdated
|
||
```javascript | ||
module.exports = { | ||
transformProps: function(props) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
props => props
;-)
I think it’s a great thing to put required props on top and option below. I can imagine some push back from very pedantic users who carefully organize props in the source code so an opt-out should be provided but I believe most of users will appreciate this. |
🎉 This PR is included in version 6.4.0 🎉 The release is available on: Your semantic-release bot 📦🚀 |
👋 **[Support Styleguidist](https://opencollective.com/styleguidist) on Open Collective** 👋 ## New features ### Page per section 🚧 This is a huge improvement for large style guides: now you can show only one component at a page instead of all components. ![](https://d3vv6lp55qjaqc.cloudfront.net/items/0W2q2K2s3n2k311O1J0y/Screen%20Recording%202018-03-22%20at%2010.06%20AM.gif) To enable: ```js module.exports = { pagePerSection: true }; ``` This is an experimental feature and we need your feedback to make it better and really useful. For example, right now there’s no isolated mode. So feel free to share your ideas [in issues](https://github.com/styleguidist/react-styleguidist/issues). (#835 by @bitionaire and @stepancar, closes #494 and #768) ### “Fork me” ribbon One more step to make Styleguidist usable for documenting open source projects: ![](https://d3vv6lp55qjaqc.cloudfront.net/items/1t331n2a3v0F2i290K0Z/Image%202018-03-22%20at%209.13.11%20AM.png) New config option to enable the ribbon, define the URL and change the label: ```js module.exports = { ribbon: { url: 'http://example.com/', text: 'Fork me on GitHub' } }; ``` And two new [theme variables](https://github.com/styleguidist/react-styleguidist/blob/master/src/styles/theme.js) to change colors: `color.ribbonBackground` and `color.ribbonText`. (#861 by @glebez and @wkwiatek, part of #195, closes #647) ### Options to change CLI output on server start and build Two new options, `printServerInstructions` and `printBuildInstructions`: ```js module.exports = { printBuildInstructions(config) { console.log( `Style guide published to ${ config.styleguideDir }. Something else interesting.` ); } }; ``` (#878 by @roblevintennis, closes #876) ### Option to modify props A new option, `updateDocs` to modify props before rendering. For example, you can load a component version number from a JSON file: ```js module.exports = { updateDocs(docs) { if (docs.doclets.version) { const versionFilePath = path.resolve( path.dirname(file), docs.doclets.version ); const version = require(versionFilePath).version; docs.doclets.version = version; docs.tags.version[0].description = version; } return docs; } }; ``` (#868 by @ryanoglesby08) ### Limited support for named exports Styleguidist used to require default exports for components. Now you can use named exports too, though Styleguidist still supports only one component per file. I hope this change will make some users happier, see more details [in the docs](https://react-styleguidist.js.org/docs/components.html#loading-and-exposing-components). (#825 by @marcdavi-es, closes #820 and #633) ### Allow arrays of component paths in sections More flexibility in structuring your style guide: ```js module.exports = { sections: [ { name: 'Forms', components: [ 'lib/components/ui/Button.js', 'lib/components/ui/Input.js' ] } ] }; ``` (#794 by @glebez, closes #774) ### Sort properties by `required` and `name` attributes This change should make props tables more predictable for the users. Instead of relying on developers to sort props in a meaningful way, Styleguidist will show required props first, and sort props in each group alphabetically. To disable sorting, use the identity function: ```javascript module.exports = { sortProps: props => props }; ``` (#784 by @dotcs) ## Bug fixes * Allow `Immutable` state in examples (#870 by @nicoffee, closes #864) * Change template container ID to prevent clashes (#859 by @glebez, closes #753) * Better props definitions with Flow types (#781 by @nanot1m)
I've noticed that properties are not sorted. I think it would make sense to first show the required properties and then the optional ones. Each of both groups should be grouped by name.
This PR solves the issue by adjusting how
propsToArray
works.