feat: integrate Prettier 3.8.1 for WASM editor and scripts#1563
feat: integrate Prettier 3.8.1 for WASM editor and scripts#1563Divyansh200102 wants to merge 5 commits into
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #1563 +/- ##
=======================================
Coverage 92.44% 92.44%
=======================================
Files 35 35
Lines 6098 6098
=======================================
Hits 5637 5637
Misses 461 461 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
|
Is it possible to split the commit? One commit before the formatting, one commit after that. Otherwise it is hard to read the diff. |
|
@pca006132 I’ve integrated Prettier 3.8.1 into the editor and updated Would you prefer proceeding with this full migration to Prettier for consistency between the editor and CI, or should I limit the changes to just the editor button and keep the existing clang-format setup? If we proceed with this then I'll modfy |
103b5f0 to
714ab5a
Compare
|
@pca006132 I have made the commits please review them when you get the time. |
| const tabSize = model.getOptions?.().tabSize ?? 2; | ||
|
|
||
| let parser = 'babel'; | ||
| if (language.includes('typescript')) parser = 'typescript'; |
There was a problem hiding this comment.
do we have cases in which the editor is not writing typescript/javascript?
| } | ||
|
|
||
| editor.pushUndoStop(); | ||
| if (viewState) editor.restoreViewState(viewState); |
There was a problem hiding this comment.
Curious what does this do. I think it is related to undo, but why do we need to do pushUndoStop after applying the edit and restoreViewState? What happens if we remove the second run?
There was a problem hiding this comment.
I called pushUndoStop() because according to Monaco docs
"Execute edits on the editor. The edits will land on the undo-redo stack, but no 'undo stop' will be pushed."
Since no undo boundary is created automatically, we must explicitly call pushUndoStop() to create one after formatting.
If we remove the second call, subsequent user edits would continue in the same undo group as the formatting edit instead of being separated.
elalish
left a comment
There was a problem hiding this comment.
What's the line length limit now? That was a big one we were missing before with Monaco's auto-formatter.
I'm fine with updating the format of all this as long as it's pretty easy to set up VSCode to use prettier to auto-format these files on save. I assume that's no big deal?
Also probably a good idea to add the format commit to git-blame-ignore-revs. @tonious do you have any major branches outstanding? I don't want to create a bunch of conflicts for you.
| } catch (err) { | ||
| console.error('Prettier formatting failed:', err); | ||
| consoleElement.textContent += `Prettier formatting failed: ${err.message}\r\n`; | ||
| consoleElement.scrollTop = consoleElement.scrollHeight; |
There was a problem hiding this comment.
I believe you can remove these lines if you use console.log instead of console.error.
There was a problem hiding this comment.
If it's too much detail to print in the UI, it's reasonable to console.log() a short version, and then console.debug() or console.error() an in depth version. It'll be accessible via the browser console.
There was a problem hiding this comment.
I'll keep the console.error(..., err) and console.log(), so the clean string goes to the user's UI, while the full stack trace is still safely dumped into the browser DevTools console for debugging.
@elalish The line length limit should be 80 characters, which is Prettier’s default printWidth. We can adjust it if you prefer a different limit. As for using prettier in vs code easily we can add a |
I've got a branch that's fairly in-depth with |
| let parser = "babel"; | ||
| if (language.includes("typescript")) parser = "typescript"; | ||
|
|
||
| const viewState = editor.saveViewState(); | ||
| editor.pushUndoStop(); | ||
|
|
||
| try { | ||
| const [{ format }, estree, babel, typescript] = await Promise.all([ | ||
| import("prettier/standalone"), | ||
| import("prettier/plugins/estree"), | ||
| import("prettier/plugins/babel"), | ||
| import("prettier/plugins/typescript"), | ||
| ]); | ||
|
|
||
| const plugins = | ||
| parser === "typescript" ? [typescript, estree] : [babel, estree]; |
There was a problem hiding this comment.
The lazy-loading approach here is interesting. When built, does it end up in a separate bundle?
It looks like there's a bunch of initialization code here that will be rerun every time the user formats their code, including the dynamic imports. Is it reasonable to split the initialization and store format, parser and plugins somewhere?
E.g.: At the top level, something like this:
const prettierWrapper = () => {
let prettierParts = null;
const lazyLoad = async () => {
const [{ format }, estree, babel, typescript] = await Promise.all([
import("prettier/standalone"),
import("prettier/plugins/estree"),
import("prettier/plugins/babel"),
import("prettier/plugins/typescript"),
]);
return { format, estree, babel, typescript };
};
const format = async (originalCode, parser="typescript", options = {}) => {
if (!prettierParts) {
prettierParts = await lazyLoad();
}
const {format, estree, babel, typescript} = prettierParts;
return await format(originalCode, {
parser,
plugins: [parser === "typescript" ? typescript : babel, estree],
...options
});
};
return format;
};
const format = prettierWrapper();Then, in this onclick handler, something like:
const formatted = await format(
originalCode,
language.includes("typescript") ? "typescript" : "babel",
{
tabWidth: tabSize,
singleQuote: true,
trailingComma: "all",
}
);Er, treat this as pseudocode -- it's completely untested 😂
I think that's good - the examples are the main thing that need to be formatted, since we don't want them to change in ManifoldCAD.org when someone hits the format button. I agree that having all of our JS/TS files formatted consistently is also good, so I agree with formatting it all. It also looks like prettier is catching more things than clang-format was. I'll let @tonious give the final approval here, since he's working on these files the most. I assume it's expected that you'll need to update a few line numbers of stack trace tests due to the formatting changes? |
yes I just saw the CI jobs and there seems to be some conflicts as well. will push the fix soon. |
tonious
left a comment
There was a problem hiding this comment.
I'm good with this, providing that checks pass, and that this branch is updated to be conflict free.
|
@Divyansh200102 shall I go ahead and take over this PR? You've done a nice job and I'd like to see it merged. |
Yes @elalish please go ahead and thank you for stepping in and helping it get merged. Appreciate it. |
|
@israrkhan921 This might be up your alley - would you be interested in taking over this PR and pushing it across the finish line? |
|
Yes, I can take it, I will check the PR and update you soon, and then start work on this. |

Pull Request Description
bindings/wasm/examples/editor/package.json: Addedprettier ^3.8.1to enable standalone browser and local formatting.bindings/wasm/examples/editor/editor.js: Implemented lazy-loaded Prettier 3.0+ formatting with undo-stack preservation and cursor/scroll state restoration.scripts/format.sh: Migrated WebAssembly file formatting (.js,.ts,.html) fromclang-formattonpx prettier.Screenshot

Note: The diff is large because Prettier was run across all relevant files, and they were reformatted according to the new Prettier configuration.