Skip to content

Commit 1b0c4ef

Browse files
authored
add CLI for saving image preview of layout (#1)
Adds an `ergodox-screenshot-layout` CLI for saving an image preview of a keyboard layout. The tool uses [puppeteer][] to visit the [Ergodox Configurator tool][configurator], import your keyboard layout specified by path, and save a screenshot. Example usage: `ergodox-screenshot-layout -f MDErgo1-Default.json` will save a preview of the layout to `screenshot.png`. The path to the keyboard layout file is specified with the `-f` option. The path to save the screenshot to can be specified with the `-d` option. The CLI also supports the `--headless` flag which can be set to false to configure puppeteer to not run chrome in headless mode (for debugging). [puppeteer]: https://github.com/GoogleChrome/puppeteer [configurator]: https://input.club/configurator-ergodox/
1 parent 597f823 commit 1b0c4ef

18 files changed

+665
-2
lines changed

.github/screenshot.png

76.1 KB
Loading

README.md

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,17 @@
1-
# ergodox layout
1+
# ergodox-layout
22

3-
the layout I use for my ergodox keyboard
3+
The layout I use for my [ergodox keyboard][].
4+
5+
[ergodox keyboard]: https://input.club/devices/infinity-ergodox/
6+
7+
## Preview
8+
9+
![](.github/screenshot.png)
10+
11+
## Project Structure
12+
13+
- `layout` - the layout files
14+
- `ergodox-screenshot-layout` - tool for getting an image preview of an ergodox layouts from the [ergodox configurator tool][configurator]
15+
16+
[configurator]: https://input.club/configurator-ergodox/
417

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
node_modules
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# ergdox-screenshot-layout
2+
3+
Save a screenshot of your ergodox layout.
4+
5+
Uses headless chrome to visit the Ergodox Configurator, import your keyboard layout JSON file, and screenshot the keyboard layout preview.
6+
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#! /usr/bin/env node
2+
3+
require("../index.js");

ergodox-screenshot-layout/index.js

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
const path = require("path");
2+
const fs = require("fs-extra");
3+
const puppeteer = require("puppeteer");
4+
const yargs = require("yargs");
5+
6+
const pkg = require("./package.json");
7+
8+
const argv = yargs.command(
9+
"$0",
10+
pkg.description,
11+
yargs => {
12+
return yargs.options({
13+
f: {
14+
alias: ["file", "layout"],
15+
demandOption: true,
16+
describe: "file path to a keyboard layout JSON file",
17+
string: true
18+
},
19+
d: {
20+
alias: ["dest", "screenshot"],
21+
describe: "file path to save the screenshot to",
22+
string: true,
23+
default: "screenshot.png"
24+
},
25+
headless: {
26+
describe: "run chromium in headless mode",
27+
boolean: true,
28+
default: true
29+
}
30+
});
31+
},
32+
argv => {
33+
return getKeyboardLayoutScreenshot(argv.file, argv.dest, argv.headless);
34+
}
35+
).argv;
36+
37+
async function importLayout(page, layoutJson) {
38+
console.log("Clicking import button");
39+
await page.waitFor("button#import-map");
40+
const importButton = await page.$("button#import-map");
41+
await importButton.click();
42+
43+
console.log("Waiting for popup");
44+
await page.waitFor(".popup textarea", { visisble: true });
45+
let popup = await page.$(".popup");
46+
47+
console.log("Injecting layout");
48+
const layoutTextArea = await page.$(".popup textarea");
49+
await page.evaluate(
50+
(textarea, layoutJson) => {
51+
textarea.value = JSON.stringify(layoutJson, null, 2);
52+
return Promise.resolve(textarea.value);
53+
},
54+
layoutTextArea,
55+
layoutJson
56+
);
57+
58+
console.log("Waiting");
59+
await page.waitFor(500);
60+
61+
console.log("Clicking submit");
62+
const submit = await page.$(".popup button.button-read");
63+
await submit.click();
64+
65+
console.log("Waiting for popup to disappear");
66+
return await page.waitFor(500);
67+
}
68+
69+
async function saveScreenshot(page, filename) {
70+
console.log("Waiting for layout preview to appear");
71+
await Promise.all([page.waitFor("#stage"), page.waitFor("#stage .key")]);
72+
const container = await page.$("#container");
73+
74+
console.log("Say cheese");
75+
return await container.screenshot({ path: filename });
76+
}
77+
78+
async function getKeyboardLayoutScreenshot(
79+
pathToLayoutJson,
80+
screenshotFilename,
81+
headless
82+
) {
83+
const layoutJson = await fs.readJson(path.resolve(pathToLayoutJson));
84+
const browser = await puppeteer.launch({
85+
headless,
86+
args: ["--disable-setuid-sandbox", "--no-sandbox"]
87+
});
88+
89+
const page = await browser.newPage();
90+
await page.goto("https://configurator.inputclub.com/?layout=MDErgo1-Default");
91+
92+
await page.waitFor(".container");
93+
await importLayout(page, layoutJson);
94+
await saveScreenshot(page, screenshotFilename);
95+
96+
console.log("Done");
97+
await browser.close();
98+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"name": "ergodox-screenshot-layout",
3+
"version": "1.0.0",
4+
"description": "save a screenshot of your ergodox layout",
5+
"main": "index.js",
6+
"author": "Ali Ukani <ali.ukani@gmail.com>",
7+
"license": "MIT",
8+
"private": true,
9+
"bin": "./bin/ergodox-screenshot-layout",
10+
"engines": {
11+
"node": ">= 8.5.0"
12+
},
13+
"dependencies": {
14+
"fs-extra": "^4.0.2",
15+
"puppeteer": "^0.12.0",
16+
"yargs": "^10.0.3"
17+
}
18+
}
76.1 KB
Loading

0 commit comments

Comments
 (0)