From e637f5319ab198dc4bfec59fc52b6b2b067185c5 Mon Sep 17 00:00:00 2001 From: Lazyuki Date: Thu, 3 Sep 2020 15:22:03 +0900 Subject: [PATCH] fix: Handle visibleName with non-alphanumeric characters (#1675) Refs https://github.com/styleguidist/react-docgen-typescript/issues/292 --- src/loaders/__tests__/examples-loader.spec.ts | 27 +++++++++++++ src/loaders/utils/resolveESModule.ts | 40 +++++++++++-------- 2 files changed, 50 insertions(+), 17 deletions(-) diff --git a/src/loaders/__tests__/examples-loader.spec.ts b/src/loaders/__tests__/examples-loader.spec.ts index 4ad67013c..f1898903f 100644 --- a/src/loaders/__tests__/examples-loader.spec.ts +++ b/src/loaders/__tests__/examples-loader.spec.ts @@ -9,7 +9,17 @@ const query = { shouldShowDefaultExample: false, }; +const subComponentQuery = { + file: '../fooSub.js', + displayName: 'FooComponent.SubComponent', + shouldShowDefaultExample: false, +}; + + const getQuery = (options = {}) => encode({ ...query, ...options }, '?'); +const getSubComponentQuery = (options = {}) => encode({ ...subComponentQuery, ...options }, '?'); + + it('should return valid, parsable JS', () => { const exampleMarkdown = ` @@ -201,6 +211,23 @@ it('should prepend example code with component require()', () => { ); }); +it('should prepend example code with root component require() for sub components', () => { + const exampleMarkdown = ``; + const result = examplesLoader.call( + { + query: getSubComponentQuery(), + _styleguidist: {}, + } as any, + exampleMarkdown + ); + + expect(result).toBeTruthy(); + expect(() => new Function(result)).not.toThrowError(SyntaxError); + expect(result).toMatch( + `const FooComponentSubComponent$0 = require('../fooSub.js');\\nconst FooComponentSubComponent = FooComponentSubComponent$0.default || (FooComponentSubComponent$0['FooComponentSubComponent'] || FooComponentSubComponent$0);` + ); +}); + it('should allow explicit import of React and component module', () => { const exampleMarkdown = ` import React from 'react'; diff --git a/src/loaders/utils/resolveESModule.ts b/src/loaders/utils/resolveESModule.ts index ef8d314f7..d071cfe29 100644 --- a/src/loaders/utils/resolveESModule.ts +++ b/src/loaders/utils/resolveESModule.ts @@ -8,20 +8,26 @@ import requireIt from './requireIt'; * @param name the name of the resulting variable * @returns AST */ -export default (requireRequest: string, name: string) => [ - // const name$0 = require(path); - b.variableDeclaration('const', [ - b.variableDeclarator(b.identifier(`${name}$0`), requireIt(requireRequest).toAST() as any), - ]), - // const name = name$0.default || name$0[name] || name$0; - b.variableDeclaration('const', [ - b.variableDeclarator( - b.identifier(name), - b.logicalExpression( - '||', - b.identifier(`${name}$0.default`), - b.logicalExpression('||', b.identifier(`${name}$0['${name}']`), b.identifier(`${name}$0`)) - ) - ), - ]), -]; +export default (requireRequest: string, name: string) => { + // The name could possibly contain invalid characters for a JS variable name + // such as "." or "-". + const safeName = name ? name.replace(/\W/, '') : name; + + return [ + // const safeName$0 = require(path); + b.variableDeclaration('const', [ + b.variableDeclarator(b.identifier(`${safeName}$0`), requireIt(requireRequest).toAST() as any), + ]), + // const safeName = safeName$0.default || safeName$0[safeName] || safeName$0; + b.variableDeclaration('const', [ + b.variableDeclarator( + b.identifier(safeName), + b.logicalExpression( + '||', + b.identifier(`${safeName}$0.default`), + b.logicalExpression('||', b.identifier(`${safeName}$0['${safeName}']`), b.identifier(`${safeName}$0`)) + ) + ), + ]), + ] +};