Skip to content

Commit

Permalink
Add documentation generator for main page, demo, and sandbox.
Browse files Browse the repository at this point in the history
  • Loading branch information
cjcenizal committed Jul 19, 2017
1 parent 78b460b commit b32a429
Show file tree
Hide file tree
Showing 10 changed files with 329 additions and 23 deletions.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@
"sterilize": "grunt sterilize",
"uiFramework:start": "grunt uiFramework:start",
"uiFramework:build": "grunt uiFramework:build",
"uiFramework:create": "yo ./ui_framework/generator-kui/app/index.js"
"uiFramework:create": "yo ./ui_framework/generator-kui/app/component.js",
"uiFramework:document": "yo ./ui_framework/generator-kui/app/documentation.js"
},
"repository": {
"type": "git",
Expand Down
23 changes: 20 additions & 3 deletions ui_framework/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,10 @@ From the command line, run `npm run uiFramework:create`.

First, you'll be prompted for what kind of component to create:

| Choice | Files created |
| Choice | Description |
|---|---|
| Stateless function | {name}.js, {name}.test.js, {_name}.scss |
| Component class | {name}.js, {name}.test.js, {_name}.scss |
| Stateless function | A stateless functional React component |
| Component class | A class-based React component |

Next, you'll enter a series of prompts.

Expand Down Expand Up @@ -123,6 +123,23 @@ complex they should be. In general, your examples should demonstrate:
content.
* The various states of the component, e.g. disabled, selected, empty of content, error state.

## Creating documentation

You can use the same Yeoman generator referenced above to create documentation.

From the command line, run `npm run uiFramework:document`.

First, you'll be prompted for what kind of documentation to create:

| Choice | Description |
|---|---|
| Page | A page for documenting a component(s) with multiple demos |
| Page demo | An individual demo of a particular component use case |
| Sandbox | An empty document where you can do pretty much anything |

Just follow the prompts and your documentation files will be created.
You can use the snippets that are printed to the terminal to integrate these files into the UI Framework documentation site.

## Principles

### Logically-grouped components
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,31 +10,19 @@ module.exports = class extends Generator {
type: 'list',
choices: [{
name: 'Stateless function',
value: 'function'
value: 'function',
}, {
name: 'Component class',
value: 'component'
value: 'component',
}],
}]).then(answers => {
this.config = answers;
});
}

writing() {
const createComponent = () => {
this.composeWith(componentGenerator, {
fileType: this.config.fileType,
});
}

switch (this.config.fileType) {
case 'component':
createComponent();
break;

case 'function':
createComponent();
break;
}
this.composeWith(componentGenerator, {
fileType: this.config.fileType,
});
}
}
31 changes: 31 additions & 0 deletions ui_framework/generator-kui/app/documentation.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
const Generator = require('yeoman-generator');

const documentationGenerator = require.resolve('../documentation/index.js');

module.exports = class extends Generator {
prompting() {
return this.prompt([{
message: 'What do you want to create?',
name: 'fileType',
type: 'list',
choices: [{
name: 'Page',
value: 'documentation',
}, {
name: 'Page demo',
value: 'demo',
}, {
name: 'Sandbox',
value: 'sandbox',
}],
}]).then(answers => {
this.config = answers;
});
}

writing() {
this.composeWith(documentationGenerator, {
fileType: this.config.fileType,
});
}
}
192 changes: 192 additions & 0 deletions ui_framework/generator-kui/documentation/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
const chalk = require('chalk');
const Generator = require('yeoman-generator');
const utils = require('../utils');

const DOCUMENTATION_PAGE_PATH = 'ui_framework/doc_site/src/views';

module.exports = class extends Generator {
constructor(args, options) {
super(args, options);

this.fileType = options.fileType;
}

prompting() {
const prompts = [{
message: 'What\'s the name of the component you\'re documenting? Use snake_case, please.',
name: 'name',
type: 'input',
store: true,
}];

if (this.fileType === 'demo') {
prompts.push({
message: 'What would you like to name this demo? Use snake_case, please.',
name: 'demoName',
type: 'input',
store: true,
});
}

return this.prompt(prompts).then(answers => {
this.config = answers;
});
}

writing() {
const config = this.config;

const writeDocumentationPage = () => {
const componentExampleName = utils.makeComponentName(config.name, false);
const componentExamplePrefix = utils.lowerCaseFirstLetter(componentExampleName);
const fileName = config.name;

const path = DOCUMENTATION_PAGE_PATH;

const vars = config.documentationVars = {
componentExampleName,
componentExamplePrefix,
fileName,
};

const documentationPagePath
= config.documentationPagePath
= `${path}/${config.name}/${config.name}_example.js`;

this.fs.copyTpl(
this.templatePath('documentation_page.js'),
this.destinationPath(documentationPagePath),
vars
);
};

const writeDocumentationPageDemo = () => {
const fileName = config.demoName || config.name;
const componentExampleName = utils.makeComponentName(fileName, false);
const componentExamplePrefix = utils.lowerCaseFirstLetter(componentExampleName);
const componentName = utils.makeComponentName(config.name);

const path = DOCUMENTATION_PAGE_PATH;

const vars = config.demoVars = {
componentExampleName,
componentExamplePrefix,
componentName,
fileName,
};

const documentationPageDemoPath
= config.documentationPageDemoPath
= `${path}/${config.name}/${fileName}.js`;

this.fs.copyTpl(
this.templatePath('documentation_page_demo.js'),
this.destinationPath(documentationPageDemoPath),
vars
);
};

const writeSandbox = () => {
const fileName = config.name;
const componentExampleName = utils.makeComponentName(fileName, false);

const path = DOCUMENTATION_PAGE_PATH;

const vars = config.sandboxVars = {
componentExampleName,
fileName,
};

const sandboxPath
= config.documentationPageDemoPath
= `${path}/${config.name}/${fileName}`;

this.fs.copyTpl(
this.templatePath('documentation_sandbox.html'),
this.destinationPath(`${sandboxPath}_sandbox.html`)
);

this.fs.copyTpl(
this.templatePath('documentation_sandbox.js'),
this.destinationPath(`${sandboxPath}_sandbox.js`),
vars
);
};

switch (this.fileType) {
case 'documentation':
writeDocumentationPage();
writeDocumentationPageDemo();
break;

case 'demo':
writeDocumentationPageDemo();
break;

case 'sandbox':
writeSandbox();
break;
}
}

end() {
const showImportDocumentationPageSnippet = () => {
const {
componentExampleName,
fileName,
} = this.config.demoVars;

this.log(chalk.gray('\n// Import example into routes.js.'));
this.log(
`${chalk.magenta('import')} ${componentExampleName}Example\n` +
` ${chalk.magenta('from')} ${chalk.cyan(`'../../views/${fileName}/${fileName}_example'`)};`
);
};

const showImportDemoSnippet = () => {
const {
componentExampleName,
componentExamplePrefix,
fileName,
} = this.config.demoVars;

this.log(chalk.gray('\n// Import demo into example.'));
this.log(
`${chalk.magenta('import')} ${componentExampleName} from './${fileName};\n` +
`${chalk.magenta('const')} ${componentExamplePrefix}Source = require('!!raw!./${fileName}');\n` +
`${chalk.magenta('const')} ${componentExamplePrefix}Html = renderToHtml(${componentExampleName});`
);
};

const showImportSandboxSnippet = () => {
const {
componentExampleName,
fileName,
} = this.config.sandboxVars;

this.log(chalk.gray('\n// Import example into routes.js.'));
this.log(
`${chalk.magenta('import')} ${componentExampleName}Sandbox\n` +
` ${chalk.magenta('from')} ${chalk.cyan(`'../../views/${fileName}/${fileName}_sandbox'`)};`
);
};

this.log('------------------------------------------------');
this.log(chalk.bold('Import snippets:'));

switch (this.fileType) {
case 'documentation':
showImportDocumentationPageSnippet();
break;

case 'demo':
showImportDemoSnippet();
break;

case 'sandbox':
showImportSandboxSnippet();
break;
}
this.log('------------------------------------------------');
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import React from 'react';

import { renderToHtml } from '../../services';

import {
GuideDemo,
GuidePage,
GuideSection,
GuideSectionTypes,
GuideText,
} from '../../components';

import <%= componentExampleName %> from './<%= fileName %>';
const <%= componentExamplePrefix %>Source = require('!!raw!./<%= fileName %>');
const <%= componentExamplePrefix %>Html = renderToHtml(<%= componentExampleName %>);

export default props => (
<GuidePage title={props.route.name}>
<GuideSection
title="<%= componentExampleName %>"
source={[{
type: GuideSectionTypes.JS,
code: <%= componentExamplePrefix %>Source,
}, {
type: GuideSectionTypes.HTML,
code: <%= componentExamplePrefix %>Html,
}]}
>
<GuideText>
Description needed: how to use the <%= componentExampleName %> component.
</GuideText>

<GuideDemo>
<<%= componentExampleName %> />
</GuideDemo>
</GuideSection>
</GuidePage>
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import React from 'react';

import {
<%= componentName %>,
} from '../../../../components';

export default () => (
<<%= componentName %>>

</<%= componentName %>>
);
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<p>Do whatever you want here!</p>
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import React from 'react';

import {
GuideDemo,
GuideSandbox,
GuideSandboxCodeToggle,
GuideSectionTypes,
} from '../../components';

const html = require('./<%= fileName %>_sandbox.html');

export default props => (
<GuideSandbox>
<GuideDemo
isFullScreen={true}
html={html}
/>

<GuideSandboxCodeToggle
source={[{
type: GuideSectionTypes.HTML,
code: html,
}]}
title={props.route.name}
/>
</GuideSandbox>
);
Loading

0 comments on commit b32a429

Please sign in to comment.