import playwright from "playwright-core";
import path from "node:path";
import { existsSync } from "node:fs";
import config from "../../../utils/config.js";
const formats = [
"JPG",
"PNG",
"WEBP",
];
const DEBUG = false;
export class Exporter {
constructor(filepath) {
this.filepath = filepath;
this.filename = path.basename(filepath);
this.extname = path.extname(this.filename);
this.basename = path.basename(this.filename, this.extname);
}
async process(options) {
if (formats.indexOf(options.format) == -1) {
throw new Error(`invalid format ${options.format}`);
}
if (options.width && typeof options.width !== "number") {
throw new Error(`invalid width ${options.width}`);
}
if (options.height && typeof options.height !== "number") {
throw new Error(`invalid height ${options.height}`);
}
if ((options.dpi != undefined) && (typeof options.dpi !== "number")) {
throw new Error(`invalid dpi ${options.dpi}`);
}
if (typeof options.quality !== "number") {
throw new Error(`invalid quality ${options.quality}`);
}
if (typeof options.metadata !== "boolean") {
throw new Error(`invalid metadata ${options.metadata}`);
}
const headless = DEBUG ? false : true;
const browser = await playwright.chromium.launch({
headless,
timeout: 0,
});
const page = await browser.newPage();
await page.goto("https://www.photopea.com");
await page.evaluate(() => addPP());
const upload = await page.locator("input[type=file]");
upload.setInputFiles(this.filepath);
await page.waitForSelector("button:has-text('File')");
const file = await page.locator("button:has-text('File')");
while (true) {
await file.click();
try {
await page.waitForSelector("div.enab > span:has-text('Export as')", {
timeout: 100,
});
const exportAs = await page.locator("div.enab > span:has-text('Export as')");
await exportAs.click();
break;
} catch (e) {
console.log(`failed to find export button, retrying`);
await file.click();
}
}
await page.waitForSelector(`div.enab > span:has-text('${options.format}')`);
const fileType = await page.locator("div.enab > span", { hasText: new RegExp(`^${options.format}$`) });
await fileType.click();
const settings = {};
await page.waitForSelector("div.form.cell");
await page.waitForSelector("button:has-text('Save')");
settings.name = await page.locator("div.form.cell * label:has-text('Name') + input");
settings.width = await page.locator("div.form.cell * label:has-text('Width') + input");
settings.height = await page.locator("div.form.cell * label:has-text('Height') + input");
if (options.dpi !== undefined) {
settings.dpi = await page.locator("div.form.cell * label:has-text('DPI') + input");
}
settings.quality = await page.locator("div.form.cell * label:has-text('Quality:') + input");
settings.aspectRatio = await page.locator("div.form.cell * [title='Keep Aspect Ratio']");
settings.save = await page.locator("button:has-text('Save')");
await settings.aspectRatio.click();
await settings.name.clear();
await settings.name.fill(this.basename);
await settings.width.clear();
await settings.width.fill(`${options.width}`);
await settings.height.clear();
await settings.height.fill(`${options.height}`);
if (options.dpi !== undefined) {
await settings.dpi.clear();
await settings.dpi.fill(`${options.dpi}`);
}
await settings.quality.clear();
await settings.quality.fill(`${options.quality}`);
await settings.save.focus();
const waitForDownload = page.waitForEvent('download');
await settings.save.click();
const download = await waitForDownload;
let downloadPath = options.overridePath ? options.overridePath : `test.${options.format.toLowerCase()}`;
if (!path.isAbsolute(downloadPath)) {
downloadPath = path.join(config.cwd, downloadPath);
}
await download.saveAs(downloadPath);
if (!DEBUG) {
await browser.close();
console.log(`done with ${this.filename}`);
}
}
}
export async function importPSD(filepath) {
if (typeof filepath !== "string") {
throw new Error(`invalid filepath ${filepath}`);
}
if (!path.isAbsolute(filepath)) {
filepath = path.join(config.cwd, filepath);
}
if (!existsSync(filepath)) {
throw new Error(`file ${filepath} does not exist`);
}
return new Exporter(filepath);
}