Skip to content

Commit

Permalink
chore(devenv): introduced parameterized demo HTML
Browse files Browse the repository at this point in the history
  • Loading branch information
asudoh committed Feb 16, 2018
1 parent 91db595 commit 274ab63
Show file tree
Hide file tree
Showing 200 changed files with 4,961 additions and 4,496 deletions.
3 changes: 3 additions & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,6 @@
dist
demo/demo.js
node_modules

# TODO: Upgrade to ESLint4 so we can apply a specific rule (one for CJS code) for below files
src/**/*.config.js
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ install:
- if [[ -n "${AAT_TOKEN}" && "$TEST_SUITE" == "a11y" ]]; then npm i https://aat.mybluemix.net/dist/karma-ibma.tgz; fi

script:
- if [[ "$TEST_SUITE" == "misc" ]]; then npm run lint; fi
- if [[ "$TEST_SUITE" == "misc" ]]; then npm run build; fi
- if [[ "$TEST_SUITE" == "misc" ]]; then npm run lint; fi
- if [[ "$TEST_SUITE" == "unit" ]]; then npm run test:unit -- -b ChromeHeadless_Travis -b Firefox; fi
- if [[ "$TEST_SUITE" == "unit-each" ]]; then find tests/spec -name "*.js" ! -name left-nav_spec.js -print0 | xargs -0 -n 1 -P 1 npm run test:unit -- -d -f; fi
- if [[ -n "${AAT_TOKEN}" && "$TEST_SUITE" == "a11y" ]]; then npm run test:a11y; fi
Expand Down
2 changes: 1 addition & 1 deletion demo/.babelrc
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@
],
"react"
],
"plugins": ["transform-class-properties", "dev-expression"]
"plugins": ["transform-class-properties", "transform-object-rest-spread", "dev-expression"]
}
38 changes: 5 additions & 33 deletions demo/js/components/CodePage/CodePage.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,54 +4,26 @@ import Markdown from 'markdown-it';

import ComponentExample from '../ComponentExample/ComponentExample';

/**
* @param {ComponentCollection|Component} metadata The component data.
* @returns {string} The HTML snippet for the component.
*/
const getContent = metadata => {
const { variants = {} } = metadata;
const { items = [] } = variants;
const variant = items[0];
return metadata.content || (variant && variant.content) || '';
};

/**
* @param {ComponentCollection|Component} metadata The component data.
* @returns {Component[]|Variant[]} The data of the component variants.
*/
const getSubItems = metadata => {
if (metadata.isCollection) {
return metadata.items;
}
if (!metadata.isCollated) {
return metadata.variants.items;
}
return [];
};

/**
* The page to show the component demo, its code as well as its README.
*/
const CodePage = ({ metadata, hideViewFullRender }) => {
const md = new Markdown({ html: true });
const subItems = getSubItems(metadata).filter(item => !item.isHidden);
const subItems = (metadata.items || []).filter(item => !item.isHidden);
/* eslint-disable react/no-danger */
const componentContent =
!metadata.isCollection && subItems.length <= 1 ? (
<ComponentExample hideViewFullRender={hideViewFullRender} component={metadata.name} htmlFile={getContent(metadata)} />
<ComponentExample hideViewFullRender={hideViewFullRender} component={metadata.name} htmlFile={metadata.renderedContent} />
) : (
subItems.map(item => (
<div key={item.id} className="component-variation">
<h2 className="component-variation__name">{item.label}</h2>
<ComponentExample
variant={item.handle.replace(/--default$/, '')}
component={metadata.name}
htmlFile={getContent(item)}
/>
{item.notes && metadata.notes !== item.notes && <p>{item.notes}</p>}
<ComponentExample variant={item.handle} component={metadata.name} htmlFile={item.renderedContent} />
</div>
))
);

/* eslint-disable react/no-danger */
return (
<div className="page code-page test">
{componentContent}
Expand Down
2 changes: 1 addition & 1 deletion demo/js/components/ComponentExample/ComponentExample.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const ComponentExample = ({ htmlFile, component, variant, codepenSlug, hideViewF
});

const codepenLink = codepenSlug && `https://codepen.io/team/carbon/full/${codepenSlug}/`;
const componentLink = variant ? `/component/${component}/${variant}` : `/component/${component}`;
const componentLink = variant ? `/component/${variant}` : `/component/${component}`;

const viewFullRender = hideViewFullRender ? null : (
<Link className="component-example__view-full-render" target="_blank" href={codepenLink || componentLink}>
Expand Down
90 changes: 84 additions & 6 deletions demo/js/components/RootPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,62 @@ import SideNav from './SideNav';
import PageHeader from './PageHeader/PageHeader';
import SideNavToggle from './SideNavToggle/SideNavToggle';

const checkStatus = response => {
if (response.status >= 200 && response.status < 400) {
return response;
}

const error = new Error(response.statusText);
error.response = response;
throw error;
};

const load = (componentItems, selectedNavItemId) => {
const metadata = componentItems && componentItems.find(item => item.id === selectedNavItemId);
const subItems = metadata.items || [];
const hasRenderedContent =
!metadata.isCollection && subItems.length <= 1 ? metadata.renderedContent : subItems.every(item => item.renderedContent);
if (!hasRenderedContent) {
return fetch(`/code/${metadata.name}`)
.then(checkStatus)
.then(response => {
const contentType = response.headers.get('content-type');
return contentType && contentType.includes('application/json') ? response.json() : response.text();
})
.then(responseContent => {
if (Object(responseContent) === responseContent) {
return componentItems.map(
item =>
item.id !== selectedNavItemId
? item
: {
...item,
items: item.items.map(
subItem =>
!responseContent[subItem.handle]
? subItem
: {
...subItem,
renderedContent: responseContent[subItem.handle],
}
),
}
);
}
return componentItems.map(
item =>
item.id !== selectedNavItemId
? item
: {
...item,
renderedContent: responseContent,
}
);
});
}
return Promise.resolve(null);
};

/**
* The top-most React component for dev env page.
*/
Expand All @@ -22,9 +78,19 @@ class RootPage extends Component {
docItems: PropTypes.arrayOf(PropTypes.shape()).isRequired, // eslint-disable-line react/no-unused-prop-types
};

constructor() {
constructor(props) {
super();
this.state = {};

const { componentItems } = props;

this.state = {
/**
* The array of component data.
* @type {Object[]}
*/
componentItems,
};

window.addEventListener('popstate', evt => {
this.switchTo(evt.state.name);
});
Expand All @@ -42,6 +108,13 @@ class RootPage extends Component {
}
}

componentWillReceiveProps(props) {
const { componentItems } = props;
if (this.props.componentItems !== componentItems) {
this.setState({ componentItems });
}
}

/**
* The handler for changing in the state of side nav's toggle button.
*/
Expand All @@ -53,7 +126,7 @@ class RootPage extends Component {
* The handler for the `click` event on the side nav for changing selection.
*/
onSideNavItemClick = evt => {
const { componentItems } = this.props;
const { componentItems } = this.state;
const selectedNavItem = componentItems && componentItems.find(item => item.id === evt.target.dataset.navId);
if (selectedNavItem) {
this.switchTo(selectedNavItem.id);
Expand All @@ -64,7 +137,7 @@ class RootPage extends Component {
* @returns The component data that is currently selected.
*/
getCurrentComponentItem() {
const { componentItems } = this.props;
const { componentItems } = this.state;
return componentItems && componentItems.find(item => item.id === this.state.selectedNavItemId);
}

Expand All @@ -74,17 +147,22 @@ class RootPage extends Component {
*/
switchTo(selectedNavItemId) {
this.setState({ selectedNavItemId }, () => {
const { componentItems } = this.props;
const { componentItems } = this.state;
const selectedNavItem = componentItems && componentItems.find(item => item.id === selectedNavItemId);
const { name } = selectedNavItem || {};
if (name) {
history.pushState({ name }, name, `/demo/${name}`);
}
load(componentItems, selectedNavItemId).then(newComponentItems => {
if (newComponentItems) {
this.setState({ componentItems: newComponentItems });
}
});
});
}

render() {
const { componentItems } = this.props;
const { componentItems } = this.state;
const metadata = this.getCurrentComponentItem();
const { name, label } = metadata || {};
const classNames = classnames({
Expand Down
1 change: 1 addition & 0 deletions demo/views/_layout.dust
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{>"{preview}"/}
40 changes: 40 additions & 0 deletions demo/views/_preview-default.dust
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<!DOCTYPE html>
<html lang="en">
<head>
<base href="/">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<title>Carbon Components</title>
<link rel="stylesheet" href="/demo/demo.css">
<style>
.offleft {
position: absolute;
top: 0;
left: -10000px;
width: 1px;
height: 1px;
overflow: hidden;
}
</style>
</head>

<body class="bx--body demo--container" data-floating-menu-container>
<div class="demo--container__panel" data-card-list data-demo-name="{name}">
{+content}
{/content}
</div>

<!-- Pseudo element to demonstrate focus-wrap behavior (focus trap) -->
<input aria-label="inpute-text-offleft" type="text" class="offleft" />

<!-- Scripts -->
<!-- <script src="/carbon-components.min.js"></script> -->
<script src="/demo/demo.js"></script>
<!-- Disable Auto Init with this flag -->
<!-- true = JavaScript will not initialize automatically -->
<!-- false = JavaScript will initialize automatically -->
<script>
CarbonComponents.settings.disableAutoInit = false;
</script>
</body>
</html>
2 changes: 2 additions & 0 deletions demo/views/_preview-empty.dust
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
{+content}
{/content}
28 changes: 20 additions & 8 deletions gulpfile.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use strict';

// Node
const fs = require('fs');
const path = require('path');

// Styles
Expand Down Expand Up @@ -40,10 +41,16 @@ const jsdocConfig = require('gulp-jsdoc3/dist/jsdocConfig.json');
// Generic utility
const del = require('del');

const writeFile = promisify(fs.writeFile);
const mkdirp = promisify(require('mkdirp'));

// Test environment
const Server = require('karma').Server;
const commander = require('commander');

// Fractal templates
const templates = require('./tools/templates');

const assign = v => v;
const cloptions = commander
.option('-k, --keepalive', 'Keeps browser open after first run of Karma test finishes')
Expand All @@ -64,8 +71,7 @@ gulp.task('browser-sync', ['sass:dev'], cb => {
let started;
nodemon({
script: './server.js',
ext: 'dust js',
watch: ['./demo/views', './server.js'],
watch: ['demo/**/*.dust', 'src/**/*.dust', 'src/**/*.config.js', 'server.js'],
env: {
PORT: cloptions.serverport,
},
Expand Down Expand Up @@ -250,11 +256,17 @@ gulp.task('sass:source', () => {
return gulp.src(srcFiles).pipe(gulp.dest('scss'));
});

gulp.task('html:source', () => {
const srcFiles = './src/components/**/*.html';

return gulp.src(srcFiles).pipe(gulp.dest('html'));
});
gulp.task('html:source', () =>
templates.render({ preview: '_preview-empty' }).then(renderedItems => {
const promises = [];
renderedItems.forEach((rendered, item) => {
const dirname = path.dirname(path.resolve(__dirname, 'html', item.relViewPath));
const filename = `${item.handle.replace(/--default$/, '')}.html`;
promises.push(mkdirp(dirname).then(() => writeFile(path.resolve(dirname, filename), rendered)));
});
return Promise.all(promises);
})
);

/**
* Lint
Expand Down Expand Up @@ -330,7 +342,7 @@ gulp.task('jsdoc', cb => {

gulp.task('test', ['test:unit', 'test:a11y']);

gulp.task('test:unit', done => {
gulp.task('test:unit', ['html:source'], done => {
new Server(
{
configFile: path.resolve(__dirname, 'tests/karma.conf.js'),
Expand Down
8 changes: 6 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@
"cz-conventional-changelog": "^1.2.0",
"del": "~2.0.2",
"diff": "^3.4.0",
"dustjs-helpers": "^1.7.0",
"dustjs-linkedin": "^2.7.0",
"eslint": "^3.0.0",
"eslint-config-airbnb": "^11.0.0",
"eslint-config-airbnb-base": "^11.0.0",
Expand Down Expand Up @@ -109,9 +111,10 @@
"markdown-it": "^8.4.0",
"merge-stream": "^1.0.0",
"minimatch": "^3.0.0",
"mkdirp": "^0.5.0",
"mock-raf": "^1.0.0",
"nodemon": "1.9.1",
"prettier": "^1.7.0",
"prettier": "^1.10.0",
"prop-types": "^15.6.0",
"pump": "^1.0.2",
"react": "^16.2.0",
Expand All @@ -131,7 +134,8 @@
"vinyl-named": "^1.1.0",
"webpack": "^3.10.0",
"webpack-dev-middleware": "^2.0.0",
"webpack-hot-middleware": "^2.21.0"
"webpack-hot-middleware": "^2.21.0",
"whatwg-fetch": "^2.0.0"
},
"files": [
"css/**/*",
Expand Down
Loading

0 comments on commit 274ab63

Please sign in to comment.