mirror of
https://github.com/storybookjs/storybook.git
synced 2025-04-09 00:19:13 +08:00
Use new storyId format for story_store
This commit is contained in:
parent
dbbd06173f
commit
0d7d8d2404
@ -7,7 +7,7 @@
|
||||
// 2. replace all runs of '-' with a single '-',
|
||||
// except if they are at the end, in which case, replace them with ''
|
||||
|
||||
function sanitize(string) {
|
||||
export function sanitize(string) {
|
||||
return string
|
||||
.toLowerCase()
|
||||
.replace(/[^a-z0-9-]/g, '-')
|
||||
|
@ -6,6 +6,7 @@ import mergeWith from 'lodash.mergewith';
|
||||
import isEqual from 'lodash.isequal';
|
||||
import Events from '@storybook/core-events';
|
||||
import debounce from 'lodash.debounce';
|
||||
import toId, { sanitize } from './id';
|
||||
|
||||
// TODO: these are copies from components/nav/lib
|
||||
// refactor to DRY
|
||||
@ -52,8 +53,6 @@ export const splitPath = (path, { rootSeparator, groupSeparator }) => {
|
||||
};
|
||||
};
|
||||
|
||||
export { toKey };
|
||||
|
||||
let count = 0;
|
||||
|
||||
function getId() {
|
||||
@ -145,58 +144,68 @@ export default class StoryStore extends EventEmitter {
|
||||
getSelection = () => this._selection;
|
||||
|
||||
addStory(
|
||||
{ kind, name, story, getDecorated, parameters = {} },
|
||||
{ kind, name: storyName, story, getDecorated, parameters = {} },
|
||||
{ rootSeparator, groupSeparator }
|
||||
) {
|
||||
const { _data } = this;
|
||||
const { root, groups } = splitPath(kind, { rootSeparator, groupSeparator });
|
||||
const rootId = root ? toKey(root) : null;
|
||||
|
||||
const h = []
|
||||
const rootAndGroups = []
|
||||
.concat(root || [])
|
||||
.concat(groups)
|
||||
.map(toGroup);
|
||||
.map(toGroup)
|
||||
// Map a bunch of extra fields onto the groups, collecting the path as we go (thus the reduce)
|
||||
.reduce((soFar, group, index, original) => {
|
||||
const { name } = group;
|
||||
const path = sanitize(index === 0 ? name : `${soFar[index - 1].path}-${name}`);
|
||||
return soFar.concat([
|
||||
{
|
||||
...group,
|
||||
path,
|
||||
depth: index,
|
||||
isComponent: index === original.length - 1,
|
||||
isRoot: index === 0,
|
||||
},
|
||||
]);
|
||||
}, []);
|
||||
|
||||
const id = h
|
||||
.map(g => g.id)
|
||||
.concat(toKey(name))
|
||||
.join('-');
|
||||
const storyId = toId(kind, storyName);
|
||||
const paths = [...rootAndGroups.map(g => g.path), storyId];
|
||||
|
||||
const child = toChild({
|
||||
// Ok, now let's add everything to the store
|
||||
rootAndGroups.forEach((group, index) => {
|
||||
const child = paths[index + 1];
|
||||
const { path } = group;
|
||||
_data[path] = merge(_data[path] || {}, {
|
||||
...group,
|
||||
...(child && { children: [child] }),
|
||||
});
|
||||
});
|
||||
|
||||
// Check that we don't already have this item in the story
|
||||
if (_data[storyId]) {
|
||||
// TODO -- we need a better error and some docs here
|
||||
throw new Error(`Story with id ${storyId} already exists in the store!
|
||||
|
||||
Perhaps you added the same story twice, or you have a name collision?
|
||||
Story ids need to be unique -- ensure you aren't using the same names modolo url-sanitization.`);
|
||||
}
|
||||
|
||||
_data[storyId] = toChild({
|
||||
kind,
|
||||
name,
|
||||
name: storyName,
|
||||
story,
|
||||
getDecorated,
|
||||
parameters,
|
||||
id,
|
||||
id: storyId,
|
||||
path: storyId,
|
||||
depth: rootAndGroups.length,
|
||||
isComponent: false,
|
||||
isRoot: false,
|
||||
});
|
||||
|
||||
// add groups
|
||||
h.reduceRight((childId, group, index, list) => {
|
||||
const path = list
|
||||
.slice(0, index + 1)
|
||||
.map(g => g.id)
|
||||
.join('-');
|
||||
|
||||
const existing = _data[path] || {};
|
||||
const isRoot = group.id === rootId;
|
||||
const isComponent = index === list.length - 1;
|
||||
const depth = index;
|
||||
|
||||
_data[path] = merge(
|
||||
existing,
|
||||
merge(group, { children: [childId], isRoot, isComponent, depth, path })
|
||||
);
|
||||
|
||||
return path;
|
||||
}, id);
|
||||
|
||||
// add item
|
||||
const existing = _data[id] || {};
|
||||
_data[id] = merge(existing, { ...child, depth: h.length, path: id });
|
||||
|
||||
// LEGACY DATA
|
||||
this.addLegacyStory({ kind, name, story, getDecorated, parameters });
|
||||
this.addLegacyStory({ kind, name: storyName, story, getDecorated, parameters });
|
||||
|
||||
// LET'S SEND IT TO THE MANAGER
|
||||
this.pushToManager();
|
||||
|
@ -9,6 +9,76 @@ const make = (kind, name, story, parameters = {}) => [
|
||||
];
|
||||
|
||||
describe('preview.story_store', () => {
|
||||
describe('raw storage', () => {
|
||||
it('stores basic kinds and stories w/ correct keys', () => {
|
||||
const store = new StoryStore({ channel });
|
||||
store.addStory(...make('a', '1', () => 0));
|
||||
store.addStory(...make('a', '2', () => 0));
|
||||
store.addStory(...make('b', '1', () => 0));
|
||||
|
||||
const extracted = store.extract();
|
||||
// We need exact key ordering, even if in theory JS doens't guarantee it
|
||||
expect(Object.keys(extracted)).toEqual(['a', 'a--1', 'a--2', 'b', 'b--1']);
|
||||
expect(extracted.a).toMatchObject({
|
||||
path: 'a',
|
||||
children: ['a--1', 'a--2'],
|
||||
isRoot: true,
|
||||
isComponent: true,
|
||||
depth: 0,
|
||||
});
|
||||
|
||||
expect(extracted['a--1']).toMatchObject({
|
||||
id: 'a--1',
|
||||
path: 'a--1',
|
||||
kind: 'a',
|
||||
name: '1',
|
||||
parameters: {},
|
||||
depth: 1,
|
||||
isRoot: false,
|
||||
isComponent: false,
|
||||
});
|
||||
});
|
||||
|
||||
it('stores root and groups also', () => {
|
||||
const store = new StoryStore({ channel });
|
||||
store.addStory(...make('a|b/c/d', '1', () => 0));
|
||||
|
||||
const extracted = store.extract();
|
||||
// We need exact key ordering, even if in theory JS doens't guarantee it
|
||||
expect(Object.keys(extracted)).toEqual(['a', 'a-b', 'a-b-c', 'a-b-c-d', 'a-b-c-d--1']);
|
||||
expect(extracted.a).toMatchObject({
|
||||
name: 'a',
|
||||
isRoot: true,
|
||||
isComponent: false,
|
||||
children: ['a-b'],
|
||||
});
|
||||
expect(extracted['a-b']).toMatchObject({
|
||||
name: 'b',
|
||||
isRoot: false,
|
||||
isComponent: false,
|
||||
children: ['a-b-c'],
|
||||
});
|
||||
expect(extracted['a-b-c']).toMatchObject({
|
||||
name: 'c',
|
||||
isRoot: false,
|
||||
isComponent: false,
|
||||
children: ['a-b-c-d'],
|
||||
});
|
||||
expect(extracted['a-b-c-d']).toMatchObject({
|
||||
name: 'd',
|
||||
isRoot: false,
|
||||
isComponent: true,
|
||||
children: ['a-b-c-d--1'],
|
||||
});
|
||||
expect(extracted['a-b-c-d--1']).toMatchObject({
|
||||
kind: 'a|b/c/d',
|
||||
name: '1',
|
||||
isRoot: false,
|
||||
isComponent: false,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('dumpStoryBook', () => {
|
||||
it('should return nothing when empty', () => {
|
||||
const store = new StoryStore({ channel });
|
||||
|
Loading…
x
Reference in New Issue
Block a user