From 0c22e4e6dde9bf0e21d3913626747ffa2a3615ef Mon Sep 17 00:00:00 2001 From: Miorel-Lucian Palii Date: Thu, 17 Oct 2024 20:37:19 -0700 Subject: [PATCH] Specify tab/indent size in LeetCode Prettier extension --- .../leetcode-prettier-extension/package.json | 1 + .../src/isMonaco.ts | 13 +++++ .../leetcode-prettier-extension/src/main.ts | 56 +++++++++++++++---- yarn.lock | 8 +++ 4 files changed, 66 insertions(+), 12 deletions(-) create mode 100644 workspaces/leetcode-prettier-extension/src/isMonaco.ts diff --git a/workspaces/leetcode-prettier-extension/package.json b/workspaces/leetcode-prettier-extension/package.json index dea45f6a..3c634ee8 100644 --- a/workspaces/leetcode-prettier-extension/package.json +++ b/workspaces/leetcode-prettier-extension/package.json @@ -31,6 +31,7 @@ "cross-env": "7.0.3", "eslint": "9.12.0", "fork-ts-checker-webpack-plugin": "9.0.2", + "monaco-editor": "0.52.0", "ts-loader": "9.5.1", "tsx": "4.19.1", "type-fest": "4.26.1", diff --git a/workspaces/leetcode-prettier-extension/src/isMonaco.ts b/workspaces/leetcode-prettier-extension/src/isMonaco.ts new file mode 100644 index 00000000..3ba8053c --- /dev/null +++ b/workspaces/leetcode-prettier-extension/src/isMonaco.ts @@ -0,0 +1,13 @@ +import type { editor as MonacoEditorNamespace } from "monaco-editor"; + +type Monaco = { editor: typeof MonacoEditorNamespace }; + +type RecursiveObj = { [key: string]: RecursiveObj | undefined }; + +export function isMonaco(obj: unknown): obj is Monaco { + return ( + // The optional chaining should make the cast safe enough. + typeof (obj as RecursiveObj | null | undefined)?.editor + ?.onDidCreateEditor === "function" + ); +} diff --git a/workspaces/leetcode-prettier-extension/src/main.ts b/workspaces/leetcode-prettier-extension/src/main.ts index 6b1181c6..e93f30ac 100644 --- a/workspaces/leetcode-prettier-extension/src/main.ts +++ b/workspaces/leetcode-prettier-extension/src/main.ts @@ -2,30 +2,62 @@ import { format } from "prettier/standalone"; import estreePlugin from "prettier/plugins/estree"; import tsPlugin from "prettier/plugins/typescript"; +import { isMonaco } from "./isMonaco.ts"; + function main(): void { - // TODO: improve types - let monaco: any = undefined; + let monaco: unknown; Object.defineProperty(globalThis, "monaco", { get() { return monaco; }, - set(newMonaco) { + set(newMonaco: unknown) { monaco = newMonaco; - monaco.editor.onDidCreateEditor((ed: any) => { + if (!isMonaco(monaco)) { + console.error( + "The `monaco` property doesn't follow the expected interface!", + ); + return; + } + + monaco.editor.onDidCreateEditor((ed) => { + ed + ?.getModel?.() + ?.updateOptions?.({ tabSize: 2, indentSize: "tabSize" }); + + if (typeof ed?.getAction !== "function") { + // TODO: console.error something interesting + return; + } + const { getAction } = ed; + ed.getAction = function (this: unknown) { - const action = getAction.apply(this, arguments); - action.run = function () { - format(ed.getValue(), { - parser: "typescript", - plugins: [estreePlugin, tsPlugin], - }).then((text) => + const action = getAction.apply( + this, + // Slight lie but `.apply` will work with the `arguments` object. + arguments as unknown as Parameters, + ); + if (!action) { + // TODO: console.error something interesting + return action; + } + + action.run = async function () { + try { + const formattedText = await format(ed.getValue(), { + parser: "typescript", + plugins: [estreePlugin, tsPlugin], + }); + // TODO: switch to https://microsoft.github.io/monaco-editor/typedoc/interfaces/editor.ITextModel.html#pushEditOperations.pushEditOperations-1 in the future - ed.setValue(text), - ); + ed.setValue(formattedText); + } catch (err) { + console.error(err); + } }; + return action; }; }); diff --git a/yarn.lock b/yarn.lock index 881721c2..5f93c7cb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1046,6 +1046,7 @@ __metadata: cross-env: "npm:7.0.3" eslint: "npm:9.12.0" fork-ts-checker-webpack-plugin: "npm:9.0.2" + monaco-editor: "npm:0.52.0" prettier: "npm:3.3.3" ts-loader: "npm:9.5.1" tsx: "npm:4.19.1" @@ -8362,6 +8363,13 @@ __metadata: languageName: node linkType: hard +"monaco-editor@npm:0.52.0": + version: 0.52.0 + resolution: "monaco-editor@npm:0.52.0" + checksum: 10c0/962c75272568eb1556835f0097da2c7768bffe1116b252bb8b3aefd34f31e2dc46baa27e3911c0a6617bf556e6d6802e6e9f0f5548edd832c33872a8a0c146d3 + languageName: node + linkType: hard + "ms@npm:^2.1.1, ms@npm:^2.1.3": version: 2.1.3 resolution: "ms@npm:2.1.3"