Skip to content
This repository was archived by the owner on Mar 4, 2020. It is now read-only.

Commit 03c0bd2

Browse files
authored
docs(Examples): allow to use TS in examples (#617)
* docs(Examples): allow to use TS in examples * add jsdoc * fix typo * rename file * add comment * `createExample` to `createExampleSourceCode` * rework with `path.relative()` * remove JSON files on remove tsx * create getRelativePathToSource function
1 parent d1a9105 commit 03c0bd2

37 files changed

+389
-47
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ docs/src/componentInfo
1212
docs/src/componentMenu.json
1313
docs/src/behaviorMenu.json
1414
docs/src/exampleMenus
15+
docs/src/exampleSources
1516
docs/dist/
1617
dll/
1718
node_modules/
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import * as T from '@babel/types'
2+
import { BabelPlugin } from './types'
3+
4+
/**
5+
* Creates an default import:
6+
* - import React from 'react'
7+
*/
8+
const createDefaultImportDeclaration = (
9+
t: typeof T,
10+
declaration: T.ImportDeclaration,
11+
specifier: T.ImportNamespaceSpecifier,
12+
): T.ImportDeclaration =>
13+
t.importDeclaration(
14+
[t.importDefaultSpecifier(t.identifier(specifier.local.name))],
15+
t.stringLiteral(declaration.source.value),
16+
)
17+
18+
/**
19+
* A plugin for Babel that performs AST transform:
20+
* - from: import * as _ from 'lodash'
21+
* - to: import _ from 'lodash'
22+
*/
23+
const starImportToDefaultPlugin: BabelPlugin = ({ types: t }) => ({
24+
visitor: {
25+
ImportDeclaration: path => {
26+
const { specifiers } = path.node
27+
const specifier = specifiers[0]
28+
29+
if (specifiers.length === 1 && t.isImportNamespaceSpecifier(specifier)) {
30+
path.replaceWith(createDefaultImportDeclaration(t, path.node, specifier))
31+
}
32+
},
33+
},
34+
})
35+
36+
export default starImportToDefaultPlugin

build/babel/types.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import * as T from '@babel/types'
2+
import { NodePath } from '@babel/traverse'
3+
4+
export type BabelPluginArguments = {
5+
types: typeof T
6+
}
7+
8+
type BabelPluginVisitorFunction<T> = (path: NodePath<T>) => void
9+
type BabelPluginVisitor<T> =
10+
| BabelPluginVisitorFunction<T>
11+
| {
12+
exit: BabelPluginVisitorFunction<T>
13+
}
14+
15+
export type BabelPlugin = (
16+
options: BabelPluginArguments,
17+
) => {
18+
visitor: {
19+
// This type is extendable, feel to add own visitor types.
20+
ImportDeclaration: BabelPluginVisitor<T.ImportDeclaration>
21+
}
22+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import * as Babel from '@babel/core'
2+
import * as gutil from 'gulp-util'
3+
import * as prettier from 'prettier'
4+
import * as through from 'through2'
5+
import * as Vinyl from 'vinyl'
6+
7+
import * as prettierConfig from '../../../.prettierrc.json'
8+
import { ExampleSource } from '../../../docs/src/types'
9+
import transformStarImportPlugin from '../../babel/transform-star-import-plugin'
10+
import { getRelativePathToSourceFile } from './util'
11+
12+
const pluginName = 'gulp-example-source'
13+
14+
const createExampleSourceCode = (file: Vinyl): ExampleSource => {
15+
const tsSource = file.contents.toString()
16+
17+
const transformResult = Babel.transform(tsSource, {
18+
plugins: [transformStarImportPlugin],
19+
presets: [['@babel/preset-typescript', { allExtensions: true, isTSX: true }]],
20+
sourceType: 'module',
21+
})
22+
const jsSource = prettier.format(transformResult.code, {
23+
...prettierConfig,
24+
parser: 'babylon',
25+
})
26+
27+
return {
28+
js: jsSource,
29+
ts: tsSource,
30+
}
31+
}
32+
33+
export default () =>
34+
through.obj((file: Vinyl, enc, cb) => {
35+
if (file.isNull()) {
36+
cb(null, file)
37+
return
38+
}
39+
40+
if (file.isStream()) {
41+
cb(new gutil.PluginError(pluginName, 'Streaming is not supported'))
42+
return
43+
}
44+
45+
const sourcePath = getRelativePathToSourceFile(file.path)
46+
const source = createExampleSourceCode(file)
47+
48+
cb(
49+
null,
50+
new Vinyl({
51+
path: sourcePath,
52+
contents: Buffer.from(JSON.stringify(source, null, 2)),
53+
}),
54+
)
55+
})
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import * as path from 'path'
2+
import config from '../../../../config'
3+
4+
const examplesPath = config.paths.docsSrc('examples', 'components')
5+
6+
/**
7+
* Generates a relative path to a source file, outputs:
8+
* Chat/Types/ChatExample.shorthand.source.json
9+
*/
10+
const getRelativePathToSourceFile = (filePath: string): string =>
11+
`${path.relative(examplesPath, filePath).replace(/\.tsx$/, '')}.source.json`
12+
13+
export default getRelativePathToSourceFile

build/gulp/plugins/util/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
export * from './checksumUtils'
22
export { default as getComponentInfo } from './getComponentInfo'
3+
export { default as getRelativePathToSourceFile } from './getRelativePathToSourceFile'
34
export { default as parseDefaultValue } from './parseDefaultValue'
45
export { default as parseDocblock } from './parseDocblock'
56
export { default as parseDocSection } from './parseDocSection'

build/gulp/tasks/docs.ts

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import * as historyApiFallback from 'connect-history-api-fallback'
22
import * as express from 'express'
33
import { task, src, dest, lastRun, parallel, series, watch } from 'gulp'
44
import * as remember from 'gulp-remember'
5+
import * as fs from 'fs'
56
import * as path from 'path'
67
import * as rimraf from 'rimraf'
78
import * as through2 from 'through2'
@@ -14,7 +15,9 @@ import config from '../../../config'
1415
import gulpComponentMenu from '../plugins/gulp-component-menu'
1516
import gulpComponentMenuBehaviors from '../plugins/gulp-component-menu-behaviors'
1617
import gulpExampleMenu from '../plugins/gulp-example-menu'
18+
import gulpExampleSource from '../plugins/gulp-example-source'
1719
import gulpReactDocgen from '../plugins/gulp-react-docgen'
20+
import { getRelativePathToSourceFile } from '../plugins/util'
1821

1922
const { paths } = config
2023
const g = require('gulp-load-plugins')()
@@ -46,13 +49,18 @@ task('clean:docs:example-menus', cb => {
4649
rimraf(paths.docsSrc('exampleMenus'), cb)
4750
})
4851

52+
task('clean:docs:example-sources', cb => {
53+
rimraf(paths.docsSrc('exampleSources'), cb)
54+
})
55+
4956
task(
5057
'clean:docs',
5158
parallel(
5259
'clean:docs:component-menu',
5360
'clean:docs:component-menu-behaviors',
5461
'clean:docs:dist',
5562
'clean:docs:example-menus',
63+
'clean:docs:example-sources',
5664
),
5765
)
5866

@@ -62,7 +70,8 @@ task(
6270

6371
const componentsSrc = [`${paths.posix.src()}/components/*/[A-Z]*.tsx`, '!**/Slot.tsx']
6472
const behaviorSrc = [`${paths.posix.src()}/lib/accessibility/Behaviors/*/[a-z]*.ts`]
65-
const examplesSrc = `${paths.posix.docsSrc()}/examples/*/*/*/index.tsx`
73+
const examplesIndexSrc = `${paths.posix.docsSrc()}/examples/*/*/*/index.tsx`
74+
const examplesSrc = `${paths.posix.docsSrc()}/examples/*/*/*/!(*index|.knobs).tsx`
6675
const markdownSrc = [
6776
'.github/CONTRIBUTING.md',
6877
'.github/setup-local-development.md',
@@ -92,18 +101,25 @@ task('build:docs:component-menu-behaviors', () =>
92101
)
93102

94103
task('build:docs:example-menu', () =>
95-
src(examplesSrc, { since: lastRun('build:docs:example-menu') })
104+
src(examplesIndexSrc, { since: lastRun('build:docs:example-menu') })
96105
.pipe(remember('example-menu')) // FIXME: with watch this unnecessarily processes index files for all examples
97106
.pipe(gulpExampleMenu())
98107
.pipe(dest(paths.docsSrc('exampleMenus'))),
99108
)
100109

110+
task('build:docs:example-sources', () =>
111+
src(examplesSrc, { since: lastRun('build:docs:example-sources') })
112+
.pipe(gulpExampleSource())
113+
.pipe(dest(paths.docsSrc('exampleSources'))),
114+
)
115+
101116
task(
102117
'build:docs:json',
103118
parallel(
104119
series('build:docs:docgen', 'build:docs:component-menu'),
105120
'build:docs:component-menu-behaviors',
106121
'build:docs:example-menu',
122+
'build:docs:example-sources',
107123
),
108124
)
109125

@@ -218,10 +234,21 @@ task('watch:docs', cb => {
218234
watch(componentsSrc, series('build:docs:docgen')).on('change', handleWatchChange)
219235

220236
// rebuild example menus
221-
watch(examplesSrc, series('build:docs:example-menu'))
237+
watch(examplesIndexSrc, series('build:docs:example-menu'))
222238
.on('change', handleWatchChange)
223239
.on('unlink', path => handleWatchUnlink('example-menu', path))
224240

241+
watch(examplesSrc, series('build:docs:example-sources'))
242+
.on('change', handleWatchChange)
243+
.on('unlink', filePath => {
244+
log(`File ${filePath} was deleted, running tasks...`)
245+
246+
const sourceFilename = getRelativePathToSourceFile(filePath)
247+
const sourcePath = config.paths.docsSrc('exampleSources', sourceFilename)
248+
249+
fs.unlinkSync(sourcePath)
250+
})
251+
225252
watch(behaviorSrc, series('build:docs:component-menu-behaviors'))
226253
.on('change', handleWatchChange)
227254
.on('unlink', path => handleWatchUnlink('component-menu-behaviors', path))

docs/src/components/ComponentDoc/ComponentExample/SourceCodeManager.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,9 @@ class SourceCodeManager {
8484

8585
private safeRequire = (path: string): string | undefined => {
8686
try {
87-
return require(`!raw-loader!../../../examples/${path}`)
87+
const filename = `${path.replace(/^components\//, '')}.source.json`
88+
89+
return require(`!docs/src/exampleSources/${filename}`).js
8890
} catch (e) {
8991
return undefined
9092
}

docs/src/examples/components/Ref/Types/RefExample.tsx

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
1-
import React from 'react'
1+
import * as React from 'react'
22
import { Button, Grid, Ref, Segment } from '@stardust-ui/react'
33

4-
class RefExample extends React.Component {
4+
type RefExampleState = {
5+
isMounted: boolean
6+
}
7+
8+
class RefExample extends React.Component<{}, RefExampleState> {
59
state = { isMounted: false }
610

711
createdRef = React.createRef<HTMLButtonElement>()
812
functionalRef = null
913

10-
handleRef = node => (this.functionalRef = node)
14+
handleRef = (node: HTMLButtonElement) => (this.functionalRef = node)
1115

1216
componentDidMount() {
1317
this.setState({ isMounted: true })

docs/src/examples/components/Ref/Types/RefForwardingExample.tsx

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,19 @@
1-
import React from 'react'
1+
import * as React from 'react'
22
import { Grid, Ref, Segment } from '@stardust-ui/react'
33

4-
const ExampleButton = React.forwardRef<HTMLButtonElement>((props, ref) => (
5-
<div>
6-
<button {...props} ref={ref} />
7-
</div>
8-
))
4+
type RefForwardingExampleState = {
5+
isMounted: boolean
6+
}
7+
8+
const ExampleButton = React.forwardRef<HTMLButtonElement, { children: React.ReactNode }>(
9+
(props, ref) => (
10+
<div>
11+
<button {...props} ref={ref} />
12+
</div>
13+
),
14+
)
915

10-
class RefForwardingExample extends React.Component {
16+
class RefForwardingExample extends React.Component<{}, RefForwardingExampleState> {
1117
forwardedRef = React.createRef<HTMLButtonElement>()
1218
state = { isMounted: false }
1319

docs/src/examples/components/Text/States/TextExampleDisabled.shorthand.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React from 'react'
1+
import * as React from 'react'
22
import { Text } from '@stardust-ui/react'
33

44
const TextExampleDisabledShorthand = () => (

docs/src/examples/components/Text/States/TextExampleDisabled.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React from 'react'
1+
import * as React from 'react'
22
import { Text } from '@stardust-ui/react'
33

44
const TextExampleDisabled = () => <Text disabled>This feature has been disabled.</Text>

docs/src/examples/components/Text/States/TextExampleError.shorthand.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React from 'react'
1+
import * as React from 'react'
22
import { Text } from '@stardust-ui/react'
33

44
const TextExampleErrorShorthand = () => <Text error content="There has been an error." />

docs/src/examples/components/Text/States/TextExampleError.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React from 'react'
1+
import * as React from 'react'
22
import { Text } from '@stardust-ui/react'
33

44
const TextExampleError = () => <Text error>There has been an error.</Text>

docs/src/examples/components/Text/States/TextExampleSuccess.shorthand.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React from 'react'
1+
import * as React from 'react'
22
import { Text } from '@stardust-ui/react'
33

44
const TextExampleSuccessShorthand = () => (

docs/src/examples/components/Text/States/TextExampleSuccess.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React from 'react'
1+
import * as React from 'react'
22
import { Text } from '@stardust-ui/react'
33

44
const TextExampleSuccess = () => <Text success>Your action has completed successfully.</Text>

docs/src/examples/components/Text/States/TextExampleTemporary.shorthand.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React from 'react'
1+
import * as React from 'react'
22
import { Text } from '@stardust-ui/react'
33

44
const TextExampleTemporaryShorthand = () => <Text temporary content="Lorem ipsum dolor" />

docs/src/examples/components/Text/States/TextExampleTemporary.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React from 'react'
1+
import * as React from 'react'
22
import { Text } from '@stardust-ui/react'
33

44
const TextExampleTemporary = () => <Text temporary>Lorem ipsum dolor</Text>

docs/src/examples/components/Text/States/TextExampleTruncated.shorthand.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React from 'react'
1+
import * as React from 'react'
22
import { Text } from '@stardust-ui/react'
33

44
const [notTruncatedText, truncatedText] = [

docs/src/examples/components/Text/States/TextExampleTruncated.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React from 'react'
1+
import * as React from 'react'
22
import { Text } from '@stardust-ui/react'
33

44
const [notTruncatedText, truncatedText] = [

docs/src/examples/components/Text/States/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React from 'react'
1+
import * as React from 'react'
22
import ComponentExample from 'docs/src/components/ComponentDoc/ComponentExample'
33
import ExampleSection from 'docs/src/components/ComponentDoc/ExampleSection'
44

docs/src/examples/components/Text/Types/TextSizesExample.shorthand.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React from 'react'
1+
import * as React from 'react'
22
import * as _ from 'lodash'
33
import { Provider, Text } from '@stardust-ui/react'
44

docs/src/examples/components/Text/Types/TextSizesExample.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React from 'react'
1+
import * as React from 'react'
22
import * as _ from 'lodash'
33
import { Provider, Text } from '@stardust-ui/react'
44

docs/src/examples/components/Text/Types/TextWeightsExample.shorthand.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React from 'react'
1+
import * as React from 'react'
22
import { Text } from '@stardust-ui/react'
33

44
const TextWeightsExampleShorthand = () => (

docs/src/examples/components/Text/Types/TextWeightsExample.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React from 'react'
1+
import * as React from 'react'
22
import { Text } from '@stardust-ui/react'
33

44
const TextWeightsExample = () => (

docs/src/examples/components/Text/Types/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React from 'react'
1+
import * as React from 'react'
22
import ComponentExample from 'docs/src/components/ComponentDoc/ComponentExample'
33
import ExampleSection from 'docs/src/components/ComponentDoc/ExampleSection'
44

0 commit comments

Comments
 (0)