- {this.renderHeader()}
+
{this.renderSee()}
{this.renderGithubSourceLink()}
diff --git a/docs/app/Components/ComponentDoc/ComponentDocHeader.js b/docs/app/Components/ComponentDoc/ComponentDocHeader.js
new file mode 100644
index 0000000000..3b806541d8
--- /dev/null
+++ b/docs/app/Components/ComponentDoc/ComponentDocHeader.js
@@ -0,0 +1,21 @@
+import PropTypes from 'prop-types'
+import React from 'react'
+import { Header } from 'semantic-ui-react'
+
+import { neverUpdate } from 'docs/app/HOC'
+
+const headerStyle = { marginBottom: '0.25em' }
+
+const ComponentDocHeader = ({ description, name }) (
+
+ {name}
+ {description}
+
+)
+
+ComponentDocHeader.propTypes = {
+ description: PropTypes.string,
+ name: PropTypes.string,
+}
+
+export default neverUpdate(ComponentDocHeader)
diff --git a/gulp/plugins/gulp-menugen.js b/gulp/plugins/gulp-menugen.js
new file mode 100644
index 0000000000..4b0a6bbcaf
--- /dev/null
+++ b/gulp/plugins/gulp-menugen.js
@@ -0,0 +1,61 @@
+import gutil from 'gulp-util'
+import _ from 'lodash'
+import path from 'path'
+import through from 'through2'
+
+import config from '../../config'
+import { parseDocExample, parseDocSection } from './util'
+
+const examplesPath = `${config.paths.docsSrc()}/Examples/`
+
+export default (filename) => {
+ const defaultFilename = 'menuInfo.json'
+ const result = {}
+ const pluginName = 'gulp-menugen'
+ let finalFile
+ let latestFile
+
+ function bufferContents(file, enc, cb) {
+ latestFile = file
+
+ if (file.isNull()) {
+ cb(null, file)
+ return
+ }
+
+ if (file.isStream()) {
+ cb(new gutil.PluginError(pluginName, 'Streaming is not supported'))
+ return
+ }
+
+ try {
+ const relativePath = file.path.replace(examplesPath, '')
+ const [,component,section] = _.split(relativePath, '/')
+
+ if(section === 'index.js') {
+ result[component] = parseDocExample(file.contents)
+ cb()
+ return
+ }
+ const { examples } = parseDocSection(file.contents)
+
+ result[component][section]['examples'] = examples
+ // result[component][section] = 100
+ cb()
+ } catch (err) {
+ const pluginError = new gutil.PluginError(pluginName, err)
+ pluginError.message += `\nFile: ${file.path}.`
+ this.emit('error', pluginError)
+ }
+ }
+
+ function endStream(cb) {
+ finalFile = latestFile.clone({ contents: false })
+ finalFile.path = path.join(latestFile.base, (filename || defaultFilename))
+ finalFile.contents = new Buffer(JSON.stringify(result, null, 2))
+ this.push(finalFile)
+ cb()
+ }
+
+ return through.obj(bufferContents, endStream)
+}
diff --git a/gulp/plugins/util/index.js b/gulp/plugins/util/index.js
index 97d3dfa8ac..6c60b8f63b 100644
--- a/gulp/plugins/util/index.js
+++ b/gulp/plugins/util/index.js
@@ -1,3 +1,5 @@
export parseDefaultValue from './parseDefaultValue'
export parseDocBlock from './parseDocBlock'
+export parseDocExample from './parseDocExample'
+export parseDocSection from './parseDocSection'
export parseType from './parseType'
diff --git a/gulp/plugins/util/parseDocExample.js b/gulp/plugins/util/parseDocExample.js
new file mode 100644
index 0000000000..492b38237c
--- /dev/null
+++ b/gulp/plugins/util/parseDocExample.js
@@ -0,0 +1,34 @@
+import _ from 'lodash'
+import { parse } from "babylon";
+import traverse from "babel-traverse";
+
+
+export default (buffer) => {
+ const ast = parse(buffer.toString(), {
+ sourceType: 'module',
+ plugins: [
+ "classProperties",
+ "jsx",
+ ]
+ });
+ const sections = {}
+
+ traverse(ast, {
+ ImportDeclaration: (path) => {
+ const specifier = _.first(path.get('specifiers'))
+
+ if(!specifier.isImportDefaultSpecifier()) return
+
+ const name = _.get(specifier, 'node.local.name')
+ const source = _.get(path, 'node.source.value')
+
+ if(_.startsWith(source, './')) {
+ sections[name] = {
+ name,
+ }
+ }
+ }
+ });
+
+ return sections
+}
\ No newline at end of file
diff --git a/gulp/plugins/util/parseDocSection.js b/gulp/plugins/util/parseDocSection.js
new file mode 100644
index 0000000000..263528d0d6
--- /dev/null
+++ b/gulp/plugins/util/parseDocSection.js
@@ -0,0 +1,46 @@
+import _ from 'lodash'
+import { parse } from "babylon";
+import traverse from "babel-traverse";
+
+export default (buffer) => {
+ const ast = parse(buffer.toString(), {
+ sourceType: 'module',
+ plugins: [
+ "classProperties",
+ "jsx",
+ ]
+ });
+ const section = {
+ examples: []
+ }
+ let position = 0
+
+ traverse(ast, {
+ JSXOpeningElement: (path) => {
+ const attrs = _.map(_.get(path, 'node.attributes'), (a) => {
+ return {
+ name: _.get(a, 'name.name'),
+ value: _.get(a, 'value.value')
+ }
+ })
+ const name = _.get(path, 'node.name.name')
+
+ if(name === 'ExampleSection') {
+ const title = _.find(attrs, { name: 'title'})
+ section.name = title.name
+ return
+ }
+
+ if(name === 'ComponentExample') {
+ const title = _.find(attrs, { name: 'title'})
+ if(title) {
+ const examplePath = _.find(attrs, { name: 'examplePath'}).value
+
+ section.examples.push({ title: title.value, path: examplePath })
+ }
+ }
+ }
+ });
+
+ return section
+}
\ No newline at end of file
diff --git a/gulp/tasks/docs.js b/gulp/tasks/docs.js
index 62377068b1..c7cd888dbe 100644
--- a/gulp/tasks/docs.js
+++ b/gulp/tasks/docs.js
@@ -8,6 +8,7 @@ import WebpackDevMiddleware from 'webpack-dev-middleware'
import WebpackHotMiddleware from 'webpack-hot-middleware'
import config from '../../config'
+import gulpMenuGen from '../plugins/gulp-menugen'
import gulpReactDocgen from '../plugins/gulp-react-docgen'
const g = loadPlugins()
@@ -45,6 +46,16 @@ task('build:docs:docgen', () => src([
.pipe(gulpReactDocgen())
.pipe(dest(config.paths.docsSrc())))
+task('build:docs:menugen', () => src(`${config.paths.docsSrc()}/Examples/**/index.js`)
+// do not remove the function keyword
+// we need 'this' scope here
+ .pipe(g.plumber(function handleError(err) {
+ log(err.toString())
+ this.emit('end')
+ }))
+ .pipe(gulpMenuGen())
+ .pipe(dest(config.paths.docsSrc())))
+
task('build:docs:html', () => src(config.paths.docsSrc('404.html'))
.pipe(dest(config.paths.docsDist())))