Skip to content

Commit

Permalink
Mayflower v10: display rendered styles (#1224)
Browse files Browse the repository at this point in the history
* WIP.

* Adds support for displaying rendered styles and html for Header, HeaderSlim, Footer, FooterSlim components.

* Branch cleanup.

* Code cleanup.

* Fixes performance issues caused by prettier formatting displayed css.

* Fixes visual regressions.

* Reduces the number of scss files for preview to work.

* Updates pnpm lock file.

* Updates preview component to use memoization on html display, removes unused prettier plugin.

Co-authored-by: Minghua Sun <clairesunstudio@gmail.com>
  • Loading branch information
smurrayatwork and clairesunstudio authored Oct 22, 2020
1 parent c6212a7 commit 85ea368
Show file tree
Hide file tree
Showing 45 changed files with 831 additions and 99 deletions.
468 changes: 467 additions & 1 deletion common/config/rush/pnpm-lock.yaml

Large diffs are not rendered by default.

98 changes: 80 additions & 18 deletions packages/react/.storybook/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ const assets = require('@massds/mayflower-assets');
const iconPath = path.resolve(__dirname, '../src/components/base/Icon/assets');
const nodeModules = path.resolve(path.join(process.cwd(), 'node_modules'));
const pnpmNodeModules = path.join(nodeModules, '.pnpm', 'node_modules');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = {
stories: ['../src/**/*.stories.@(js|mdx)'],
Expand All @@ -29,31 +30,93 @@ module.exports = {
{
name: '@storybook/preset-scss',
options: {
cssLoaderOptions: {
sourceMap: true
styleLoaderOptions: false,
sassLoaderOptions: false,
cssLoaderOptions: false,
rule: {
oneOf: [
{
exclude: [
path.resolve(__dirname, '../src/components/styles/_index.scss')
],
use: [
{
loader: 'css-loader',
options: {
sourceMap: process.env.NODE_ENV === 'development'
}
},
{
loader: 'sass-loader',
options: {
sourceMap: process.env.NODE_ENV === 'development',
implementation: require('sass'),
sassOptions: {
// This ensures production builds of storybook maintain
// spacing for displaying styles.
outputStyle: 'expanded',
includePaths: [
nodeModules,
pnpmNodeModules,
path.resolve(__dirname, '../src'),
path.resolve(__dirname, '../src/components'),
path.resolve(__dirname, '../src/components/styles'),
].concat(assets.includePaths)
}
}
}
]
},
{
include: [
path.resolve(__dirname, '../src/components/styles/_index.scss')
],
use: [
{
loader: MiniCssExtractPlugin.loader
},
{
loader: 'css-loader',
options: {
sourceMap: process.env.NODE_ENV === 'development'
}
},
{
loader: 'sass-loader',
options: {
sourceMap: process.env.NODE_ENV === 'development',
implementation: require('sass'),
sassOptions: {
includePaths: [
nodeModules,
pnpmNodeModules,
path.resolve(__dirname, '../src'),
path.resolve(__dirname, '../src/components'),
path.resolve(__dirname, '../src/components/styles'),
].concat(assets.includePaths)
}
}
}
]
}
]
},
sassLoaderOptions: {
sourceMap: true,
implementation: require('sass'),
sassOptions: {
includePaths: [
nodeModules,
pnpmNodeModules,
path.resolve(__dirname, '../src'),
path.resolve(__dirname, '../src/components'),
path.resolve(__dirname, '../src/components/styles'),
].concat(assets.includePaths)
}
}
}
},
],
webpackFinal: (config, { configType }) => {
// modify storybook's file-loader rule to avoid conflicts with svgr
const fileLoaderRule = config.module.rules.find(rule => rule.test.test && rule.test.test('.svg'));
fileLoaderRule.exclude = iconPath;



config.plugins.push(
new MiniCssExtractPlugin({
// Options similar to the same options in webpackOptions.output
// both options are optional
filename: '[name].css',
chunkFilename: '[id].css',
})
);
config.module.rules.unshift({
test: /\.svg$/,
include: iconPath,
Expand All @@ -67,7 +130,6 @@ module.exports = {
},
],
});

config.resolve = {
...config.resolve,
alias: {
Expand Down
70 changes: 43 additions & 27 deletions packages/react/.storybook/preview.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,14 @@ import {
Canvas, Story
} from '@storybook/addon-docs/blocks';
import { ActionBar, Source } from '@storybook/components';

import prettier from 'prettier/standalone';
import parserHtml from 'prettier/parser-html';
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
import { okaidia } from 'react-syntax-highlighter/dist/esm/styles/prism';
import '../src/index.scss';
import SyntaxHighlighter, { Renderer, Wrapper } from './syntax-highlighter';

import '../src/components/styles/_index.scss';

import logo from '!url-loader!@massds/mayflower-assets/static/images/stateseal.png';

const storyKindOrder = [
'about', // storyKindOrder.indexOf -1 follow alphabetical order
Expand All @@ -33,46 +36,59 @@ const storyKindOrder = [
'others/pages'
];

export const StoryPage = ({ StoryComponent = null, showStories = false, Description }) => {
export const StoryPage = ({ StoryComponent = null, showStories = false, Description, styles = null }) => {
const docsContext = React.useContext(DocsContext);
const [showHTML, setShowHTML] = React.useState(true);
const [showCSS, setShowCSS] = React.useState(true);

const css = React.useMemo(() => showCSS && styles ? styles.toString() : null, [showCSS, styles]);

const { id, name, parameters = {}, args } = docsContext;
const { component } = parameters;
const HtmlComponent = StoryComponent || component;
let html = null;
if (HtmlComponent) {
html = prettier.format(ReactDOMServer
.renderToStaticMarkup(
(
<HtmlComponent {...args} />
)),
{
htmlWhitespaceSensitivity: 'ignore',
endOfLine: 'auto',
parser: 'html',
plugins: [parserHtml]
}
);
}

let html = React.useMemo(() => {
const markup = ReactDOMServer.renderToStaticMarkup((
<HtmlComponent {...args} />
));
const prettyMarkup = prettier.format(markup,
{
htmlWhitespaceSensitivity: 'ignore',
endOfLine: 'auto',
parser: 'html',
plugins: [parserHtml]
});
// Replaces the path to the state seal with a base64 image.
return prettyMarkup.replace(/static\/media\/stateseal\.(.*)\.png/, logo);
}, [args]);

const actionItem = {
title: showHTML ? 'Hide HTML' : 'Show HTML?',
onClick: () => setShowHTML((prev) => !prev)
};
const cssActionItem = {
title: showCSS ? 'Hide Styles' : 'Show Styles?',
onClick: () => setShowCSS((prev) => !prev)
};

return(
<>
<Title>{component.displayName}</Title>
<Subtitle />
{ Description && <Description />}
<Primary name={name} />
<ArgsTable story={CURRENT_SELECTION}/>
{html && (
<Heading>
HTML
<ActionBar actionItems={[actionItem]} />
</Heading>
)}
{!showHTML && <Source storyId={id} error="Click Show HTML above to view markup source." />}
{html && showHTML && <Source storyId={id} language="html" code={html} dark />}
{html && (
<Heading>
HTML
<ActionBar actionItems={[actionItem]} />
</Heading>
)}
{!showHTML && <Source storyId={id} error="Click Show HTML above to view markup source." />}
{html && showHTML && <SyntaxHighlighter format={false} renderer={Renderer} language="html" code={html} dark />}
<Heading>Styles<ActionBar actionItems={[cssActionItem]} /></Heading>
{!showCSS && <Source storyId={id} error="Click Show Styles above to view styles source." />}
{css && showCSS && <SyntaxHighlighter format={false} renderer={Renderer} language="css" code={css} dark />}
{ showStories && <Stories />}
</>
);
Expand Down
Loading

0 comments on commit 85ea368

Please sign in to comment.