Skip to content

Commit f2a9ee0

Browse files
committed
feat: add support for grouping by symbols by "group" key
1 parent 6290cae commit f2a9ee0

File tree

2 files changed

+61
-35
lines changed

2 files changed

+61
-35
lines changed

README.md

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -108,29 +108,30 @@ module.exports = {
108108

109109
## API
110110

111-
| Parameter | Explanation | Input Type | Default |
112-
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------- | ----------------------------------------------------------------------------------- |
113-
| output | Specifies the filename for the generated asketch.json file or a folder when outputBy === 'kind'. | string | `"dist/stories.asketch.json"` |
114-
| input | The location of Storybook's generated iframe.html. Use this over `url` if possible for performance. | string | `"dist/iframe.html"` |
115-
| url | Storybook iframe URL. Will end in `iframe.html`. Prefer `input` for performance if possible. | string | `"http://localhost:9001/iframe.html"` |
116-
| stories | Stories to extract from Storybook. You should probably override the default. | object/string | `"all"` |
117-
| concurrency | Number of headless Chrome tabs to run in parallel. Drastically impacts performance. | integer | `4` |
118-
| symbolGutter | Gutter to place between symbols in Sketch. | integer | `100` |
119-
| viewports | Viewport configuration. Will be arranged left-to-right by width. Try to avoid changing the key, as this is used to identify the symbol. | object | Mobile viewport (320px wide) and desktop viewport (1920px wide). See example below. |
120-
| querySelector | Query selector to select your node on each page. Uses `document.querySelectorAll`. | string | `"#root"` |
121-
| verbose | Verbose logging output. | boolean | `false` |
122-
| fixPseudo | Attempt to insert real elements in place of pseudo-elements | boolean | `false` |
123-
| puppeteerOptions | Options to be passed directly to `puppeteer.launch`. See [puppeteer docs](https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#puppeteerlaunchoptions) for usage. | object | `{}` |
124-
| removePreviewMargin | Remove preview margin from the iframe body. | boolean | `true` |
125-
| layoutBy | How to layout the stories. (values: 'kind') | string | null |
126-
| outputBy | How to output the stories (values: 'kind') | string | null |
111+
| Parameter | Explanation | Input Type | Default |
112+
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------- | ----------------------------------------------------------------------------------- |
113+
| output | Specifies the filename for the generated asketch.json file or a folder when outputBy === 'kind'. | string | `"dist/stories.asketch.json"` |
114+
| input | The location of Storybook's generated iframe.html. Use this over `url` if possible for performance. | string | `"dist/iframe.html"` |
115+
| url | Storybook iframe URL. Will end in `iframe.html`. Prefer `input` for performance if possible. | string | `"http://localhost:9001/iframe.html"` |
116+
| stories | Stories to extract from Storybook. You should probably override the default. | object/string | `"all"` |
117+
| concurrency | Number of headless Chrome tabs to run in parallel. Drastically impacts performance. | integer | `4` |
118+
| symbolGutter | Gutter to place between symbols in Sketch. | integer | `100` |
119+
| viewports | Viewport configuration. Will be arranged left-to-right by width. Try to avoid changing the key, as this is used to identify the symbol. | object | Mobile viewport (320px wide) and desktop viewport (1920px wide). See example below. |
120+
| querySelector | Query selector to select your node on each page. Uses `document.querySelectorAll`. | string | `"#root"` |
121+
| verbose | Verbose logging output. | boolean | `false` |
122+
| fixPseudo | Attempt to insert real elements in place of pseudo-elements | boolean | `false` |
123+
| puppeteerOptions | Options to be passed directly to `puppeteer.launch`. See [puppeteer docs](https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#puppeteerlaunchoptions) for usage. | object | `{}` |
124+
| removePreviewMargin | Remove preview margin from the iframe body. | boolean | `true` |
125+
| layoutBy | Group symboles in the sketch output by the "kind" or "group" key | "kind" \| "group" | null |
126+
| outputBy | Write multiple sketch files by "kind" or the "group" key | "kind" \| "group" | null |
127127

128128
### Example story2sketch.config.js
129129

130130
```js
131131
module.exports = {
132132
output: "dist/great-ui.asketch.json",
133133
input: "dist/iframe.html",
134+
layoutBy: "group",
134135
concurrency: 2,
135136
symbolGutter: 200,
136137
viewports: {
@@ -148,6 +149,7 @@ module.exports = {
148149
pageTitle: "great-ui",
149150
stories: [
150151
{
152+
group: "Buttons",
151153
kind: "Buttons/Button",
152154
stories: [
153155
{
@@ -156,6 +158,7 @@ module.exports = {
156158
]
157159
},
158160
{
161+
group: "Buttons",
159162
kind: "Buttons/ButtonGroup",
160163
stories: [
161164
{
@@ -168,6 +171,7 @@ module.exports = {
168171
]
169172
},
170173
{
174+
group: "Data",
171175
kind: "Table",
172176
stories: [
173177
{

src/server/Story2sketch.js

Lines changed: 41 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ export default class Story2sketch {
6767

6868
reset() {
6969
this.symbolsByViewport = {};
70-
this.symbolsByKind = {};
70+
this.symbolsByGrouping = {};
7171
this.widestByViewport = {};
7272
this.tallestByStory = {};
7373
this.processedStories = 0;
@@ -136,16 +136,36 @@ export default class Story2sketch {
136136
return sketchPage;
137137
}
138138

139+
getGrouping({ group, kind }) {
140+
let grouping = "all";
141+
142+
if (this.outputBy === "kind") {
143+
grouping = kind;
144+
} else if (this.outputBy === "group") {
145+
grouping = group;
146+
}
147+
148+
if (this.layoutBy === "kind") {
149+
grouping = kind;
150+
} else if (this.layoutBy === "group") {
151+
grouping = group;
152+
}
153+
154+
return grouping;
155+
}
156+
139157
async createPagePool() {
140158
const pagePool = new PagePool(this.browser, this.concurrency);
141159

142160
await pagePool.init();
143161

144-
for (const { kind, stories } of this.stories) {
145-
this.symbolsByKind[kind] = {};
162+
for (const { group, kind, stories } of this.stories) {
163+
const grouping = this.getGrouping({ group, kind });
164+
165+
this.symbolsByGrouping[grouping] = {};
146166

147167
for (const { id } of this.sortedViewports) {
148-
this.symbolsByKind[kind][id] = Array(stories.length);
168+
this.symbolsByGrouping[grouping][id] = Array(stories.length);
149169
}
150170

151171
for (const story of stories) {
@@ -174,7 +194,7 @@ export default class Story2sketch {
174194

175195
// Assign by index to retain the order of the symbols
176196
this.symbolsByViewport[viewportKey][storyIndex] = symbol;
177-
this.symbolsByKind[kind][viewportKey][storyIndex] = symbol;
197+
this.symbolsByGrouping[grouping][viewportKey][storyIndex] = symbol;
178198
}
179199

180200
this.tallestByStory[storyIndex] = tallest;
@@ -297,15 +317,17 @@ export default class Story2sketch {
297317
];
298318
}
299319

300-
positionSymbolsByKind() {
320+
positionSymbolsByGrouping() {
301321
const width = this.sortedViewports.reduce(
302322
(totalWidth, viewport) =>
303323
totalWidth + this.widestByViewport[viewport.id] + this.symbolGutter,
304324
0
305325
);
306326

307-
for (const [index, kind] of Object.keys(this.symbolsByKind).entries()) {
308-
const symbolsByViewport = this.symbolsByKind[kind];
327+
for (const [index, grouping] of Object.keys(
328+
this.symbolsByGrouping
329+
).entries()) {
330+
const symbolsByViewport = this.symbolsByGrouping[grouping];
309331

310332
this.sketchPage.layers = [
311333
...this.sketchPage.layers,
@@ -314,15 +336,15 @@ export default class Story2sketch {
314336
}
315337
}
316338

317-
writeByKind() {
339+
writeByGrouping() {
318340
mkdirp(this.output);
319341

320-
for (const kind of Object.keys(this.symbolsByKind)) {
342+
for (const grouping of Object.keys(this.symbolsByGrouping)) {
321343
const sketchPage = {
322344
...this.sketchPage,
323-
layers: this.positionSymbols(this.symbolsByKind[kind])
345+
layers: this.positionSymbols(this.symbolsByGrouping[grouping])
324346
};
325-
const filename = `${kind
347+
const filename = `${grouping
326348
.replace(" ", "_")
327349
.replace("/", "+")}.asketch.json`;
328350

@@ -334,9 +356,9 @@ export default class Story2sketch {
334356

335357
console.log(
336358
chalk.green(
337-
`Success! ${
338-
this.processedStories
339-
} stories written by kind to ${chalk.white.bold(this.output)}`
359+
`Success! ${this.processedStories} stories written by ${
360+
this.outputBy
361+
} to ${chalk.white.bold(this.output)}`
340362
)
341363
);
342364
}
@@ -357,11 +379,11 @@ export default class Story2sketch {
357379
}
358380
});
359381

360-
if (this.outputBy === "kind") {
361-
this.writeByKind();
382+
if (this.outputBy) {
383+
this.writeByGrouping();
362384
} else {
363-
if (this.layoutBy === "kind") {
364-
this.positionSymbolsByKind();
385+
if (this.layoutBy) {
386+
this.positionSymbolsByGrouping();
365387
} else {
366388
this.positionSymbolsByViewport();
367389
}

0 commit comments

Comments
 (0)