73 lines
3.6 KiB
JavaScript
73 lines
3.6 KiB
JavaScript
'use strict';
|
|
// Runs the real Ink app against a seeded demo vault and saves 16:10 screenshots.
|
|
// electron scripts/capture/capture.cjs --ozone-platform=headless --force-device-scale-factor=1.5
|
|
// Env: INK_APP (path to the Ink repo, read only), OUT (output dir), THEMES (comma list), SCENES (comma list)
|
|
const { app, BrowserWindow } = require('electron');
|
|
const path = require('node:path');
|
|
const os = require('node:os');
|
|
const fs = require('node:fs');
|
|
|
|
const INK = process.env.INK_APP || path.resolve(__dirname, '../../../../App/Ink');
|
|
const OUT = process.env.OUT || path.resolve(__dirname, '../../src/assets/screens');
|
|
const THEMES = (process.env.THEMES || 'dark,light').split(',');
|
|
const ONLY = process.env.SCENES ? process.env.SCENES.split(',') : null;
|
|
const { seedVault } = require('./seed-vault.cjs');
|
|
const scenes = require('./scenes.cjs');
|
|
|
|
const W = 1600, H = 1000;
|
|
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
const theme = process.env.THEME || THEMES[0];
|
|
|
|
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'ink-shots-'));
|
|
const vault = path.join(tmp, 'Notes');
|
|
fs.mkdirSync(vault);
|
|
const seeded = seedVault(vault);
|
|
|
|
// No network: a link card gets a fixed title and description instead of fetching.
|
|
const linkpreview = require(path.join(INK, 'electron/linkpreview.cjs'));
|
|
linkpreview.hooks.lookup = async () => [{ address: '93.184.216.34' }];
|
|
linkpreview.hooks.fetch = async () => new Response(
|
|
'<html><head><title>JSON Canvas</title><meta property="og:title" content="JSON Canvas"><meta name="description" content="An open file format for infinite canvas data.">' +
|
|
'</head><body></body></html>', { status: 200, headers: { 'content-type': 'text/html' } });
|
|
|
|
app.setPath('userData', tmp);
|
|
fs.writeFileSync(path.join(tmp, 'settings.json'), JSON.stringify({
|
|
vault, lastPage: seeded.lastPage, theme, bounds: { width: W, height: H },
|
|
fontSize: 16, outline: false, sidebarCollapsed: false, tagsOpen: true,
|
|
vaults: { [vault]: seeded.vaultSettings },
|
|
}));
|
|
app.commandLine.appendSwitch('lang', 'en-US');
|
|
require(path.join(INK, 'electron/main.cjs'));
|
|
|
|
app.whenReady().then(async () => {
|
|
let win;
|
|
for (let i = 0; i < 100 && !(win = BrowserWindow.getAllWindows()[0]); i++) await sleep(100);
|
|
win.setContentSize(W, H);
|
|
const wc = win.webContents;
|
|
if (wc.isLoading()) await new Promise((r) => wc.once('did-finish-load', r));
|
|
const js = (code) => wc.executeJavaScript(`(async () => { ${code} })()`);
|
|
const key = async (keyCode, modifiers = []) => { wc.sendInputEvent({ type: 'keyDown', keyCode, modifiers }); wc.sendInputEvent({ type: 'keyUp', keyCode, modifiers }); await sleep(250); };
|
|
const type = async (t, d = 45) => { for (const ch of t) { wc.sendInputEvent({ type: 'char', keyCode: ch }); await sleep(d); } await sleep(200); };
|
|
const click = async (x, y) => { wc.sendInputEvent({ type: 'mouseMove', x, y }); wc.sendInputEvent({ type: 'mouseDown', x, y, button: 'left', clickCount: 1 }); wc.sendInputEvent({ type: 'mouseUp', x, y, button: 'left', clickCount: 1 }); await sleep(250); };
|
|
const shot = async (name) => {
|
|
await sleep(500);
|
|
const img = await wc.capturePage();
|
|
const file = path.join(OUT, `${name}-${theme}.png`);
|
|
fs.mkdirSync(OUT, { recursive: true });
|
|
fs.writeFileSync(file, img.toPNG());
|
|
const s = img.getSize();
|
|
console.log(`saved ${path.basename(file)} ${s.width}x${s.height}`);
|
|
};
|
|
const ctx = { win, wc, js, key, type, click, shot, sleep, vault, W, H };
|
|
|
|
try {
|
|
await sleep(2200);
|
|
for (const [name, fn] of Object.entries(scenes)) {
|
|
if (ONLY && !ONLY.includes(name)) continue;
|
|
try { await fn(ctx); } catch (e) { console.log(`FAILED ${name}: ${e.message}`); }
|
|
}
|
|
} finally {
|
|
app.exit(0);
|
|
}
|
|
});
|