-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1 from yikuansun/dev
Use webpack
- Loading branch information
Showing
9 changed files
with
312 additions
and
54 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -74,3 +74,5 @@ typings/ | |
|
||
# FuseBox cache | ||
.fusebox/ | ||
|
||
package-lock.json |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,58 @@ | ||
# photopea.js | ||
A JS-based wrapper for the [Photopea API](https://www.photopea.com/api/). | ||
|
||
## [Documentation](https://github.com/yikuansun/photopeaapi/wiki) | ||
## Installation | ||
The easiest way to install photopea.js is through a CDN. | ||
``` | ||
haven't set it up yet... come back later. | ||
``` | ||
You can also download [`photopea.min.js`](./dist/photopea.min.js) and host it yourself: | ||
``` | ||
<script src="./photopea.min.js"></script> | ||
``` | ||
If you're using a Node framework, like Webpack, Rollup, or Vite, simply install with npm: | ||
``` | ||
npm install photopea | ||
``` | ||
You can then import the module in your code: | ||
``` | ||
import Photopea from "photopea"; | ||
``` | ||
|
||
## Usage | ||
`Photopea` is a class with methods that can interact with any instance of Photopea. | ||
### Constructors | ||
For plugins, use window.parent as the Photopea content window: | ||
``` | ||
let pea = new Photopea(window.parent); | ||
``` | ||
To create a new Photopea embed, use `Photopea.createEmbed`: | ||
``` | ||
Photopea.createEmbed(container).then(async (pea) => { | ||
// photopea initialized | ||
// pea is the new Photopea object | ||
// you can also use async/await: | ||
/* | ||
let pea = await Photopea.createEmbed(container); | ||
*/ | ||
}); | ||
``` | ||
`container` is the parent DOM element and should be a `div` with a set width and height. | ||
### Methods | ||
These are methods for objects of the Photopea class, created with the constructors above. These are all Promises, so be sure to use `.then()` or `await`. | ||
#### `async runScript(script)` | ||
- `script` (string): the [script](https://www.photopea.com/learn/scripts) to run in Photopea. | ||
- Returns: an array containing all of the scripts outputs, ending with `"done"`. | ||
#### `async loadAsset(asset)` | ||
- `asset` (ArrayBuffer): a buffer of the asset to load in Photopea. | ||
- Returns: `[ "done" ]`. | ||
#### `async openFromURL(url, asSmart=true)` | ||
- `url` (string): The URL of the image/psd file to open. | ||
- `asSmart` (boolean): whether to open the image as a layer. Set to `false` if you are opening an image or psd file in a new document. | ||
- Returns: `[ "done" ]`. | ||
#### `async exportImage(type="png")` | ||
- `type` (string): export image filetype. Can be png or jpg. | ||
- Returns: a Blob of the exported image. To get the image URL, use `URL.createObjectURL`. | ||
|
||
## Demo | ||
See [dist/test.html](./dist/test.html) |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
<!DOCTYPE html> | ||
<html> | ||
<head> | ||
<script src="./photopea.min.js"></script> | ||
</head> | ||
<body> | ||
<div id="container" style="width: 800px; height: 400px;"></div> | ||
<script> | ||
let container = document.getElementById("container"); | ||
Photopea.createEmbed(container).then(async (pea) => { | ||
let output = await pea.runScript(` | ||
app.echoToOE("hello world"); | ||
`); | ||
console.log(output) | ||
await pea.openFromURL("https://www.photopea.com/api/img2/pug.png", false); | ||
await pea.runScript(`app.activeDocument.activeLayer.blendMode = "lddg";`); | ||
await pea.openFromURL("https://www.photopea.com/api/img2/pug.png", true); | ||
await pea.runScript(`app.activeDocument.activeLayer.blendMode = "scrn";`); | ||
await pea.runScript(`app.activeDocument.activeLayer.translate(20, 20);`); | ||
output = await pea.runScript(` | ||
app.echoToOE("hello world 2"); | ||
`); | ||
console.log(output) | ||
let finalImage = await pea.exportImage(); | ||
let img = new Image(); | ||
img.src = URL.createObjectURL(finalImage); | ||
document.body.appendChild(img); | ||
}); | ||
</script> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
{ | ||
"name": "photopea", | ||
"version": "0.0.1", | ||
"description": "JS wrapper for the Photopea API.", | ||
"type": "module", | ||
"main": "src/index.js", | ||
"dependencies": { | ||
"acorn": "^8.12.1", | ||
"acorn-import-attributes": "^1.9.5", | ||
"ajv": "^6.12.6", | ||
"ajv-keywords": "^3.5.2", | ||
"browserslist": "^4.23.2", | ||
"buffer-from": "^1.1.2", | ||
"caniuse-lite": "^1.0.30001642", | ||
"chrome-trace-event": "^1.0.4", | ||
"clone-deep": "^4.0.1", | ||
"colorette": "^2.0.20", | ||
"commander": "^2.20.3", | ||
"cross-spawn": "^7.0.3", | ||
"electron-to-chromium": "^1.4.829", | ||
"enhanced-resolve": "^5.17.0", | ||
"envinfo": "^7.13.0", | ||
"es-module-lexer": "^1.5.4", | ||
"escalade": "^3.1.2", | ||
"eslint-scope": "^5.1.1", | ||
"esrecurse": "^4.3.0", | ||
"estraverse": "^4.3.0", | ||
"events": "^3.3.0", | ||
"fast-deep-equal": "^3.1.3", | ||
"fast-json-stable-stringify": "^2.1.0", | ||
"fastest-levenshtein": "^1.0.16", | ||
"find-up": "^4.1.0", | ||
"flat": "^5.0.2", | ||
"function-bind": "^1.1.2", | ||
"glob-to-regexp": "^0.4.1", | ||
"graceful-fs": "^4.2.11", | ||
"has-flag": "^4.0.0", | ||
"hasown": "^2.0.2", | ||
"import-local": "^3.1.0", | ||
"interpret": "^3.1.1", | ||
"is-core-module": "^2.15.0", | ||
"is-plain-object": "^2.0.4", | ||
"isexe": "^2.0.0", | ||
"isobject": "^3.0.1", | ||
"jest-worker": "^27.5.1", | ||
"json-parse-even-better-errors": "^2.3.1", | ||
"json-schema-traverse": "^0.4.1", | ||
"kind-of": "^6.0.3", | ||
"loader-runner": "^4.3.0", | ||
"locate-path": "^5.0.0", | ||
"merge-stream": "^2.0.0", | ||
"mime-db": "^1.52.0", | ||
"mime-types": "^2.1.35", | ||
"neo-async": "^2.6.2", | ||
"node-releases": "^2.0.17", | ||
"p-limit": "^2.3.0", | ||
"p-locate": "^4.1.0", | ||
"p-try": "^2.2.0", | ||
"path-exists": "^4.0.0", | ||
"path-key": "^3.1.1", | ||
"path-parse": "^1.0.7", | ||
"picocolors": "^1.0.1", | ||
"pkg-dir": "^4.2.0", | ||
"punycode": "^2.3.1", | ||
"randombytes": "^2.1.0", | ||
"rechoir": "^0.8.0", | ||
"resolve": "^1.22.8", | ||
"resolve-cwd": "^3.0.0", | ||
"resolve-from": "^5.0.0", | ||
"safe-buffer": "^5.2.1", | ||
"schema-utils": "^3.3.0", | ||
"serialize-javascript": "^6.0.2", | ||
"shallow-clone": "^3.0.1", | ||
"shebang-command": "^2.0.0", | ||
"shebang-regex": "^3.0.0", | ||
"source-map": "^0.6.1", | ||
"source-map-support": "^0.5.21", | ||
"supports-color": "^8.1.1", | ||
"supports-preserve-symlinks-flag": "^1.0.0", | ||
"tapable": "^2.2.1", | ||
"terser": "^5.31.3", | ||
"terser-webpack-plugin": "^5.3.10", | ||
"undici-types": "^5.26.5", | ||
"update-browserslist-db": "^1.1.0", | ||
"uri-js": "^4.4.1", | ||
"watchpack": "^2.4.1", | ||
"webpack-merge": "^5.10.0", | ||
"webpack-sources": "^3.2.3", | ||
"which": "^2.0.2", | ||
"wildcard": "^2.0.1" | ||
}, | ||
"devDependencies": { | ||
"webpack": "^5.93.0", | ||
"webpack-cli": "^5.1.4" | ||
}, | ||
"scripts": { | ||
"build": "webpack" | ||
}, | ||
"keywords": [ | ||
"photopea" | ||
], | ||
"author": "Yikuan Sun", | ||
"license": "MIT" | ||
} |
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
export default class Photopea { | ||
|
||
static async createEmbed(parentElement, config) { | ||
let _config = ""; | ||
if (typeof(config) == "object") _config = JSON.stringify(config); | ||
else if (typeof(config) == "string") _config = config; | ||
let frame = document.createElement("iframe"); | ||
frame.style.border = "0"; | ||
frame.style.width = "100%"; | ||
frame.style.height = "100%"; | ||
if (config) frame.src = "https://www.photopea.com#" + encodeURI(_config); | ||
else frame.src = "https://www.photopea.com"; | ||
parentElement.appendChild(frame); | ||
let waitForInit = new Promise(function(res, rej) { | ||
let messageHandle = (e) => { | ||
if (e.source == frame.contentWindow && e.data == "done") { | ||
let pea = new Photopea(frame.contentWindow); | ||
window.removeEventListener("message", messageHandle); | ||
res(pea); | ||
} | ||
}; | ||
window.addEventListener("message", messageHandle); | ||
}); | ||
return await waitForInit; | ||
} | ||
|
||
contentWindow; | ||
constructor(contentWindow) { | ||
this.contentWindow = contentWindow; | ||
} | ||
|
||
async runScript(script) { | ||
await this._pause(); | ||
let waitForMessage = new Promise((res, rej) => { | ||
let outputs = []; | ||
let messageHandle = (e) => { | ||
if (e.source == this.contentWindow) { | ||
outputs.push(e.data); | ||
if (e.data == "done") { | ||
window.removeEventListener("message", messageHandle); | ||
res(outputs); | ||
} | ||
} | ||
}; | ||
window.addEventListener("message", messageHandle); | ||
|
||
this.contentWindow.postMessage(script, "*"); | ||
}); | ||
return await waitForMessage; | ||
} | ||
|
||
async loadAsset(asset) { | ||
await this._pause(); | ||
let waitForMessage = new Promise((res, rej) => { | ||
let outputs = []; | ||
let messageHandle = (e) => { | ||
if (e.source == this.contentWindow) { | ||
outputs.push(e.data); | ||
if (e.data == "done") { | ||
window.removeEventListener("message", messageHandle); | ||
res(outputs); | ||
} | ||
} | ||
}; | ||
window.addEventListener("message", messageHandle); | ||
|
||
this.contentWindow.postMessage(asset, "*"); | ||
}); | ||
return await waitForMessage; | ||
} | ||
|
||
async openFromURL(url, asSmart=true) { | ||
await this._pause(); | ||
let layerCountOld = "done"; | ||
while (layerCountOld == "done") layerCountOld = (await this.runScript(`app.echoToOE(${asSmart?"app.activeDocument.layers.length":"app.documents.length"})`))[0]; | ||
let layerCountNew = layerCountOld; | ||
await this.runScript(`app.open("${url}", null, ${asSmart});`); | ||
while (layerCountNew == layerCountOld || layerCountNew == "done") { | ||
layerCountNew = (await this.runScript(`app.echoToOE(${asSmart?"app.activeDocument.layers.length":"app.documents.length"})`))[0]; | ||
} | ||
return [ "done" ]; | ||
} | ||
|
||
async exportImage(type="png") { | ||
await this._pause(); | ||
let buffer = "done"; | ||
while (buffer == "done") { | ||
let data = await this.runScript(`app.activeDocument.saveToOE("${type}");`); | ||
buffer = data[0]; | ||
} | ||
return new Blob([ buffer ], { | ||
type: "image/" + type, | ||
}); | ||
|
||
} | ||
|
||
async _pause(ms=10) { | ||
return await new Promise((res, rej) => { | ||
setTimeout(() => { res(); }, ms); | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import path from "path"; | ||
import { fileURLToPath } from "url"; | ||
|
||
const __filename = fileURLToPath(import.meta.url); | ||
const __dirname = path.dirname(__filename); | ||
|
||
export default { | ||
entry: "./src/index.js", | ||
output: { | ||
filename: "photopea.min.js", | ||
path: path.resolve(__dirname, "dist"), | ||
library: "Photopea", | ||
libraryExport: "default", | ||
libraryTarget: "umd", | ||
globalObject: "this", | ||
}, | ||
}; |