Skip to content

Commit

Permalink
feat: storybook without docs addon
Browse files Browse the repository at this point in the history
  • Loading branch information
atanasster committed Apr 14, 2020
1 parent 9105e72 commit 8174079
Show file tree
Hide file tree
Showing 36 changed files with 525 additions and 242 deletions.
20 changes: 18 additions & 2 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
{
"type": "node",
"request": "launch",
"name": "storybook",
"name": "storybook-6",
"runtimeExecutable": "npm",
"cwd": "${workspaceFolder}",
"cwd": "${workspaceFolder}/examples/storybook-6",
"runtimeArgs": [
"run-script",
"debug"
Expand All @@ -19,6 +19,22 @@
"<node_internals>/**"
]
},
{
"type": "node",
"request": "launch",
"name": "storybook-6-no-docs",
"runtimeExecutable": "npm",
"cwd": "${workspaceFolder}/examples/storybook-6-no-docs",
"runtimeArgs": [
"run-script",
"debug"
],
"port": 9229,
"skipFiles": [
"<node_internals>/**"
]
},

{
"type": "node",
"request": "launch",
Expand Down
1 change: 1 addition & 0 deletions core/instrument/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
"@component-controls/specification": "^0.6.0",
"@hutson/parse-repository-url": "^5.0.0",
"@mdx-js/loader": "^1.5.5",
"camelcase":"^6.0.0",
"crypto": "^1.0.1",
"deepmerge": "^4.2.2",
"find-cache-dir": "^3.3.1",
Expand Down
15 changes: 11 additions & 4 deletions core/instrument/src/babel/csf-stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,16 @@ import {
} from '@component-controls/specification';
import { File } from '@babel/types';
import traverse from '@babel/traverse';
import { extractFunctionParameters } from './get-function-parameters';
import { extractFunctionParameters } from './extract-function-parameters';
import { extractAttributes } from './extract-attributes';
import { componentsFromParams } from '../misc/componentAttributes';
import { sourceLocation } from './utils';
import { componentsFromParams } from '../misc/component-attributes';
import { sourceLocation } from '../misc/source-location';
import { ParseStorieReturnType, InstrumentOptions } from '../types';

export const extractCSFStories = (ast: File): StoriesStore => {
export const extractCSFStories = (
ast: File,
_options: InstrumentOptions,
): ParseStorieReturnType => {
const globals: Stories = {};
const localStories: Stories = {};

Expand All @@ -28,6 +32,7 @@ export const extractCSFStories = (ast: File): StoriesStore => {
const story: Story = {
loc: sourceLocation(el.loc),
name,
id: name,
};
traverse(path.node, extractFunctionParameters(story), path.scope, path);
return story;
Expand Down Expand Up @@ -148,6 +153,8 @@ export const extractCSFStories = (ast: File): StoriesStore => {
if (Object.keys(store.kinds).length === 1) {
//@ts-ignore
store.kinds[Object.keys(store.kinds)[0]].components = components;
} else {
throw new Error(`CSF stories should have one default export`);
}
return store;
};
2 changes: 1 addition & 1 deletion core/instrument/src/babel/extract-arguments-usage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
StoryArgument,
ArgUsageLocation,
} from '@component-controls/specification';
import { adjustSourceLocation } from './utils';
import { adjustSourceLocation } from '../misc/source-location';

const findArguments = (
args: StoryArguments,
Expand Down
1 change: 1 addition & 0 deletions core/instrument/src/babel/extract-attributes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ const nodeToValue = (node: any): any => {
const nodeToAttribute = (node: any): StoryAttribute | undefined => {
const value = node.value || node;
const name = node.key ? node.key.name ?? node.key.value : node.name;

const retVal = nodeToValue(value);
return retVal !== undefined
? name
Expand Down
4 changes: 2 additions & 2 deletions core/instrument/src/babel/extract-component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import {
} from '@component-controls/specification';
import { createHash } from 'crypto';
import { followImports } from './follow-imports';
import { packageInfo } from '../misc/packageInfo';
import { propsInfo } from '../misc/propsInfo';
import { packageInfo } from '../misc/package-info';
import { propsInfo } from '../misc/props-info';
import { InstrumentOptions } from '../types';

const globalCache: {
Expand Down
2 changes: 1 addition & 1 deletion core/instrument/src/babel/extract-exports.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as parser from '@babel/parser';
import traverse from '@babel/traverse';
import { CodeLocation } from '@component-controls/specification';
import { sourceLocation } from './utils';
import { sourceLocation } from '../misc/source-location';

export interface ExportType {
name: string;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import traverse from '@babel/traverse';
import generate from '@babel/generator';
import {
Story,
CodeLocation,
StoryArguments,
} from '@component-controls/specification';
import { adjustSourceLocation } from './utils';
import { adjustSourceLocation } from '../misc/source-location';
import {
extractArgumentsUsage,
addArgumentUsage,
} from './extract-arguments-usage';
import { ExportType } from '../types';

interface KeyType {
name: string;
Expand All @@ -21,12 +23,22 @@ interface ASTPropNode {
value?: ASTPropNode;
left?: ASTPropNode;
}
export const extractFunctionParameters = (story: Story) => ({
export const extractFunctionParameters = (
story: Story,
exports?: ExportType,
) => ({
ArrowFunctionExpression: (path: any) => {
const node = path.node;
if (!story.arguments) {
story.arguments = [];
}
if (exports) {
const { code } = generate(node, {
retainFunctionParens: true,
retainLines: true,
});
exports.render = code.trim();
}
story.loc = {
start: {
column: node.loc.start.column,
Expand Down Expand Up @@ -100,4 +112,19 @@ export const extractFunctionParameters = (story: Story) => ({
}
path.skip();
},
JSXElement: (path: any) => {
if (exports && path.parent.children) {
const children = path.parent.children
.map((child: any) => {
const { code } = generate(child, {
retainFunctionParens: true,
retainLines: true,
});
return code.trim();
})
.join('\n');
exports.render = `() => (<>\n${children}\n</>)`;
}
path.skip();
},
});
108 changes: 78 additions & 30 deletions core/instrument/src/babel/mdx-stories.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,75 @@
import generate from '@babel/generator';
import {
StoriesStore,
Story,
StoriesKind,
StoryParameters,
} from '@component-controls/specification';
import camelCase from 'camelcase';
import { File } from '@babel/types';
import traverse from '@babel/traverse';
import { extractFunctionParameters } from './get-function-parameters';
import { extractFunctionParameters } from './extract-function-parameters';
import { extractAttributes } from './extract-attributes';
import { sourceLocation } from './utils';
import { componentsFromParams } from '../misc/componentAttributes';
import { sourceLocation } from '../misc/source-location';
import { ParseStorieReturnType, InstrumentOptions, ExportType } from '../types';

import { componentsFromParams } from '../misc/component-attributes';

export const extractMDXStories = (
ast: File,
_options: Required<InstrumentOptions>,
): ParseStorieReturnType => {
const collectAttributes = (
node: any,
exports?: ExportType,
): StoryParameters => {
return node.attributes.reduce((acc: StoryParameters, attribute: any) => {
if (exports) {
const { code } = generate(
attribute.value.expression || attribute.value,
{
retainFunctionParens: true,
retainLines: true,
},
);
const codeTrim = code.trim();
if (!exports.story) {
exports.story = {};
}
exports.story[attribute.name?.name] = codeTrim;
}

if (attribute.value.type === 'StringLiteral') {
return { ...acc, [attribute.name?.name]: attribute.value?.value };
} else if (attribute.value.type === 'JSXExpressionContainer') {
return {
...acc,
[attribute.name?.name]: extractAttributes(attribute.value.expression),
};
}
return acc;
}, {});
};

export const extractMDXStories = (ast: File): StoriesStore => {
let components: { [key: string]: string | undefined } = {};
const store: StoriesStore = {
const collectComponent = (attributes: StoryParameters) => {
const attrComponents = componentsFromParams(attributes);
components = attrComponents.reduce(
(acc, componentName) => ({ ...acc, [componentName]: undefined }),
components,
);
return attrComponents.length > 0 ? attrComponents[0] : undefined;
};

const store: Required<Pick<
ParseStorieReturnType,
'stories' | 'kinds' | 'components' | 'exports'
>> = {
stories: {},
kinds: {},
components: {},
exports: {},
};
const { transformMDX } = _options.mdx;
traverse(ast as any, {
JSXElement: (path: any) => {
const node = path.node.openingElement;
Expand All @@ -32,59 +84,53 @@ export const extractMDXStories = (ast: File): StoriesStore => {
'ComponentSource',
].indexOf(node.name.name) > -1
) {
const attributes: StoryParameters = node.attributes.reduce(
(acc: StoryParameters, attribute: any) => {
if (attribute.value.type === 'StringLiteral') {
return { ...acc, [attribute.name?.name]: attribute.value?.value };
} else if (attribute.value.type === 'JSXExpressionContainer') {
return {
...acc,
[attribute.name?.name]: extractAttributes(
attribute.value.expression,
),
};
}
return acc;
},
{},
);
const attrComponents = componentsFromParams(attributes);
components = attrComponents.reduce(
(acc, componentName) => ({ ...acc, [componentName]: undefined }),
components,
);
const component =
attrComponents.length > 0 ? attrComponents[0] : undefined;
switch (node.name.name) {
case 'Story': {
const exports = transformMDX ? {} : undefined;
const attributes = collectAttributes(node, exports);
const { name } = attributes;
if (typeof name === 'string') {
if (store.stories[name]) {
throw new Error(`Dusplaicated story name ${name}`);
}
const id = camelCase(name);
const story: Story = {
...attributes,
name,
id,
loc: sourceLocation(path.node.loc),
};
const component = collectComponent(attributes);
if (component) {
story.component = component;
}
traverse(
path.node,
extractFunctionParameters(story),
extractFunctionParameters(story, exports),
path.scope,
path,
);
store.stories[name] = story;
if (exports) {
store.exports[id] = exports;
}
}
break;
}
case 'Meta': {
const exports = transformMDX ? {} : undefined;
const attributes = collectAttributes(node, exports);
const { title } = attributes;
if (title) {
const kind: StoriesKind = {
components: {},
...attributes,
title,
};
if (exports) {
store.exports.default = exports;
}
const component = collectComponent(attributes);
if (component !== undefined) {
kind.component = component;
}
Expand All @@ -103,6 +149,8 @@ export const extractMDXStories = (ast: File): StoriesStore => {
if (Object.keys(store.kinds).length === 1) {
//@ts-ignore
store.kinds[Object.keys(store.kinds)[0]].components = components;
} else {
throw new Error(`MDX stories should have one <Meta /> component`);
}
return store;
};
3 changes: 3 additions & 0 deletions core/instrument/src/babel/remove-mdx-attributes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,8 @@ export const removeMDXAttributes = () => {
path.remove();
}
},
ExportDefaultDeclaration: (path: any) => {
path.replaceWith(path.node.declaration);
},
};
};
Loading

0 comments on commit 8174079

Please sign in to comment.