Skip to content

Commit

Permalink
Merge pull request #93 from KasimAhmic/improve_take_screenshots
Browse files Browse the repository at this point in the history
Add new takeScreenshots.js file
  • Loading branch information
chriscoyier authored Jan 18, 2021
2 parents 04c5263 + 9dbce46 commit b779914
Show file tree
Hide file tree
Showing 4 changed files with 195 additions and 11 deletions.
39 changes: 34 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,22 +20,51 @@ https://coding-fonts.css-tricks.com/

Then make a Pull Request for it. You should be able to see a built preview on Netlify as part of the PR.

## Commands
## NPM Commands

Take all screenshots for one font:

```
```bash
FONT='font-name' npm run screenshots
```

Take all screenshots:

```
```bash
npm run screenshots:all
```

Take all screenshots for one language:
Take specific language screenshots

```bash
FONT='font-name' npm run screenshots:js
FONT='font-name' npm run screenshots:html
FONT='font-name' npm run screenshots:css
FONT='font-name' npm run screenshots:charmap
```

## Taking Screenshots Using takeScreenshots.js

You can take control of the screenshots

takeScreenshots accepts the follow arguments:
```
Options:
--version Show version number
-f, --font Font to use for screenshots
-l, --lang Code sample to use for screenshot
-t, --theme Theme to use for screenshots
--parallel Run the screenshots in parallel
-h, --help Show help
```

`--font`, `--lang`, and `--theme` all accept the 'all' keyword to handle taking screenshots of all of their respective data points.

The `--parallel` flag allows the running of Puppeteer in parallel which is useful if you need to repeatedly take screenshots of a font. Do note that this will spawn as many Puppeteer instances as you have the total permutations you request.
Take the following command for example.

```
node take_screenshots.js --all-for-lang="html"
node takeScreenshots.js -f source-code-pro -l all -t all
```

It will spawn 8 Puppeteer instances (1 font * 4 languages * 2 themes = 8 instances) all at once to take the screenshots. This is usually fine and doesn't result in any issues but in the event you were to do this for all fonts as well, you'd spawn hundreds of instances which will almost always in a failure.
10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@
"dev": "ELEVENTY_ENV=development eleventy --serve & npm run sass:watch",
"sass:watch": "sass --watch src/assets/styles/sass/style.scss:src/assets/styles/style.css",
"screenshots": "npm run screenshots:js && npm run screenshots:html && npm run screenshots:css && npm run screenshots:charmap",
"screenshots:js": "node take_screenshots.js --lang js --theme light --font \"$FONT\" && node take_screenshots.js --lang js --theme dark --font \"$FONT\"",
"screenshots:html": "node take_screenshots.js --lang html --theme light --font \"$FONT\" && node take_screenshots.js --lang html --theme dark --font \"$FONT\"",
"screenshots:css": "node take_screenshots.js --lang css --theme light --font \"$FONT\" && node take_screenshots.js --lang css --theme dark --font \"$FONT\"",
"screenshots:charmap": "node take_screenshots.js --lang charmap --theme light --font \"$FONT\" && node take_screenshots.js --lang charmap --theme dark --font \"$FONT\"",
"screenshots:all": "node take_screenshots.js --all true"
"screenshots:js": "node takeScreenshots.js --lang js --theme all --font \"$FONT\"",
"screenshots:html": "node takeScreenshots.js --lang html --theme all --font \"$FONT\"",
"screenshots:css": "node takeScreenshots.js --lang css --theme all --font \"$FONT\"",
"screenshots:charmap": "node takeScreenshots.js --lang charmap --theme all --font \"$FONT\"",
"screenshots:all": "node takeScreenshots.js --font all --lang all --theme all"
},
"repository": {
"type": "git",
Expand Down
4 changes: 3 additions & 1 deletion src/assets/scripts/font-sample-loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,6 @@ if (fontInfo) {
});
document.body.style.fontFamily = fontInfo.title;
pre.style.fontFamily = fontInfo.title;
}
} else {
console.warn(`${font} does not appear to be a valid font. Please check the font name.`);
}
153 changes: 153 additions & 0 deletions takeScreenshots.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
const samples = require('./src/_data/samples.json');
const puppeteer = require('puppeteer');
const { exit } = require('process');
const yargs = require('yargs');
const fs = require('fs');

const args = yargs(process.argv.slice(2))
.usage('Usage: $0 [options]')

.describe('f', 'Font to use for screenshots')
.alias('f', 'font')

.describe('l', 'Code sample to use for screenshot')
.alias('l', 'lang')

.describe('t', 'Theme to use for screenshots')
.alias('t', 'theme')

.describe('parallel', 'Run the screenshots in parallel\n ~ Be careful when running too many screenshots at once.')

.help('h')
.alias('h', 'help')

.example('node $0 -f source-code-pro -l js -t dark', 'Take a screenshot of the Source Code Pro font, using the JavaScript code sample, and the dark theme.\n')
.example('node $0 -f menlo -l all -t light', 'Take a screenshot of the Menlo font, using all of the code samples, and the light theme.\n')
.example('node $0 -f all -l all -t all', 'Take a screenshot of all of the fonts, using all of the code samples, and all of the themes.\n')
.example('node $0 -f input -l all -t all --parallel', 'Take a screenshot of the Input font, using all of the code samples, all of the themes, and do so in parallel.')

.demandOption(['lang', 'font', 'theme'])

.wrap(115)
.epilog('Developed for Coding Fonts (https://coding-fonts.css-tricks.com/)')
.argv;

const buildFontDirectories = (fonts) => {
fonts.forEach((font) => {
const directory = `src/screenshots/${font}`;

if (!fs.existsSync(directory)) {
console.log(`${directory} does not exist. Making directory...`);
fs.mkdirSync(directory);
}
});
};

const takeScreenshots = async (font, lang, theme) => {
console.log(`Taking screenshot for:`);
console.log(` => Font:\t${font}`);
console.log(` => Language:\t${lang}`);
console.log(` => Theme:\t${theme}`);

const browser = await puppeteer.launch({
args: ['--no-sandbox', '--disable-setuid-sandbox']
});

const page = await browser.newPage();

await page.setViewport({
width: 800,
height: 600,
deviceScaleFactor: 2
});

page.on('console', msg => console.warn('Browser Log:', msg.text()));

await page.goto(
`http://localhost:8080/code_samples/${lang}?font=${font}&theme=${theme}`,
{
waitUntil: 'networkidle0',
timeout: 100000
}
);

await page.screenshot({
path: `src/screenshots/${font}/${lang}-${theme}.png`
});

await browser.close();
};

const parseInputs = (fonts, langs, themes) => {
fonts = fonts === 'all'
? fs.readdirSync('./src/fonts')
.filter((file) => file.endsWith('.md'))
.map((file) => file.replace('.md', '').toLocaleLowerCase())
: [fonts.toLocaleLowerCase()]

langs = langs === 'all'
? samples.languages.map(lang => lang.value)
: [langs];

themes = themes === 'all'
? samples.themes
: [themes];

return [fonts, langs, themes];
};

const run = async (fonts, langs, themes, parallel) => {
console.log(`Running in ${parallel ? 'parallel' : 'serial'} mode`);
console.log(`Taking ${fonts.length * langs.length * themes.length} screenshots\n`);

const asyncForEach = async (array, callback) => {
for (let i = 0; i < array.length; i++) {
await callback(array[i], i, array);
}
};

if (parallel) {
fonts.forEach(async (font) => {
langs.forEach(async (lang) => {
themes.forEach(async (theme) => {
try {
await takeScreenshots(font, lang, theme);
} catch (e) {
console.error('\nAn error occurred. Please review the stack trace below and report the issue if necessary.\n');
console.error(e);
exit();
}
});
});
});
} else {
await asyncForEach(fonts, async (font) => {
await asyncForEach(langs, async (lang) => {
await asyncForEach(themes, async (theme) => {
try {
await takeScreenshots(font, lang, theme);
} catch (e) {
console.error('\nAn error occurred. Please review the stack trace below and report the issue if necessary.\n');
console.error(e);
exit();
}
});
});
});
}
}

const main = async () => {
let fonts = args.font;
let langs = args.lang;
let themes = args.theme;
let parallel = args.parallel;

[fonts, langs, themes] = parseInputs(fonts, langs, themes);

buildFontDirectories(fonts);

run(fonts, langs, themes, parallel);
};

main();

0 comments on commit b779914

Please sign in to comment.