Skip to content

Commit 9d94158

Browse files
Merge pull request #92 from soren121/component-expression-name
fix: use correct component identifier throughout docblock
2 parents 2156412 + feb3c6f commit 9d94158

3 files changed

Lines changed: 55 additions & 9 deletions

File tree

src/__tests__/__snapshots__/generateDocgenCodeBlock.test.ts.snap

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,30 @@ try {
2828
catch (__react_docgen_typescript_loader_error) { }"
2929
`;
3030
31+
exports[`adds component with display name to docgen collection 1`] = `
32+
"import * as React from "react";
33+
34+
interface ButtonComponentProps {
35+
text: string;
36+
}
37+
38+
export const Button = (props: ButtonComponentProps) => (
39+
<button>{props.text}</button>
40+
);
41+
42+
Button.displayName = "MyButtonDisplayName";
43+
44+
try {
45+
// @ts-ignore
46+
Button.__docgenInfo = { "description": "", "displayName": "MyButtonDisplayName", "props": { "text": { "defaultValue": null, "description": "", "name": "text", "required": true, "type": { "name": "string" } } } };
47+
// @ts-ignore
48+
if (typeof STORYBOOK_REACT_CLASSES !== "undefined")
49+
// @ts-ignore
50+
STORYBOOK_REACT_CLASSES["DisplayName.tsx#MyButtonDisplayName"] = { docgenInfo: Button.__docgenInfo, name: "MyButtonDisplayName", path: "DisplayName.tsx#MyButtonDisplayName" };
51+
}
52+
catch (__react_docgen_typescript_loader_error) { }"
53+
`;
54+
3155
exports[`component fixture DefaultPropValue.tsx has code block generated 1`] = `
3256
"import * as React from "react";
3357
@@ -93,8 +117,6 @@ export const Button = (props: ButtonComponentProps) => (
93117
Button.displayName = "MyButtonDisplayName";
94118
95119
try {
96-
// @ts-ignore
97-
MyButtonDisplayName.displayName = "MyButtonDisplayName";
98120
// @ts-ignore
99121
Button.__docgenInfo = { "description": "", "displayName": "MyButtonDisplayName", "props": { "text": { "defaultValue": null, "description": "", "name": "text", "required": true, "type": { "name": "string" } } } };
100122
}

src/__tests__/generateDocgenCodeBlock.test.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,8 @@ function loadFixtureTests(): GeneratorOptions[] {
3030
}
3131

3232
const fixtureTests: GeneratorOptions[] = loadFixtureTests();
33-
const simpleFixture = fixtureTests.find(
34-
(f) => f.filename === "Simple.tsx"
35-
) as GeneratorOptions;
33+
const simpleFixture = fixtureTests.find((f) => f.filename === "Simple.tsx")!
34+
const displayNameFixture = fixtureTests.find((f) => f.filename === "DisplayName.tsx")!
3635

3736
describe("component fixture", () => {
3837
fixtureTests.forEach((generatorOptions) => {
@@ -51,6 +50,15 @@ it("adds component to docgen collection", () => {
5150
).toMatchSnapshot();
5251
});
5352

53+
it("adds component with display name to docgen collection", () => {
54+
expect(
55+
generateDocgenCodeBlock({
56+
...displayNameFixture,
57+
docgenCollectionName: "STORYBOOK_REACT_CLASSES",
58+
})
59+
).toMatchSnapshot();
60+
});
61+
5462
it("generates value info for enums", () => {
5563
expect(
5664
generateDocgenCodeBlock(

src/generateDocgenCodeBlock.ts

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,16 @@ export interface GeneratorOptions {
1111
typePropName: string;
1212
}
1313

14+
/**
15+
* Gets the identifier name for the component.
16+
*
17+
* If the component has a displayName that differs from its
18+
* identifier, this will return the identifier.
19+
*/
20+
function getComponentIdentifier(d: ComponentDoc): string {
21+
return d.expression?.getName() || d.displayName
22+
}
23+
1424
/**
1525
* Inserts a ts-ignore comment above the supplied statement.
1626
*
@@ -42,12 +52,18 @@ function insertTsIgnoreBeforeStatement(statement: ts.Statement): ts.Statement {
4252
* SimpleComponent.displayName = "SimpleComponent";
4353
* ```
4454
*/
45-
function setDisplayName(d: ComponentDoc): ts.Statement {
55+
function setDisplayName(d: ComponentDoc): ts.Statement | null {
56+
// If the expression name doesn't match the display name,
57+
// then we know the component has already set a displayName
58+
if (d.expression && d.expression.getName() !== d.displayName) {
59+
return null
60+
}
61+
4662
return insertTsIgnoreBeforeStatement(
4763
ts.factory.createExpressionStatement(
4864
ts.factory.createBinaryExpression(
4965
ts.factory.createPropertyAccessExpression(
50-
ts.factory.createIdentifier(d.displayName),
66+
ts.factory.createIdentifier(getComponentIdentifier(d)),
5167
ts.factory.createIdentifier("displayName")
5268
),
5369
ts.SyntaxKind.EqualsToken,
@@ -270,7 +286,7 @@ function insertDocgenIntoGlobalCollection(
270286
ts.factory.createPropertyAssignment(
271287
ts.factory.createIdentifier("docgenInfo"),
272288
ts.factory.createPropertyAccessExpression(
273-
ts.factory.createIdentifier(d.displayName),
289+
ts.factory.createIdentifier(getComponentIdentifier(d)),
274290
ts.factory.createIdentifier("__docgenInfo")
275291
)
276292
),
@@ -316,7 +332,7 @@ function setComponentDocGen(
316332
ts.factory.createBinaryExpression(
317333
// SimpleComponent.__docgenInfo
318334
ts.factory.createPropertyAccessExpression(
319-
ts.factory.createIdentifier(d.expression?.getName() || d.displayName),
335+
ts.factory.createIdentifier(getComponentIdentifier(d)),
320336
ts.factory.createIdentifier("__docgenInfo")
321337
),
322338
ts.SyntaxKind.EqualsToken,

0 commit comments

Comments
 (0)