Skip to content

Commit

Permalink
feat: parameters instrumentation
Browse files Browse the repository at this point in the history
  • Loading branch information
atanasster committed Feb 14, 2020
1 parent 7832976 commit 69c2313
Show file tree
Hide file tree
Showing 5 changed files with 156 additions and 26 deletions.
29 changes: 29 additions & 0 deletions core/instrument/src/babel-traverse/get-csf-stories.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { Stories, Story } from '../types';
import traverse from '@babel/traverse';
import { extractFunctionParameters } from './get-function-parameters';

export const extractCSFStories = (stories: Stories) => ({
ExportNamedDeclaration: (path: any) => {
const {
declaration: {
declarations: [declaration],
},
} = path.node;
const el = declaration.init.body;
const name = declaration.id.name;
const story: Story = {
source: {
start: {
column: el.loc.start.column,
line: el.loc.start.line,
},
end: {
column: el.loc.end.column,
line: el.loc.end.line,
},
},
};
traverse(path.node, extractFunctionParameters(story), path.scope, path);
stories[name] = story;
},
});
51 changes: 51 additions & 0 deletions core/instrument/src/babel-traverse/get-function-parameters.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { Story, CodeSource, StoryParameters } from '../types';

interface ASTPropNode {
name?: string;
loc: CodeSource;
properties?: any;
}
export const extractFunctionParameters = (story: Story) => ({
ArrowFunctionExpression: (path: any) => {
const node = path.node;
if (!story.parameters) {
story.parameters = [];
}
const pushParams = (node: ASTPropNode, parameters: StoryParameters) => {
const loc = {
start: {
column: node.loc.start.column,
line: node.loc.start.line,
},
end: {
column: node.loc.end.column,
line: node.loc.end.line,
},
};
if (node.name) {
parameters.push({
value: node.name,
loc,
});
} else if (node.properties) {
const nestedParameters: StoryParameters = [];
parameters.push({
value: nestedParameters,
loc,
});
node.properties.forEach(({ value }: { value: ASTPropNode }) => {
pushParams(value, nestedParameters);
});
}
};
if (node.params) {
node.params.forEach(
(p: { name: string; loc: CodeSource; properties?: any }) => {
if (story.parameters) {
pushParams(p, story.parameters);
}
},
);
}
},
});
10 changes: 5 additions & 5 deletions core/instrument/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import * as parser from '@babel/parser';
import traverse from '@babel/traverse';
import { extractCSFStories } from './babel-traverse/get-csf-stories';
export * from './types';

export const parseSource = (source: string) => {
const ast = parser.parse(source, {
sourceType: 'module',
plugins: ['jsx', 'typescript'],
});
traverse(ast, {
enter(path) {
console.log(path);
},
});
const stories = {};
traverse(ast, extractCSFStories(stories));
return stories;
};
24 changes: 24 additions & 0 deletions core/instrument/src/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
export interface SourceLoc {
line: number;
column: number;
}

export interface CodeSource {
start: SourceLoc;
end: SourceLoc;
}
export interface StoryParameter {
value: string | StoryParameters;
loc: CodeSource;
}

export type StoryParameters = StoryParameter[];

export interface Story {
parameters?: StoryParameters;
source: CodeSource;
}

export interface Stories {
[name: string]: Story;
}
68 changes: 47 additions & 21 deletions integrations/storybook/src/config-legacy.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
import { addDecorator, useEffect } from '@storybook/client-api';
import { CHANNEL_CREATED } from '@storybook/core-events';
import { storyNameFromExport } from '@storybook/csf';
import { ComponentControls } from '@component-controls/specification';
import { getControlValues } from '@component-controls/core';
import { __STORYBOOK_STORY_STORE__ as storyStore } from 'global';
// import { parseSource } from '@component-controls/instrument';
import {
parseSource,
Stories,
StoryParameters,
} from '@component-controls/instrument';
import addons, { makeDecorator } from '@storybook/addons';
import { FORCE_RE_RENDER } from '@storybook/core-events';
import { docgenToControls } from './shared/smartControls';
Expand Down Expand Up @@ -39,22 +44,49 @@ addDecorator(
if (storyStore._smartcontrols === undefined) {
storyStore._smartcontrols = true;
Object.keys(storyStore._data).forEach((id: string) => {
const parameters = storyStore._data[id].parameters || {};
const story = storyStore._data[id];
const parameters = story.parameters || {};
const { addonControls = {}, controls } = parameters;
const { smart } = addonControls;
if (smart) {
const smartControls = docgenToControls(
storyStore._data[id].parameters,
);
if (smartControls && Object.keys(smartControls).length) {
storyStore._data[id].parameters.controls = {
...smartControls,
...controls,
};
storyStore._data[id].parameters.addonControls = {
...storyStore._data[id].parameters.addonControls,
smartLoaded: true,
};
const code =
parameters.mdxSource ||
(parameters.storySource && parameters.storySource.source);
let params: StoryParameters | undefined;
if (code) {
const stories: Stories = parseSource(code);
const storyProps:
| {
name: string;
parameters: StoryParameters | undefined;
}
| undefined = Object.keys(stories)
.map(name => ({
parameters: stories[name].parameters,
name: storyNameFromExport(name),
}))
.find(({ name }) => name === story.name);
if (
storyProps &&
storyProps.parameters &&
storyProps.parameters.length
) {
params = storyProps.parameters;
story.parameters.addonControls.properties = params;
}
}
if (params && params.length) {
const smartControls = docgenToControls(story.parameters);
if (smartControls && Object.keys(smartControls).length) {
story.parameters.controls = {
...smartControls,
...controls,
};
story.parameters.addonControls = {
...story.parameters.addonControls,
smartLoaded: true,
};
}
}
}
});
Expand Down Expand Up @@ -96,13 +128,7 @@ addDecorator(
};
}, []);
const { parameters = {} } = context; // parseSource(source));
/* const source =
parameters.mdxSource ||
(parameters.storySource && parameters.storySource.source);
*/ const {
controls,
addonControls,
} = parameters;
const { controls, addonControls } = parameters;
const { legacyContext = false } = addonControls || {};
const props = getControlValues(controls);

Expand Down

0 comments on commit 69c2313

Please sign in to comment.