Skip to content
This repository has been archived by the owner on Jan 16, 2023. It is now read-only.

Commit

Permalink
Merge pull request #41 from hipstersmoothie/index
Browse files Browse the repository at this point in the history
Generate `index.html` for Monorepos
  • Loading branch information
hipstersmoothie authored Dec 3, 2018
2 parents e1e655a + b5a5d56 commit 44a3778
Show file tree
Hide file tree
Showing 5 changed files with 260 additions and 5 deletions.
20 changes: 17 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,13 @@ Install Storybook Deployer with:
```
npm i @storybook/storybook-deployer --save-dev
```

Then add a NPM script like this:

```json
{
"scripts": {
"deploy-storybook": "storybook-to-ghpages",
"deploy-storybook": "storybook-to-ghpages"
}
}
```
Expand All @@ -28,7 +29,7 @@ If you customize the build configuration with some additional params (like stati
```json
{
"scripts": {
"build-storybook": "build-storybook -s public",
"build-storybook": "build-storybook -s public"
}
}
```
Expand All @@ -53,12 +54,23 @@ npm run deploy-storybook -- --existing-output-dir=.out

If you manage a monorepo with multiple storybooks you can you pass the `packages` flag to `deploy-storybook` to scan a directory for `package.json`s.

The following command will search the `packages` directory for packages.
The following command will search the `packages` directory for packages. It will also generate a default `index.html` that links to all of the loaded storybooks.

```sh
npm run deploy-storybook -- --packages packages
```

### Customize Monorepo `index.html`

To customize the monorepo `index.html` you can pass the `monorepo-index-generator` flag to `deploy-storybook`. This file should export a function that receive the following arguments and returns the html for the page.

- an array of all the `package.json` data from the loaded storybooks as the first argument
- the output directory

```sh
npm run deploy-storybook -- --monorepo-index-generator my-custom-generator.js
```

### Deploying Storybook as part of a CI service

To deploy Storybook as part of a CI step, pass the `ci` flag to `npm run deploy-storybook`.
Expand Down Expand Up @@ -109,11 +121,13 @@ npm run deploy-storybook -- --remote=upstream
```

Or, to specify a target branch and serve your storybook with rawgit instead of gh-pages:

```sh
npm run deploy-storybook -- --branch=feature-branch
```

Or, to specify a source branch other than `master`, pass a `--source-branch` flag to `npm run deploy-storybook`:

```sh
npm run deploy-storybook -- --source-branch=release
```
10 changes: 8 additions & 2 deletions bin/storybook_to_ghpages
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const glob = require('glob');
const packageJson = require(path.resolve('./package.json'));
const argv = require('yargs').argv;
const parseRepo = require('parse-repo');
const buildMonorepoIndex = require('../src/build-monorepo-index')

const SKIP_BUILD = Boolean(argv['existing-output-dir'])
const OUTPUT_DIR = argv.out || argv['existing-output-dir'] || 'out' + Math.ceil(Math.random() * 9999);
Expand Down Expand Up @@ -75,20 +76,25 @@ function buildSubPackage(origDir, dir) {
shell.mkdir('-p', outputPath);
shell.cp('-r', builtStorybook, outputPath);
shell.rm('-rf', builtStorybook);

return subPackage;
}

if (!SKIP_BUILD) {
if (argv.packages) {
const origDir = process.cwd();

glob
const packages = glob
.sync(path.join(origDir, argv.packages, '**/package.json'), {
ignore: '**/node_modules/**'
})
.map(json => path.dirname(json))
.map(subPackage => buildSubPackage(origDir, subPackage));
.map(subPackage => buildSubPackage(origDir, subPackage))
.filter(subPackage => subPackage);

shell.cd(origDir);

buildMonorepoIndex(packages, argv['monorepo-index-generator'], OUTPUT_DIR);
} else {
console.log('=> Building storybook');
buildStorybook(packageJson);
Expand Down
69 changes: 69 additions & 0 deletions src/build-monorepo-index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
const shell = require('shelljs');
const fs = require('fs');
const path = require('path');

const colors = ['purple', 'pink', 'orange', 'green', 'blue', 'red'];

function generateHTML(packages) {
const packageRows = packages.map(
(package, index) => `
<a href="${path.join(package.name, 'index.html')}" class="package-row">
<span class="title is-${colors[index % colors.length]}">
${package.name}
</span>
<span class="description">${package.description}</span>
</a>
`
);
const index = `
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Storybooks</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" href="monorepo-index.css">
</head>
<body>
<img class="banner" src="storybook.svg" alt="Storybook"/>
<div class="content">
${packageRows.join('')}
</div>
</body>
</html>
`;

return index;
}

module.exports = function buildMonorepoIndex(
packages,
customHTMLGenerate,
outputDir
) {
let index;

console.log(`=> Building index.html for monorepo`);

if (customHTMLGenerate) {
const fn = require(path.join(process.cwd(), customHTMLGenerate));

if (typeof fn === 'function') {
index = fn(packages, outputDir);
}
} else {
index = generateHTML(packages);

shell.cp(
path.join(__dirname, 'storybook.svg'),
path.join(outputDir, 'storybook.svg')
);
shell.cp(
path.join(__dirname, 'monorepo-index.css'),
path.join(outputDir, 'monorepo-index.css')
);
}

fs.writeFileSync(path.join(outputDir, 'index.html'), index);
};
121 changes: 121 additions & 0 deletions src/monorepo-index.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
html {
height: 100%;
}

body {
display: flex;
flex-direction: column;
justify-content: center;
min-height: 60%;
margin: 2rem;
}

.content {
display: flex;
flex-direction: column;
width: fit-content;
justify-content: center;
margin: 3rem auto;
}

.banner {
max-width: 600px;
width: 100%;
margin: 3rem auto;
}

.package-row {
margin-bottom: 2rem;
color: #666;
display: flex;
align-items: stretch;
text-decoration: none;
transition: 0.3s;
}

.package-row:hover {
box-shadow: 0 15px 20px #bbb;
}

.package-row .title {
padding: 2rem;
color: white;
border-top-left-radius: 5%;
border-bottom-left-radius: 5%;
font-weight: bold;
}

.package-row .description {
padding: 2rem 2rem 2rem 1rem;
border-top-right-radius: 5%;
border-bottom-right-radius: 5%;
background: #f1f1f1;
flex-grow: 1;
box-shadow: 0px 10px 0 #d8d8d8;
text-align: center;
}

.package-row:active .description {
background: #d8d8d8;
box-shadow: 0px 10px 0 #bebebe;
}

.is-purple {
background: #b57ee5;
box-shadow: 0px 10px 0 #9c65cc;
}

.package-row:active .is-purple {
background: #9c65cc;
box-shadow: 0px 10px 0 #824bb2;
}

.is-pink {
background: #f1618c;
box-shadow: 0px 10px 0 #d84873;
}

.package-row:active .is-pink {
background: #d84873;
box-shadow: 0px 10px 0 #be2e59;
}

.is-orange {
background: #f3ad38;
box-shadow: 0px 10px 0 #da941f;
}

.package-row:active .is-orange {
background: #da941f;
box-shadow: 0px 10px 0 #c07a05;
}

.is-green {
background: #a2e05e;
box-shadow: 0px 10px 0 #89c745;
}

.package-row:active .is-green {
background: #89c745;
box-shadow: 0px 10px 0 #6fad2b;
}

.is-blue {
background: #6dabf5;
box-shadow: 0px 10px 0 #5492dc;
}

.package-row:active .is-blue {
background: #5492dc;
box-shadow: 0px 10px 0 #3a78c2;
}

.is-red {
background: #f16161;
box-shadow: 0px 10px 0 #d84848;
}

.package-row:active .is-red {
background: #d84848;
box-shadow: 0px 10px 0 #be2e2e;
}
45 changes: 45 additions & 0 deletions src/storybook.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 44a3778

Please sign in to comment.