Migrate build system from Webpack to Parcel (#1102)

* Migrate webpack to parcel

* Always colour shell output

* Fix typos

* Fix updateImage function having undefined editorInstance

* Readd webpack for deployment builds (licence checker)

* Only use webpack for license generation

* Re add typscript support

* Fix cloudlare deploy

* Bump wasm-pack version

* Update ci script

* Print versions in ci script

* Use optional-dependencies for wasm-pack

* Execute wget after rust install

* Finding wasm-opt version

* Print wasm-opt version

* Revert test?

* Try to revert

* Deploy cloudflare via github actions

* Fix indentation in ci script

* Change project to graphite-dev

* Trigger ci

* Parcel ci (#1152)

* CI Test

* Add write permissions for pr

* Manually add cloudflare ci comment to prs

* Unskip cargo about

* Make compile on new versions of npm

* Add deployment script to rebuild editor.graphite.rs on tag creation

* Remove deploy script

* Comment out unused Svelte props causing warnings

* Many small fixes, including fixing @ imports

---------

Co-authored-by: hypercube <0hypercube@gmail.com>
Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
Dennis Kobert 2023-04-25 00:43:27 +02:00 committed by Keavon Chambers
parent c814abc347
commit e6216009ee
29 changed files with 4532 additions and 7616 deletions

View File

@ -1,33 +0,0 @@
#!/bin/sh
# Switch to the correct branch
if [[ -z "${CF_PAGES_BRANCH}" ]]; then
git switch master || git switch -c unknown-branch
else
git switch $CF_PAGES_BRANCH || git switch -c $CF_PAGES_BRANCH
fi
# Install the latest version of the Rust toolchain
echo 🔧 Install Rust
curl https://sh.rustup.rs -sSf | sh -s -- -y
export PATH=$PATH:/opt/buildhome/.cargo/bin
echo rustc version:
rustc --version
# Install the project's Node dependencies through npm
echo 🚧 Install Node dependencies
echo node version:
node --version
echo npm version:
npm --version
cd frontend
npm ci
# Install the cargo-about Rust dependency that's used during the Webpack build process (in `webpack.config.js`)
echo 📦 Install cargo-about
cargo install cargo-about
# Build for production
echo 👷 Build Graphite web client
export NODE_ENV=production
npm run build && mv public dist # `&&` is used here to preserve the exit code

View File

@ -13,6 +13,10 @@ env:
jobs: jobs:
build: build:
runs-on: self-hosted runs-on: self-hosted
permissions:
contents: read
deployments: write
pull-requests: write
env: env:
RUSTC_WRAPPER: /usr/bin/sccache RUSTC_WRAPPER: /usr/bin/sccache
CARGO_INCREMENTAL: 0 CARGO_INCREMENTAL: 0
@ -21,6 +25,20 @@ jobs:
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- name: Comment deploy start
if: github.event_name != 'push'
uses: mshick/add-pr-comment@v2
with:
message-id: cloudflare-deploy
message: |
### <span aria-hidden="true">🚧</span> Deploy Preview building...
| Name | Link |
|---------------------------------|------------------------|
|<span aria-hidden="true">🔨</span> Latest commit | ${{ github.sha }} |
|<span aria-hidden="true">🔍</span> Latest deploy log | ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} |
---
- name: 🔧 Set up Node - name: 🔧 Set up Node
uses: actions/setup-node@v1 uses: actions/setup-node@v1
with: with:
@ -40,11 +58,36 @@ jobs:
- name: 🌐 Build Graphite web code - name: 🌐 Build Graphite web code
env: env:
NODE_ENV: production NODE_ENV: production
SKIP_CARGO_ABOUT: true
run: | run: |
cd frontend cd frontend
mold -run npm run build mold -run npm run build
- name: Publish
id: cloudflare
uses: cloudflare/pages-action@1
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
projectName: graphite-dev # e.g. 'my-project'
directory: frontend/dist # e.g. 'dist'
gitHubToken: ${{ secrets.GITHUB_TOKEN }}
- name: Comment deploy url
uses: mshick/add-pr-comment@v2
with:
message-id: cloudflare-deploy
message: |
### <span aria-hidden="true">✅</span> Deploy Preview ready!
| Name | Link |
|---------------------------------|------------------------|
|<span aria-hidden="true">🔨</span> Latest commit | ${{ github.sha }} |
|<span aria-hidden="true">🔍</span> Latest deploy log | ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} |
|<span aria-hidden="true">😎</span> Deploy Preview Url | [${{ steps.cloudflare.outputs.url }}](${{ steps.cloudflare.outputs.url }}) |
|<span aria-hidden="true">🌳</span> Environment | ${{ steps.cloudflare.outputs.environment }} |
---
- name: 👕 Lint Graphite web formatting - name: 👕 Lint Graphite web formatting
env: env:
NODE_ENV: production NODE_ENV: production

56
.github/workflows/deploy.yml vendored Normal file
View File

@ -0,0 +1,56 @@
name: Deploy release
on:
push:
tags:
- 'latest-stable'
env:
CARGO_TERM_COLOR: always
jobs:
build:
runs-on: self-hosted
permissions:
contents: read
deployments: write
env:
RUSTC_WRAPPER: /usr/bin/sccache
CARGO_INCREMENTAL: 0
SCCACHE_DIR: /var/lib/github-actions/.cache
steps:
- uses: actions/checkout@v2
- name: 🔧 Set up Node
uses: actions/setup-node@v1
with:
node-version: '16.x'
- name: 🚧 Install Node dependencies
run: |
cd frontend
npm ci
- name: 🔼 Update Rust to latest stable
run: |
rustc --version
rustup update stable
rustc --version
- name: 🌐 Build Graphite web code
env:
NODE_ENV: production
run: |
cd frontend
mold -run npm run build
- name: Publish
id: cloudflare
uses: cloudflare/pages-action@1
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
projectName: graphite-editor
directory: frontend/dist
gitHubToken: ${{ secrets.GITHUB_TOKEN }}

View File

@ -48,9 +48,6 @@ opt-level = 1
[profile.dev.package.graphene-std] [profile.dev.package.graphene-std]
opt-level = 1 opt-level = 1
[profile.dev.package.graphite-wasm]
opt-level = 1
[profile.dev.package.autoquant] [profile.dev.package.autoquant]
opt-level = 3 opt-level = 3
@ -60,5 +57,5 @@ opt-level = 3
[profile.dev.package.xxhash-rust] [profile.dev.package.xxhash-rust]
opt-level = 3 opt-level = 3
#[profile.dev] [profile.dev]
#opt-level = 3 opt-level = 1

3
frontend/.gitignore vendored
View File

@ -1,3 +1,6 @@
node_modules/ node_modules/
wasm/pkg/ wasm/pkg/
public/build/ public/build/
dist/**
!dist/.git-keep-directory
.parcel-cache

12
frontend/.parcelrc Normal file
View File

@ -0,0 +1,12 @@
{
"extends": "@parcel/config-default",
"transformers": {
"*.svg": [
"...",
"@parcel/transformer-inline-string"
],
"*.svelte": [
"parcel-transformer-svelte3-plus"
]
}
}

0
frontend/dist/.git-keep-directory vendored Normal file
View File

13
frontend/index.html Normal file
View File

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Graphite Editor</title>
</head>
<body>
<!-- This script tag points to the source of the JS file we want to load and bundle -->
<script type="module" src="src/main.ts"></script>
</body>
</html>

11413
frontend/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -3,17 +3,24 @@
"private": true, "private": true,
"description": "Graphite's web app frontend. Planned to be replaced by a native GUI written in Rust in the future.", "description": "Graphite's web app frontend. Planned to be replaced by a native GUI written in Rust in the future.",
"author": "Graphite Authors <contact@graphite.rs>", "author": "Graphite Authors <contact@graphite.rs>",
"browserslist": "> 1.5%, last 2 versions, not dead, not ie 11, not op_mini all, not ios_saf < 13",
"type": "module",
"alias": {
"@graphite-frontend/*": "~/$1",
"@graphite/../assets/*": "~/assets/$1",
"@graphite/../public/*": "~/public/$1",
"@graphite/*": "~/src/$1"
},
"scripts": { "scripts": {
"start": "npm run serve", "start": "npm run build-wasm && concurrently -k \"parcel serve index.html --port 8080\" \"npm run watch:wasm\" || (npm run print-building-help && exit 1)",
"serve": "webpack serve || (npm run print-building-help && exit 1)", "build": "npm run build-wasm-prod && npm run build-licenses && parcel build index.html || (npm run print-building-help && exit 1)",
"build": "webpack build || (npm run print-building-help && exit 1)", "build-licenses": "webpack build",
"build-prod-unix": "NODE_ENV=production webpack build || (npm run print-building-help && exit 1)", "tauri:dev": "echo 'Make sure you build the wasm binary for tauri using `npm run tauri:build-wasm`' && parcel serve index.html --port 8080",
"build-prod-windows": "set NODE_ENV=production && webpack build || (npm run print-building-help && exit 1)", "build-wasm": "wasm-pack build ./wasm --dev --target=web",
"check": "svelte-check", "build-wasm-prod": "wasm-pack build ./wasm --release --target=web",
"lint": "webpack lint || (npm run print-linting-help && exit 1)", "tauri:build-wasm": "wasm-pack build ./wasm --release --target=web -- --features tauri",
"lint-no-fix": "webpack lint --no-fix || (npm run print-linting-help && exit 1)", "watch:wasm": "cargo watch --postpone --workdir wasm --shell \"wasm-pack build . --dev --target=web -- --color always\"",
"tauri:build": "webpack tauri:build", "--------------------": "",
"tauri:serve": "webpack tauri:serve",
"print-building-help": "echo 'Graphite project failed to build. Did you remember to `npm install` the dependencies in `/frontend`?'", "print-building-help": "echo 'Graphite project failed to build. Did you remember to `npm install` the dependencies in `/frontend`?'",
"print-linting-help": "echo 'Graphite project had lint errors, or may have otherwise failed. In the latter case, did you remember to `npm install` the dependencies in `/frontend`?'" "print-linting-help": "echo 'Graphite project had lint errors, or may have otherwise failed. In the latter case, did you remember to `npm install` the dependencies in `/frontend`?'"
}, },
@ -24,35 +31,27 @@
"reflect-metadata": "^0.1.13" "reflect-metadata": "^0.1.13"
}, },
"devDependencies": { "devDependencies": {
"@parcel/transformer-inline-string": "^2.8.3",
"@parcel/transformer-webmanifest": "^2.8.3",
"@types/license-checker-webpack-plugin": "^0.2.1", "@types/license-checker-webpack-plugin": "^0.2.1",
"@types/node": "^18.11.18", "@types/node": "^18.15.11",
"@types/webpack": "^5.28.0", "@types/webpack": "^5.28.1",
"@types/webpack-dev-server": "^4.7.2", "buffer": "^5.7.1",
"@typescript-eslint/eslint-plugin": "^5.48.0", "concurrently": "^7.6.0",
"@typescript-eslint/parser": "^5.48.0",
"@wasm-tool/wasm-pack-plugin": "^1.6.0",
"css-loader": "^6.7.3",
"eslint": "^8.31.0",
"eslint-config-prettier": "^8.6.0",
"eslint-plugin-import": "^2.26.0",
"license-checker-webpack-plugin": "^0.2.1", "license-checker-webpack-plugin": "^0.2.1",
"prettier": "^2.8.2", "parcel": "^2.8.3",
"sass": "^1.57.1", "parcel-transformer-svelte3-plus": "^0.2.8",
"sass-loader": "^13.2.0", "postcss": "^8.4.21",
"svelte": "^3.55.0", "process": "^0.11.10",
"svelte-check": "^3.0.1", "svelte": "^3.56.0",
"svelte-check-plugin": "^1.0.4", "svelte-preprocess": "^4.10.7",
"svelte-loader": "^3.1.4",
"svelte-preprocess": "^5.0.0",
"ts-loader": "^9.4.2",
"ts-node": "^10.9.1", "ts-node": "^10.9.1",
"typescript": "^4.9.4", "typescript": "^4.9.5",
"webpack": "^5.75.0", "webpack": "^5.75.0",
"webpack-cli": "^5.0.1", "webpack-cli": "^5.0.1"
"webpack-dev-server": "^4.11.1"
}, },
"optionalDependencies": { "optionalDependencies": {
"wasm-pack": "^0.10.3" "wasm-pack": "0.10.3"
}, },
"//": "Notes about dependency issues and incompatibilities should be added here when needed.", "//": "Notes about dependency issues and incompatibilities should be added here when needed.",
"homepage": "https://graphite.rs", "homepage": "https://graphite.rs",

View File

@ -23,12 +23,10 @@ graphite-editor = { version = "0.0.0", path = "../../editor" }
chrono = "^0.4.23" chrono = "^0.4.23"
tokio = {version ="1", features = ["full"] } tokio = {version ="1", features = ["full"] }
ron = "0.8" ron = "0.8"
log = "0.4" log = "0.4"
fern = {version = "0.6", features = ["colored"] } fern = {version = "0.6", features = ["colored"] }
futures = "0.3.25" futures = "0.3.25"
[features] [features]
gpu = ["graphite-editor/gpu"] gpu = ["graphite-editor/gpu"]
quantization = ["graphite-editor/quantization"] quantization = ["graphite-editor/quantization"]
@ -37,4 +35,4 @@ quantization = ["graphite-editor/quantization"]
default = [ "custom-protocol" ] default = [ "custom-protocol" ]
# this feature is used for production builds where `devPath` points to the filesystem # this feature is used for production builds where `devPath` points to the filesystem
# DO NOT remove this # DO NOT remove this
custom-protocol = [ "tauri/custom-protocol" ] custom-protocol = ["tauri/custom-protocol"]

View File

@ -66,8 +66,8 @@ async fn main() {
tauri::Builder::default() tauri::Builder::default()
.invoke_handler(tauri::generate_handler![set_random_seed, handle_message]) .invoke_handler(tauri::generate_handler![set_random_seed, handle_message])
.setup(|_app| { .setup(|_app| {
//use tauri::Manager; use tauri::Manager;
//_app.get_window("main").unwrap().open_devtools(); _app.get_window("main").unwrap().open_devtools();
Ok(()) Ok(())
}) })
.run(tauri::generate_context!()) .run(tauri::generate_context!())

View File

@ -1,9 +1,9 @@
{ {
"$schema": "../node_modules/@tauri-apps/cli/schema.json", "$schema": "../node_modules/@tauri-apps/cli/schema.json",
"build": { "build": {
"beforeBuildCommand": "npm run build", "beforeBuildCommand": "npm run tauri:build-wasm",
"beforeDevCommand": "npm start", "beforeDevCommand": "npm run tauri:dev",
"distDir": "../public", "distDir": "../dist",
"devPath": "http://127.0.0.1:8080/" "devPath": "http://127.0.0.1:8080/"
}, },
"package": { "package": {

View File

@ -185,7 +185,7 @@
flex-direction: column; flex-direction: column;
} }
.widget-row { .widget-row.widget-row {
flex: 0 0 auto; flex: 0 0 auto;
display: flex; display: flex;
min-height: 32px; min-height: 32px;

View File

@ -76,7 +76,7 @@
} }
} }
& + .text-button { &.text-button + .text-button {
margin-left: 8px; margin-left: 8px;
} }

View File

@ -13,8 +13,8 @@
let open = false; let open = false;
export let value: Color; export let value: Color;
export let noTransparency = false; // TODO: Rename to allowTransparency, also implement allowNone // export let noTransparency = false; // TODO: Rename to allowTransparency, also implement allowNone
export let disabled = false; // TODO: Design and implement // export let disabled = false; // TODO: Design and implement
export let tooltip: string | undefined = undefined; export let tooltip: string | undefined = undefined;
export let sharpRightCorners = false; export let sharpRightCorners = false;

View File

@ -1,7 +1,7 @@
<script lang="ts"> <script lang="ts">
import LayoutRow from "@graphite/components/layout/LayoutRow.svelte"; import LayoutRow from "@graphite/components/layout/LayoutRow.svelte";
export let maximized = false; // export let maximized = false;
</script> </script>
<LayoutRow class="window-buttons-mac"> <LayoutRow class="window-buttons-mac">

View File

@ -0,0 +1 @@
// This is a dummy entry point for webpack

View File

@ -1,47 +1,47 @@
/* eslint-disable import/first */ /* eslint-disable import/first */
// Graphics // Graphics
import GraphiteLogotypeSolid from "@graphite/../assets/graphics/graphite-logotype-solid.svg"; import GraphiteLogotypeSolid from "@graphite-frontend/assets/graphics/graphite-logotype-solid.svg";
const GRAPHICS = { const GRAPHICS = {
GraphiteLogotypeSolid: { svg: GraphiteLogotypeSolid, size: undefined }, GraphiteLogotypeSolid: { svg: GraphiteLogotypeSolid, size: undefined },
} as const; } as const;
// 12px Solid // 12px Solid
import Add from "@graphite/../assets/icon-12px-solid/add.svg"; import Add from "@graphite-frontend/assets/icon-12px-solid/add.svg";
import Checkmark from "@graphite/../assets/icon-12px-solid/checkmark.svg"; import Checkmark from "@graphite-frontend/assets/icon-12px-solid/checkmark.svg";
import CloseX from "@graphite/../assets/icon-12px-solid/close-x.svg"; import CloseX from "@graphite-frontend/assets/icon-12px-solid/close-x.svg";
import DropdownArrow from "@graphite/../assets/icon-12px-solid/dropdown-arrow.svg"; import DropdownArrow from "@graphite-frontend/assets/icon-12px-solid/dropdown-arrow.svg";
import Edit from "@graphite/../assets/icon-12px-solid/edit.svg"; import Edit from "@graphite-frontend/assets/icon-12px-solid/edit.svg";
import Empty12px from "@graphite/../assets/icon-12px-solid/empty-12px.svg"; import Empty12px from "@graphite-frontend/assets/icon-12px-solid/empty-12px.svg";
import FullscreenEnter from "@graphite/../assets/icon-12px-solid/fullscreen-enter.svg"; import FullscreenEnter from "@graphite-frontend/assets/icon-12px-solid/fullscreen-enter.svg";
import FullscreenExit from "@graphite/../assets/icon-12px-solid/fullscreen-exit.svg"; import FullscreenExit from "@graphite-frontend/assets/icon-12px-solid/fullscreen-exit.svg";
import Grid from "@graphite/../assets/icon-12px-solid/grid.svg"; import Grid from "@graphite-frontend/assets/icon-12px-solid/grid.svg";
import Info from "@graphite/../assets/icon-12px-solid/info.svg"; import Info from "@graphite-frontend/assets/icon-12px-solid/info.svg";
import KeyboardArrowDown from "@graphite/../assets/icon-12px-solid/keyboard-arrow-down.svg"; import KeyboardArrowDown from "@graphite-frontend/assets/icon-12px-solid/keyboard-arrow-down.svg";
import KeyboardArrowLeft from "@graphite/../assets/icon-12px-solid/keyboard-arrow-left.svg"; import KeyboardArrowLeft from "@graphite-frontend/assets/icon-12px-solid/keyboard-arrow-left.svg";
import KeyboardArrowRight from "@graphite/../assets/icon-12px-solid/keyboard-arrow-right.svg"; import KeyboardArrowRight from "@graphite-frontend/assets/icon-12px-solid/keyboard-arrow-right.svg";
import KeyboardArrowUp from "@graphite/../assets/icon-12px-solid/keyboard-arrow-up.svg"; import KeyboardArrowUp from "@graphite-frontend/assets/icon-12px-solid/keyboard-arrow-up.svg";
import KeyboardBackspace from "@graphite/../assets/icon-12px-solid/keyboard-backspace.svg"; import KeyboardBackspace from "@graphite-frontend/assets/icon-12px-solid/keyboard-backspace.svg";
import KeyboardCommand from "@graphite/../assets/icon-12px-solid/keyboard-command.svg"; import KeyboardCommand from "@graphite-frontend/assets/icon-12px-solid/keyboard-command.svg";
import KeyboardControl from "@graphite/../assets/icon-12px-solid/keyboard-control.svg"; import KeyboardControl from "@graphite-frontend/assets/icon-12px-solid/keyboard-control.svg";
import KeyboardEnter from "@graphite/../assets/icon-12px-solid/keyboard-enter.svg"; import KeyboardEnter from "@graphite-frontend/assets/icon-12px-solid/keyboard-enter.svg";
import KeyboardOption from "@graphite/../assets/icon-12px-solid/keyboard-option.svg"; import KeyboardOption from "@graphite-frontend/assets/icon-12px-solid/keyboard-option.svg";
import KeyboardShift from "@graphite/../assets/icon-12px-solid/keyboard-shift.svg"; import KeyboardShift from "@graphite-frontend/assets/icon-12px-solid/keyboard-shift.svg";
import KeyboardSpace from "@graphite/../assets/icon-12px-solid/keyboard-space.svg"; import KeyboardSpace from "@graphite-frontend/assets/icon-12px-solid/keyboard-space.svg";
import KeyboardTab from "@graphite/../assets/icon-12px-solid/keyboard-tab.svg"; import KeyboardTab from "@graphite-frontend/assets/icon-12px-solid/keyboard-tab.svg";
import Link from "@graphite/../assets/icon-12px-solid/link.svg"; import Link from "@graphite-frontend/assets/icon-12px-solid/link.svg";
import Overlays from "@graphite/../assets/icon-12px-solid/overlays.svg"; import Overlays from "@graphite-frontend/assets/icon-12px-solid/overlays.svg";
import Remove from "@graphite/../assets/icon-12px-solid/remove.svg"; import Remove from "@graphite-frontend/assets/icon-12px-solid/remove.svg";
import ResetColors from "@graphite/../assets/icon-12px-solid/reset-colors.svg"; import ResetColors from "@graphite-frontend/assets/icon-12px-solid/reset-colors.svg";
import Snapping from "@graphite/../assets/icon-12px-solid/snapping.svg"; import Snapping from "@graphite-frontend/assets/icon-12px-solid/snapping.svg";
import Swap from "@graphite/../assets/icon-12px-solid/swap.svg"; import Swap from "@graphite-frontend/assets/icon-12px-solid/swap.svg";
import VerticalEllipsis from "@graphite/../assets/icon-12px-solid/vertical-ellipsis.svg"; import VerticalEllipsis from "@graphite-frontend/assets/icon-12px-solid/vertical-ellipsis.svg";
import Warning from "@graphite/../assets/icon-12px-solid/warning.svg"; import Warning from "@graphite-frontend/assets/icon-12px-solid/warning.svg";
import WindowButtonWinClose from "@graphite/../assets/icon-12px-solid/window-button-win-close.svg"; import WindowButtonWinClose from "@graphite-frontend/assets/icon-12px-solid/window-button-win-close.svg";
import WindowButtonWinMaximize from "@graphite/../assets/icon-12px-solid/window-button-win-maximize.svg"; import WindowButtonWinMaximize from "@graphite-frontend/assets/icon-12px-solid/window-button-win-maximize.svg";
import WindowButtonWinMinimize from "@graphite/../assets/icon-12px-solid/window-button-win-minimize.svg"; import WindowButtonWinMinimize from "@graphite-frontend/assets/icon-12px-solid/window-button-win-minimize.svg";
import WindowButtonWinRestoreDown from "@graphite/../assets/icon-12px-solid/window-button-win-restore-down.svg"; import WindowButtonWinRestoreDown from "@graphite-frontend/assets/icon-12px-solid/window-button-win-restore-down.svg";
const SOLID_12PX = { const SOLID_12PX = {
Add: { svg: Add, size: 12 }, Add: { svg: Add, size: 12 },
@ -81,61 +81,61 @@ const SOLID_12PX = {
} as const; } as const;
// 16px Solid // 16px Solid
import AlignBottom from "@graphite/../assets/icon-16px-solid/align-bottom.svg"; import AlignBottom from "@graphite-frontend/assets/icon-16px-solid/align-bottom.svg";
import AlignHorizontalCenter from "@graphite/../assets/icon-16px-solid/align-horizontal-center.svg"; import AlignHorizontalCenter from "@graphite-frontend/assets/icon-16px-solid/align-horizontal-center.svg";
import AlignLeft from "@graphite/../assets/icon-16px-solid/align-left.svg"; import AlignLeft from "@graphite-frontend/assets/icon-16px-solid/align-left.svg";
import AlignRight from "@graphite/../assets/icon-16px-solid/align-right.svg"; import AlignRight from "@graphite-frontend/assets/icon-16px-solid/align-right.svg";
import AlignTop from "@graphite/../assets/icon-16px-solid/align-top.svg"; import AlignTop from "@graphite-frontend/assets/icon-16px-solid/align-top.svg";
import AlignVerticalCenter from "@graphite/../assets/icon-16px-solid/align-vertical-center.svg"; import AlignVerticalCenter from "@graphite-frontend/assets/icon-16px-solid/align-vertical-center.svg";
import BooleanDifference from "@graphite/../assets/icon-16px-solid/boolean-difference.svg"; import BooleanDifference from "@graphite-frontend/assets/icon-16px-solid/boolean-difference.svg";
import BooleanIntersect from "@graphite/../assets/icon-16px-solid/boolean-intersect.svg"; import BooleanIntersect from "@graphite-frontend/assets/icon-16px-solid/boolean-intersect.svg";
import BooleanSubtractBack from "@graphite/../assets/icon-16px-solid/boolean-subtract-back.svg"; import BooleanSubtractBack from "@graphite-frontend/assets/icon-16px-solid/boolean-subtract-back.svg";
import BooleanSubtractFront from "@graphite/../assets/icon-16px-solid/boolean-subtract-front.svg"; import BooleanSubtractFront from "@graphite-frontend/assets/icon-16px-solid/boolean-subtract-front.svg";
import BooleanUnion from "@graphite/../assets/icon-16px-solid/boolean-union.svg"; import BooleanUnion from "@graphite-frontend/assets/icon-16px-solid/boolean-union.svg";
import CheckboxChecked from "@graphite/../assets/icon-16px-solid/checkbox-checked.svg"; import CheckboxChecked from "@graphite-frontend/assets/icon-16px-solid/checkbox-checked.svg";
import CheckboxUnchecked from "@graphite/../assets/icon-16px-solid/checkbox-unchecked.svg"; import CheckboxUnchecked from "@graphite-frontend/assets/icon-16px-solid/checkbox-unchecked.svg";
import Copy from "@graphite/../assets/icon-16px-solid/copy.svg"; import Copy from "@graphite-frontend/assets/icon-16px-solid/copy.svg";
import Eyedropper from "@graphite/../assets/icon-16px-solid/eyedropper.svg"; import Eyedropper from "@graphite-frontend/assets/icon-16px-solid/eyedropper.svg";
import EyeHidden from "@graphite/../assets/icon-16px-solid/eye-hidden.svg"; import EyeHidden from "@graphite-frontend/assets/icon-16px-solid/eye-hidden.svg";
import EyeVisible from "@graphite/../assets/icon-16px-solid/eye-visible.svg"; import EyeVisible from "@graphite-frontend/assets/icon-16px-solid/eye-visible.svg";
import File from "@graphite/../assets/icon-16px-solid/file.svg"; import File from "@graphite-frontend/assets/icon-16px-solid/file.svg";
import FlipHorizontal from "@graphite/../assets/icon-16px-solid/flip-horizontal.svg"; import FlipHorizontal from "@graphite-frontend/assets/icon-16px-solid/flip-horizontal.svg";
import FlipVertical from "@graphite/../assets/icon-16px-solid/flip-vertical.svg"; import FlipVertical from "@graphite-frontend/assets/icon-16px-solid/flip-vertical.svg";
import Folder from "@graphite/../assets/icon-16px-solid/folder.svg"; import Folder from "@graphite-frontend/assets/icon-16px-solid/folder.svg";
import GraphiteLogo from "@graphite/../assets/icon-16px-solid/graphite-logo.svg"; import GraphiteLogo from "@graphite-frontend/assets/icon-16px-solid/graphite-logo.svg";
import Layer from "@graphite/../assets/icon-16px-solid/layer.svg"; import Layer from "@graphite-frontend/assets/icon-16px-solid/layer.svg";
import NodeArtboard from "@graphite/../assets/icon-16px-solid/node-artboard.svg"; import NodeArtboard from "@graphite-frontend/assets/icon-16px-solid/node-artboard.svg";
import NodeBlur from "@graphite/../assets/icon-16px-solid/node-blur.svg"; import NodeBlur from "@graphite-frontend/assets/icon-16px-solid/node-blur.svg";
import NodeBrushwork from "@graphite/../assets/icon-16px-solid/node-brushwork.svg"; import NodeBrushwork from "@graphite-frontend/assets/icon-16px-solid/node-brushwork.svg";
import NodeColorCorrection from "@graphite/../assets/icon-16px-solid/node-color-correction.svg"; import NodeColorCorrection from "@graphite-frontend/assets/icon-16px-solid/node-color-correction.svg";
import NodeGradient from "@graphite/../assets/icon-16px-solid/node-gradient.svg"; import NodeGradient from "@graphite-frontend/assets/icon-16px-solid/node-gradient.svg";
import NodeImage from "@graphite/../assets/icon-16px-solid/node-image.svg"; import NodeImage from "@graphite-frontend/assets/icon-16px-solid/node-image.svg";
import NodeImaginate from "@graphite/../assets/icon-16px-solid/node-imaginate.svg"; import NodeImaginate from "@graphite-frontend/assets/icon-16px-solid/node-imaginate.svg";
import NodeMagicWand from "@graphite/../assets/icon-16px-solid/node-magic-wand.svg"; import NodeMagicWand from "@graphite-frontend/assets/icon-16px-solid/node-magic-wand.svg";
import NodeMask from "@graphite/../assets/icon-16px-solid/node-mask.svg"; import NodeMask from "@graphite-frontend/assets/icon-16px-solid/node-mask.svg";
import NodeMotionBlur from "@graphite/../assets/icon-16px-solid/node-motion-blur.svg"; import NodeMotionBlur from "@graphite-frontend/assets/icon-16px-solid/node-motion-blur.svg";
import NodeNodes from "@graphite/../assets/icon-16px-solid/node-nodes.svg"; import NodeNodes from "@graphite-frontend/assets/icon-16px-solid/node-nodes.svg";
import NodeOutput from "@graphite/../assets/icon-16px-solid/node-output.svg"; import NodeOutput from "@graphite-frontend/assets/icon-16px-solid/node-output.svg";
import NodeShape from "@graphite/../assets/icon-16px-solid/node-shape.svg"; import NodeShape from "@graphite-frontend/assets/icon-16px-solid/node-shape.svg";
import NodeText from "@graphite/../assets/icon-16px-solid/node-text.svg"; import NodeText from "@graphite-frontend/assets/icon-16px-solid/node-text.svg";
import NodeTransform from "@graphite/../assets/icon-16px-solid/node-transform.svg"; import NodeTransform from "@graphite-frontend/assets/icon-16px-solid/node-transform.svg";
import Paste from "@graphite/../assets/icon-16px-solid/paste.svg"; import Paste from "@graphite-frontend/assets/icon-16px-solid/paste.svg";
import Random from "@graphite/../assets/icon-16px-solid/random.svg"; import Random from "@graphite-frontend/assets/icon-16px-solid/random.svg";
import Regenerate from "@graphite/../assets/icon-16px-solid/regenerate.svg"; import Regenerate from "@graphite-frontend/assets/icon-16px-solid/regenerate.svg";
import Reload from "@graphite/../assets/icon-16px-solid/reload.svg"; import Reload from "@graphite-frontend/assets/icon-16px-solid/reload.svg";
import Rescale from "@graphite/../assets/icon-16px-solid/rescale.svg"; import Rescale from "@graphite-frontend/assets/icon-16px-solid/rescale.svg";
import Reset from "@graphite/../assets/icon-16px-solid/reset.svg"; import Reset from "@graphite-frontend/assets/icon-16px-solid/reset.svg";
import Settings from "@graphite/../assets/icon-16px-solid/settings.svg"; import Settings from "@graphite-frontend/assets/icon-16px-solid/settings.svg";
import Trash from "@graphite/../assets/icon-16px-solid/trash.svg"; import Trash from "@graphite-frontend/assets/icon-16px-solid/trash.svg";
import ViewModeNormal from "@graphite/../assets/icon-16px-solid/view-mode-normal.svg"; import ViewModeNormal from "@graphite-frontend/assets/icon-16px-solid/view-mode-normal.svg";
import ViewModeOutline from "@graphite/../assets/icon-16px-solid/view-mode-outline.svg"; import ViewModeOutline from "@graphite-frontend/assets/icon-16px-solid/view-mode-outline.svg";
import ViewModePixels from "@graphite/../assets/icon-16px-solid/view-mode-pixels.svg"; import ViewModePixels from "@graphite-frontend/assets/icon-16px-solid/view-mode-pixels.svg";
import ViewportDesignMode from "@graphite/../assets/icon-16px-solid/viewport-design-mode.svg"; import ViewportDesignMode from "@graphite-frontend/assets/icon-16px-solid/viewport-design-mode.svg";
import ViewportGuideMode from "@graphite/../assets/icon-16px-solid/viewport-guide-mode.svg"; import ViewportGuideMode from "@graphite-frontend/assets/icon-16px-solid/viewport-guide-mode.svg";
import ViewportSelectMode from "@graphite/../assets/icon-16px-solid/viewport-select-mode.svg"; import ViewportSelectMode from "@graphite-frontend/assets/icon-16px-solid/viewport-select-mode.svg";
import ZoomIn from "@graphite/../assets/icon-16px-solid/zoom-in.svg"; import ZoomIn from "@graphite-frontend/assets/icon-16px-solid/zoom-in.svg";
import ZoomOut from "@graphite/../assets/icon-16px-solid/zoom-out.svg"; import ZoomOut from "@graphite-frontend/assets/icon-16px-solid/zoom-out.svg";
import ZoomReset from "@graphite/../assets/icon-16px-solid/zoom-reset.svg"; import ZoomReset from "@graphite-frontend/assets/icon-16px-solid/zoom-reset.svg";
const SOLID_16PX = { const SOLID_16PX = {
AlignBottom: { svg: AlignBottom, size: 16 }, AlignBottom: { svg: AlignBottom, size: 16 },
@ -196,17 +196,17 @@ const SOLID_16PX = {
} as const; } as const;
// 16px Two-Tone // 16px Two-Tone
import MouseHintDrag from "@graphite/../assets/icon-16px-two-tone/mouse-hint-drag.svg"; import MouseHintDrag from "@graphite-frontend/assets/icon-16px-two-tone/mouse-hint-drag.svg";
import MouseHintLmbDouble from "@graphite/../assets/icon-16px-two-tone/mouse-hint-lmb-double.svg"; import MouseHintLmbDouble from "@graphite-frontend/assets/icon-16px-two-tone/mouse-hint-lmb-double.svg";
import MouseHintLmbDrag from "@graphite/../assets/icon-16px-two-tone/mouse-hint-lmb-drag.svg"; import MouseHintLmbDrag from "@graphite-frontend/assets/icon-16px-two-tone/mouse-hint-lmb-drag.svg";
import MouseHintLmb from "@graphite/../assets/icon-16px-two-tone/mouse-hint-lmb.svg"; import MouseHintLmb from "@graphite-frontend/assets/icon-16px-two-tone/mouse-hint-lmb.svg";
import MouseHintMmbDrag from "@graphite/../assets/icon-16px-two-tone/mouse-hint-mmb-drag.svg"; import MouseHintMmbDrag from "@graphite-frontend/assets/icon-16px-two-tone/mouse-hint-mmb-drag.svg";
import MouseHintMmb from "@graphite/../assets/icon-16px-two-tone/mouse-hint-mmb.svg"; import MouseHintMmb from "@graphite-frontend/assets/icon-16px-two-tone/mouse-hint-mmb.svg";
import MouseHintNone from "@graphite/../assets/icon-16px-two-tone/mouse-hint-none.svg"; import MouseHintNone from "@graphite-frontend/assets/icon-16px-two-tone/mouse-hint-none.svg";
import MouseHintRmbDrag from "@graphite/../assets/icon-16px-two-tone/mouse-hint-rmb-drag.svg"; import MouseHintRmbDrag from "@graphite-frontend/assets/icon-16px-two-tone/mouse-hint-rmb-drag.svg";
import MouseHintRmb from "@graphite/../assets/icon-16px-two-tone/mouse-hint-rmb.svg"; import MouseHintRmb from "@graphite-frontend/assets/icon-16px-two-tone/mouse-hint-rmb.svg";
import MouseHintScrollDown from "@graphite/../assets/icon-16px-two-tone/mouse-hint-scroll-down.svg"; import MouseHintScrollDown from "@graphite-frontend/assets/icon-16px-two-tone/mouse-hint-scroll-down.svg";
import MouseHintScrollUp from "@graphite/../assets/icon-16px-two-tone/mouse-hint-scroll-up.svg"; import MouseHintScrollUp from "@graphite-frontend/assets/icon-16px-two-tone/mouse-hint-scroll-up.svg";
const TWO_TONE_16PX = { const TWO_TONE_16PX = {
MouseHintDrag: { svg: MouseHintDrag, size: 16 }, MouseHintDrag: { svg: MouseHintDrag, size: 16 },
@ -223,29 +223,29 @@ const TWO_TONE_16PX = {
} as const; } as const;
// 24px Two-Tone // 24px Two-Tone
import GeneralArtboardTool from "@graphite/../assets/icon-24px-two-tone/general-artboard-tool.svg"; import GeneralArtboardTool from "@graphite-frontend/assets/icon-24px-two-tone/general-artboard-tool.svg";
import GeneralEyedropperTool from "@graphite/../assets/icon-24px-two-tone/general-eyedropper-tool.svg"; import GeneralEyedropperTool from "@graphite-frontend/assets/icon-24px-two-tone/general-eyedropper-tool.svg";
import GeneralFillTool from "@graphite/../assets/icon-24px-two-tone/general-fill-tool.svg"; import GeneralFillTool from "@graphite-frontend/assets/icon-24px-two-tone/general-fill-tool.svg";
import GeneralGradientTool from "@graphite/../assets/icon-24px-two-tone/general-gradient-tool.svg"; import GeneralGradientTool from "@graphite-frontend/assets/icon-24px-two-tone/general-gradient-tool.svg";
import GeneralNavigateTool from "@graphite/../assets/icon-24px-two-tone/general-navigate-tool.svg"; import GeneralNavigateTool from "@graphite-frontend/assets/icon-24px-two-tone/general-navigate-tool.svg";
import GeneralSelectTool from "@graphite/../assets/icon-24px-two-tone/general-select-tool.svg"; import GeneralSelectTool from "@graphite-frontend/assets/icon-24px-two-tone/general-select-tool.svg";
import RasterBrushTool from "@graphite/../assets/icon-24px-two-tone/raster-brush-tool.svg"; import RasterBrushTool from "@graphite-frontend/assets/icon-24px-two-tone/raster-brush-tool.svg";
import RasterCloneTool from "@graphite/../assets/icon-24px-two-tone/raster-clone-tool.svg"; import RasterCloneTool from "@graphite-frontend/assets/icon-24px-two-tone/raster-clone-tool.svg";
import RasterDetailTool from "@graphite/../assets/icon-24px-two-tone/raster-detail-tool.svg"; import RasterDetailTool from "@graphite-frontend/assets/icon-24px-two-tone/raster-detail-tool.svg";
import RasterFrameTool from "@graphite/../assets/icon-24px-two-tone/raster-frame-tool.svg"; import RasterFrameTool from "@graphite-frontend/assets/icon-24px-two-tone/raster-frame-tool.svg";
import RasterHealTool from "@graphite/../assets/icon-24px-two-tone/raster-heal-tool.svg"; import RasterHealTool from "@graphite-frontend/assets/icon-24px-two-tone/raster-heal-tool.svg";
import RasterImaginateTool from "@graphite/../assets/icon-24px-two-tone/raster-imaginate-tool.svg"; import RasterImaginateTool from "@graphite-frontend/assets/icon-24px-two-tone/raster-imaginate-tool.svg";
import RasterPatchTool from "@graphite/../assets/icon-24px-two-tone/raster-patch-tool.svg"; import RasterPatchTool from "@graphite-frontend/assets/icon-24px-two-tone/raster-patch-tool.svg";
import RasterRelightTool from "@graphite/../assets/icon-24px-two-tone/raster-relight-tool.svg"; import RasterRelightTool from "@graphite-frontend/assets/icon-24px-two-tone/raster-relight-tool.svg";
import VectorEllipseTool from "@graphite/../assets/icon-24px-two-tone/vector-ellipse-tool.svg"; import VectorEllipseTool from "@graphite-frontend/assets/icon-24px-two-tone/vector-ellipse-tool.svg";
import VectorFreehandTool from "@graphite/../assets/icon-24px-two-tone/vector-freehand-tool.svg"; import VectorFreehandTool from "@graphite-frontend/assets/icon-24px-two-tone/vector-freehand-tool.svg";
import VectorLineTool from "@graphite/../assets/icon-24px-two-tone/vector-line-tool.svg"; import VectorLineTool from "@graphite-frontend/assets/icon-24px-two-tone/vector-line-tool.svg";
import VectorPathTool from "@graphite/../assets/icon-24px-two-tone/vector-path-tool.svg"; import VectorPathTool from "@graphite-frontend/assets/icon-24px-two-tone/vector-path-tool.svg";
import VectorPenTool from "@graphite/../assets/icon-24px-two-tone/vector-pen-tool.svg"; import VectorPenTool from "@graphite-frontend/assets/icon-24px-two-tone/vector-pen-tool.svg";
import VectorRectangleTool from "@graphite/../assets/icon-24px-two-tone/vector-rectangle-tool.svg"; import VectorRectangleTool from "@graphite-frontend/assets/icon-24px-two-tone/vector-rectangle-tool.svg";
import VectorShapeTool from "@graphite/../assets/icon-24px-two-tone/vector-shape-tool.svg"; import VectorShapeTool from "@graphite-frontend/assets/icon-24px-two-tone/vector-shape-tool.svg";
import VectorSplineTool from "@graphite/../assets/icon-24px-two-tone/vector-spline-tool.svg"; import VectorSplineTool from "@graphite-frontend/assets/icon-24px-two-tone/vector-spline-tool.svg";
import VectorTextTool from "@graphite/../assets/icon-24px-two-tone/vector-text-tool.svg"; import VectorTextTool from "@graphite-frontend/assets/icon-24px-two-tone/vector-text-tool.svg";
const TWO_TONE_24PX = { const TWO_TONE_24PX = {
GeneralArtboardTool: { svg: GeneralArtboardTool, size: 24 }, GeneralArtboardTool: { svg: GeneralArtboardTool, size: 24 },

View File

@ -1,15 +1,15 @@
import type WasmBindgenPackage from "@graphite/../wasm/pkg"; import type WasmBindgenPackage from "@graphite-frontend/wasm/pkg";
import init, { setRandomSeed, wasmMemory, JsEditorHandle } from "@graphite-frontend/wasm/pkg/graphite_wasm.js";
import { panicProxy } from "@graphite/utility-functions/panic-proxy"; import { panicProxy } from "@graphite/utility-functions/panic-proxy";
import { type JsMessageType } from "@graphite/wasm-communication/messages"; import { type JsMessageType } from "@graphite/wasm-communication/messages";
import { createSubscriptionRouter, type SubscriptionRouter } from "@graphite/wasm-communication/subscription-router"; import { createSubscriptionRouter, type SubscriptionRouter } from "@graphite/wasm-communication/subscription-router";
export type WasmRawInstance = typeof WasmBindgenPackage; export type WasmRawInstance = WebAssembly.Memory;
export type WasmEditorInstance = InstanceType<WasmRawInstance["JsEditorHandle"]>; export type WasmEditorInstance = JsEditorHandle;
export type Editor = Readonly<ReturnType<typeof createEditor>>; export type Editor = Readonly<ReturnType<typeof createEditor>>;
// `wasmImport` starts uninitialized because its initialization needs to occur asynchronously, and thus needs to occur by manually calling and awaiting `initWasm()` // `wasmImport` starts uninitialized because its initialization needs to occur asynchronously, and thus needs to occur by manually calling and awaiting `initWasm()`
let wasmImport: WasmRawInstance | undefined; let wasmImport: WebAssembly.Memory | undefined;
let editorInstance: WasmEditorInstance | undefined;
export async function updateImage(path: BigUint64Array, mime: string, imageData: Uint8Array, transform: Float64Array, documentId: bigint): Promise<void> { export async function updateImage(path: BigUint64Array, mime: string, imageData: Uint8Array, transform: Float64Array, documentId: bigint): Promise<void> {
const blob = new Blob([imageData], { type: mime }); const blob = new Blob([imageData], { type: mime });
@ -21,7 +21,7 @@ export async function updateImage(path: BigUint64Array, mime: string, imageData:
image.src = blobURL; image.src = blobURL;
await image.decode(); await image.decode();
editorInstance?.setImageBlobURL(documentId, path, blobURL, image.naturalWidth, image.naturalHeight,transform); window["editorInstance"]?.setImageBlobURL(documentId, path, blobURL, image.naturalWidth, image.naturalHeight, transform);
} }
export async function fetchImage(path: BigUint64Array, mime: string, documentId: bigint, url: string): Promise<void> { export async function fetchImage(path: BigUint64Array, mime: string, documentId: bigint, url: string): Promise<void> {
@ -35,7 +35,7 @@ export async function fetchImage(path: BigUint64Array, mime: string, documentId:
image.src = blobURL; image.src = blobURL;
await image.decode(); await image.decode();
editorInstance?.setImageBlobURL(documentId, path, blobURL, image.naturalWidth, image.naturalHeight, undefined); window["editorInstance"]?.setImageBlobURL(documentId, path, blobURL, image.naturalWidth, image.naturalHeight, undefined);
} }
const tauri = "__TAURI_METADATA__" in window && import("@tauri-apps/api"); const tauri = "__TAURI_METADATA__" in window && import("@tauri-apps/api");
@ -44,7 +44,7 @@ export async function dispatchTauri(message: unknown): Promise<void> {
try { try {
const response = await (await tauri).invoke("handle_message", { message }); const response = await (await tauri).invoke("handle_message", { message });
editorInstance?.tauriResponse(response); window["editorInstance"]?.tauriResponse(response);
} catch { } catch {
// eslint-disable-next-line no-console // eslint-disable-next-line no-console
console.error("Failed to dispatch Tauri message"); console.error("Failed to dispatch Tauri message");
@ -58,18 +58,16 @@ export async function initWasm(): Promise<void> {
// Import the WASM module JS bindings and wrap them in the panic proxy // Import the WASM module JS bindings and wrap them in the panic proxy
// eslint-disable-next-line import/no-cycle // eslint-disable-next-line import/no-cycle
wasmImport = await import("@graphite/../wasm/pkg"); await init();
wasmImport = await wasmMemory();
// Provide a random starter seed which must occur after initializing the WASM module, since WASM can't generate its own random numbers // Provide a random starter seed which must occur after initializing the WASM module, since WASM can't generate its own random numbers
const randomSeedFloat = Math.floor(Math.random() * Number.MAX_SAFE_INTEGER); const randomSeedFloat = Math.floor(Math.random() * Number.MAX_SAFE_INTEGER);
const randomSeed = BigInt(randomSeedFloat); const randomSeed = BigInt(randomSeedFloat);
wasmImport?.setRandomSeed(randomSeed); setRandomSeed(randomSeed);
// TODO: Tauri: reenable this if (!tauri) return;
// try { await (await tauri).invoke("set_random_seed", { seed: randomSeedFloat });
// await invoke("set_random_seed", { seed: randomSeedFloat });
// } catch {
// // Ignore errors
// }
} }
// Should be called after running `initWasm()` and its promise resolving // Should be called after running `initWasm()` and its promise resolving
@ -80,12 +78,12 @@ export function createEditor() {
const raw: WasmRawInstance = wasmImport; const raw: WasmRawInstance = wasmImport;
// Instance: Object containing many functions from `editor_api.rs` that are part of the editor instance (generated by wasm-bindgen) // Instance: Object containing many functions from `editor_api.rs` that are part of the editor instance (generated by wasm-bindgen)
const instance: WasmEditorInstance = new raw.JsEditorHandle((messageType: JsMessageType, messageData: Record<string, unknown>): void => { const instance: WasmEditorInstance = new JsEditorHandle((messageType: JsMessageType, messageData: Record<string, unknown>): void => {
// This callback is called by WASM when a FrontendMessage is received from the WASM wrapper editor instance // This callback is called by WASM when a FrontendMessage is received from the WASM wrapper editor instance
// We pass along the first two arguments then add our own `raw` and `instance` context for the last two arguments // We pass along the first two arguments then add our own `raw` and `instance` context for the last two arguments
subscriptions.handleJsMessage(messageType, messageData, raw, instance); subscriptions.handleJsMessage(messageType, messageData, raw, instance);
}); });
editorInstance = instance; window["editorInstance"] = instance;
// Subscriptions: Allows subscribing to messages in JS that are sent from the WASM backend // Subscriptions: Allows subscribing to messages in JS that are sent from the WASM backend
const subscriptions: SubscriptionRouter = createSubscriptionRouter(); const subscriptions: SubscriptionRouter = createSubscriptionRouter();

View File

@ -506,15 +506,15 @@ export class TriggerFileDownload extends JsMessage {
readonly name!: string; readonly name!: string;
} }
export class TriggerLoadAutoSaveDocuments extends JsMessage {} export class TriggerLoadAutoSaveDocuments extends JsMessage { }
export class TriggerLoadPreferences extends JsMessage {} export class TriggerLoadPreferences extends JsMessage { }
export class TriggerOpenDocument extends JsMessage {} export class TriggerOpenDocument extends JsMessage { }
export class TriggerImport extends JsMessage {} export class TriggerImport extends JsMessage { }
export class TriggerPaste extends JsMessage {} export class TriggerPaste extends JsMessage { }
export class TriggerRasterDownload extends JsMessage { export class TriggerRasterDownload extends JsMessage {
readonly svg!: string; readonly svg!: string;
@ -618,7 +618,7 @@ export class TriggerNodeGraphFrameGenerate extends JsMessage {
readonly imaginateNode!: BigUint64Array | undefined; readonly imaginateNode!: BigUint64Array | undefined;
} }
export class TriggerRefreshBoundsOfViewports extends JsMessage {} export class TriggerRefreshBoundsOfViewports extends JsMessage { }
export class TriggerRevokeBlobUrl extends JsMessage { export class TriggerRevokeBlobUrl extends JsMessage {
readonly url!: string; readonly url!: string;
@ -628,7 +628,7 @@ export class TriggerSavePreferences extends JsMessage {
readonly preferences!: Record<string, unknown>; readonly preferences!: Record<string, unknown>;
} }
export class DocumentChanged extends JsMessage {} export class DocumentChanged extends JsMessage { }
export class UpdateDocumentLayerTreeStructureJs extends JsMessage { export class UpdateDocumentLayerTreeStructureJs extends JsMessage {
constructor(readonly layerId: bigint, readonly children: UpdateDocumentLayerTreeStructureJs[]) { constructor(readonly layerId: bigint, readonly children: UpdateDocumentLayerTreeStructureJs[]) {
@ -645,7 +645,7 @@ export function newUpdateDocumentLayerTreeStructure(input: { dataBuffer: DataBuf
const pointerNum = Number(input.dataBuffer.pointer); const pointerNum = Number(input.dataBuffer.pointer);
const lengthNum = Number(input.dataBuffer.length); const lengthNum = Number(input.dataBuffer.length);
const wasmMemoryBuffer = wasm.wasmMemory().buffer; const wasmMemoryBuffer = wasm.buffer;
// Decode the folder structure encoding // Decode the folder structure encoding
const encoding = new DataView(wasmMemoryBuffer, pointerNum, lengthNum); const encoding = new DataView(wasmMemoryBuffer, pointerNum, lengthNum);
@ -713,7 +713,7 @@ export class UpdateImageData extends JsMessage {
readonly imageData!: ImaginateImageData[]; readonly imageData!: ImaginateImageData[];
} }
export class DisplayRemoveEditableTextbox extends JsMessage {} export class DisplayRemoveEditableTextbox extends JsMessage { }
export class UpdateDocumentLayerDetails extends JsMessage { export class UpdateDocumentLayerDetails extends JsMessage {
@Type(() => LayerPanelEntry) @Type(() => LayerPanelEntry)
@ -772,7 +772,7 @@ export class ImaginateImageData {
readonly transform!: Float64Array ; readonly transform!: Float64Array ;
} }
export class DisplayDialogDismiss extends JsMessage {} export class DisplayDialogDismiss extends JsMessage { }
export class Font { export class Font {
fontFamily!: string; fontFamily!: string;
@ -791,7 +791,7 @@ export class TriggerVisitLink extends JsMessage {
url!: string; url!: string;
} }
export class TriggerTextCommit extends JsMessage {} export class TriggerTextCommit extends JsMessage { }
export class TriggerTextCopy extends JsMessage { export class TriggerTextCopy extends JsMessage {
readonly copyText!: string; readonly copyText!: string;
@ -801,7 +801,7 @@ export class TriggerAboutGraphiteLocalizedCommitDate extends JsMessage {
readonly commitDate!: string; readonly commitDate!: string;
} }
export class TriggerViewportResize extends JsMessage {} export class TriggerViewportResize extends JsMessage { }
// WIDGET PROPS // WIDGET PROPS
@ -1145,7 +1145,7 @@ export class PivotAssist extends WidgetProps {
// WIDGET // WIDGET
const widgetSubTypes = [ const widgetSubTypes = [
{ value: BreadcrumbTrailButtons, name: "BreadcrumbTrailButtons"}, { value: BreadcrumbTrailButtons, name: "BreadcrumbTrailButtons" },
{ value: CheckboxInput, name: "CheckboxInput" }, { value: CheckboxInput, name: "CheckboxInput" },
{ value: ColorInput, name: "ColorInput" }, { value: ColorInput, name: "ColorInput" },
{ value: DropdownInput, name: "DropdownInput" }, { value: DropdownInput, name: "DropdownInput" },
@ -1327,25 +1327,25 @@ function createLayoutGroup(layoutGroup: any): LayoutGroup {
} }
// WIDGET LAYOUTS // WIDGET LAYOUTS
export class UpdateDialogDetails extends WidgetDiffUpdate {} export class UpdateDialogDetails extends WidgetDiffUpdate { }
export class UpdateDocumentModeLayout extends WidgetDiffUpdate {} export class UpdateDocumentModeLayout extends WidgetDiffUpdate { }
export class UpdateToolOptionsLayout extends WidgetDiffUpdate {} export class UpdateToolOptionsLayout extends WidgetDiffUpdate { }
export class UpdateDocumentBarLayout extends WidgetDiffUpdate {} export class UpdateDocumentBarLayout extends WidgetDiffUpdate { }
export class UpdateToolShelfLayout extends WidgetDiffUpdate {} export class UpdateToolShelfLayout extends WidgetDiffUpdate { }
export class UpdateWorkingColorsLayout extends WidgetDiffUpdate {} export class UpdateWorkingColorsLayout extends WidgetDiffUpdate { }
export class UpdatePropertyPanelOptionsLayout extends WidgetDiffUpdate {} export class UpdatePropertyPanelOptionsLayout extends WidgetDiffUpdate { }
export class UpdatePropertyPanelSectionsLayout extends WidgetDiffUpdate {} export class UpdatePropertyPanelSectionsLayout extends WidgetDiffUpdate { }
export class UpdateLayerTreeOptionsLayout extends WidgetDiffUpdate {} export class UpdateLayerTreeOptionsLayout extends WidgetDiffUpdate { }
export class UpdateNodeGraphBarLayout extends WidgetDiffUpdate {} export class UpdateNodeGraphBarLayout extends WidgetDiffUpdate { }
export class UpdateMenuBarLayout extends JsMessage { export class UpdateMenuBarLayout extends JsMessage {
layoutTarget!: unknown; layoutTarget!: unknown;

View File

@ -11,9 +11,12 @@
"esModuleInterop": true, "esModuleInterop": true,
"allowSyntheticDefaultImports": true, "allowSyntheticDefaultImports": true,
"sourceMap": true, "sourceMap": true,
"baseUrl": ".",
"types": ["node", "svelte", "svelte/store", "svelte/motion", "svelte/transition", "svelte/animate", "svelte/easing"], "types": ["node", "svelte", "svelte/store", "svelte/motion", "svelte/transition", "svelte/animate", "svelte/easing"],
"baseUrl": ".",
"paths": { "paths": {
"~*": ["./*"],
"/*": ["./*"],
"@graphite-frontend/*": ["./*"],
"@graphite/*": ["src/*"] "@graphite/*": ["src/*"]
}, },
"lib": ["esnext", "dom", "dom.iterable", "scripthost"] "lib": ["esnext", "dom", "dom.iterable", "scripthost"]
@ -25,6 +28,10 @@
"module": "commonjs", "module": "commonjs",
"useDefineForClassFields": false, "useDefineForClassFields": false,
"noImplicitOverride": true "noImplicitOverride": true
},
"moduleTypes": {
"webpack.config.ts": "cjs",
"webpack-config-scripts/**/*": "cjs"
} }
} }
} }

View File

@ -25,7 +25,7 @@ graph-craft = { path = "../../node-graph/graph-craft" }
log = "0.4" log = "0.4"
graphene-core = { path = "../../node-graph/gcore", features = ["async", "std", "alloc"] } graphene-core = { path = "../../node-graph/gcore", features = ["async", "std", "alloc"] }
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
wasm-bindgen = { version = "0.2.73" } wasm-bindgen = { version = "0.2.84" }
serde-wasm-bindgen = "0.4.1" serde-wasm-bindgen = "0.4.1"
js-sys = "0.3.55" js-sys = "0.3.55"
wasm-bindgen-futures = "0.4.33" wasm-bindgen-futures = "0.4.33"

View File

@ -30,7 +30,7 @@ pub fn set_random_seed(seed: u64) {
/// We directly interface with the updateImage JS function for massively increased performance over serializing and deserializing. /// We directly interface with the updateImage JS function for massively increased performance over serializing and deserializing.
/// This avoids creating a json with a list millions of numbers long. /// This avoids creating a json with a list millions of numbers long.
#[wasm_bindgen(module = "@graphite/wasm-communication/editor")] #[wasm_bindgen(module = "/../src/wasm-communication/editor.ts")]
extern "C" { extern "C" {
fn updateImage(path: Vec<u64>, mime: String, imageData: &[u8], transform: js_sys::Float64Array, document_id: u64); fn updateImage(path: Vec<u64>, mime: String, imageData: &[u8], transform: js_sys::Float64Array, document_id: u64);
fn fetchImage(path: Vec<u64>, mime: String, document_id: u64, identifier: String); fn fetchImage(path: Vec<u64>, mime: String, document_id: u64, identifier: String);

View File

@ -25,7 +25,7 @@ thread_local! {
/// Initialize the backend /// Initialize the backend
#[wasm_bindgen(start)] #[wasm_bindgen(start)]
pub fn init() { pub fn init_graphite() {
// Set up the panic hook // Set up the panic hook
panic::set_hook(Box::new(panic_hook)); panic::set_hook(Box::new(panic_hook));

View File

@ -1,20 +1,14 @@
import * as path from "path"; import * as path from "path";
import fs from "fs"; import fs from "fs";
import { spawnSync } from "child_process"; import { spawnSync } from "child_process";
import WasmPackPlugin from "@wasm-tool/wasm-pack-plugin";
import SvelteCheckPlugin from "svelte-check-plugin";
import SveltePreprocess from "svelte-preprocess";
import * as webpack from "webpack"; import * as webpack from "webpack";
import "webpack-dev-server";
const LicenseCheckerWebpackPlugin = require("license-checker-webpack-plugin"); const LicenseCheckerWebpackPlugin = require("license-checker-webpack-plugin");
const mode = process.env.NODE_ENV === "production" ? "production" : "development";
const config: webpack.Configuration = { const config: webpack.Configuration = {
mode,
entry: { entry: {
bundle: ["./src/main.ts"] bundle: ["./src/main-webpack-licenses.ts"]
}, },
mode: "production",
resolve: { resolve: {
alias: { alias: {
// Note: Later in this config file, we'll automatically add paths from `tsconfig.compilerOptions.paths` // Note: Later in this config file, we'll automatically add paths from `tsconfig.compilerOptions.paths`
@ -24,105 +18,15 @@ const config: webpack.Configuration = {
mainFields: ["svelte", "browser", "module", "main"] mainFields: ["svelte", "browser", "module", "main"]
}, },
output: { output: {
path: path.resolve(__dirname, "public/build"), path: path.resolve(__dirname, "dist"),
publicPath: "/build/", publicPath: "/dist/",
filename: "[name].js", filename: "[name].js",
chunkFilename: "[name].[id].js" chunkFilename: "[name].[id].js"
}, },
module: { module: {
rules: [ rules: []
// Rule: Svelte
{
test: /\.svelte$/,
use: {
loader: "svelte-loader",
options: {
compilerOptions: {
// Dev mode must be enabled for HMR to work!
dev: mode === "development"
},
// TODO: Reenable in prod, see: https://github.com/sveltejs/rollup-plugin-svelte#extracting-css
// emitCss: mode === "production",
emitCss: false,
hotReload: mode === "development",
hotOptions: {
// List of options and defaults: https://www.npmjs.com/package/svelte-loader-hot#usage
noPreserveState: false,
optimistic: true,
},
preprocess: SveltePreprocess({
scss: true,
sass: true,
}),
onwarn(warning: { code: string; }, handler: (warn: any) => any) {
const suppress = [
"css-unused-selector",
"unused-export-let",
"a11y-no-noninteractive-tabindex",
];
if (suppress.includes(warning.code)) return;
handler(warning);
},
}
},
},
// Required to prevent errors from Svelte on Webpack 5+
// https://github.com/sveltejs/svelte-loader#usage
{
test: /node_modules\/svelte\/.*\.mjs$/,
resolve: {
fullySpecified: false
}
},
// Rule: SASS
{
test: /\.(scss|sass)$/,
use: [
"css-loader",
"sass-loader"
]
},
// Rule: CSS
{
test: /\.css$/,
use: [
"css-loader",
]
},
// Rule: TypeScript
{
test: /\.ts$/,
use: "ts-loader",
exclude: /node_modules/
},
// Rule: SVG
{
test: /\.svg$/,
type: "asset/source",
},
]
},
devServer: {
hot: true,
}, },
plugins: [ plugins: [
// WASM Pack Plugin integrates compiled Rust code (.wasm) and generated wasm-bindgen code (.js) with the webpack bundle
// Use this JS to import the bundled Rust entry points: const wasm = import("@graphite/../wasm/pkg").then(panicProxy);
// Then call WASM functions with: (await wasm).functionName()
// https://github.com/wasm-tool/wasm-pack-plugin
new WasmPackPlugin({
crateDirectory: path.resolve(__dirname, "wasm"),
// Remove when this issue is resolved: https://github.com/wasm-tool/wasm-pack-plugin/issues/93
outDir: path.resolve(__dirname, "wasm/pkg"),
watchDirectories: ["../editor", "../document-legacy", "../proc-macros", "../node-graph"].map((folder) => path.resolve(__dirname, folder)),
}),
// License Checker Webpack Plugin validates the license compatibility of all dependencies which are compiled into the webpack bundle // License Checker Webpack Plugin validates the license compatibility of all dependencies which are compiled into the webpack bundle
// It also writes the third-party license notices to a file which is displayed in the application // It also writes the third-party license notices to a file which is displayed in the application
// https://github.com/microsoft/license-checker-webpack-plugin // https://github.com/microsoft/license-checker-webpack-plugin
@ -137,7 +41,6 @@ const config: webpack.Configuration = {
// new SvelteCheckPlugin(), // new SvelteCheckPlugin(),
], ],
devtool: mode === "development" ? "source-map" : false,
experiments: { experiments: {
asyncWebAssembly: true, asyncWebAssembly: true,
}, },
@ -189,7 +92,7 @@ interface Dependency extends PackageInfo {
function formatThirdPartyLicenses(jsLicenses: {dependencies: Dependency[]}): string { function formatThirdPartyLicenses(jsLicenses: {dependencies: Dependency[]}): string {
let rustLicenses: LicenseInfo[] | undefined; let rustLicenses: LicenseInfo[] | undefined;
if (process.env.NODE_ENV === "production" && process.env.SKIP_CARGO_ABOUT === undefined) { if (process.env.SKIP_CARGO_ABOUT === undefined) {
try { try {
rustLicenses = generateRustLicenses(); rustLicenses = generateRustLicenses();
} catch (err) { } catch (err) {
@ -335,10 +238,10 @@ function htmlDecode(input: string): string {
quot: `"`, quot: `"`,
}; };
return input.replace(/&([^;]+);/g, (entity, entityCode: string) => { return input.replace(/&([^;]+);/g, (entity: string, entityCode: string) => {
let match; let match;
const maybeEntity = Object.entries(htmlEntities).find((entry) => entry[1] === entityCode); const maybeEntity = Object.entries(htmlEntities).find(([key, _]) => key === entityCode);
if (maybeEntity) { if (maybeEntity) {
return maybeEntity[1]; return maybeEntity[1];
} }

6
node_modules/.package-lock.json generated vendored
View File

@ -1,6 +0,0 @@
{
"name": "Graphite",
"lockfileVersion": 2,
"requires": true,
"packages": {}
}

6
package-lock.json generated
View File

@ -1,6 +0,0 @@
{
"name": "Graphite",
"lockfileVersion": 2,
"requires": true,
"packages": {}
}

View File

@ -1,8 +0,0 @@
{
"description": "A convenience package for calling the real package.json in ./frontend",
"private": true,
"scripts": {
"start": "cd frontend && npm start",
"serve": "cd frontend && npm start"
}
}