Skip to content

Commit 6290cae

Browse files
hipstersmoothiechrisvxd
authored andcommitted
feat: add support for outputting multiple files by kind, or laying out stories by kind
1 parent e09d6ce commit 6290cae

File tree

4 files changed

+93
-17
lines changed

4 files changed

+93
-17
lines changed

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ module.exports = {
110110

111111
| Parameter | Explanation | Input Type | Default |
112112
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------- | ----------------------------------------------------------------------------------- |
113-
| output | Specifies the filename for the generated asketch.json file. | string | `"dist/stories.asketch.json"` |
113+
| output | Specifies the filename for the generated asketch.json file or a folder when outputBy === 'kind'. | string | `"dist/stories.asketch.json"` |
114114
| input | The location of Storybook's generated iframe.html. Use this over `url` if possible for performance. | string | `"dist/iframe.html"` |
115115
| url | Storybook iframe URL. Will end in `iframe.html`. Prefer `input` for performance if possible. | string | `"http://localhost:9001/iframe.html"` |
116116
| stories | Stories to extract from Storybook. You should probably override the default. | object/string | `"all"` |
@@ -122,6 +122,8 @@ module.exports = {
122122
| fixPseudo | Attempt to insert real elements in place of pseudo-elements | boolean | `false` |
123123
| 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 | `{}` |
124124
| 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 |
125127

126128
### Example story2sketch.config.js
127129

@@ -188,7 +190,6 @@ module.exports = {
188190
},
189191
...
190192
};
191-
192193
```
193194

194195
<a name="questions"><a/>

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
"chalk": "^2.3.0",
5555
"cosmiconfig": "^4.0.0",
5656
"find-up": "^2.1.0",
57+
"mkdirp": "^0.5.1",
5758
"mock-require": "^3.0.1",
5859
"progress": "^2.0.0",
5960
"puppeteer": "^1.0.0",

src/server/Story2sketch.js

Lines changed: 83 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
import puppeteer from "puppeteer";
44
import fs from "fs";
5+
import path from "path";
6+
import mkdirp from "mkdirp";
57
import chalk from "chalk";
68
import ProgressBar from "progress";
79

@@ -35,7 +37,9 @@ export default class Story2sketch {
3537
fixPseudo = false,
3638
stories,
3739
puppeteerOptions = {},
38-
removePreviewMargin = true
40+
removePreviewMargin = true,
41+
layoutBy = null,
42+
outputBy = null
3943
}) {
4044
this.output = output;
4145
this.url = url;
@@ -47,6 +51,8 @@ export default class Story2sketch {
4751
this.stories = stories;
4852
this.verbose = verbose;
4953
this.fixPseudo = fixPseudo;
54+
this.layoutBy = layoutBy;
55+
this.outputBy = outputBy;
5056
this.removePreviewMargin = removePreviewMargin === true;
5157
this.puppeteerOptions = puppeteerOptions;
5258

@@ -61,6 +67,7 @@ export default class Story2sketch {
6167

6268
reset() {
6369
this.symbolsByViewport = {};
70+
this.symbolsByKind = {};
6471
this.widestByViewport = {};
6572
this.tallestByStory = {};
6673
this.processedStories = 0;
@@ -135,6 +142,12 @@ export default class Story2sketch {
135142
await pagePool.init();
136143

137144
for (const { kind, stories } of this.stories) {
145+
this.symbolsByKind[kind] = {};
146+
147+
for (const { id } of this.sortedViewports) {
148+
this.symbolsByKind[kind][id] = Array(stories.length);
149+
}
150+
138151
for (const story of stories) {
139152
const storyIndex = this.storyCount;
140153

@@ -161,6 +174,7 @@ export default class Story2sketch {
161174

162175
// Assign by index to retain the order of the symbols
163176
this.symbolsByViewport[viewportKey][storyIndex] = symbol;
177+
this.symbolsByKind[kind][viewportKey][storyIndex] = symbol;
164178
}
165179

166180
this.tallestByStory[storyIndex] = tallest;
@@ -251,26 +265,80 @@ export default class Story2sketch {
251265
}
252266
}
253267

254-
positionSymbols() {
255-
let xOffset = 0;
268+
positionSymbols(symbolsByViewport, xOffsetStart = 0) {
269+
let layers = [];
270+
let xOffset = xOffsetStart;
256271

257272
for (const { id } of this.sortedViewports) {
258273
let yOffset = 0;
259274

260-
const symbols = this.symbolsByViewport[id];
275+
const symbols = symbolsByViewport[id];
261276

262277
for (const [index, symbol] of symbols.entries()) {
263278
// Skip failed symbols
264279
if (symbol) {
265280
symbol.frame.x = xOffset;
266281
symbol.frame.y = yOffset;
267-
this.sketchPage.layers.push(symbol);
282+
layers.push(symbol);
268283
yOffset += this.tallestByStory[index] + this.symbolGutter;
269284
}
270285
}
271286

272287
xOffset += this.widestByViewport[id] + this.symbolGutter;
273288
}
289+
290+
return layers;
291+
}
292+
293+
positionSymbolsByViewport() {
294+
this.sketchPage.layers = [
295+
...this.sketchPage.layers,
296+
...this.positionSymbols(this.symbolsByViewport)
297+
];
298+
}
299+
300+
positionSymbolsByKind() {
301+
const width = this.sortedViewports.reduce(
302+
(totalWidth, viewport) =>
303+
totalWidth + this.widestByViewport[viewport.id] + this.symbolGutter,
304+
0
305+
);
306+
307+
for (const [index, kind] of Object.keys(this.symbolsByKind).entries()) {
308+
const symbolsByViewport = this.symbolsByKind[kind];
309+
310+
this.sketchPage.layers = [
311+
...this.sketchPage.layers,
312+
...this.positionSymbols(symbolsByViewport, width * index)
313+
];
314+
}
315+
}
316+
317+
writeByKind() {
318+
mkdirp(this.output);
319+
320+
for (const kind of Object.keys(this.symbolsByKind)) {
321+
const sketchPage = {
322+
...this.sketchPage,
323+
layers: this.positionSymbols(this.symbolsByKind[kind])
324+
};
325+
const filename = `${kind
326+
.replace(" ", "_")
327+
.replace("/", "+")}.asketch.json`;
328+
329+
fs.writeFileSync(
330+
path.join(this.output, filename),
331+
JSON.stringify(sketchPage)
332+
);
333+
}
334+
335+
console.log(
336+
chalk.green(
337+
`Success! ${
338+
this.processedStories
339+
} stories written by kind to ${chalk.white.bold(this.output)}`
340+
)
341+
);
274342
}
275343

276344
async execute() {
@@ -289,9 +357,17 @@ export default class Story2sketch {
289357
}
290358
});
291359

292-
this.positionSymbols();
360+
if (this.outputBy === "kind") {
361+
this.writeByKind();
362+
} else {
363+
if (this.layoutBy === "kind") {
364+
this.positionSymbolsByKind();
365+
} else {
366+
this.positionSymbolsByViewport();
367+
}
293368

294-
fs.writeFileSync(this.output, JSON.stringify(this.sketchPage));
369+
fs.writeFileSync(this.output, JSON.stringify(this.sketchPage));
370+
}
295371

296372
console.log(
297373
chalk.green(

src/server/index.js

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,15 @@ import path from "path";
1010
import chalk from "chalk";
1111
import logoAscii from "./logoAscii";
1212

13+
// Ensure paths are absolute, not relative
14+
const absolute = p => (p && p[0] !== "/" ? path.join(process.cwd(), p) : p);
15+
1316
const tidyConfig = config => {
1417
const newConfig = { ...config };
1518

16-
// Ensure paths are absolute, not relative
17-
if (newConfig.output && newConfig.output[0] !== "/") {
18-
newConfig.output = path.join(process.cwd(), newConfig.output);
19-
}
20-
21-
if (newConfig.input && newConfig.input[0] !== "/") {
22-
newConfig.input = path.join(process.cwd(), newConfig.input);
23-
}
19+
newConfig.input = absolute(newConfig.input);
20+
newConfig.output = absolute(newConfig.output);
21+
newConfig.outputBy = absolute(newConfig.outputBy);
2422

2523
// Convert input file to URL if defined
2624
if (newConfig.input) {

0 commit comments

Comments
 (0)