1
1
mirror of https://github.com/primer/css.git synced 2024-11-28 13:12:16 +03:00

Merge pull request #707 from primer/fix-storybook

Fix Storybook
This commit is contained in:
Shawn Allen 2019-03-07 14:30:49 -08:00 committed by GitHub
commit fadc008488
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 3535 additions and 2208 deletions

2
.gitignore vendored
View File

@ -4,7 +4,7 @@
.changelog
.next/
.sass-cache
.storybuild/
_site
build/
dist/
node_modules/

View File

@ -1,7 +0,0 @@
{
"presets": [
"env",
"react",
"minify"
]
}

13
.storybook/.eslintrc.json Normal file
View File

@ -0,0 +1,13 @@
{
"extends": [
"plugin:github/react"
],
"rules": {
"import/no-namespace": 0
},
"settings": {
"react": {
"version": "detect"
}
}
}

View File

@ -1,27 +0,0 @@
import React from 'react'
import {storiesOf} from '@storybook/react'
import octicons from 'octicons'
export const Octicon = (props) => {
const {name} = props
if (name in octicons) {
const svg = octicons[name].toSVG(props)
return <span dangerouslySetInnerHTML={ {__html: svg } } />
} else {
throw new Error(`No such octicon: "${name}"!`)
}
}
const story = storiesOf('Octicons', module)
Object.keys(octicons).forEach(name => {
story.add(name, () => {
return (
<div>
<Octicon name={name} height="64" />
<Octicon name={name} height="32" />
<Octicon name={name} height="16" />
</div>
)
})
})

View File

@ -1 +1 @@
import '@storybook/addon-options/register'
import '@storybook/addon-viewport/register'

View File

@ -1,29 +1,46 @@
import React from 'react'
import { configure, addDecorator } from '@storybook/react'
import { setOptions } from '@storybook/addon-options'
import '../modules/primer/index.scss'
import { version } from '../modules/primer/package.json'
import {configure, addParameters, addDecorator} from '@storybook/react'
import {name, homepage, version} from '../package.json'
import {INITIAL_VIEWPORTS} from '@storybook/addon-viewport'
setOptions({
name: `Primer v${version}`,
url: 'http://primer.github.io/',
showDownPanel: false,
// this enables HMR for the SCSS source files
import '../src/index.scss'
// wrap every view in 4x padding
addDecorator(story => <div className="p-4">{story()}</div>)
addParameters({
options: {
brandTitle: `${name}@${version}`,
brandUrl: homepage,
showAddonsPanel: false
},
viewport: {
viewports: {
sm: {
name: 'Small ($width-sm)',
styles: {width: '544px', height: 'auto'}
},
md: {
name: 'Medium ($width-md)',
styles: {width: '768px', height: 'auto'}
},
lg: {
name: 'Large ($width-lg)',
styles: {width: '1012px', height: 'auto'}
},
xl: {
name: 'XL ($width-xl)',
styles: {width: '1280px', height: 'auto'}
},
...INITIAL_VIEWPORTS
}
}
})
addDecorator(story => (
<div className='p-4'>
{story()}
</div>
))
const contexts = [
require.context('../modules', true, /stories.*\.js$/),
]
configure(() => {
contexts.forEach(context => {
context.keys()
.filter(key => !key.includes('node_modules'))
.forEach(context)
})
const loadMarkdown = require.context('../src', true, /\.md$/)
for (const path of loadMarkdown.keys()) {
loadMarkdown(path)
}
}, module)

View File

@ -1,27 +0,0 @@
import parseCodeBlocks from 'code-blocks/lib/fromString'
import htmlToReact from 'html-to-react'
const htmlParser = new htmlToReact.Parser()
const blockToStory = block => {
return {
title: block.title,
story: () => htmlParser.parse(block.value),
block,
}
}
export default function storiesFromMarkdown(req) {
return req.keys().reduce((stories, file) => {
const markdown = req(file)
const path = file.replace(/^\.\//, '')
const blocks = parseCodeBlocks(markdown, path)
.filter(block => {
// read: ```html *
// skip: ```html * story="false"
return block.lang === 'html' && block.info.story !== 'false'
})
.map(blockToStory)
return stories.concat(blocks)
}, [])
}

View File

@ -1,8 +0,0 @@
// FIXME this should go away when we merge and release:
// <https://github.com/primer/primer-module-build/pull/19>
const plugins = require("primer-module-build/lib/.postcss.json")
delete plugins.use
module.exports = {
plugins,
}

View File

@ -0,0 +1,52 @@
/* eslint-disable no-console */
const {dirname} = require('path')
const parseFromString = require('code-blocks/lib/fromString')
module.exports = function storyLoader(markdown) {
// resourcePath is the full path ("/Users/probot/primer/css/...") to the file being parsed
// rootContext is really just dirname(resourcePath)
const {resourcePath = '', rootContext} = this
// the sourcePath option provides a way to collapse the
// navigation hierarchy by trimming even more of the
// resourcePath's prefix; if it's not provided, use the
// rootContext
const {sourcePath = rootContext} = this.query || {}
// strip the sourcePath from the beginning of the resourcePath
const file = resourcePath.replace(`${sourcePath}/`, '')
// finally, remove "/README" or "/docs" from the path,
// then strip the ".md" filename extension
const path = dirname(file)
.replace(/(\/README|\/docs)/, '')
.replace(/\.md$/, '')
const stories = storiesFromMarkdown(markdown, file)
if (stories.length) {
console.warn(`${stories.length} stories found in ${file}!`)
return `
const {storiesOf} = require('@storybook/react')
const htmlToReact = require('html-to-react')
const chapter = storiesOf(${JSON.stringify(path)}, module)
const stories = ${JSON.stringify(stories)}
const htmlParser = new htmlToReact.Parser()
for (const {title, value} of stories) {
chapter.add(title, () => htmlParser.parse(value))
}
`
} else {
return `module.exports = {markdown: ${JSON.stringify(markdown)}}`
}
}
function storiesFromMarkdown(markdown, file) {
const path = file.replace(/^\.\//, '')
return parseFromString(markdown, path).filter(block => {
// yes: ```html
// no: ```html dead
// no: ```html inert
return block.lang === 'html' && !block.info.dead && !block.info.inert
})
}

View File

@ -1,29 +1,32 @@
const path = require('path');
const {resolve} = require('path')
const sourcePath = resolve(__dirname, '../src')
const modulesPath = path.resolve(__dirname, '../modules')
module.exports = ({config}) => {
const babel = config.module.rules.find(rule => {
return rule.test.test('test.js')
}).use[0]
module.exports = (config, env) => {
if (env === 'PRODUCTION') {
config.plugins = config.plugins
.filter(plugin => plugin.constructor.name !== 'UglifyJsPlugin')
}
const rules = config.module.rules
rules.forEach((rule, index) => {
if ('README.md'.match(rule.test)) {
// console.warn('replacing MD rule:', rule)
rules.splice(index, 1, {
test: /\.md$/,
loader: 'raw-loader',
})
}
config.module.rules = config.module.rules.filter(rule => {
return !rule.test.test('test.md')
})
rules.push(
config.module.rules.push(
{
test: /\.md$/,
include: sourcePath,
loaders: [
babel,
{
loader: require.resolve('./story-loader'),
options: {
sourcePath
}
}
]
},
{
test: /\.scss$/,
include: sourcePath,
loaders: [
'style-loader',
'css-loader',
@ -31,20 +34,11 @@ module.exports = (config, env) => {
loader: 'postcss-loader',
options: {
config: {
path: require.resolve('./postcss.config.js'),
},
},
},
{
loader: 'sass-loader',
options: {
includePaths: [
modulesPath,
],
path: require.resolve('../postcss.config.js')
}
}
},
],
include: modulesPath,
}
]
}
)

View File

@ -96,23 +96,12 @@ Our Storybook setup allows you to view every HTML code block in Primer CSS's Mar
npm run start-storybook
```
Then visit http://localhost:8000 to test your work.
This should open up the site in your browser (if not, navigate to `http://localhost:8001`).
### Code blocks
All `html` fenced code blocks in `src/**/*.md` will be rendered as stories and listed under the relevant module's name in the left-hand nav. File changes should trigger a live reload automatically (after a brief delay).
If the bundle you're working on has a `stories.js`, it probably includes a snippet like this:
```js
const stories = storiesOf('Module name', module)
storiesFromMarkdown(require.context('.', true, /\.md$/))
.forEach(({title, story}) => {
stories.add(title, story)
})
```
This is how we find all of the Markdown files in the bundle directory and generate stories from their code blocks. Storybook sections are labeled by the first argument to `storiesOf()` (in the above example, "Module name"), and individual stories get their titles from either the previous Markdown heading or the `title` attribute in the fenced code block. See the [`code-blocks` docs](https://npmjs.com/package/code-blocks) and the [`storiesFromMarkdown()` source](./.storybook/lib/storiesFromMarkdown.js) for more info.
Note: At this time, we do not load any stories from `src/**/stories.js`.
## Scripts
Our [`package.json`](package.json) houses a collection of [run-scripts] that we use to maintain, test, build, and publish Primer CSS, notably:
@ -121,7 +110,7 @@ Our [`package.json`](package.json) houses a collection of [run-scripts] that we
* `check-links` runs a link checker on your local development server (`localhost:3000`, started with `npm start`).
* `lint` lints all of our SCSS source files.
* `lint-js` lints the docs site and supporting scripts.
* `now-build` and `now-start` are run on [Now] to build and start the docs site server.
* `now-build` and `now-start` are run on [Now] to build and start the docs site server. `now-test` runs them both in order.
* `sync` copies Markdown docs from `src/` to `pages/css/` and preps them for inclusion in the docs site.
* `test-urls` compares a (pre-generated) list of paths from the [Primer Style Guide](https://styleguide.github.com/primer/) to files in `pages/css`, and lets us know if we've inadvertently deleted or renamed anything.
* `test-migrate` tests the [`primer-migrate`](MIGRATING.md#primer-migrate) command line utility.

View File

@ -8,7 +8,7 @@ import Frame from './Frame'
import 'prism-github/prism-github.scss'
const LANG_PATTERN = /\blanguage-\.?(jsx?|html)\b/
const LANG_PATTERN = /\blanguage-\.?(jsx|html)\b/
const converter = new HTMLtoJSX({
indent: ' ',
@ -23,9 +23,9 @@ const languageTransforms = {
}
export default function CodeExample(props) {
const {children, dangerouslySetInnerHTML, dead, source, ...rest} = props
const {children, dangerouslySetInnerHTML, inert, source, ...rest} = props
const lang = getLanguage(props.className)
if (lang && !dead) {
if (lang && !inert) {
const liveProps = {
code: source,
scope: {Octicon, getIconByName},

5410
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -2,7 +2,7 @@
"name": "@primer/css",
"version": "12.1.1",
"description": "Primer is the CSS framework that powers GitHub's front-end design. primer includes 23 packages that are grouped into 3 core meta-packages for easy install. Each package and meta-package is independently versioned and distributed via npm, so it's easy to include all or part of Primer within your own project.",
"homepage": "http://primer.github.io/",
"homepage": "https://primer.style/css",
"author": "GitHub, Inc.",
"license": "MIT",
"style": "dist/primer.css",
@ -24,21 +24,21 @@
"scripts": {
"fresh": "rm -rf node_modules; npm install",
"dist": "script/dist",
"build-storybook": "build-storybook -o build",
"check-links": "script/check-links http://localhost:3000/css -v",
"lint": "npm-run-all -s lint-css lint-js",
"lint-css": "stylelint --quiet --syntax scss src/**/*.scss",
"lint-js": "eslint lib docs",
"lint-js": "eslint lib docs .storybook",
"now-build": "next build",
"now-start": "next start",
"now-test": "npm-run-all -s now-build now-start",
"postpublish": "script/postpublish",
"prepare": "npm run dist",
"prepublishOnly": "script/prepublish",
"publish-storybook": "npm run storybook && gh-pages -d build -b gh-pages -r https://github.com/primer/storybook",
"publish-storybook": "script/publish-storybook",
"start": "next dev",
"dev": "next dev",
"start-storybook": "start-storybook -p 8000 -c .storybook",
"start-storybook": "start-storybook -p 8001",
"build-storybook": "build-storybook -o .storybuild",
"test": "npm-run-all -s test-urls test-migrate",
"test-all-modules": "ava --verbose tests/test-*.js",
"test-urls": "node docs-test/urls.js",
@ -49,9 +49,8 @@
"@mdx-js/mdx": "^0.16.6",
"@mdx-js/tag": "0.15.0",
"@primer/components": "11.0.0",
"@storybook/addon-options": "3.4.3",
"@storybook/addons": "3.4.3",
"@storybook/react": "3.4.3",
"@storybook/addon-viewport": "5.0.0",
"@storybook/react": "5.0.0",
"@svgr/webpack": "2.4.1",
"@zeit/next-css": "^1.0.1",
"@zeit/next-sass": "^1.0.1",

View File

@ -43,7 +43,7 @@ As of [Primer v10.10.0](https://github.com/primer/css/releases/v10.10.0), `prime
Rather than toggling the `d-none` class in JavaScript, you should toggle the `hidden` property on an element. This means that you won't have to restore any more specific display utility (`d-inline` or `d-flex`, for instance) just to work around the order in which they're listed in the stylesheet.
```js dead
```js
// Good:
element.hidden = !visible

View File

@ -7,3 +7,7 @@ if [[ -f $file ]]; then
cat $file | xargs rm -rfv
rm $file
fi
if [[ "$GITHUB_REF" = "refs/heads/master" ]]; then
npm run publish-storybook
fi

View File

@ -1,24 +1,4 @@
#!/usr/bin/env node
const ghpages = require('gh-pages')
const {GITHUB_ACTOR, GITHUB_TOKEN} = process.env
if (GITHUB_TOKEN) {
console.error('Publish storybook: No GITHUB_TOKEN found for storybook publishing.')
process.exitCode = 1
return
}
ghpages.publish('build', {
branch: 'gh-pages',
repo: `https://${GITHUB_ACTOR}:${process.env.GITHUB_TOKEN}@github.com/primer/storybook.git`,
user: {
name: 'Primer CSS',
email: 'design-systems@github.com'
}
}, error => {
if (error) {
console.error('gh-pages failed to publish:', error.message.replace(process.env.GITHUB_TOKEN, '[secret]'))
process.exitCode = 1
}
})
#!/bin/bash
remote=${STORYBOOK_GIT_URL:-https://github.com/primer/storybook}
npm run build-storybook
npx gh-pages -d .storybuild -b gh-pages -r "$remote" "$@"