diff --git a/TODO.md b/TODO.md deleted file mode 100644 index 77011cc..0000000 --- a/TODO.md +++ /dev/null @@ -1,42 +0,0 @@ -# Project TODO List - -## Sketchy UI Libraries Overhaul - -**1. Fork `wired-elements` (High Priority):** - - The currently used `wired-elements@3.0.0-rc.6` is old, and the original library appears unmaintained (last release 2018). - - **Action:** Create an internal fork of `wired-elements` (e.g., under `vendor/bleedy-wired-elements` or as a private Git submodule/repository). - - **Source:** Obtain the source code for `wired-elements@3.0.0-rc.6`. - - **Integrate Patch:** Apply the existing `patches/wired-elements@3.0.0-rc.6.patch` to this fork. - - **Audit & Update:** - - Thoroughly audit all components within the fork that use `Rough.js` (especially those using fillers like `ZigZagFiller`). - - Update these components to correctly use the API of the current `Rough.js` version (`4.6.6` or latest stable). The primary goal is to ensure all calls match `Rough.js`'s expected API (e.g., consistently using `fillPolygons` if that's the current standard in `Rough.js`). - - This should eliminate the need for the `patches/roughjs@4.6.6.patch`. - - **Dependencies:** Review and potentially update other dependencies of the forked `wired-elements` (e.g., Lit). - - **Update Project Usage:** Modify `bleedy.py`'s `package.json` and imports to use this internal fork. - -**2. Eliminate `Rough.js` Patch (Dependent on #1):** - - Once the forked `wired-elements` correctly interfaces with `Rough.js`, the `patches/roughjs@4.6.6.patch` should no longer be necessary. - - **Action:** Remove `patches/roughjs@4.6.6.patch` and its entry from `npm.patchedDependencies` in `package.json`. - -**3. Verify and Address `DoodleCSS` and `paper-css`:** - - **Action (Manual Check Needed):** Manually verify the maintenance status and stability of `DoodleCSS` and `paper-css`. - - `DoodleCSS` (github.com/chr15m/DoodleCSS): Last commit appears to be ~2 years ago. - - `paper-css`: Needs similar verification. - - **Strategy:** - - If deemed stable enough and causing no issues: Document their versions and keep them. - - If problematic or very outdated: - - Option A: Absorb their essential styles directly into the project's own SCSS/CSS structure. - - Option B: Find actively maintained alternatives that provide a similar aesthetic. - - Option C: Replicate the necessary effects using modern CSS or SVGs. - -## PyScript Version Check Hook -- Fully implement and test the `scripts/check-pyscript-version.sh` script. -- Integrate with Husky as a pre-commit hook. -- Ensure the script correctly parses `index.html`, fetches the latest PyScript version, and handles the `.pyscript_version_ack` file logic. - -## Architecture Documentation -- Create `ARCHITECTURE.md` detailing: - - Vue component structure. - - PyScript integration and JS-Python communication flow (current and planned improvements). - - Data flow through the application. - - Details about the sketchy UI libraries, the reasons for forking/patching, and the long-term strategy for them. diff --git a/index.html b/index.html index 7ee734c..ba65fcc 100644 --- a/index.html +++ b/index.html @@ -5,20 +5,12 @@ Bleedy - - + + - -
- -

Bleedy.py is loading...

-

Please wait while the bits and bytes get sketchy!

- -
-
diff --git a/package-lock.json b/package-lock.json index 36352db..792f9a3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,15 +12,15 @@ "@types/file-saver": "^2.0.7", "@zip.js/zip.js": "^2.7.54", "doodle.css": "^0.0.2", - "element-plus": "^2.9.5", + "element-plus": "^2.9.1", "file-saver": "^2.0.5", "jszip": "^3.10.1", "paper-css": "^0.4.1", "pinia": "^2.3.0", "roughjs": "^4.6.6", "unplugin-icons": "^0.22.0", - "vue": "^3.5.13", - "vue-router": "^4.5.1", + "vue": "^3.5.14", + "vue-router": "^4.5.0", "vue3-image-preview": "^0.2.7", "vuedraggable": "^4.1.0", "wired-elements": "^3.0.0-rc.6" @@ -376,18 +376,18 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", - "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", - "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", + "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", "license": "MIT", "engines": { "node": ">=6.9.0" @@ -418,12 +418,12 @@ } }, "node_modules/@babel/parser": { - "version": "7.26.8", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.8.tgz", - "integrity": "sha512-TZIQ25pkSoaKEYYaHbbxkfL36GNsQ6iFiBbeuzAkLnXayKR1yP1zFe+NxuZWWsUyvt8icPU9CCq0sgWGXR1GEw==", + "version": "7.27.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.5.tgz", + "integrity": "sha512-OsQd175SxWkGlzbny8J3K8TnnDD0N3lrIUtB92xwyRpzaenGZhxDvxN/JgU00U3CDZNj9tPuDJ5H0WS4Nt3vKg==", "license": "MIT", "dependencies": { - "@babel/types": "^7.26.8" + "@babel/types": "^7.27.3" }, "bin": { "parser": "bin/babel-parser.js" @@ -592,13 +592,13 @@ } }, "node_modules/@babel/types": { - "version": "7.26.8", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.8.tgz", - "integrity": "sha512-eUuWapzEGWFEpHFxgEaBG8e3n6S8L3MSu0oda755rOfabWPnh0Our1AozNFVUxGFIhbKgd1ksprsoDGMinTOTA==", + "version": "7.27.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.3.tgz", + "integrity": "sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw==", "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.25.9", - "@babel/helper-validator-identifier": "^7.25.9" + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -2856,53 +2856,53 @@ } }, "node_modules/@vue/compiler-core": { - "version": "3.5.13", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.13.tgz", - "integrity": "sha512-oOdAkwqUfW1WqpwSYJce06wvt6HljgY3fGeM9NcVA1HaYOij3mZG9Rkysn0OHuyUAGMbEbARIpsG+LPVlBJ5/Q==", + "version": "3.5.14", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.14.tgz", + "integrity": "sha512-k7qMHMbKvoCXIxPhquKQVw3Twid3Kg4s7+oYURxLGRd56LiuHJVrvFKI4fm2AM3c8apqODPfVJGoh8nePbXMRA==", "license": "MIT", "dependencies": { - "@babel/parser": "^7.25.3", - "@vue/shared": "3.5.13", + "@babel/parser": "^7.27.2", + "@vue/shared": "3.5.14", "entities": "^4.5.0", "estree-walker": "^2.0.2", - "source-map-js": "^1.2.0" + "source-map-js": "^1.2.1" } }, "node_modules/@vue/compiler-dom": { - "version": "3.5.13", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.13.tgz", - "integrity": "sha512-ZOJ46sMOKUjO3e94wPdCzQ6P1Lx/vhp2RSvfaab88Ajexs0AHeV0uasYhi99WPaogmBlRHNRuly8xV75cNTMDA==", + "version": "3.5.14", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.14.tgz", + "integrity": "sha512-1aOCSqxGOea5I80U2hQJvXYpPm/aXo95xL/m/mMhgyPUsKe9jhjwWpziNAw7tYRnbz1I61rd9Mld4W9KmmRoug==", "license": "MIT", "dependencies": { - "@vue/compiler-core": "3.5.13", - "@vue/shared": "3.5.13" + "@vue/compiler-core": "3.5.14", + "@vue/shared": "3.5.14" } }, "node_modules/@vue/compiler-sfc": { - "version": "3.5.13", - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.13.tgz", - "integrity": "sha512-6VdaljMpD82w6c2749Zhf5T9u5uLBWKnVue6XWxprDobftnletJ8+oel7sexFfM3qIxNmVE7LSFGTpv6obNyaQ==", + "version": "3.5.14", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.14.tgz", + "integrity": "sha512-9T6m/9mMr81Lj58JpzsiSIjBgv2LiVoWjIVa7kuXHICUi8LiDSIotMpPRXYJsXKqyARrzjT24NAwttrMnMaCXA==", "license": "MIT", "dependencies": { - "@babel/parser": "^7.25.3", - "@vue/compiler-core": "3.5.13", - "@vue/compiler-dom": "3.5.13", - "@vue/compiler-ssr": "3.5.13", - "@vue/shared": "3.5.13", + "@babel/parser": "^7.27.2", + "@vue/compiler-core": "3.5.14", + "@vue/compiler-dom": "3.5.14", + "@vue/compiler-ssr": "3.5.14", + "@vue/shared": "3.5.14", "estree-walker": "^2.0.2", - "magic-string": "^0.30.11", - "postcss": "^8.4.48", - "source-map-js": "^1.2.0" + "magic-string": "^0.30.17", + "postcss": "^8.5.3", + "source-map-js": "^1.2.1" } }, "node_modules/@vue/compiler-ssr": { - "version": "3.5.13", - "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.13.tgz", - "integrity": "sha512-wMH6vrYHxQl/IybKJagqbquvxpWCuVYpoUJfCqFZwa/JY1GdATAQ+TgVtgrwwMZ0D07QhA99rs/EAAWfvG6KpA==", + "version": "3.5.14", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.14.tgz", + "integrity": "sha512-Y0G7PcBxr1yllnHuS/NxNCSPWnRGH4Ogrp0tsLA5QemDZuJLs99YjAKQ7KqkHE0vCg4QTKlQzXLKCMF7WPSl7Q==", "license": "MIT", "dependencies": { - "@vue/compiler-dom": "3.5.13", - "@vue/shared": "3.5.13" + "@vue/compiler-dom": "3.5.14", + "@vue/shared": "3.5.14" } }, "node_modules/@vue/compiler-vue2": { @@ -3052,53 +3052,53 @@ } }, "node_modules/@vue/reactivity": { - "version": "3.5.13", - "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.13.tgz", - "integrity": "sha512-NaCwtw8o48B9I6L1zl2p41OHo/2Z4wqYGGIK1Khu5T7yxrn+ATOixn/Udn2m+6kZKB/J7cuT9DbWWhRxqixACg==", + "version": "3.5.14", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.14.tgz", + "integrity": "sha512-7cK1Hp343Fu/SUCCO52vCabjvsYu7ZkOqyYu7bXV9P2yyfjUMUXHZafEbq244sP7gf+EZEz+77QixBTuEqkQQw==", "license": "MIT", "dependencies": { - "@vue/shared": "3.5.13" + "@vue/shared": "3.5.14" } }, "node_modules/@vue/runtime-core": { - "version": "3.5.13", - "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.13.tgz", - "integrity": "sha512-Fj4YRQ3Az0WTZw1sFe+QDb0aXCerigEpw418pw1HBUKFtnQHWzwojaukAs2X/c9DQz4MQ4bsXTGlcpGxU/RCIw==", + "version": "3.5.14", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.14.tgz", + "integrity": "sha512-w9JWEANwHXNgieAhxPpEpJa+0V5G0hz3NmjAZwlOebtfKyp2hKxKF0+qSh0Xs6/PhfGihuSdqMprMVcQU/E6ag==", "license": "MIT", "dependencies": { - "@vue/reactivity": "3.5.13", - "@vue/shared": "3.5.13" + "@vue/reactivity": "3.5.14", + "@vue/shared": "3.5.14" } }, "node_modules/@vue/runtime-dom": { - "version": "3.5.13", - "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.13.tgz", - "integrity": "sha512-dLaj94s93NYLqjLiyFzVs9X6dWhTdAlEAciC3Moq7gzAc13VJUdCnjjRurNM6uTLFATRHexHCTu/Xp3eW6yoog==", + "version": "3.5.14", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.14.tgz", + "integrity": "sha512-lCfR++IakeI35TVR80QgOelsUIdcKjd65rWAMfdSlCYnaEY5t3hYwru7vvcWaqmrK+LpI7ZDDYiGU5V3xjMacw==", "license": "MIT", "dependencies": { - "@vue/reactivity": "3.5.13", - "@vue/runtime-core": "3.5.13", - "@vue/shared": "3.5.13", + "@vue/reactivity": "3.5.14", + "@vue/runtime-core": "3.5.14", + "@vue/shared": "3.5.14", "csstype": "^3.1.3" } }, "node_modules/@vue/server-renderer": { - "version": "3.5.13", - "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.13.tgz", - "integrity": "sha512-wAi4IRJV/2SAW3htkTlB+dHeRmpTiVIK1OGLWV1yeStVSebSQQOwGwIq0D3ZIoBj2C2qpgz5+vX9iEBkTdk5YA==", + "version": "3.5.14", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.14.tgz", + "integrity": "sha512-Rf/ISLqokIvcySIYnv3tNWq40PLpNLDLSJwwVWzG6MNtyIhfbcrAxo5ZL9nARJhqjZyWWa40oRb2IDuejeuv6w==", "license": "MIT", "dependencies": { - "@vue/compiler-ssr": "3.5.13", - "@vue/shared": "3.5.13" + "@vue/compiler-ssr": "3.5.14", + "@vue/shared": "3.5.14" }, "peerDependencies": { - "vue": "3.5.13" + "vue": "3.5.14" } }, "node_modules/@vue/shared": { - "version": "3.5.13", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.13.tgz", - "integrity": "sha512-/hnE/qP5ZoGpol0a5mDi45bOd7t3tjYJBjsgCsivow7D48cJeV5l05RD82lPqi7gRiphZM37rnhW1l6ZoCNNnQ==", + "version": "3.5.14", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.14.tgz", + "integrity": "sha512-oXTwNxVfc9EtP1zzXAlSlgARLXNC84frFYkS0HHz0h3E4WZSP9sywqjqzGCP9Y34M8ipNmd380pVgmMuwELDyQ==", "license": "MIT" }, "node_modules/@vue/test-utils": { @@ -4078,9 +4078,9 @@ "license": "ISC" }, "node_modules/element-plus": { - "version": "2.9.5", - "resolved": "https://registry.npmjs.org/element-plus/-/element-plus-2.9.5.tgz", - "integrity": "sha512-r+X79oogLbYq8p9L5f9fHSHhUFNM0AL72aikqiZVxSc2/08mK6m/PotiB9e/D90QmWTIHIaFnFmW65AcXmneig==", + "version": "2.9.4", + "resolved": "https://registry.npmjs.org/element-plus/-/element-plus-2.9.4.tgz", + "integrity": "sha512-sGnW0wd9zf6lEGixXV2gfwx3X6VTMkP52qTkX7zbURJ2oariyslrKTBh2txt1sdn1pUvj2l0KY3OfSXoZGmDOw==", "license": "MIT", "dependencies": { "@ctrl/tinycolor": "^3.4.1", @@ -5952,9 +5952,9 @@ "license": "MIT" }, "node_modules/nanoid": { - "version": "3.3.8", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", - "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==", + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", "funding": [ { "type": "github", @@ -6387,9 +6387,9 @@ } }, "node_modules/postcss": { - "version": "8.5.2", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.2.tgz", - "integrity": "sha512-MjOadfU3Ys9KYoX0AdkBlFEF1Vx37uCCeN4ZHnmwm9FfpbsGWMZeBLMmmpY+6Ocqod7mkdZ0DT31OlbsFrLlkA==", + "version": "8.5.4", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.4.tgz", + "integrity": "sha512-QSa9EBe+uwlGTFmHsPKokv3B/oEMQZxfqW0QqNCyhpa6mB1afzulwn8hihglqAb2pOw+BJgNlmXQ8la2VeHB7w==", "funding": [ { "type": "opencollective", @@ -6406,7 +6406,7 @@ ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.8", + "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, @@ -9971,16 +9971,16 @@ "license": "MIT" }, "node_modules/vue": { - "version": "3.5.13", - "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.13.tgz", - "integrity": "sha512-wmeiSMxkZCSc+PM2w2VRsOYAZC8GdipNFRTsLSfodVqI9mbejKeXEGr8SckuLnrQPGe3oJN5c3K0vpoU9q/wCQ==", + "version": "3.5.14", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.14.tgz", + "integrity": "sha512-LbOm50/vZFG6Mhy6KscQYXZMQ0LMCC/y40HDJPPvGFQ+i/lUH+PJHR6C3assgOQiXdl6tAfsXHbXYVBZZu65ew==", "license": "MIT", "dependencies": { - "@vue/compiler-dom": "3.5.13", - "@vue/compiler-sfc": "3.5.13", - "@vue/runtime-dom": "3.5.13", - "@vue/server-renderer": "3.5.13", - "@vue/shared": "3.5.13" + "@vue/compiler-dom": "3.5.14", + "@vue/compiler-sfc": "3.5.14", + "@vue/runtime-dom": "3.5.14", + "@vue/server-renderer": "3.5.14", + "@vue/shared": "3.5.14" }, "peerDependencies": { "typescript": "*" @@ -10085,9 +10085,9 @@ } }, "node_modules/vue-router": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.5.1.tgz", - "integrity": "sha512-ogAF3P97NPm8fJsE4by9dwSYtDwXIY1nFY9T6DyQnGHd1E2Da94w9JIolpe42LJGIl0DwOHBi8TcRPlPGwbTtw==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.5.0.tgz", + "integrity": "sha512-HDuk+PuH5monfNuY+ct49mNmkCRK4xJAV9Ts4z9UFc4rzdDnxQLyCMGGc8pKhZhHTVzfanpNwB/lwqevcBwI4w==", "license": "MIT", "dependencies": { "@vue/devtools-api": "^6.6.4" diff --git a/package.json b/package.json index 2f8eff0..31275d7 100644 --- a/package.json +++ b/package.json @@ -17,16 +17,17 @@ "dependencies": { "@element-plus/icons-vue": "^2.3.1", "@types/file-saver": "^2.0.7", + "@zip.js/zip.js": "^2.7.54", "doodle.css": "^0.0.2", - "element-plus": "^2.9.5", + "element-plus": "^2.9.1", "file-saver": "^2.0.5", "jszip": "^3.10.1", "paper-css": "^0.4.1", "pinia": "^2.3.0", "roughjs": "^4.6.6", "unplugin-icons": "^0.22.0", - "vue": "^3.5.13", - "vue-router": "^4.5.1", + "vue": "^3.5.14", + "vue-router": "^4.5.0", "vue3-image-preview": "^0.2.7", "vuedraggable": "^4.1.0", "wired-elements": "^3.0.0-rc.6" diff --git a/public/js/bleedy_interop.js b/public/js/bleedy_interop.js deleted file mode 100644 index c26f9ad..0000000 --- a/public/js/bleedy_interop.js +++ /dev/null @@ -1,39 +0,0 @@ -// public/js/bleedy_interop.js - -/** - * Dispatches a custom event to inform the Vue application that an image has been processed. - * @param {string} name - The name of the processed image file. - * @param {string} blobUrl - The blob URL of the processed image. - * @param {string} format - The format of the processed image (e.g., 'PNG', 'JPEG'). - */ -export function dispatchProcessedImageToVue(name, blobUrl, format) { - console.log(`JS interop: dispatching processed image - Name: ${name}, Format: ${format}`); - const event = new CustomEvent('bleedy-image-processed', { - detail: { - name, - blobUrl, - format, - } - }); - window.dispatchEvent(event); -} - -/** - * Dispatches a custom event to update the Vue application on processing progress. - * @param {object} progressDetail - The progress detail object. - * @param {number} progressDetail.progress - Overall progress percentage. - * @param {number} progressDetail.processed - Number of files processed. - * @param {number} progressDetail.total - Total number of files. - * @param {number} progressDetail.elapsed - Elapsed time in seconds. - * @param {number} progressDetail.remaining - Estimated remaining time in seconds. - */ -export function dispatchProgressToVue(progressDetail) { - // console.log('JS interop: dispatching progress', progressDetail); // Can be noisy - const event = new CustomEvent('processing-progress', { - detail: progressDetail - }); - window.dispatchEvent(event); -} - -// Log to confirm the module is loaded by PyScript -console.log("bleedy_interop.js loaded"); diff --git a/public/pyscript/config.toml b/public/pyscript/config.toml index e4756b9..9bc9dc7 100644 --- a/public/pyscript/config.toml +++ b/public/pyscript/config.toml @@ -1,7 +1,3 @@ -interpreter = "0.26.1" # Pin Pyodide version packages = ["pillow" ] # "opencv-contrib-python-headless" experimental_create_proxy = "auto" -sync_main_only = true - -[js_modules.main] -"/js/bleedy_interop.js" = "interop" \ No newline at end of file +sync_main_only = true \ No newline at end of file diff --git a/public/pyscript/main.py b/public/pyscript/main.py index ed14b5c..831291b 100644 --- a/public/pyscript/main.py +++ b/public/pyscript/main.py @@ -1,15 +1,13 @@ from PIL import Image from io import BytesIO -from pyscript import when # noqa # pyright: ignore [reportAttributeAccessIssue] -from pyscript.ffi import to_js # noqa # pyright: ignore [reportMissingImports] -# window is kept for performance.now(), console, Uint8Array, File, URL are used. -# document, display, page are no longer needed. -from js import window, console, Uint8Array, File, URL # noqa # pyright: ignore [reportMissingImports] -from pyscript.js_modules import interop # Our new JS bridge +from pyscript import when, display # noqa # pyright: ignore [reportAttributeAccessIssue] +from pyscript.web import page # noqa # pyright: ignore [reportMissingImports] +from pyscript.ffi import to_js # noqa # pyright: ignore [reportMissingImports] +from js import document, window, console, Uint8Array, File, URL # noqa # pyright: ignore [reportMissingImports] async def add_bleed(image: Image, bleed: int) -> Image: - console.log(f"(PY) Adding {bleed} pixels of bleed to the image") + console.log(f"Adding {bleed} pixels of bleed to the image") old_width, old_height = image.size new_img = Image.new("RGB", (old_width + 2 * bleed, old_height + 2 * bleed)) new_img.paste(image, (bleed, bleed)) @@ -24,91 +22,80 @@ async def add_bleed(image: Image, bleed: int) -> Image: Image.Transpose.FLIP_LEFT_RIGHT) new_img.paste(segment, (horizontal_position, 0)) - console.log("(PY) Bleed added to the image") + console.log("Bleed added to the image") return new_img async def process_image(img: Image, bleed: int) -> Image: if bleed <= 0: - console.log("(PY) No bleed required. Returning original image.") + console.log("No bleed required. Returning original image.") return img return await add_bleed(img, bleed) + async def create_image_file(modified_image: Image, name: str, fmt: str) -> File: stream = BytesIO() - actual_fmt = fmt if fmt else 'PNG' # Ensure format is not None for saving - modified_image.save(stream, format=actual_fmt.upper()) + modified_image.save(stream, format=fmt.upper()) stream_val = stream.getvalue() js_array = Uint8Array.new(len(stream_val)) js_array.assign(stream_val) + # js_array = Uint8Array.new(stream.getvalue()) + + return File.new([to_js(js_array)], name, to_js({"type": f"image/{fmt.lower()}"})) - # Create a JS File object. Name and type are important for blob URL and download. - return File.new([to_js(js_array)], name, to_js({"type": f"image/{actual_fmt.lower()}"})) +async def display_image_file(img_file: File): + #Create new tag and insert into page + new_image = document.createElement('img') + new_image.src = URL.createObjectURL(img_file) + document.getElementById("bleedy-output").appendChild(new_image) -# display_image_file function is removed as results are dispatched via interop @when("process-images", ".image-bleed-processor") async def process_files(event): - console.log("🚀 (PY) Starting image processing in PyScript!") + console.log("🚀 Starting image processing in PyScript!") try: - files_js = event.detail.files # Keep as JS Array-like of File objects (e.g., FileList) + files = event.detail.files.to_py() # Convert JS objects to Python bleed_amount = event.detail.bleedAmount - num_files = files_js.length # Use .length for JS FileList or Array - - console.log(f"📏 (PY) Bleed amount set to: {bleed_amount}px") - console.log(f"🖼️ (PY) Number of images to process: {num_files}") + console.log(f"📏 Bleed amount set to: {bleed_amount}px") + console.log(f"🖼️ Number of images to process: {len(files)}") start_time = window.performance.now() processed_count = 0 def update_progress(): elapsed = (window.performance.now() - start_time) / 1000 # in seconds - progress_val = (processed_count / num_files) * 100 if num_files > 0 else 0 + progress = (processed_count / len(files)) * 100 rate = processed_count / elapsed if elapsed > 0 else 0 - remaining_val = (num_files - processed_count) / rate if rate > 0 else 0 - - progress_detail = { - "progress": progress_val, - "processed": processed_count, - "total": num_files, - "elapsed": elapsed, - "remaining": remaining_val - } - # Dispatch progress event using the interop module - # Ensure the dictionary is converted to a JS object for the JS function - interop.dispatchProgressToVue(to_js(progress_detail)) - - # Initial progress update (0%) - update_progress() - - for i in range(num_files): - file_obj = files_js.item(i) # Get File object from FileList/JS Array - console.log(f"⚙️ (PY) Processing file {i + 1}/{num_files}: {file_obj.name}") - - array_buf = Uint8Array.new(await file_obj.arrayBuffer()) # Get ArrayBuffer from JS File - bytes_list = bytearray(array_buf) # Convert to bytearray for BytesIO + remaining = (len(files) - processed_count) / rate if rate > 0 else 0 + + # Dispatch progress event using window directly + window.dispatchEvent(window.CustomEvent.new("processing-progress", { + "detail": { + "progress": progress, + "processed": processed_count, + "total": len(files), + "elapsed": elapsed, + "remaining": remaining + } + })) + + for i, file in enumerate(files): + console.log(f"⚙️ Processing file {i + 1}/{len(files)}: {file.name}") + processed_count = i + 1 + update_progress() + array_buf = Uint8Array.new(await file.arrayBuffer()) + bytes_list = bytearray(array_buf) image_bytes = BytesIO(bytes_list) img = Image.open(image_bytes) - - img_format_str = img.format if img.format else 'PNG' # Default to PNG if format is not detected - console.log(f"📄 (PY) Image details - Name: {file_obj.name}, Format: {img_format_str}, Size: {img.width}x{img.height}") - + console.log(f"📄 Image details - Name: {file.name}, Format: {img.format}, Size: {img.width}x{img.height}") modified_image = await process_image(img, bleed_amount) - modified_img_file = await create_image_file(modified_image, file_obj.name, img_format_str) - - # Create a blob URL in Python to pass to JS, as JS side expects a URL - blob_url = URL.createObjectURL(modified_img_file) - - # Dispatch processed image data to Vue via JS interop module - interop.dispatchProcessedImageToVue(modified_img_file.name, blob_url, img_format_str) - - processed_count += 1 - update_progress() # Update progress after each image - - console.log(f"✅ (PY) File {i + 1}/{num_files}: {file_obj.name} processed successfully") - - console.log("🎉 (PY) All images processed successfully!") + modified_img_file = await create_image_file(modified_image, file.name, img.format) + await display_image_file(modified_img_file) + # Example: processing file data with PIL + # file_data = file.arrayBuffer().to_py() + # img = Image.open(BytesIO(file_data)) + # img_with_border = ImageOps.expand(img, border=bleed_amount, fill="red") + # img_with_border.show() + console.log(f"✅ File {i + 1}/{len(files)}: {file.name} processed successfully") + console.log("🎉 All images processed successfully!") except Exception as e: - console.error(f"❌ (PY) Error processing images: {str(e)}") - # Future: dispatch an error event to JS/Vue via interop - # if hasattr(interop, 'dispatchErrorToVue'): - # interop.dispatchErrorToVue(str(e)) + console.error(f"❌ Error processing images: {str(e)}") diff --git a/scripts/check-pyscript-version.sh b/scripts/check-pyscript-version.sh deleted file mode 100644 index d59d666..0000000 --- a/scripts/check-pyscript-version.sh +++ /dev/null @@ -1,68 +0,0 @@ -#!/bin/bash - -# Placeholder script for checking PyScript version consistency -# To be integrated with Husky as a pre-commit hook. - -# --- Configuration --- -# Path to the index.html file relative to the repository root -INDEX_HTML_PATH="index.html" -# Expected PyScript version (should be kept in sync with actual upgrades) -EXPECTED_PYSCRIPT_VERSION="2025.5.1" -# Path to the acknowledgment file, relative to the repository root -# This file can contain a version string that, if it matches the *latest found online*, allows a commit even if different from EXPECTED_PYSCRIPT_VERSION -# This is for cases where we know a new version is out but are not ready to upgrade yet. -# Example content for .pyscript_version_ack: 2025.6.1 -ACK_FILE_PATH=".pyscript_version_ack" -# URL to check for the latest PyScript version string (e.g., on pyscript.net or a stable API endpoint) -# This is a placeholder; a more robust method might be needed, like parsing a specific element from pyscript.net/latest/ -LATEST_VERSION_URL="https://pyscript.net/latest/" # This URL itself might not directly give the version string easily. - -echo "Bleedy - PyScript Version Check (Placeholder)" - -# --- 1. Check current version in index.html --- -# Placeholder: Actual parsing logic needed here. -# Example: grep for 'releases/YYYY.M.X/core.js' and extract YYYY.M.X -# current_version_in_html=$(grep -o 'releases/[0-9.]\+/core.js' "$INDEX_HTML_PATH" | head -n 1 | sed -E 's/releases\/(.*)\/core.js/\1/') -# For now, we'll simulate this: -current_version_in_html=$EXPECTED_PYSCRIPT_VERSION # Assume it matches for this placeholder - -if [ -z "$current_version_in_html" ]; then - echo "Error: Could not determine PyScript version from $INDEX_HTML_PATH." - # exit 1 # Uncomment to enforce failure -fi -echo "Current version in $INDEX_HTML_PATH: $current_version_in_html" - -if [ "$current_version_in_html" != "$EXPECTED_PYSCRIPT_VERSION" ]; then - echo "Error: PyScript version in $INDEX_HTML_PATH ($current_version_in_html) does not match expected version ($EXPECTED_PYSCRIPT_VERSION)." - echo "Please update $INDEX_HTML_PATH or this script's EXPECTED_PYSCRIPT_VERSION." - # exit 1 # Uncomment to enforce failure -fi - -# --- 2. Check latest official PyScript version (Simulated) --- -# Placeholder: Actual fetching and parsing logic needed. -# Example: curl -s $LATEST_VERSION_URL | ... parse out version ... -# For now, we'll simulate this: -latest_official_version="2025.5.1" # Simulate that the current version is the latest official -# latest_official_version="2025.6.1" # Simulate a newer version is available - -echo "Latest official PyScript version (simulated check): $latest_official_version" - -# --- 3. Check acknowledgment file if versions diverge --- -acknowledged_version="" -if [ -f "$ACK_FILE_PATH" ]; then - acknowledged_version=$(cat "$ACK_FILE_PATH") -fi - -if [ "$current_version_in_html" != "$latest_official_version" ]; then - echo "Warning: Your current PyScript version ($current_version_in_html) is different from the latest official version ($latest_official_version)." - if [ "$acknowledged_version" == "$latest_official_version" ]; then - echo "However, the latest version ($latest_official_version) has been acknowledged in $ACK_FILE_PATH. Proceeding." - else - echo "The latest version ($latest_official_version) has NOT been acknowledged in $ACK_FILE_PATH (or file doesn't exist/ack is for different version: '$acknowledged_version')." - echo "To proceed with commit without upgrading, create/update $ACK_FILE_PATH with the version string: $latest_official_version" - # exit 1 # Uncomment to enforce failure - fi -fi - -echo "PyScript version check complete (Placeholder - actual checks and enforcement not fully active)." -exit 0 # Placeholder: always allow commit for now diff --git a/src/App.vue b/src/App.vue index 7dc8c57..501b7cd 100644 --- a/src/App.vue +++ b/src/App.vue @@ -135,9 +135,9 @@ el-header { background-color: var(--primary-dark); padding: 0; - --el-header-height: 6.5rem; /* Set header height */ + --el-header-height: "6.5rem"; /* Set header height */ - min-height: 6.5rem; + min-height: "6.5rem"; } .header-content { diff --git a/src/components/FilePicker.vue b/src/components/FilePicker.vue new file mode 100644 index 0000000..c5526b1 --- /dev/null +++ b/src/components/FilePicker.vue @@ -0,0 +1,58 @@ + + + + + diff --git a/src/components/FileUploader.vue b/src/components/FileUploader.vue new file mode 100644 index 0000000..3e7d617 --- /dev/null +++ b/src/components/FileUploader.vue @@ -0,0 +1,48 @@ + + + + + diff --git a/src/components/ImageProcessor.vue b/src/components/ImageProcessor.vue index 15a2f39..0bcfa4d 100644 --- a/src/components/ImageProcessor.vue +++ b/src/components/ImageProcessor.vue @@ -33,7 +33,6 @@