Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Docs mode with --docs flag #7154

Merged
merged 7 commits into from Jun 24, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions jest.config.js
Expand Up @@ -69,6 +69,9 @@ module.exports = {
'/dll/',
'/__mocks__ /',
],
globals: {
DOCS_MODE: false,
},
snapshotSerializers: ['jest-emotion', 'enzyme-to-json/serializer'],
coverageDirectory: 'coverage',
setupFilesAfterEnv: ['./scripts/jest.init.js'],
Expand Down
40 changes: 31 additions & 9 deletions lib/api/src/index.tsx
Expand Up @@ -43,7 +43,10 @@ const { STORY_CHANGED, SET_STORIES, SELECT_STORY } = Events;

export type Module = StoreData &
RouterData &
ProviderData & { mode?: 'production' | 'development' };
ProviderData & {
mode?: 'production' | 'development';
state: State;
};

export type State = Other &
LayoutSubState &
Expand Down Expand Up @@ -82,6 +85,10 @@ interface ProviderData {
provider: Provider;
}

interface DocsModeData {
docsMode: boolean;
}

interface StoreData {
store: Store;
}
Expand All @@ -92,7 +99,7 @@ interface Children {

type StatePartial = Partial<State>;

export type Props = Children & RouterData & ProviderData;
export type Props = Children & RouterData & ProviderData & DocsModeData;

class ManagerProvider extends Component<Props, State> {
static displayName = 'Manager';
Expand All @@ -103,26 +110,41 @@ class ManagerProvider extends Component<Props, State> {

constructor(props: Props) {
super(props);
const { provider, location, path, viewMode, storyId, navigate } = props;
const {
provider,
location,
path,
viewMode = props.docsMode ? 'docs' : 'story',
storyId,
docsMode,
navigate,
} = props;

const store = new Store({
getState: () => this.state,
setState: (stateChange: StatePartial, callback) => this.setState(stateChange, callback),
});

const routeData = { location, path, viewMode, storyId };

// Initialize the state to be the initial (persisted) state of the store.
// This gives the modules the chance to read the persisted state, apply their defaults
// and override if necessary
this.state = store.getInitialState(getInitialState({}));
const docsModeState = {
layout: { isToolshown: false, showPanel: false },
ui: { docsMode: true },
};
this.state = store.getInitialState(
getInitialState({
...routeData,
...(docsMode ? docsModeState : null),
})
);

const apiData = {
navigate,
store,
provider,
location,
path,
viewMode,
storyId,
};

this.modules = [
Expand All @@ -134,7 +156,7 @@ class ManagerProvider extends Component<Props, State> {
initStories,
initURL,
initVersions,
].map(initModule => initModule(apiData));
].map(initModule => initModule({ ...routeData, ...apiData, state: this.state }));

// Create our initial state by combining the initial state of all modules, then overlaying any saved state
const state = getInitialState(...this.modules.map(m => m.state));
Expand Down
2 changes: 2 additions & 0 deletions lib/api/src/modules/layout.ts
Expand Up @@ -24,6 +24,7 @@ export interface UI {
url?: string;
enableShortcuts: boolean;
sidebarAnimations: boolean;
docsMode: boolean;
}

export interface SubState {
Expand Down Expand Up @@ -132,6 +133,7 @@ const initial: SubState = {
ui: {
enableShortcuts: true,
sidebarAnimations: true,
docsMode: false,
},
layout: {
isToolshown: true,
Expand Down
17 changes: 9 additions & 8 deletions lib/api/src/modules/url.ts
Expand Up @@ -10,6 +10,7 @@ interface Additions {
panelPosition?: PanelPositions;
showNav?: boolean;
selectedPanel?: string;
viewMode?: string;
}

// Initialize the state based on the URL.
Expand All @@ -21,7 +22,7 @@ interface Additions {
// - nav: 0/1 -- show or hide the story list
//
// We also support legacy URLs from storybook <5
const initialUrlSupport = ({ navigate, location, path }: Module) => {
const initialUrlSupport = ({ navigate, state: { location, path, viewMode, storyId } }: Module) => {
const addition: Additions = {};
const query = queryFromLocation(location);
let selectedPanel;
Expand Down Expand Up @@ -70,20 +71,20 @@ const initialUrlSupport = ({ navigate, location, path }: Module) => {
}

if (selectedKind && selectedStory) {
const storyId = toId(selectedKind, selectedStory);
setTimeout(() => navigate(`/story/${storyId}`, { replace: true }), 1);
const id = toId(selectedKind, selectedStory);
setTimeout(() => navigate(`/${viewMode}/${id}`, { replace: true }), 1);
} else if (selectedKind) {
// Create a "storyId" of the form `kind-sanitized--*`
const standInId = toId(selectedKind, 'star').replace(/star$/, '*');
setTimeout(() => navigate(`/story/${standInId}`, { replace: true }), 1);
setTimeout(() => navigate(`/${viewMode}/${standInId}`, { replace: true }), 1);
} else if (!queryPath || queryPath === '/') {
setTimeout(() => navigate(`/story/*`, { replace: true }), 1);
setTimeout(() => navigate(`/${viewMode}/*`, { replace: true }), 1);
} else if (Object.keys(query).length > 1) {
// remove other queries
setTimeout(() => navigate(`${queryPath}`, { replace: true }), 1);
}

return { layout: addition, selectedPanel, location, path, customQueryParams };
return { viewMode, layout: addition, selectedPanel, location, path, customQueryParams, storyId };
};

export interface QueryParams {
Expand All @@ -102,7 +103,7 @@ export interface SubAPI {
setQueryParams: (input: QueryParams) => void;
}

export default function({ store, navigate, location, path: initialPath, ...rest }: Module) {
export default function({ store, navigate, state, provider, ...rest }: Module) {
const api: SubAPI = {
getQueryParam: key => {
const { customQueryParams } = store.getState();
Expand Down Expand Up @@ -142,6 +143,6 @@ export default function({ store, navigate, location, path: initialPath, ...rest

return {
api,
state: initialUrlSupport({ store, navigate, location, path: initialPath, ...rest }),
state: initialUrlSupport({ store, navigate, state, provider, ...rest }),
};
}
1 change: 1 addition & 0 deletions lib/api/src/tests/layout.test.js
Expand Up @@ -17,6 +17,7 @@ describe('layout API', () => {
ui: {
enableShortcuts: true,
sidebarAnimations: true,
docsMode: false,
},
layout: {
isToolshown: true,
Expand Down
24 changes: 13 additions & 11 deletions lib/api/src/tests/url.test.js
Expand Up @@ -5,12 +5,14 @@ import initURL from '../modules/url';
jest.useFakeTimers();

describe('initial state', () => {
const viewMode = 'story';

it('redirects to /story/* if path is blank', () => {
const navigate = jest.fn();
const location = { search: null };
const {
state: { layout },
} = initURL({ navigate, location });
} = initURL({ navigate, state: { location, viewMode } });

// Nothing unexpected in layout
expect(layout).toEqual({});
Expand All @@ -25,7 +27,7 @@ describe('initial state', () => {

const {
state: { layout },
} = initURL({ navigate, location });
} = initURL({ navigate, state: { location } });

expect(layout).toEqual({ isFullscreen: true });
});
Expand All @@ -36,7 +38,7 @@ describe('initial state', () => {

const {
state: { layout },
} = initURL({ navigate, location });
} = initURL({ navigate, state: { location } });

expect(layout).toEqual({ showNav: false });
});
Expand All @@ -47,7 +49,7 @@ describe('initial state', () => {

const {
state: { layout },
} = initURL({ navigate, location });
} = initURL({ navigate, state: { location } });

expect(layout).toEqual({ panelPosition: 'bottom' });
});
Expand All @@ -58,7 +60,7 @@ describe('initial state', () => {

const {
state: { layout },
} = initURL({ navigate, location });
} = initURL({ navigate, state: { location } });

expect(layout).toEqual({ panelPosition: 'right' });
});
Expand All @@ -69,7 +71,7 @@ describe('initial state', () => {

const {
state: { layout },
} = initURL({ navigate, location });
} = initURL({ navigate, state: { location } });

expect(layout).toEqual({ showPanel: false });
});
Expand All @@ -91,7 +93,7 @@ describe('initial state', () => {
const location = { search: qs.stringify(defaultLegacyParameters) };
const {
state: { layout, selectedPanel },
} = initURL({ navigate, location });
} = initURL({ navigate, state: { location, viewMode } });

// Nothing unexpected in layout
expect(layout).toEqual({});
Expand All @@ -111,7 +113,7 @@ describe('initial state', () => {
};
const {
state: { layout },
} = initURL({ navigate, location });
} = initURL({ navigate, state: { location } });

expect(layout).toEqual({ isFullscreen: true });
});
Expand All @@ -127,7 +129,7 @@ describe('initial state', () => {
};
const {
state: { layout },
} = initURL({ navigate, location });
} = initURL({ navigate, state: { location } });

expect(layout).toEqual({ showNav: false, showPanel: false });
});
Expand All @@ -142,7 +144,7 @@ describe('initial state', () => {
};
const {
state: { layout },
} = initURL({ navigate, location });
} = initURL({ navigate, state: { location } });

expect(layout).toEqual({ panelPosition: 'right' });
});
Expand All @@ -158,7 +160,7 @@ describe('queryParams', () => {
},
getState: () => state,
};
const { api } = initURL({ location: { search: '' }, navigate: jest.fn(), store });
const { api } = initURL({ state: { location: { search: '' } }, navigate: jest.fn(), store });

api.setQueryParams({ foo: 'bar' });

Expand Down
3 changes: 3 additions & 0 deletions lib/api/src/typings.d.ts
@@ -1,2 +1,5 @@
declare module 'global';
declare module 'telejson';

// provided by the webpack define plugin
declare var DOCS_MODE: string | undefined;
1 change: 1 addition & 0 deletions lib/core/src/server/build-dev.js
Expand Up @@ -343,5 +343,6 @@ export async function buildDev({ packageJson, ...loadOptions }) {
...loadOptions,
packageJson,
configDir: loadOptions.configDir || cliOptions.configDir || './.storybook',
docsMode: !!cliOptions.docs,
});
}
2 changes: 2 additions & 0 deletions lib/core/src/server/build-static.js
Expand Up @@ -123,6 +123,7 @@ async function buildManager(configType, outputDir, configDir, options) {
configDir,
corePresets: [require.resolve('./manager/manager-preset.js')],
frameworkPresets: options.frameworkPresets,
docsMode: options.docsMode,
});

if (options.debugWebpack) {
Expand Down Expand Up @@ -203,5 +204,6 @@ export function buildStatic({ packageJson, ...loadOptions }) {
packageJson,
configDir: loadOptions.configDir || cliOptions.configDir || './.storybook',
outputDir: loadOptions.outputDir || cliOptions.outputDir || './storybook-static',
docsMode: !!cliOptions.docs,
});
}
1 change: 1 addition & 0 deletions lib/core/src/server/cli/dev.js
Expand Up @@ -36,6 +36,7 @@ async function getCLI(packageJson) {
.option('--quiet', 'Suppress verbose build output')
.option('--no-dll', 'Do not use dll reference')
.option('--debug-webpack', 'Display final webpack configurations for debugging purposes')
.option('--docs', 'Build a documentation-only site using addon-docs')
.parse(process.argv);

// Workaround the `-h` shorthand conflict.
Expand Down
1 change: 1 addition & 0 deletions lib/core/src/server/cli/prod.js
Expand Up @@ -16,6 +16,7 @@ function getCLI(packageJson) {
.option('--loglevel [level]', 'Control level of logging during build')
.option('--no-dll', 'Do not use dll reference')
.option('--debug-webpack', 'Display final webpack configurations for debugging purposes')
.option('--docs', 'Build a documentation-only site using addon-docs')
.parse(process.argv);

logger.setLevel(program.loglevel);
Expand Down
12 changes: 11 additions & 1 deletion lib/core/src/server/manager/manager-webpack.config.js
Expand Up @@ -19,7 +19,16 @@ const coreDirName = path.dirname(require.resolve('@storybook/core/package.json')
const context = path.join(coreDirName, '../../node_modules');
const cacheDir = findCacheDir({ name: 'storybook' });

export default ({ configDir, configType, entries, dll, outputDir, cache, babelOptions }) => {
export default ({
configDir,
configType,
docsMode,
entries,
dll,
outputDir,
cache,
babelOptions,
}) => {
const { raw, stringified } = loadEnv();
const isProd = configType === 'PRODUCTION';

Expand Down Expand Up @@ -63,6 +72,7 @@ export default ({ configDir, configType, entries, dll, outputDir, cache, babelOp
new DefinePlugin({
'process.env': stringified,
NODE_ENV: JSON.stringify(process.env.NODE_ENV),
DOCS_MODE: docsMode, // global docs mode
}),
// See https://github.com/graphql/graphql-language-service/issues/111#issuecomment-306723400
new ContextReplacementPlugin(/graphql-language-service-interface[/\\]dist/, /\.js$/),
Expand Down
4 changes: 4 additions & 0 deletions lib/ui/src/components/layout/container.js
Expand Up @@ -486,11 +486,13 @@ class Layout extends Component {
{isDragging ? <HoverBlocker /> : null}
{children({
mainProps: {
viewMode,
animate: !isDragging,
isFullscreen,
position: getMainPosition({ bounds, resizerNav, isNavHidden, isFullscreen, margin }),
},
previewProps: {
viewMode,
animate: !isDragging,
isFullscreen,
isToolshown,
Expand All @@ -506,6 +508,7 @@ class Layout extends Component {
}),
},
navProps: {
viewMode,
animate: !isDragging,
hidden: isNavHidden,
position: {
Expand All @@ -516,6 +519,7 @@ class Layout extends Component {
},
},
panelProps: {
viewMode,
animate: !isDragging,
align: options.panelPosition,
hidden: isPanelHidden,
Expand Down