diff --git a/changelog_unreleased/api/13227.md b/changelog_unreleased/api/13227.md
new file mode 100644
index 000000000..73b1fa5dc
--- /dev/null
+++ b/changelog_unreleased/api/13227.md
@@ -0,0 +1,3 @@
+#### "Rethrow embed errors" checkbox on the Playground (#13227 by @thorn0)
+
+Previously, the behavior of the Playground was confusingly inconsistent with the local behavior of Prettier in that it surfaced parsing errors in embedded languages for debug purposes. Now this behavior is controlled by a checkbox and disabled by default.
diff --git a/website/playground/EditorState.js b/website/playground/EditorState.js
index 6396cf0c3..0ad15dc01 100644
--- a/website/playground/EditorState.js
+++ b/website/playground/EditorState.js
@@ -14,6 +14,7 @@ export default class EditorState extends React.Component {
showSecondFormat: false,
showInput: true,
showOutput: true,
+ rethrowEmbedErrors: false,
toggleSidebar: () => this.setState(stateToggler("showSidebar")),
toggleAst: () => this.setState(stateToggler("showAst")),
toggleDoc: () => this.setState(stateToggler("showDoc")),
@@ -21,6 +22,8 @@ export default class EditorState extends React.Component {
toggleSecondFormat: () => this.setState(stateToggler("showSecondFormat")),
toggleInput: () => this.setState(stateToggler("showInput")),
toggleOutput: () => this.setState(stateToggler("showOutput")),
+ toggleEmbedErrors: () =>
+ this.setState(stateToggler("rethrowEmbedErrors")),
...storage.get("editor_state"),
};
}
diff --git a/website/playground/Playground.js b/website/playground/Playground.js
index c76e724fb..1b0393b80 100644
--- a/website/playground/Playground.js
+++ b/website/playground/Playground.js
@@ -208,6 +208,7 @@ class Playground extends React.Component {
debugDoc={editorState.showDoc}
debugComments={showShowComments && editorState.showComments}
reformat={editorState.showSecondFormat}
+ rethrowEmbedErrors={editorState.rethrowEmbedErrors}
>
{({ formatted, debug }) => {
const fullReport = this.getMarkdown({
@@ -289,6 +290,11 @@ class Playground extends React.Component {
checked={editorState.showSecondFormat}
onChange={editorState.toggleSecondFormat}
/>
+
{editorState.showDoc && (
this.getMarkdown({ doc: debug.doc })}
diff --git a/website/playground/PrettierFormat.js b/website/playground/PrettierFormat.js
index 6d048ebb8..d66828be3 100644
--- a/website/playground/PrettierFormat.js
+++ b/website/playground/PrettierFormat.js
@@ -19,6 +19,7 @@ export default class PrettierFormat extends React.Component {
"debugDoc",
"debugComments",
"reformat",
+ "rethrowEmbedErrors",
]) {
if (prevProps[key] !== this.props[key]) {
this.format();
@@ -37,6 +38,7 @@ export default class PrettierFormat extends React.Component {
debugDoc: doc,
debugComments: comments,
reformat,
+ rethrowEmbedErrors,
} = this.props;
if (!enabled) {
@@ -44,7 +46,13 @@ export default class PrettierFormat extends React.Component {
}
worker
- .format(code, options, { ast, doc, comments, reformat })
+ .format(code, options, {
+ ast,
+ doc,
+ comments,
+ reformat,
+ rethrowEmbedErrors,
+ })
.then((result) => this.setState(result));
}
diff --git a/website/static/worker.js b/website/static/worker.js
index 0b115053e..5d70c5585 100644
--- a/website/static/worker.js
+++ b/website/static/worker.js
@@ -2,8 +2,6 @@
"use strict";
-self.PRETTIER_DEBUG = true;
-
const imported = Object.create(null);
function importScriptOnce(url) {
if (!imported[url]) {
@@ -72,96 +70,106 @@ function serializeAst(ast) {
}
function handleMessage(message) {
- if (message.type === "meta") {
- return {
- type: "meta",
- supportInfo: JSON.parse(
- JSON.stringify(
- prettier.getSupportInfo({
- showUnreleased: true,
- plugins: [docExplorerPlugin],
- })
- )
- ),
- version: prettier.version,
- };
- }
-
- if (message.type === "format") {
- const options = message.options || {};
-
- delete options.ast;
- delete options.doc;
- delete options.output2;
-
- const plugins = [{ parsers }, docExplorerPlugin];
- options.plugins = plugins;
-
- const formatResult = formatCode(message.code, options);
-
- const response = {
- formatted: formatResult.formatted,
- cursorOffset: formatResult.cursorOffset,
- error: formatResult.error,
- debug: {
- ast: null,
- doc: null,
- comments: null,
- reformatted: null,
- },
- };
-
- if (message.debug.ast) {
- let ast;
- let errored = false;
- try {
- ast = serializeAst(prettier.__debug.parse(message.code, options).ast);
- } catch (e) {
- errored = true;
- ast = String(e);
- }
-
- if (!errored) {
- try {
- ast = formatCode(ast, { parser: "json", plugins }).formatted;
- } catch {
- ast = serializeAst(ast);
- }
- }
- response.debug.ast = ast;
- }
-
- if (message.debug.doc) {
- try {
- response.debug.doc = prettier.__debug.formatDoc(
- prettier.__debug.printToDoc(message.code, options),
- { plugins }
- );
- } catch {
- response.debug.doc = "";
- }
- }
-
- if (message.debug.comments) {
- response.debug.comments = formatCode(
- JSON.stringify(formatResult.comments || []),
- { parser: "json", plugins }
- ).formatted;
- }
-
- if (message.debug.reformat) {
- response.debug.reformatted = formatCode(
- response.formatted,
- options
- ).formatted;
- }
-
- return response;
+ switch (message.type) {
+ case "meta":
+ return handleMetaMessage();
+ case "format":
+ return handleFormatMessage(message);
}
}
-function formatCode(text, options) {
+function handleMetaMessage() {
+ return {
+ type: "meta",
+ supportInfo: JSON.parse(
+ JSON.stringify(
+ prettier.getSupportInfo({
+ showUnreleased: true,
+ plugins: [docExplorerPlugin],
+ })
+ )
+ ),
+ version: prettier.version,
+ };
+}
+
+function handleFormatMessage(message) {
+ const plugins = [{ parsers }, docExplorerPlugin];
+ const options = { ...message.options, plugins };
+
+ delete options.ast;
+ delete options.doc;
+ delete options.output2;
+
+ const formatResult = formatCode(
+ message.code,
+ options,
+ message.debug.rethrowEmbedErrors
+ );
+
+ const response = {
+ formatted: formatResult.formatted,
+ cursorOffset: formatResult.cursorOffset,
+ error: formatResult.error,
+ debug: {
+ ast: null,
+ doc: null,
+ comments: null,
+ reformatted: null,
+ },
+ };
+
+ if (message.debug.ast) {
+ let ast;
+ let errored = false;
+ try {
+ ast = serializeAst(prettier.__debug.parse(message.code, options).ast);
+ } catch (e) {
+ errored = true;
+ ast = String(e);
+ }
+
+ if (!errored) {
+ try {
+ ast = formatCode(ast, { parser: "json", plugins }).formatted;
+ } catch {
+ ast = serializeAst(ast);
+ }
+ }
+ response.debug.ast = ast;
+ }
+
+ if (message.debug.doc) {
+ try {
+ response.debug.doc = prettier.__debug.formatDoc(
+ prettier.__debug.printToDoc(message.code, options),
+ { plugins }
+ );
+ } catch {
+ response.debug.doc = "";
+ }
+ }
+
+ if (message.debug.comments) {
+ response.debug.comments = formatCode(
+ JSON.stringify(formatResult.comments || []),
+ { parser: "json", plugins }
+ ).formatted;
+ }
+
+ if (message.debug.reformat) {
+ response.debug.reformatted = formatCode(
+ response.formatted,
+ options
+ ).formatted;
+ }
+
+ return response;
+}
+
+function formatCode(text, options, rethrowEmbedErrors) {
try {
+ self.PRETTIER_DEBUG = rethrowEmbedErrors;
return prettier.formatWithCursor(text, options);
} catch (e) {
if (e.constructor && e.constructor.name === "SyntaxError") {
@@ -171,6 +179,8 @@ function formatCode(text, options) {
// Likely a bug in Prettier
// Provide the whole stack for debugging
return { formatted: stringifyError(e), error: true };
+ } finally {
+ self.PRETTIER_DEBUG = undefined;
}
}