mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-28 10:38:12 +08:00
Restore ESLint and Prettier auto-formatting and CI linting (#1457)
* Restore ESLint and Prettier autoformatting * Fix formatting and lints in web files * Hacky fix to eslint crash * Fix remaining lints * Add lint-fix script --------- Co-authored-by: 0hypercube <0hypercube@gmail.com>
This commit is contained in:
co-authored by
0hypercube
parent
9784d31edb
commit
a6ca43bb2d
@@ -1,8 +1,7 @@
|
||||
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 { createSubscriptionRouter, type SubscriptionRouter } from "@graphite/wasm-communication/subscription-router";
|
||||
import init, { setRandomSeed, wasmMemory, JsEditorHandle } from "@graphite-frontend/wasm/pkg/graphite_wasm.js";
|
||||
|
||||
export type WasmRawInstance = WebAssembly.Memory;
|
||||
export type WasmEditorInstance = JsEditorHandle;
|
||||
@@ -11,7 +10,7 @@ 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()`
|
||||
let wasmImport: WebAssembly.Memory | undefined;
|
||||
|
||||
export async function updateImage(path: BigUint64Array, nodeId: bigint, mime: string, imageData: Uint8Array, transform: Float64Array, documentId: bigint): Promise<void> {
|
||||
export async function updateImage(path: BigUint64Array, nodeId: bigint, mime: string, imageData: Uint8Array, transform: Float64Array, documentId: bigint) {
|
||||
const blob = new Blob([imageData], { type: mime });
|
||||
|
||||
const blobURL = URL.createObjectURL(blob);
|
||||
@@ -21,10 +20,11 @@ export async function updateImage(path: BigUint64Array, nodeId: bigint, mime: st
|
||||
image.src = blobURL;
|
||||
await image.decode();
|
||||
|
||||
window["editorInstance"]?.setImageBlobURL(documentId, path, nodeId, blobURL, image.naturalWidth, image.naturalHeight, transform);
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
(window as any).editorInstance?.setImageBlobURL(documentId, path, nodeId, blobURL, image.naturalWidth, image.naturalHeight, transform);
|
||||
}
|
||||
|
||||
export async function fetchImage(path: BigUint64Array, nodeId: bigint, mime: string, documentId: bigint, url: string): Promise<void> {
|
||||
export async function fetchImage(path: BigUint64Array, nodeId: bigint, mime: string, documentId: bigint, url: string) {
|
||||
const data = await fetch(url);
|
||||
const blob = await data.blob();
|
||||
|
||||
@@ -35,16 +35,18 @@ export async function fetchImage(path: BigUint64Array, nodeId: bigint, mime: str
|
||||
image.src = blobURL;
|
||||
await image.decode();
|
||||
|
||||
window["editorInstance"]?.setImageBlobURL(documentId, path, nodeId, blobURL, image.naturalWidth, image.naturalHeight, undefined);
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
(window as any).editorInstance?.setImageBlobURL(documentId, path, nodeId, blobURL, image.naturalWidth, image.naturalHeight, undefined);
|
||||
}
|
||||
|
||||
const tauri = "__TAURI_METADATA__" in window && import("@tauri-apps/api");
|
||||
export async function dispatchTauri(message: unknown): Promise<void> {
|
||||
export async function dispatchTauri(message: unknown) {
|
||||
if (!tauri) return;
|
||||
|
||||
try {
|
||||
const response = await (await tauri).invoke("handle_message", { message });
|
||||
window["editorInstance"]?.tauriResponse(response);
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
(window as any).editorInstance?.tauriResponse(response);
|
||||
} catch {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error("Failed to dispatch Tauri message");
|
||||
@@ -52,7 +54,7 @@ export async function dispatchTauri(message: unknown): Promise<void> {
|
||||
}
|
||||
|
||||
// Should be called asynchronously before `createEditor()`
|
||||
export async function initWasm(): Promise<void> {
|
||||
export async function initWasm() {
|
||||
// Skip if the WASM module is already initialized
|
||||
if (wasmImport !== undefined) return;
|
||||
|
||||
@@ -60,8 +62,8 @@ export async function initWasm(): Promise<void> {
|
||||
// eslint-disable-next-line import/no-cycle
|
||||
await init();
|
||||
wasmImport = await wasmMemory();
|
||||
window["imageCanvases"] = {};
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
(window as any).imageCanvases = {};
|
||||
|
||||
// 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);
|
||||
@@ -79,12 +81,13 @@ export function createEditor() {
|
||||
const raw: WasmRawInstance = wasmImport;
|
||||
|
||||
// Instance: Object containing many functions from `editor_api.rs` that are part of the editor instance (generated by wasm-bindgen)
|
||||
const instance: WasmEditorInstance = new JsEditorHandle((messageType: JsMessageType, messageData: Record<string, unknown>): void => {
|
||||
const instance: WasmEditorInstance = new JsEditorHandle((messageType: JsMessageType, messageData: Record<string, unknown>) => {
|
||||
// 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
|
||||
subscriptions.handleJsMessage(messageType, messageData, raw, instance);
|
||||
});
|
||||
window["editorInstance"] = instance;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
(window as any).editorInstance = instance;
|
||||
|
||||
// Subscriptions: Allows subscribing to messages in JS that are sent from the WASM backend
|
||||
const subscriptions: SubscriptionRouter = createSubscriptionRouter();
|
||||
@@ -97,14 +100,16 @@ export function createEditor() {
|
||||
try {
|
||||
const url = new URL(`https://raw.githubusercontent.com/GraphiteEditor/Graphite/master/demo-artwork/${demoArtwork}.graphite`);
|
||||
const data = await fetch(url);
|
||||
|
||||
|
||||
const filename = url.pathname.split("/").pop() || "Untitled";
|
||||
const content = await data.text();
|
||||
instance.openDocumentFile(filename, content);
|
||||
|
||||
// Remove the hash fragment from the URL
|
||||
history.replaceState("", "", `${window.location.pathname}${window.location.search}`);
|
||||
} catch {}
|
||||
} catch {
|
||||
// Do nothing
|
||||
}
|
||||
})();
|
||||
|
||||
return {
|
||||
@@ -115,5 +120,6 @@ export function createEditor() {
|
||||
}
|
||||
|
||||
export function injectImaginatePollServerStatus() {
|
||||
window["editorInstance"]?.injectImaginatePollServerStatus()
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
(window as any).editorInstance?.injectImaginatePollServerStatus();
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
/* eslint-disable max-classes-per-file */
|
||||
|
||||
import { Transform, Type, plainToClass } from "class-transformer";
|
||||
@@ -11,7 +12,7 @@ export class JsMessage {
|
||||
}
|
||||
|
||||
const TupleToVec2 = Transform(({ value }: { value: [number, number] | undefined }) => (value === undefined ? undefined : { x: value[0], y: value[1] }));
|
||||
const BigIntTupleToVec2 = Transform(({ value }: { value: [bigint, bigint] | undefined }) => (value === undefined ? undefined : { x: Number(value[0]), y: Number(value[1]) }));
|
||||
// const BigIntTupleToVec2 = Transform(({ value }: { value: [bigint, bigint] | undefined }) => (value === undefined ? undefined : { x: Number(value[0]), y: Number(value[1]) }));
|
||||
|
||||
export type XY = { x: number; y: number };
|
||||
|
||||
@@ -506,19 +507,19 @@ export class UpdateMouseCursor extends JsMessage {
|
||||
readonly cursor!: MouseCursorIcon;
|
||||
}
|
||||
|
||||
export class TriggerLoadAutoSaveDocuments extends JsMessage { }
|
||||
export class TriggerLoadAutoSaveDocuments extends JsMessage {}
|
||||
|
||||
export class TriggerLoadPreferences extends JsMessage { }
|
||||
export class TriggerLoadPreferences extends JsMessage {}
|
||||
|
||||
export class TriggerFetchAndOpenDocument extends JsMessage {
|
||||
readonly url!: string;
|
||||
}
|
||||
|
||||
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 TriggerCopyToClipboardBlobUrl extends JsMessage {
|
||||
readonly blobUrl!: string;
|
||||
@@ -557,7 +558,7 @@ export class TriggerRasterizeRegionBelowLayer extends JsMessage {
|
||||
readonly size!: [number, number];
|
||||
}
|
||||
|
||||
export class TriggerRefreshBoundsOfViewports extends JsMessage { }
|
||||
export class TriggerRefreshBoundsOfViewports extends JsMessage {}
|
||||
|
||||
export class TriggerRevokeBlobUrl extends JsMessage {
|
||||
readonly url!: string;
|
||||
@@ -567,10 +568,13 @@ export class TriggerSavePreferences extends JsMessage {
|
||||
readonly preferences!: Record<string, unknown>;
|
||||
}
|
||||
|
||||
export class DocumentChanged extends JsMessage { }
|
||||
export class DocumentChanged extends JsMessage {}
|
||||
|
||||
export class UpdateDocumentLayerTreeStructureJs extends JsMessage {
|
||||
constructor(readonly layerId: bigint, readonly children: UpdateDocumentLayerTreeStructureJs[]) {
|
||||
constructor(
|
||||
readonly layerId: bigint,
|
||||
readonly children: UpdateDocumentLayerTreeStructureJs[],
|
||||
) {
|
||||
super();
|
||||
}
|
||||
}
|
||||
@@ -660,7 +664,7 @@ export class UpdateImageData extends JsMessage {
|
||||
readonly imageData!: ImaginateImageData[];
|
||||
}
|
||||
|
||||
export class DisplayRemoveEditableTextbox extends JsMessage { }
|
||||
export class DisplayRemoveEditableTextbox extends JsMessage {}
|
||||
|
||||
export class UpdateDocumentLayerDetails extends JsMessage {
|
||||
@Type(() => LayerPanelEntry)
|
||||
@@ -706,7 +710,7 @@ export class ImaginateImageData {
|
||||
readonly transform!: Float64Array;
|
||||
}
|
||||
|
||||
export class DisplayDialogDismiss extends JsMessage { }
|
||||
export class DisplayDialogDismiss extends JsMessage {}
|
||||
|
||||
export class Font {
|
||||
fontFamily!: string;
|
||||
@@ -729,7 +733,7 @@ export class TriggerVisitLink extends JsMessage {
|
||||
url!: string;
|
||||
}
|
||||
|
||||
export class TriggerTextCommit extends JsMessage { }
|
||||
export class TriggerTextCommit extends JsMessage {}
|
||||
|
||||
export class TriggerTextCopy extends JsMessage {
|
||||
readonly copyText!: string;
|
||||
@@ -739,7 +743,7 @@ export class TriggerAboutGraphiteLocalizedCommitDate extends JsMessage {
|
||||
readonly commitDate!: string;
|
||||
}
|
||||
|
||||
export class TriggerViewportResize extends JsMessage { }
|
||||
export class TriggerViewportResize extends JsMessage {}
|
||||
|
||||
// WIDGET PROPS
|
||||
|
||||
@@ -760,7 +764,7 @@ export class CheckboxInput extends WidgetProps {
|
||||
|
||||
export class ColorInput extends WidgetProps {
|
||||
@Transform(({ value }: { value: { red: number; green: number; blue: number; alpha: number } | undefined }) =>
|
||||
value === undefined ? new Color("none") : new Color(value.red, value.green, value.blue, value.alpha)
|
||||
value === undefined ? new Color("none") : new Color(value.red, value.green, value.blue, value.alpha),
|
||||
)
|
||||
value!: Color;
|
||||
|
||||
@@ -784,7 +788,7 @@ type MenuEntryCommon = {
|
||||
export type MenuBarEntry = MenuEntryCommon & {
|
||||
action: Widget;
|
||||
children?: MenuBarEntry[][];
|
||||
disabled?: boolean,
|
||||
disabled?: boolean;
|
||||
};
|
||||
|
||||
// An entry in the all-encompassing MenuList component which defines all types of menus ranging from `MenuBarInput` to `DropdownInput` widgets
|
||||
@@ -1042,7 +1046,7 @@ export class TextButton extends WidgetProps {
|
||||
emphasized!: boolean;
|
||||
|
||||
noBackground!: boolean;
|
||||
|
||||
|
||||
minWidth!: number;
|
||||
|
||||
disabled!: boolean;
|
||||
@@ -1217,7 +1221,7 @@ export function defaultWidgetLayout(): WidgetLayout {
|
||||
}
|
||||
|
||||
// Updates a widget layout based on a list of updates, giving the new layout by mutating the `layout` argument
|
||||
export function patchWidgetLayout(layout: /* &mut */ WidgetLayout, updates: WidgetDiffUpdate): void {
|
||||
export function patchWidgetLayout(layout: /* &mut */ WidgetLayout, updates: WidgetDiffUpdate) {
|
||||
layout.layoutTarget = updates.layoutTarget;
|
||||
|
||||
updates.diff.forEach((update) => {
|
||||
@@ -1315,19 +1319,19 @@ function createLayoutGroup(layoutGroup: any): LayoutGroup {
|
||||
}
|
||||
|
||||
// WIDGET LAYOUTS
|
||||
export class UpdateDialogButtons extends WidgetDiffUpdate { }
|
||||
export class UpdateDialogButtons extends WidgetDiffUpdate {}
|
||||
|
||||
export class UpdateDialogColumn1 extends WidgetDiffUpdate { }
|
||||
export class UpdateDialogColumn1 extends WidgetDiffUpdate {}
|
||||
|
||||
export class UpdateDialogColumn2 extends WidgetDiffUpdate { }
|
||||
export class UpdateDialogColumn2 extends WidgetDiffUpdate {}
|
||||
|
||||
export class UpdateDocumentBarLayout extends WidgetDiffUpdate { }
|
||||
export class UpdateDocumentBarLayout extends WidgetDiffUpdate {}
|
||||
|
||||
export class UpdateDocumentModeLayout extends WidgetDiffUpdate { }
|
||||
export class UpdateDocumentModeLayout extends WidgetDiffUpdate {}
|
||||
|
||||
export class UpdateGraphViewOverlayButtonLayout extends WidgetDiffUpdate { }
|
||||
export class UpdateGraphViewOverlayButtonLayout extends WidgetDiffUpdate {}
|
||||
|
||||
export class UpdateLayerTreeOptionsLayout extends WidgetDiffUpdate { }
|
||||
export class UpdateLayerTreeOptionsLayout extends WidgetDiffUpdate {}
|
||||
|
||||
// Extends JsMessage instead of WidgetDiffUpdate because the menu bar isn't diffed
|
||||
export class UpdateMenuBarLayout extends JsMessage {
|
||||
@@ -1339,17 +1343,17 @@ export class UpdateMenuBarLayout extends JsMessage {
|
||||
layout!: MenuBarEntry[];
|
||||
}
|
||||
|
||||
export class UpdateNodeGraphBarLayout extends WidgetDiffUpdate { }
|
||||
export class UpdateNodeGraphBarLayout extends WidgetDiffUpdate {}
|
||||
|
||||
export class UpdatePropertyPanelOptionsLayout extends WidgetDiffUpdate { }
|
||||
export class UpdatePropertyPanelOptionsLayout extends WidgetDiffUpdate {}
|
||||
|
||||
export class UpdatePropertyPanelSectionsLayout extends WidgetDiffUpdate { }
|
||||
export class UpdatePropertyPanelSectionsLayout extends WidgetDiffUpdate {}
|
||||
|
||||
export class UpdateToolOptionsLayout extends WidgetDiffUpdate { }
|
||||
export class UpdateToolOptionsLayout extends WidgetDiffUpdate {}
|
||||
|
||||
export class UpdateToolShelfLayout extends WidgetDiffUpdate { }
|
||||
export class UpdateToolShelfLayout extends WidgetDiffUpdate {}
|
||||
|
||||
export class UpdateWorkingColorsLayout extends WidgetDiffUpdate { }
|
||||
export class UpdateWorkingColorsLayout extends WidgetDiffUpdate {}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
function createMenuLayout(menuBarEntry: any[]): MenuBarEntry[] {
|
||||
@@ -1366,7 +1370,7 @@ function createMenuLayoutRecursive(children: any[][]): MenuBarEntry[][] {
|
||||
action: hoistWidgetHolders([entry.action])[0],
|
||||
children: entry.children ? createMenuLayoutRecursive(entry.children) : undefined,
|
||||
disabled: entry.disabled ?? false,
|
||||
}))
|
||||
})),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -13,18 +13,18 @@ type JsMessageCallbackMap = Record<string, JsMessageCallback<any> | undefined>;
|
||||
export function createSubscriptionRouter() {
|
||||
const subscriptions: JsMessageCallbackMap = {};
|
||||
|
||||
const subscribeJsMessage = <T extends JsMessage, Args extends unknown[]>(messageType: new (...args: Args) => T, callback: JsMessageCallback<T>): void => {
|
||||
const subscribeJsMessage = <T extends JsMessage, Args extends unknown[]>(messageType: new (...args: Args) => T, callback: JsMessageCallback<T>) => {
|
||||
subscriptions[messageType.name] = callback;
|
||||
};
|
||||
|
||||
const handleJsMessage = (messageType: JsMessageType, messageData: Record<string, unknown>, wasm: WasmRawInstance, instance: WasmEditorInstance): void => {
|
||||
const handleJsMessage = (messageType: JsMessageType, messageData: Record<string, unknown>, wasm: WasmRawInstance, instance: WasmEditorInstance) => {
|
||||
// Find the message maker for the message type, which can either be a JS class constructor or a function that returns an instance of the JS class
|
||||
const messageMaker = messageMakers[messageType];
|
||||
if (!messageMaker) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(
|
||||
`Received a frontend message of type "${messageType}" but was not able to parse the data. ` +
|
||||
"(Perhaps this message parser isn't exported in `messageMakers` at the bottom of `messages.ts`.)"
|
||||
"(Perhaps this message parser isn't exported in `messageMakers` at the bottom of `messages.ts`.)",
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user