Skip to content

Add limited support for named exports. Add docs relating to this support. #825

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

Merged
merged 10 commits into from
Mar 21, 2018
Merged

Conversation

marcdavi-es
Copy link
Contributor

Summary

This responds to the need expressed in #820 and #633

It preserves the base case of Styleguidist loading default exports by default, while adding some limited support for exposing named exports where a module exposes no default export and either:

  • just one named export; or
  • a named export which matches the component name understood by Styleguidist.

I think these cases are non-controversial. In each case, it is almost guaranteed that the developer intends these named exports to be interpreted as the exported component.

I have added documentation covering this. The documentation is careful to emphasise that this is not a complete solution for named exports - Styleguidist will do its best but in complicated cases will just fall back to exposing the module as a whole, as it currently does.

Super happy to take questions and feedback on this. I love what you guys are doing with this tool.

Question

In the existing implementation of globalizeComponent, there are references to component.props.path. I couldn't get this property to show its face with a bunch of different configurations/attempts. I suspect maybe it's a legacy thing which is still hanging around.

If I'm missing something here please let me know and I'll take account of this in the PR.

@marcdavi-es marcdavi-es mentioned this pull request Feb 15, 2018
@marcdavi-es marcdavi-es reopened this Feb 16, 2018
@codecov-io
Copy link

codecov-io commented Feb 16, 2018

Codecov Report

Merging #825 into master will increase coverage by 0.16%.
The diff coverage is 100%.

Impacted Files Coverage Δ
src/utils/getComponent.js 100% <100%> (ø)
src/utils/globalizeComponent.js 100% <100%> (+28.57%) ⬆️
src/rsg-components/Markdown/Markdown.js 100% <0%> (ø) ⬆️
...g-components/Markdown/Checkbox/CheckboxRenderer.js 100% <0%> (ø)

@marcdavi-es
Copy link
Contributor Author

One of the tests fails on one of the builds but passes on the others. It seems that the afterEach block in globalizeComponent.spec.js isn't doing its job in this case.

I tried refactoring the test to avoid reliance on the enumerable properties of global but still no joy. Would appreciate any input on this.

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, this is interesting and I hope will make Styleguidist more flexible.

In the existing implementation of globalizeComponent, there are references to component.props.path.

I think it's safe to remove if everything still works.

I tried refactoring the test to avoid reliance on the enumerable properties of global but still no joy. Would appreciate any input on this.

Maybe try to put afterEach inside describe? Just a guess ;-/

// will fall back on the file name, convert it to PascalCase
// and expose globally as ComponentFour
```

Copy link
Member

Choose a reason for hiding this comment

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

There's one more use case: folder name when the file name is index.js.

// and expose globally as ComponentFour
```

### default vs named exports
Copy link
Member

Choose a reason for hiding this comment

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

Default


### default vs named exports

Styleguidist defaults to exposing the `default` export from your component file. It understands functions exported as CommonJs `module.exports` as default exports.
Copy link
Member

Choose a reason for hiding this comment

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

Maybe “Stylegudist will use ECMAScript module’s default export or CommonJS module.exports if they are defined”?

// will be exposed globally as ComponentEight
```

If you export several React components as named exports from a single module, Styleguidist is likely to behave unreliably. If it cannot understand which named export to expose, it will fall back to exposing the module as a whole.
Copy link
Member

Choose a reason for hiding this comment

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

it will fall back to exposing the module as a whole.

Not sure what exactly that mean, but most likey you'll not be able to access components, so we can say that instead ;-)


Styleguidist _loads_ your components and _exposes_ them globally for your examples to consume.

### Identifier
Copy link
Member

Choose a reason for hiding this comment

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

Would be nice to make this section shorted and easier to scan. Maybe use one big table instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Resorting to HTML table format here to play nicely with the code blocks. It makes this file a little ugly but the output is good.

Copy link
Member

Choose a reason for hiding this comment

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

Could be simpler:

| foo | bar |
| --- | --- | 
| `foo`<br>`bar` | bar |

Also you can remove the last column and use the same component name everywhere, and merge displayName and fallback columns since they are mutually exclusive.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah yeah nice. Done.

Copy link
Member

Choose a reason for hiding this comment

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

Wow, it's like 10 times smaller now ;-)

* @param {string} name
* @return {function|object}
*/
export default function getComponent(module, name) {
Copy link
Member

Choose a reason for hiding this comment

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

I guess your understanding of this code is very good now, could you please add comments to each variation? Preferably with code examples. This is one of the most obscure parts of the code base ;-/

Copy link
Member

Choose a reason for hiding this comment

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

Nice! Please add a blank line before each comment to make it easier to read.

@@ -1,18 +1,30 @@
import globalizeComponent from '../globalizeComponent';

jest.mock('../getComponent');
Copy link
Member

Choose a reason for hiding this comment

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

Can we avoid mocking here? Doesn't look necessary.

@@ -1,18 +1,30 @@
import globalizeComponent from '../globalizeComponent';

jest.mock('../getComponent');
// eslint-disable-next-line import/first
import getComponent, { returnValue } from '../getComponent';
Copy link
Member

Choose a reason for hiding this comment

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

ESM imports are hoisted to the top of the file, so disabling ESLint here is unnecessary and misleading.

@marcdavi-es
Copy link
Contributor Author

Thanks for the feedback :)

I'm out this weekend but I'll get to this on Monday.

@marcdavi-es
Copy link
Contributor Author

@sapegin I think that's everything. Let me know if you're happy with those changes :)

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, almost!


Styleguidist _loads_ your components and _exposes_ them globally for your examples to consume.

### Identifier
Copy link
Member

Choose a reason for hiding this comment

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

Could be simpler:

| foo | bar |
| --- | --- | 
| `foo`<br>`bar` | bar |

Also you can remove the last column and use the same component name everywhere, and merge displayName and fallback columns since they are mutually exclusive.

* @param {string} name
* @return {function|object}
*/
export default function getComponent(module, name) {
Copy link
Member

Choose a reason for hiding this comment

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

Nice! Please add a blank line before each comment to make it easier to read.

* @return {function|object}
*/
export default function getComponent(module, name) {
//
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Had to leave this little 'comment' in here to stop Prettier complaining about the blank line...

Copy link
Member

Choose a reason for hiding this comment

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

Sorry, I wasn't clear enough: blank lines to separate code “paragraphs”, not just empty line before each comment ;-)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

So you mean changing this

	// If the module defines a default export, return that
	// e.g.
	// ```
	// export default function Component() { ... }
	// ```
	if (module.default) { ...

to this

	// If the module defines a default export, return that
	// e.g.
        //
	// ```
	// export default function Component() { ... }
	// ```
        //
	if (module.default) { ...

Or something else? :)

Copy link
Member

Choose a reason for hiding this comment

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

Exactly! Just to separate different sections of code.

@marcdavi-es
Copy link
Contributor Author

@sapegin Thanks - yeah that table was ugly. Think it's much cleaner now.


Styleguidist _loads_ your components and _exposes_ them globally for your examples to consume.

### Identifier
Copy link
Member

Choose a reason for hiding this comment

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

Wow, it's like 10 times smaller now ;-)

@marcdavi-es
Copy link
Contributor Author

@sapegin Sweet - comments spaced out better now :)

@sapegin sapegin added this to the 6.3.0 milestone Feb 21, 2018
@sapegin sapegin merged commit fb1d2ec into styleguidist:master Mar 21, 2018
sapegin pushed a commit that referenced this pull request Mar 22, 2018
👋 **[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)
@sapegin
Copy link
Member

sapegin commented Mar 22, 2018

🎉 This PR is included in version 6.5.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.

3 participants