1 | import "core-js/modules/es.array.reduce.js";
|
2 | import memoize from 'memoizerific';
|
3 | import deprecate from 'util-deprecate';
|
4 | import dedent from 'ts-dedent';
|
5 | import mapValues from 'lodash/mapValues';
|
6 | import countBy from 'lodash/countBy';
|
7 | import global from 'global';
|
8 | import { sanitize } from '@storybook/csf';
|
9 | import { combineParameters } from '../index';
|
10 | import merge from './merge';
|
11 | const {
|
12 | FEATURES
|
13 | } = global;
|
14 | const warnLegacyShowRoots = deprecate(() => {}, dedent`
|
15 | The 'showRoots' config option is deprecated and will be removed in Storybook 7.0. Use 'sidebar.showRoots' instead.
|
16 | Read more about it in the migration guide: https://github.com/storybookjs/storybook/blob/master/MIGRATION.md
|
17 | `);
|
18 | const warnChangedDefaultHierarchySeparators = deprecate(() => {}, dedent`
|
19 | The default hierarchy separators changed in Storybook 6.0.
|
20 | '|' and '.' will no longer create a hierarchy, but codemods are available.
|
21 | Read more about it in the migration guide: https://github.com/storybookjs/storybook/blob/master/MIGRATION.md
|
22 | `);
|
23 | export const denormalizeStoryParameters = ({
|
24 | globalParameters,
|
25 | kindParameters,
|
26 | stories
|
27 | }) => {
|
28 | return mapValues(stories, storyData => Object.assign({}, storyData, {
|
29 | parameters: combineParameters(globalParameters, kindParameters[storyData.kind], storyData.parameters)
|
30 | }));
|
31 | };
|
32 | const STORY_KIND_PATH_SEPARATOR = /\s*\/\s*/;
|
33 | export const transformStoryIndexToStoriesHash = (index, {
|
34 | provider
|
35 | }) => {
|
36 | const countByTitle = countBy(Object.values(index.stories), 'title');
|
37 | const input = Object.entries(index.stories).reduce((acc, [id, {
|
38 | title,
|
39 | name,
|
40 | importPath,
|
41 | parameters
|
42 | }]) => {
|
43 | const docsOnly = name === 'Page' && countByTitle[title] === 1;
|
44 | acc[id] = {
|
45 | id,
|
46 | kind: title,
|
47 | name,
|
48 | parameters: Object.assign({
|
49 | fileName: importPath,
|
50 | options: {},
|
51 | docsOnly
|
52 | }, parameters)
|
53 | };
|
54 | return acc;
|
55 | }, {});
|
56 | return transformStoriesRawToStoriesHash(input, {
|
57 | provider,
|
58 | prepared: false
|
59 | });
|
60 | };
|
61 | export const transformStoriesRawToStoriesHash = (input, {
|
62 | provider,
|
63 | prepared = true
|
64 | }) => {
|
65 | const values = Object.values(input).filter(Boolean);
|
66 | const usesOldHierarchySeparator = values.some(({
|
67 | kind
|
68 | }) => kind.match(/\.|\|/));
|
69 |
|
70 | const storiesHashOutOfOrder = values.reduce((acc, item) => {
|
71 | var _item$parameters;
|
72 |
|
73 | const {
|
74 | kind,
|
75 | parameters
|
76 | } = item;
|
77 | const {
|
78 | sidebar = {},
|
79 | showRoots: deprecatedShowRoots
|
80 | } = provider.getConfig();
|
81 | const {
|
82 | showRoots = deprecatedShowRoots,
|
83 | collapsedRoots = [],
|
84 | renderLabel
|
85 | } = sidebar;
|
86 |
|
87 | if (typeof deprecatedShowRoots !== 'undefined') {
|
88 | warnLegacyShowRoots();
|
89 | }
|
90 |
|
91 | const setShowRoots = typeof showRoots !== 'undefined';
|
92 |
|
93 | if (usesOldHierarchySeparator && !setShowRoots && FEATURES !== null && FEATURES !== void 0 && FEATURES.warnOnLegacyHierarchySeparator) {
|
94 | warnChangedDefaultHierarchySeparators();
|
95 | }
|
96 |
|
97 | const groups = kind.trim().split(STORY_KIND_PATH_SEPARATOR);
|
98 | const root = (!setShowRoots || showRoots) && groups.length > 1 ? [groups.shift()] : [];
|
99 | const rootAndGroups = [...root, ...groups].reduce((list, name, index) => {
|
100 | const parent = index > 0 && list[index - 1].id;
|
101 | const id = sanitize(parent ? `${parent}-${name}` : name);
|
102 |
|
103 | if (parent === id) {
|
104 | throw new Error(dedent`
|
105 | Invalid part '${name}', leading to id === parentId ('${id}'), inside kind '${kind}'
|
106 |
|
107 | Did you create a path that uses the separator char accidentally, such as 'Vue <docs/>' where '/' is a separator char? See https://github.com/storybookjs/storybook/issues/6128
|
108 | `);
|
109 | }
|
110 |
|
111 | if (root.length && index === 0) {
|
112 | list.push({
|
113 | type: 'root',
|
114 | id,
|
115 | name,
|
116 | depth: index,
|
117 | children: [],
|
118 | isComponent: false,
|
119 | isLeaf: false,
|
120 | isRoot: true,
|
121 | renderLabel,
|
122 | startCollapsed: collapsedRoots.includes(id)
|
123 | });
|
124 | } else {
|
125 | list.push({
|
126 | type: 'group',
|
127 | id,
|
128 | name,
|
129 | parent,
|
130 | depth: index,
|
131 | children: [],
|
132 | isComponent: false,
|
133 | isLeaf: false,
|
134 | isRoot: false,
|
135 | renderLabel,
|
136 | parameters: {
|
137 | docsOnly: parameters === null || parameters === void 0 ? void 0 : parameters.docsOnly,
|
138 | viewMode: parameters === null || parameters === void 0 ? void 0 : parameters.viewMode
|
139 | }
|
140 | });
|
141 | }
|
142 |
|
143 | return list;
|
144 | }, []);
|
145 | const paths = [...rootAndGroups.map(({
|
146 | id
|
147 | }) => id), item.id];
|
148 |
|
149 | rootAndGroups.forEach((group, index) => {
|
150 | const child = paths[index + 1];
|
151 | const {
|
152 | id
|
153 | } = group;
|
154 | acc[id] = merge(acc[id] || {}, Object.assign({}, group, child && {
|
155 | children: [child]
|
156 | }));
|
157 | });
|
158 | acc[item.id] = Object.assign({
|
159 | type: (_item$parameters = item.parameters) !== null && _item$parameters !== void 0 && _item$parameters.docsOnly ? 'docs' : 'story'
|
160 | }, item, {
|
161 | depth: rootAndGroups.length,
|
162 | parent: rootAndGroups[rootAndGroups.length - 1].id,
|
163 | isLeaf: true,
|
164 | isComponent: false,
|
165 | isRoot: false,
|
166 | renderLabel,
|
167 | prepared
|
168 | });
|
169 | return acc;
|
170 | }, {});
|
171 |
|
172 | function addItem(acc, item) {
|
173 | if (!acc[item.id]) {
|
174 |
|
175 | acc[item.id] = item;
|
176 | const {
|
177 | children
|
178 | } = item;
|
179 |
|
180 | if (children) {
|
181 | const childNodes = children.map(id => storiesHashOutOfOrder[id]);
|
182 |
|
183 | if (childNodes.every(childNode => childNode.isLeaf)) {
|
184 | acc[item.id].isComponent = true;
|
185 | acc[item.id].type = 'component';
|
186 | }
|
187 |
|
188 | childNodes.forEach(childNode => addItem(acc, childNode));
|
189 | }
|
190 | }
|
191 |
|
192 | return acc;
|
193 | }
|
194 |
|
195 | return Object.values(storiesHashOutOfOrder).reduce(addItem, {});
|
196 | };
|
197 | export function isRoot(item) {
|
198 | if (item) {
|
199 | return item.isRoot;
|
200 | }
|
201 |
|
202 | return false;
|
203 | }
|
204 | export function isGroup(item) {
|
205 | if (item) {
|
206 | return !item.isRoot && !item.isLeaf;
|
207 | }
|
208 |
|
209 | return false;
|
210 | }
|
211 | export function isStory(item) {
|
212 | if (item) {
|
213 | return item.isLeaf;
|
214 | }
|
215 |
|
216 | return false;
|
217 | }
|
218 | export const getComponentLookupList = memoize(1)(hash => {
|
219 | return Object.entries(hash).reduce((acc, i) => {
|
220 | const value = i[1];
|
221 |
|
222 | if (value.isComponent) {
|
223 | acc.push([...i[1].children]);
|
224 | }
|
225 |
|
226 | return acc;
|
227 | }, []);
|
228 | });
|
229 | export const getStoriesLookupList = memoize(1)(hash => {
|
230 | return Object.keys(hash).filter(k => !(hash[k].children || Array.isArray(hash[k])));
|
231 | }); |
\ | No newline at end of file |