From bcb97e19603f3815220c67e34527b5c3143dc954 Mon Sep 17 00:00:00 2001 From: olfedias Date: Wed, 19 Dec 2018 13:02:15 +0100 Subject: [PATCH 1/4] docs(Examples): separate contexts, use sources to render dedicated examples --- .../ComponentExample/SourceCodeManager.ts | 6 ++-- .../ComponentDoc/ComponentExamples.tsx | 24 +++++++------- docs/src/components/ExternalExampleLayout.tsx | 32 +++++++++++++++---- docs/src/utils/exampleContext.ts | 11 ------- docs/src/utils/exampleContexts.ts | 13 ++++++++ docs/src/utils/exampleKebabNameToFilename.ts | 15 --------- .../utils/exampleKebabNameToSourceFilename.ts | 15 +++++++++ docs/src/utils/index.tsx | 4 +-- 8 files changed, 71 insertions(+), 49 deletions(-) delete mode 100644 docs/src/utils/exampleContext.ts create mode 100644 docs/src/utils/exampleContexts.ts delete mode 100644 docs/src/utils/exampleKebabNameToFilename.ts create mode 100644 docs/src/utils/exampleKebabNameToSourceFilename.ts diff --git a/docs/src/components/ComponentDoc/ComponentExample/SourceCodeManager.ts b/docs/src/components/ComponentDoc/ComponentExample/SourceCodeManager.ts index 3545893e2d..e0ff8f8c31 100644 --- a/docs/src/components/ComponentDoc/ComponentExample/SourceCodeManager.ts +++ b/docs/src/components/ComponentDoc/ComponentExample/SourceCodeManager.ts @@ -1,3 +1,5 @@ +import { exampleSourcesContext } from '../../../utils' + interface SourceCodeData { path: string code: string @@ -84,9 +86,9 @@ class SourceCodeManager { private safeRequire = (path: string): string | undefined => { try { - const filename = `${path.replace(/^components\//, '')}.source.json` + const filename = `${path.replace(/^components\//, './')}.source.json` - return require(`!docs/src/exampleSources/${filename}`).js + return exampleSourcesContext(filename).js } catch (e) { return undefined } diff --git a/docs/src/components/ComponentDoc/ComponentExamples.tsx b/docs/src/components/ComponentDoc/ComponentExamples.tsx index 0c8231e9e1..b880b5bc68 100644 --- a/docs/src/components/ComponentDoc/ComponentExamples.tsx +++ b/docs/src/components/ComponentDoc/ComponentExamples.tsx @@ -2,7 +2,7 @@ import * as _ from 'lodash' import PropTypes from 'prop-types' import * as React from 'react' -import { exampleContext } from 'docs/src/utils' +import { exampleGroupsContext, exampleSourcesContext } from 'docs/src/utils' import { Grid, List } from 'semantic-ui-react' import { examplePathPatterns } from './ComponentExample' import ContributionPrompt from './ContributionPrompt' @@ -30,23 +30,22 @@ export default class ComponentExamples extends React.Component { const { displayName } = this.props - const allPaths = exampleContext.keys() // rule #1 - const indexPath = _.find(allPaths, path => + const indexPath = _.find(exampleGroupsContext.keys(), path => new RegExp(`\/${displayName}\/index\.tsx$`).test(path), ) if (!indexPath) { return null } - const ExamplesElement = React.createElement(exampleContext(indexPath).default) as any + const ExamplesElement = React.createElement(exampleGroupsContext(indexPath).default) as any if (!ExamplesElement) { return null } // rules #2 and #3 - const missingPaths = this.testExamplesStructure(displayName, allPaths) + const missingPaths = this.testExamplesStructure(displayName, exampleSourcesContext.keys()) return missingPaths && missingPaths.length ? (
{this.renderMissingShorthandExamples(missingPaths)} {ExamplesElement} @@ -82,23 +81,24 @@ export default class ComponentExamples extends React.Component `${pattern}.tsx`) + ].map(pattern => `${pattern}.source.json`) + const [normalRegExp, shorthandRegExp] = [normalExtension, shorthandExtension].map( extension => new RegExp(`${examplesPattern}\\w*${extension}$`), ) - const allExamplesPaths = allPaths.filter(path => allExamplesRegExp.test(path)) - const expectedShorthandExamples = allExamplesPaths + const expectedShorthandExamples = allPaths .filter(path => normalRegExp.test(path)) .map(path => path.replace(normalExtension, shorthandExtension)) - const actualShorthandExamples = allExamplesPaths.filter(path => shorthandRegExp.test(path)) + const actualShorthandExamples = allPaths.filter(path => shorthandRegExp.test(path)) - return _.difference(expectedShorthandExamples, actualShorthandExamples) + return _.difference(expectedShorthandExamples, actualShorthandExamples).map(exampleFile => + exampleFile.replace(/\.source\.json$/, '.tsx'), + ) } } diff --git a/docs/src/components/ExternalExampleLayout.tsx b/docs/src/components/ExternalExampleLayout.tsx index 082b9e8f84..7e33e1590f 100644 --- a/docs/src/components/ExternalExampleLayout.tsx +++ b/docs/src/components/ExternalExampleLayout.tsx @@ -1,11 +1,14 @@ import * as _ from 'lodash/fp' import PropTypes from 'prop-types' import * as React from 'react' +import SourceRender from 'react-source-render' -import { exampleContext, exampleKebabNameToFilename, parseExamplePath } from 'docs/src/utils' +import { ExampleSource } from 'docs/src/types' +import { exampleSourcesContext, exampleKebabNameToFilename, parseExamplePath } from 'docs/src/utils' import PageNotFound from '../views/PageNotFound' +import { babelConfig, importResolver } from './Playground/renderConfig' -const examplePaths = exampleContext.keys() +const examplePaths = exampleSourcesContext.keys() const ExternalExampleLayout: any = props => { const { exampleName } = props.match.params @@ -17,11 +20,26 @@ const ExternalExampleLayout: any = props => { }, examplePaths) if (!examplePath) return - - const ExampleComponent = exampleContext(examplePath).default - if (!ExampleComponent) return - - return + const exampleSource: ExampleSource = exampleSourcesContext(examplePath) + + return ( + + + {({ element, error }) => ( + <> + {element} + {/* This block allows to see issues with examples as visual regressions. */} + {error &&
{error.toString()}
} + + )} +
+
+ ) } ExternalExampleLayout.propTypes = { diff --git a/docs/src/utils/exampleContext.ts b/docs/src/utils/exampleContext.ts deleted file mode 100644 index 2f1a1f991c..0000000000 --- a/docs/src/utils/exampleContext.ts +++ /dev/null @@ -1,11 +0,0 @@ -/** - * Get the Webpack Context for all doc site examples. - */ - -const exampleContext = require.context( - 'docs/src/examples/', - true, - /(\w+Example(\w|\.)*|index)\.tsx$/, -) - -export default exampleContext diff --git a/docs/src/utils/exampleContexts.ts b/docs/src/utils/exampleContexts.ts new file mode 100644 index 0000000000..7181812ff4 --- /dev/null +++ b/docs/src/utils/exampleContexts.ts @@ -0,0 +1,13 @@ +/** + * Get the Webpack Context for doc site example groups. + */ +export const exampleGroupsContext = require.context('docs/src/examples/', true, /index.tsx$/) + +/** + * Get the Webpack Context for doc site example sources. + */ +export const exampleSourcesContext = require.context( + 'docs/src/exampleSources/', + true, + /.source.json$/, +) diff --git a/docs/src/utils/exampleKebabNameToFilename.ts b/docs/src/utils/exampleKebabNameToFilename.ts deleted file mode 100644 index bd9e67889c..0000000000 --- a/docs/src/utils/exampleKebabNameToFilename.ts +++ /dev/null @@ -1,15 +0,0 @@ -import * as _ from 'lodash/fp' - -/** - * Converts kebab-cased-example-name back into the original filename. - * @param {string} exampleKebabName - */ -const exampleKebabNameToFilename = exampleKebabName => { - // button-example => ButtonExample.tsx - // button-example-shorthand => ButtonExample.shorthand.tsx - return `${_.startCase(exampleKebabName) - .replace(/ /g, '') - .replace(/Shorthand$/, '.shorthand')}.tsx` -} - -export default exampleKebabNameToFilename diff --git a/docs/src/utils/exampleKebabNameToSourceFilename.ts b/docs/src/utils/exampleKebabNameToSourceFilename.ts new file mode 100644 index 0000000000..caccfb667b --- /dev/null +++ b/docs/src/utils/exampleKebabNameToSourceFilename.ts @@ -0,0 +1,15 @@ +import * as _ from 'lodash/fp' + +/** + * Converts kebab-cased-example-name back into the original filename. + * @param {string} exampleKebabName + */ +const exampleKebabNameToSourceFilename = exampleKebabName => { + // button-example => ButtonExample.source.json + // button-example-shorthand => ButtonExample.shorthand.source.json + return `${_.startCase(exampleKebabName) + .replace(/ /g, '') + .replace(/Shorthand$/, '.shorthand')}.source.json` +} + +export default exampleKebabNameToSourceFilename diff --git a/docs/src/utils/index.tsx b/docs/src/utils/index.tsx index 5e8a3dcf88..b1a938c532 100644 --- a/docs/src/utils/index.tsx +++ b/docs/src/utils/index.tsx @@ -1,7 +1,7 @@ export { default as componentInfoContext } from './componentInfoContext' export { default as componentInfoShape } from './componentInfoShape' -export { default as exampleContext } from './exampleContext' -export { default as exampleKebabNameToFilename } from './exampleKebabNameToFilename' +export { exampleGroupsContext, exampleSourcesContext } from './exampleContexts' +export { default as exampleKebabNameToFilename } from './exampleKebabNameToSourceFilename' export { default as examplePathToHash } from './examplePathToHash' export { default as getComponentGroup } from './getComponentGroup' export { default as getComponentPathname } from './getComponentPathname' From 047834f56ad5752256b920b3bc35930eb0c1660b Mon Sep 17 00:00:00 2001 From: Oleksandr Fediashov Date: Wed, 2 Jan 2019 11:55:16 +0200 Subject: [PATCH 2/4] fixes to review comments --- .../components/ComponentDoc/ComponentExamples.tsx | 10 +++++----- docs/src/components/ExternalExampleLayout.tsx | 8 ++++++-- docs/src/utils/exampleContexts.ts | 6 +++--- docs/src/utils/exampleKebabNameToSourceFilename.ts | 12 +++++++----- docs/src/utils/index.tsx | 4 ++-- package.json | 2 +- yarn.lock | 8 ++++---- 7 files changed, 28 insertions(+), 22 deletions(-) diff --git a/docs/src/components/ComponentDoc/ComponentExamples.tsx b/docs/src/components/ComponentDoc/ComponentExamples.tsx index 75b74d41df..295c588fbb 100644 --- a/docs/src/components/ComponentDoc/ComponentExamples.tsx +++ b/docs/src/components/ComponentDoc/ComponentExamples.tsx @@ -2,7 +2,7 @@ import * as _ from 'lodash' import * as PropTypes from 'prop-types' import * as React from 'react' -import { exampleGroupsContext, exampleSourcesContext } from 'docs/src/utils' +import { exampleIndexContext, exampleSourcesContext } from 'docs/src/utils' import { Grid, List } from 'semantic-ui-react' import { examplePathPatterns } from './ComponentExample' import ContributionPrompt from './ContributionPrompt' @@ -32,20 +32,20 @@ export default class ComponentExamples extends React.Component + const indexPath = _.find(exampleIndexContext.keys(), path => new RegExp(`\/${displayName}\/index\.tsx$`).test(path), ) if (!indexPath) { return null } - const ExamplesElement = React.createElement(exampleGroupsContext(indexPath).default) as any + const ExamplesElement = React.createElement(exampleIndexContext(indexPath).default) as any if (!ExamplesElement) { return null } // rules #2 and #3 - const missingPaths = this.testExamplesStructure(displayName, exampleSourcesContext.keys()) + const missingPaths = this.getMissingExamplePaths(displayName, exampleSourcesContext.keys()) return missingPaths && missingPaths.length ? (
{this.renderMissingShorthandExamples(missingPaths)} {ExamplesElement} @@ -80,7 +80,7 @@ export default class ComponentExamples extends React.Component ) - private testExamplesStructure(displayName: string, allPaths: string[]): string[] { + private getMissingExamplePaths(displayName: string, allPaths: string[]): string[] { const examplesPattern = `\.\/${displayName}[\\w\/]*\/\\w+Example` const [normalExtension, shorthandExtension] = [ diff --git a/docs/src/components/ExternalExampleLayout.tsx b/docs/src/components/ExternalExampleLayout.tsx index c694cafeac..38b262754c 100644 --- a/docs/src/components/ExternalExampleLayout.tsx +++ b/docs/src/components/ExternalExampleLayout.tsx @@ -4,7 +4,11 @@ import * as React from 'react' import SourceRender from 'react-source-render' import { ExampleSource } from 'docs/src/types' -import { exampleSourcesContext, exampleKebabNameToFilename, parseExamplePath } from 'docs/src/utils' +import { + exampleSourcesContext, + exampleKebabNameToSourceFilename, + parseExamplePath, +} from 'docs/src/utils' import PageNotFound from '../views/PageNotFound' import { babelConfig, importResolver } from './Playground/renderConfig' @@ -12,7 +16,7 @@ const examplePaths = exampleSourcesContext.keys() const ExternalExampleLayout: any = props => { const { exampleName } = props.match.params - const exampleFilename = exampleKebabNameToFilename(exampleName) + const exampleFilename = exampleKebabNameToSourceFilename(exampleName) const examplePath = _.find(path => { const { exampleName } = parseExamplePath(path) diff --git a/docs/src/utils/exampleContexts.ts b/docs/src/utils/exampleContexts.ts index 7181812ff4..2d2a67d87a 100644 --- a/docs/src/utils/exampleContexts.ts +++ b/docs/src/utils/exampleContexts.ts @@ -1,10 +1,10 @@ /** - * Get the Webpack Context for doc site example groups. + * The Webpack Context for doc site example groups. */ -export const exampleGroupsContext = require.context('docs/src/examples/', true, /index.tsx$/) +export const exampleIndexContext = require.context('docs/src/examples/', true, /index.tsx$/) /** - * Get the Webpack Context for doc site example sources. + * The Webpack Context for doc site example sources. */ export const exampleSourcesContext = require.context( 'docs/src/exampleSources/', diff --git a/docs/src/utils/exampleKebabNameToSourceFilename.ts b/docs/src/utils/exampleKebabNameToSourceFilename.ts index caccfb667b..c4788090f3 100644 --- a/docs/src/utils/exampleKebabNameToSourceFilename.ts +++ b/docs/src/utils/exampleKebabNameToSourceFilename.ts @@ -1,15 +1,17 @@ -import * as _ from 'lodash/fp' +import * as _ from 'lodash' /** * Converts kebab-cased-example-name back into the original filename. * @param {string} exampleKebabName */ const exampleKebabNameToSourceFilename = exampleKebabName => { - // button-example => ButtonExample.source.json + const trimmedKebabName = exampleKebabName.trim() + // button-example => ButtonExample + // button-example-shorthand => ButtonExampleShorthand + const startCasedName = _.startCase(trimmedKebabName) + // button-example-shorthand => ButtonExample.shorthand.source.json - return `${_.startCase(exampleKebabName) - .replace(/ /g, '') - .replace(/Shorthand$/, '.shorthand')}.source.json` + return `${startCasedName.replace(/Shorthand$/, '.shorthand')}.source.json` } export default exampleKebabNameToSourceFilename diff --git a/docs/src/utils/index.tsx b/docs/src/utils/index.tsx index b1a938c532..87a1fae93c 100644 --- a/docs/src/utils/index.tsx +++ b/docs/src/utils/index.tsx @@ -1,7 +1,7 @@ export { default as componentInfoContext } from './componentInfoContext' export { default as componentInfoShape } from './componentInfoShape' -export { exampleGroupsContext, exampleSourcesContext } from './exampleContexts' -export { default as exampleKebabNameToFilename } from './exampleKebabNameToSourceFilename' +export { exampleIndexContext, exampleSourcesContext } from './exampleContexts' +export { default as exampleKebabNameToSourceFilename } from './exampleKebabNameToSourceFilename' export { default as examplePathToHash } from './examplePathToHash' export { default as getComponentGroup } from './getComponentGroup' export { default as getComponentPathname } from './getComponentPathname' diff --git a/package.json b/package.json index f18be5d3a7..f5183c6773 100644 --- a/package.json +++ b/package.json @@ -130,7 +130,7 @@ "react": "^16.0.0", "react-ace": "^5.1.2", "react-custom-scrollbars": "^4.2.1", - "react-docgen-typescript": "^1.12.0", + "react-docgen-typescript": "^1.12.2", "react-document-title": "^2.0.3", "react-dom": "^16.0.0", "react-element-to-jsx-string": "^14.0.2", diff --git a/yarn.lock b/yarn.lock index de7d7dcfb4..0429bd4713 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8393,10 +8393,10 @@ react-custom-scrollbars@^4.2.1: prop-types "^15.5.10" raf "^3.1.0" -react-docgen-typescript@^1.12.0: - version "1.12.0" - resolved "https://registry.yarnpkg.com/react-docgen-typescript/-/react-docgen-typescript-1.12.0.tgz#be25d3604e05676f05a1248952f8d5823d7a216a" - integrity sha512-EAb2W5UNTTR75zTWm8bbn9iQmh+W/9DvnCazIdzDb+TnzvpcxEFCjRia+Rhpkx4FRRS3AYyJrw5Ar3zX51gJfQ== +react-docgen-typescript@^1.12.2: + version "1.12.2" + resolved "https://registry.yarnpkg.com/react-docgen-typescript/-/react-docgen-typescript-1.12.2.tgz#d5fb578d12f6876efdde69176f4ea658e75a9a29" + integrity sha512-pcot0jGiMIyhmwNeSU83GvClNwk9NbcnYHcGf4pKMmw5J43d5OzYRcTzrZTGlIOWjYfYazYhvTxjujE625P3Mw== react-document-title@^2.0.3: version "2.0.3" From 35263411d81c3e7221b696b3b5e9fd6fdac935dc Mon Sep 17 00:00:00 2001 From: Oleksandr Fediashov Date: Wed, 2 Jan 2019 12:35:54 +0200 Subject: [PATCH 3/4] simplify regex --- docs/src/components/ComponentDoc/ComponentExamples.tsx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/docs/src/components/ComponentDoc/ComponentExamples.tsx b/docs/src/components/ComponentDoc/ComponentExamples.tsx index 295c588fbb..524a355b30 100644 --- a/docs/src/components/ComponentDoc/ComponentExamples.tsx +++ b/docs/src/components/ComponentDoc/ComponentExamples.tsx @@ -81,15 +81,14 @@ export default class ComponentExamples extends React.Component `${pattern}.source.json`) const [normalRegExp, shorthandRegExp] = [normalExtension, shorthandExtension].map( - extension => new RegExp(`${examplesPattern}\\w*${extension}$`), + extension => new RegExp(`${examplesPattern}${extension}$`), ) const expectedShorthandExamples = allPaths From 93e1bc0ce682dabb23ea14b48216456388afc47d Mon Sep 17 00:00:00 2001 From: Oleksandr Fediashov Date: Wed, 2 Jan 2019 12:55:23 +0200 Subject: [PATCH 4/4] restore changes --- docs/src/utils/exampleKebabNameToSourceFilename.ts | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/docs/src/utils/exampleKebabNameToSourceFilename.ts b/docs/src/utils/exampleKebabNameToSourceFilename.ts index c4788090f3..d9a60b70cf 100644 --- a/docs/src/utils/exampleKebabNameToSourceFilename.ts +++ b/docs/src/utils/exampleKebabNameToSourceFilename.ts @@ -4,14 +4,12 @@ import * as _ from 'lodash' * Converts kebab-cased-example-name back into the original filename. * @param {string} exampleKebabName */ -const exampleKebabNameToSourceFilename = exampleKebabName => { - const trimmedKebabName = exampleKebabName.trim() - // button-example => ButtonExample - // button-example-shorthand => ButtonExampleShorthand - const startCasedName = _.startCase(trimmedKebabName) - +const exampleKebabNameToSourceFilename = (exampleKebabName: string) => { + // button-example => ButtonExample.source.json // button-example-shorthand => ButtonExample.shorthand.source.json - return `${startCasedName.replace(/Shorthand$/, '.shorthand')}.source.json` + return `${_.startCase(exampleKebabName) + .replace(/ /g, '') + .replace(/Shorthand$/, '.shorthand')}.source.json` } export default exampleKebabNameToSourceFilename