-
Notifications
You must be signed in to change notification settings - Fork 51
feat(docs): adding 'behaviors' section to menu #119
Changes from all commits
8ad5ae9
65003f9
7669fd8
83fca4f
0309b1f
96aa2e9
b19a9b8
db2afcd
a756006
71420a9
1485c92
21482f1
597541c
45bb369
e5fb701
6b13568
8db220b
361a29d
2e33979
651c476
e7aa5c7
97b8991
84ba5fa
2437532
19eaf6a
0c5379d
e19d4b0
924cca8
aef0b86
4f0085d
47b2e29
e488c98
9607352
047e464
1f646ed
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,98 @@ | ||
| import * as gutil from 'gulp-util' | ||
| import * as path from 'path' | ||
| import * as through2 from 'through2' | ||
| import * as Vinyl from 'vinyl' | ||
| import * as _ from 'lodash' | ||
| import * as fs from 'fs' | ||
|
|
||
| const pluginName = 'gulp-component-menu-behaviors' | ||
| const extract = require('extract-comments') | ||
| const doctrine = require('doctrine') | ||
|
|
||
| type BehaviorMenuItem = { | ||
| displayName: string | ||
| type: string | ||
| variations: { | ||
| name: string | ||
| text: string | ||
| } | ||
| } | ||
|
|
||
| export default () => { | ||
| const result: BehaviorMenuItem[] = [] | ||
| function bufferContents(file, enc, cb) { | ||
| if (file.isNull()) { | ||
| cb(null, file) | ||
| return | ||
| } | ||
|
|
||
| if (file.isStream()) { | ||
| cb(new gutil.PluginError(pluginName, 'Streaming is not supported')) | ||
| return | ||
| } | ||
|
|
||
| try { | ||
| const absPath = path.resolve(process.cwd(), file.path) | ||
| const dir = path.dirname(absPath) | ||
| const componentType = _.lowerFirst(path.basename(path.dirname(dir)).replace(/s$/, '')) | ||
| const behaviorVariantName = file.basename | ||
| const behaviorName = path.basename(dir) | ||
|
|
||
| let description | ||
| const fileContent = fs.readFileSync(file.path).toString() | ||
| const blockComments = extract(fileContent).filter(comment => comment.type === 'BlockComment') // filtering only block comments | ||
| const emptyDescriptionText = 'Behavior file has no description.' | ||
|
|
||
| // getting object that describes '@description' part of the comment's text | ||
| if (!_.isEmpty(blockComments)) { | ||
| const commentTokens = doctrine.parse(blockComments[0].raw, { unwrap: true }).tags | ||
| const descriptionToken = commentTokens.find(token => token.title === 'description') | ||
| description = descriptionToken ? descriptionToken.description : emptyDescriptionText | ||
| } else { | ||
| description = emptyDescriptionText | ||
| } | ||
|
|
||
| result.push({ | ||
| displayName: behaviorName, | ||
| type: componentType, | ||
| variations: { | ||
| name: behaviorVariantName, | ||
| text: description, | ||
| }, | ||
| }) | ||
| cb() | ||
| } catch (err) { | ||
| const pluginError = new gutil.PluginError(pluginName, err) | ||
| const relativePath = path.relative(process.cwd(), file.path) | ||
| pluginError.message = [ | ||
| gutil.colors.magenta(`Error in file: ${relativePath}`), | ||
| gutil.colors.red(err.message), | ||
| gutil.colors.gray(err.stack), | ||
| ].join('\n\n') | ||
| this.emit('error', pluginError) | ||
| } | ||
| } | ||
|
|
||
| function getParsedResults() { | ||
| return _(result) | ||
| .groupBy('displayName') | ||
| .map((behaviors, displayName) => ({ | ||
| displayName, | ||
| type: behaviors[0].type, | ||
| variations: _.map(behaviors, 'variations'), | ||
| })) | ||
| .value() | ||
| } | ||
|
|
||
| function endStream(cb) { | ||
| const file = new Vinyl({ | ||
| path: './behaviorMenu.json', | ||
| contents: Buffer.from(JSON.stringify(getParsedResults(), null, 2)), | ||
| }) | ||
|
|
||
| this.push(file) | ||
| cb() | ||
| } | ||
|
|
||
| return through2.obj(bufferContents, endStream) | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,7 @@ | ||
| import * as historyApiFallback from 'connect-history-api-fallback' | ||
| import * as express from 'express' | ||
| import { task, src, dest, lastRun, parallel, series, watch } from 'gulp' | ||
| import * as remember from 'gulp-remember' | ||
| import * as path from 'path' | ||
| import * as rimraf from 'rimraf' | ||
| import * as through2 from 'through2' | ||
|
|
@@ -11,14 +12,15 @@ import * as WebpackHotMiddleware from 'webpack-hot-middleware' | |
| import sh from '../sh' | ||
| import config from '../../../config' | ||
| import gulpComponentMenu from '../plugins/gulp-component-menu' | ||
| import gulpComponentMenuBehaviors from '../plugins/gulp-component-menu-behaviors' | ||
| import gulpExampleMenu from '../plugins/gulp-example-menu' | ||
| import gulpReactDocgen from '../plugins/gulp-react-docgen' | ||
|
|
||
| const { paths } = config | ||
| const g = require('gulp-load-plugins')() | ||
| const { colors, log, PluginError } = g.util | ||
|
|
||
| const handleWatchChange = e => log(`File ${e.path} was ${e.type}, running tasks...`) | ||
| const handleWatchChange = (path, stats) => log(`File ${path} was changed, running tasks...`) | ||
|
|
||
| // ---------------------------------------- | ||
| // Clean | ||
|
|
@@ -32,6 +34,10 @@ task('clean:docs:component-menu', cb => { | |
| rimraf(paths.docsSrc('componentMenu.json'), cb) | ||
| }) | ||
|
|
||
| task('clean:docs:component-menu-behaviors', cb => { | ||
| rimraf(paths.docsSrc('behaviorMenu.json'), cb) | ||
| }) | ||
|
|
||
| task('clean:docs:dist', cb => { | ||
| rimraf(paths.docsDist(), cb) | ||
| }) | ||
|
|
@@ -45,6 +51,7 @@ task( | |
| parallel( | ||
| 'clean:docs:component-info', | ||
| 'clean:docs:component-menu', | ||
| 'clean:docs:component-menu-behaviors', | ||
| 'clean:docs:dist', | ||
| 'clean:docs:example-menus', | ||
| ), | ||
|
|
@@ -55,6 +62,7 @@ task( | |
| // ---------------------------------------- | ||
|
|
||
| const componentsSrc = [`${config.paths.src()}/components/*/[A-Z]*.tsx`] | ||
| const behaviorSrc = [`${config.paths.src()}/lib/accessibility/Behaviors/*/[A-Z]*.ts`] | ||
| const examplesSrc = `${paths.docsSrc()}/examples/*/*/*/index.tsx` | ||
| const markdownSrc = ['.github/CONTRIBUTING.md', 'specifications/*.md'] | ||
|
|
||
|
|
@@ -70,6 +78,13 @@ task('build:docs:component-menu', () => | |
| .pipe(dest(paths.docsSrc())), | ||
| ) | ||
|
|
||
| task('build:docs:component-menu-behaviors', () => | ||
| src(behaviorSrc, { since: lastRun('build:docs:component-menu-behaviors') }) | ||
| .pipe(remember('component-menu-behaviors')) | ||
| .pipe(gulpComponentMenuBehaviors()) | ||
| .pipe(dest(paths.docsSrc())), | ||
| ) | ||
|
|
||
| task('build:docs:example-menu', () => | ||
| src(examplesSrc, { since: lastRun('build:docs:example-menu') }) | ||
| .pipe(gulpExampleMenu()) | ||
|
|
@@ -78,7 +93,12 @@ task('build:docs:example-menu', () => | |
|
|
||
| task( | ||
| 'build:docs:json', | ||
| parallel('build:docs:docgen', 'build:docs:component-menu', 'build:docs:example-menu'), | ||
| parallel( | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Watch (
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. good point :)
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I added watch for behaviours. Watch currently does not work on Windows (not caused by this PR), I will address that in #172 once this PR is merged. |
||
| 'build:docs:docgen', | ||
| 'build:docs:component-menu', | ||
| 'build:docs:component-menu-behaviors', | ||
| 'build:docs:example-menu', | ||
| ), | ||
| ) | ||
|
|
||
| task('build:docs:html', () => src(paths.docsSrc('404.html')).pipe(dest(paths.docsDist()))) | ||
|
|
@@ -193,6 +213,13 @@ task('watch:docs', cb => { | |
| // rebuild example menus | ||
| watch(examplesSrc, series('build:docs:example-menu')).on('change', handleWatchChange) | ||
|
|
||
| watch(behaviorSrc, series('build:docs:component-menu-behaviors')) | ||
| .on('change', handleWatchChange) | ||
| .on('unlink', path => { | ||
| log(`File ${path} was deleted, running tasks...`) | ||
| remember.forget('component-menu-behaviors', path) | ||
| }) | ||
|
|
||
| // rebuild images | ||
| watch(`${config.paths.src()}/**/*.{png,jpg,gif}`, series('build:docs:images')).on( | ||
| 'change', | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,72 @@ | ||
| import * as _ from 'lodash' | ||
| import PropTypes from 'prop-types' | ||
| import * as React from 'react' | ||
| const behaviorMenuItems = require('docs/src/behaviorMenu') | ||
| import { Grid } from 'semantic-ui-react' | ||
| import ComponentExampleTitle from './ComponentDoc/ComponentExample/ComponentExampleTitle' | ||
| class DocsBehaviorRoot extends React.Component<any, any> { | ||
| static propTypes = { | ||
| children: PropTypes.node, | ||
| match: PropTypes.shape({ | ||
| params: PropTypes.shape({ | ||
| name: PropTypes.string.isRequired, | ||
| }), | ||
| }), | ||
| } | ||
|
|
||
| baseName(fileName: string) { | ||
| const divided = _.startCase(fileName.replace('ts', '')) | ||
| return _.upperFirst(_.lowerCase(divided)) | ||
| } | ||
|
|
||
| render() { | ||
| const exampleStyle: React.CSSProperties = { | ||
| position: 'relative', | ||
| transition: 'box-shadow 200ms, background 200ms', | ||
| background: '#fff', | ||
| boxShadow: '0 1px 2px #ccc', | ||
| margin: '10px', | ||
| } | ||
|
|
||
| const commentBox: React.CSSProperties = { | ||
| padding: 5, | ||
| } | ||
| const { match } = this.props | ||
| return ( | ||
| <div style={commentBox}> | ||
| {behaviorMenuItems | ||
| .find(behavior => behavior.displayName === _.capitalize(match.params.name)) | ||
| .variations.map((variation, keyValue) => ( | ||
| <Grid key={keyValue} className="docs-example" style={exampleStyle}> | ||
| <Grid.Column width={16} style={{ borderBottom: '1px solid #ddd' }}> | ||
| <div style={{ display: 'flex' }}> | ||
| <div style={{ flex: '1' }}> | ||
| <ComponentExampleTitle | ||
| id={_.kebabCase(variation.name)} | ||
| title={this.baseName(variation.name)} | ||
| description={`Behavior name: ${variation.name.replace('.ts', '')}`} | ||
| /> | ||
| </div> | ||
| <div style={{ flex: '0 0 auto' }} /> | ||
| </div> | ||
| </Grid.Column> | ||
| <div style={{ paddingTop: '1rem', paddingBottom: '1rem' }}> | ||
| <span> Description: </span> | ||
| <br /> | ||
| {variation.text.split('\n').map((splittedText, keyValue) => { | ||
| return ( | ||
| <span key={keyValue}> | ||
| {splittedText} | ||
| <br /> | ||
| </span> | ||
| ) | ||
| })} | ||
| </div> | ||
| </Grid> | ||
| ))} | ||
| </div> | ||
| ) | ||
| } | ||
| } | ||
|
|
||
| export default DocsBehaviorRoot |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,2 +1,2 @@ | ||
| export const repoURL = 'https://github.com/stardust-ui/react' | ||
| export const typeOrder = ['component'] | ||
| export const typeOrder = ['component', 'behavior'] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about
DefaultBehavior.ts?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is not real behavior which would need documentation, so it doesn't need be included