Add playground for current version (#18830)

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: fisker <lionkay@gmail.com>
This commit is contained in:
authored and GitHub committed 2026-02-05 22:29:59 +08:00
1 parent efcc72d91b
commit d9bd8abfeb
17 files changed
+412 -199

No files matched your search

+7 -1
View File
@@ -1,6 +1,8 @@
const fs = require("node:fs");
const path = require("node:path");
const root = path.join(__dirname, "../../");
function setupVscode() {
const settingsFile = path.join(__dirname, "../../.vscode/settings.json");
@@ -27,7 +29,11 @@ module.exports = {
name: "plugin-prepare",
factory: () => ({
hooks: {
async afterAllInstalled() {
async afterAllInstalled({ cwd }) {
if (cwd !== root) {
return;
}
setupVscode();
try {
await buildBabelCodeFrameForTest();
+62 -36
View File
@@ -1,6 +1,6 @@
#!/usr/bin/env node
import fs from "node:fs/promises";
import assert from "node:assert/strict";
import path from "node:path";
import url from "node:url";
import esbuild from "esbuild";
@@ -13,58 +13,61 @@ import {
PROJECT_ROOT,
WEBSITE_DIR,
writeFile,
writeJson,
} from "./utilities/index.js";
const runYarn = (command, args, options) =>
spawn("yarn", [command, ...args], { stdio: "inherit", ...options });
const IS_PULL_REQUEST = process.env.PULL_REQUEST === "true";
const PACKAGES_DIRECTORY = IS_PULL_REQUEST
? DIST_DIR
: url.fileURLToPath(new URL("../node_modules", import.meta.url));
const PLAYGROUND_LIB_DIRECTORY = path.join(WEBSITE_DIR, "static/lib");
const NODE_MODULES_DIR = url.fileURLToPath(
new URL("../node_modules", import.meta.url),
);
async function writeScript(file, code) {
const { code: minified } = await esbuild.transform(code, {
loader: "js",
minify: true,
});
await writeFile(path.join(PLAYGROUND_LIB_DIRECTORY, file), minified.trim());
await writeFile(file, minified.trim());
}
async function buildPrettier() {
// --- Build prettier for PR ---
const packageJsonFile = path.join(PROJECT_ROOT, "package.json");
const packageJsonContent = await fs.readFile(packageJsonFile);
const packageJson = JSON.parse(packageJsonContent);
await writeJson(packageJsonFile, {
...packageJson,
version: `999.999.999-pr.${process.env.REVIEW_ID}`,
});
/** @param {"stable" | "next"} version */
async function buildPlaygroundFiles(version) {
assert.ok(version === "stable" || version === "next");
try {
await runYarn("build", ["--clean", "--playground"], {
cwd: PROJECT_ROOT,
});
} finally {
// restore
await writeFile(packageJsonFile, packageJsonContent);
let packagesDirectory;
const versionData = { name: version };
const libDirectory = path.join(WEBSITE_DIR, `static/lib/${version}/`);
if (version === "stable") {
packagesDirectory = NODE_MODULES_DIR;
const { version: prettierVersion } = await import(
url.pathToFileURL(path.join(packagesDirectory, "prettier/standalone.mjs"))
);
versionData.version = prettierVersion;
}
if (version === "next") {
packagesDirectory = DIST_DIR;
versionData.gitTree = await getGitTreeInformation();
if (IS_PULL_REQUEST) {
versionData.pr = process.env.REVIEW_ID;
}
}
}
async function buildPlaygroundFiles() {
const pluginFiles = [];
// Builtin plugins
for (const fileName of await fastGlob(["plugins/*.mjs"], {
cwd: path.join(PACKAGES_DIRECTORY, "prettier"),
cwd: path.join(packagesDirectory, "prettier"),
ignore: ["plugins/flow*"],
})) {
pluginFiles.push(`prettier/${fileName}`);
}
// TODO: Support stable version
// External plugins
if (IS_PULL_REQUEST) {
if (version === "next") {
for (const pluginName of ["plugin-hermes"]) {
pluginFiles.push(`${pluginName}/index.mjs`);
}
@@ -74,6 +77,7 @@ async function buildPlaygroundFiles() {
}
const packageManifest = {
version: versionData,
prettier: {
file: "prettier/standalone.mjs",
},
@@ -82,7 +86,7 @@ async function buildPlaygroundFiles() {
const plugin = { file };
const pluginModule = await import(
url.pathToFileURL(path.join(PACKAGES_DIRECTORY, file))
url.pathToFileURL(path.join(packagesDirectory, file))
);
for (const property of ["languages", "options", "defaultOptions"]) {
@@ -107,24 +111,46 @@ async function buildPlaygroundFiles() {
await Promise.all([
...[packageManifest.prettier, ...packageManifest.plugins].map(({ file }) =>
copyFile(
path.join(PACKAGES_DIRECTORY, file),
path.join(PLAYGROUND_LIB_DIRECTORY, file),
path.join(packagesDirectory, file),
path.join(libDirectory, file),
),
),
writeScript(
"package-manifest.mjs",
path.join(libDirectory, "package-manifest.mjs"),
`export default ${serialize(packageManifest, { space: 2 })};`,
),
]);
}
if (IS_PULL_REQUEST) {
console.log("Building prettier...");
await buildPrettier();
async function getGitTreeInformation() {
const { stdout: branch } = await spawn("git", [
"rev-parse",
"--abbrev-ref",
"HEAD",
]);
const { stdout: diff } = await spawn("git", ["diff", "--name-only"]);
if (diff) {
return { branch };
}
const { stdout: commit } = await spawn("git", [
"rev-parse",
"--short",
"HEAD",
]);
return { branch, commit };
}
console.log("Preparing files for playground...");
await buildPlaygroundFiles();
console.log("Building prettier...");
await runYarn("build", ["--clean", "--playground"], { cwd: PROJECT_ROOT });
console.log("Preparing files for playground (stable)...");
await buildPlaygroundFiles("stable");
console.log("Preparing files for playground (next)...");
await buildPlaygroundFiles("next");
// --- Site ---
console.log("Installing website dependencies...");
+2
View File
@@ -77,6 +77,8 @@ const config = {
path: "../docs",
sidebarCollapsed: false,
breadcrumbs: false,
lastVersion:
process.env.PULL_REQUEST === "true" ? "current" : undefined,
versions: {
current: {
label: "next",
+3 -3
View File
@@ -162,7 +162,7 @@ function setup(props) {
const getMarkdown = ({ formatted, reformatted, full, doc }) => {
const { content, options } = state;
const { availableOptions, version } = props;
const { availableOptions } = props;
const orderedOptions = orderOptions(availableOptions, [
...ENABLED_OPTIONS,
"rangeStart",
@@ -176,7 +176,7 @@ function setup(props) {
output: formatted,
output2: reformatted,
doc,
version,
version: props.version,
url: window.location.href,
options,
cliOptions,
@@ -547,7 +547,7 @@ const Playground = {
name: "Playground",
props: {
availableOptions: { type: Array, required: true },
version: { type: String, required: true },
version: { type: Object, required: true },
},
setup,
};
+3
View File
@@ -1,6 +1,7 @@
import { onMounted, reactive, toRaw, watch } from "vue";
import { settings } from "./composables/playground-settings.js";
import { worker } from "./composables/prettier-worker.js";
import { version } from "./composables/use-version.js";
function setup(props, { slots }) {
const state = reactive({ formatted: "", debug: {} });
@@ -14,6 +15,7 @@ function setup(props, { slots }) {
props.code,
toRaw(props.options),
toRaw(settings),
version.value,
);
Object.assign(state, result);
@@ -24,6 +26,7 @@ function setup(props, { slots }) {
onMounted(componentDidMount);
watch(() => props.code, format);
watch(() => props.options, format, { deep: true });
watch(() => version.value, format);
// Should not trigger format when these changes
const ignoredKeys = new Set(["showSidebar", "showInput"]);
@@ -2,14 +2,20 @@
@import {PlaygroundSettings} from "./playground-settings.js"
@import {FormatMessage, MetaMessage} from "../../static/worker.mjs"
*/
class WorkerApi {
#worker = new Worker("/worker.mjs", { type: "module" });
#workers = {};
#counter = 0;
#handlers = {};
constructor() {
const worker = this.#worker;
#initWorker(version) {
if (this.#workers[version]) {
return this.#workers[version];
}
const worker = new Worker(`/worker.mjs?version=${version}`, {
type: "module",
});
this.#workers[version] = worker;
const handlers = this.#handlers;
worker.addEventListener("message", (event) => {
@@ -28,20 +34,25 @@ class WorkerApi {
resolve(message);
}
});
return worker;
}
#postMessage(message) {
const worker = this.#initWorker(message.version);
const uid = ++this.#counter;
const worker = this.#worker;
return new Promise((resolve, reject) => {
this.#handlers[uid] = [resolve, reject];
worker.postMessage({ uid, message });
});
}
getMetadata() {
/**
* @param {MetaMessage["version"]} version
*/
getMetadata(version) {
/** @type {MetaMessage} */
const message = { type: "meta" };
const message = { type: "meta", version };
return this.#postMessage(message);
}
@@ -49,10 +60,11 @@ class WorkerApi {
* @param {FormatMessage["code"]} code
* @param {FormatMessage["options"]} options
* @param {FormatMessage["settings"]} settings
* @param {FormatMessage["version"]} version
*/
format(code, options, settings) {
format(code, options, settings, version) {
/** @type {FormatMessage} */
const message = { type: "format", code, options, settings };
const message = { type: "format", version, code, options, settings };
return this.#postMessage(message);
}
}
@@ -0,0 +1,50 @@
import { ref } from "vue";
const ALLOWED_VERSIONS = new Set(["next", "stable"]);
const IS_PULL_REQUEST = import.meta.env.VITE_IS_PR;
const DEFAULT_VERSION = IS_PULL_REQUEST ? "next" : "stable";
const DOCS_VERSION_KEY = "docs-preferred-version-default";
function getVersion() {
const versionInUrl = new URLSearchParams(window.location.search).get(
"version",
);
if (ALLOWED_VERSIONS.has(versionInUrl)) {
return versionInUrl;
}
let docsVersion = localStorage.getItem(DOCS_VERSION_KEY);
if (docsVersion === "current") {
docsVersion = "next";
}
if (ALLOWED_VERSIONS.has(docsVersion)) {
return docsVersion;
}
return DEFAULT_VERSION;
}
function setVersion(value) {
value = ALLOWED_VERSIONS.has(value) ? value : DEFAULT_VERSION;
// Save to localStorage, so the docs can respond to version change
localStorage.setItem(DOCS_VERSION_KEY, value === "next" ? "current" : value);
const url = new URL(window.location);
if (!IS_PULL_REQUEST && value === DEFAULT_VERSION) {
url.searchParams.delete("version");
} else {
url.searchParams.set("version", value);
}
window.history.replaceState({}, "", url);
version.value = value;
}
const version = ref(undefined);
setVersion(getVersion());
export { setVersion, version };
+42 -17
View File
@@ -5,42 +5,67 @@ import VersionLink from "./version-link.vue";
const logo = "/icon.png";
defineProps({
version: { type: String, required: true },
const props = defineProps({
version: { type: Object, required: true },
});
</script>
<template>
<header>
<header class="header">
<a href="/" class="logo-wrapper">
<img class="logo" :src="logo" alt="" />
<h1>Prettier <VersionLink :version></VersionLink></h1>
<h1>Prettier</h1>
</a>
<span class="links">
<GithubButton
href="https://github.com/prettier/prettier"
dataShowCount="true"
class="github-button"
aria-label="Star prettier on GitHub"
>GitHub</GithubButton
>
<VersionLink :version="version" />
<div class="links">
<div class="github-button">
<GithubButton
href="https://github.com/prettier/prettier"
dataShowCount="true"
aria-label="Star prettier on GitHub"
>GitHub</GithubButton
>
</div>
<ThemeToggle></ThemeToggle>
</span>
</div>
</header>
</template>
<style>
.header {
display: flex;
align-items: center;
gap: 10px;
}
.logo-wrapper {
display: flex;
align-items: center;
}
.logo-wrapper h1 {
font-size: 20px;
display: block;
font-family: inherit;
font-weight: 400;
line-height: 18px;
position: relative;
margin: 0;
}
.logo {
height: 34px;
margin-right: 10px;
}
.links {
display: flex;
gap: 8px;
align-items: flex-end;
}
.links > * {
display: flex;
}
.github-button span {
display: flex;
}
+16 -8
View File
@@ -1,26 +1,34 @@
import "./install-service-worker.js";
import { createApp, onMounted, reactive } from "vue";
import { createApp, onMounted, reactive, toRaw, watch } from "vue";
import { settings } from "./composables/playground-settings.js";
import { worker } from "./composables/prettier-worker.js";
import { setVersion, version } from "./composables/use-version.js";
import Header from "./header.vue";
import Playground from "./Playground.jsx";
import { fixPrettierVersion } from "./utilities.js";
import { formatVersion } from "./utilities.js";
const App = {
name: "App",
setup() {
const state = reactive({ loaded: false });
const state = reactive({
loaded: false,
});
const componentDidMount = async () => {
const { supportInfo, version } = await worker.getMetadata();
const updateMetadata = async () => {
const { supportInfo, version: versionData } = await worker.getMetadata(
version.value,
);
Object.assign(state, {
loaded: true,
availableOptions: supportInfo.options.map(augmentOption),
version: fixPrettierVersion(version),
version: formatVersion(versionData),
});
};
watch(() => version.value, updateMetadata);
const render = () => {
const { loaded, availableOptions, version } = state;
@@ -30,13 +38,13 @@ const App = {
return (
<>
<Header version={version}></Header>
<Header version={version} />
<Playground availableOptions={availableOptions} version={version} />
</>
);
};
onMounted(componentDidMount);
onMounted(() => updateMetadata());
return render;
},
};
+1 -1
View File
@@ -14,7 +14,7 @@ function formatMarkdown({
const isIdempotent = !output2 || output === output2;
return [
`**Prettier ${version}**`,
`**Prettier ${version.text}**`,
`[Playground link](${url})`,
optionsString === "" ? null : codeBlock(optionsString, "sh"),
"",
+4 -21
View File
@@ -56,6 +56,10 @@ header {
header {
padding: 10px;
}
.github-button {
display: none;
}
}
header a,
@@ -67,27 +71,6 @@ header a:hover {
text-decoration: none;
}
.logo-wrapper {
display: flex;
align-items: center;
}
.logo {
height: 34px;
margin-right: 10px;
}
header h1 {
font-size: 20px;
display: block;
font-family: inherit;
font-weight: 400;
line-height: 18px;
position: relative;
z-index: 9999;
margin: 0;
}
.theme-icon {
padding-block: 2px;
}
+25 -5
View File
@@ -1,9 +1,29 @@
export function fixPrettierVersion(version) {
const match = version.match(/^\d+\.\d+\.\d+-pr.(\d+)$/);
if (match) {
return `pr-${match[1]}`;
export function formatVersion(version) {
if (version.name === "stable") {
return {
text: `v${version.version}`,
title: `Prettier v${version.version}`,
link: `https://github.com/prettier/prettier/releases/tag/${version.version}`,
};
}
return version;
if (version.name === "next" && version.pr) {
return {
text: `PR #${version.pr}`,
title: `Prettier #${version.pr}`,
link: `https://github.com/prettier/prettier/pull/${version.pr}`,
};
}
const commit = version.gitTree?.commit;
return {
text: commit ?? "uncommitted changes",
title: `Prettier (${commit ?? "uncommitted"})`,
link: commit
? `https://github.com/prettier/prettier/commit/${commit}`
: "https://github.com/prettier/prettier/",
};
}
export function getDefaults(availableOptions, optionNames) {
+38 -32
View File
@@ -1,51 +1,57 @@
<script setup>
import { computed, watch, onMounted } from "vue";
import { watch, onMounted } from "vue";
import {
version as playgroundVersion,
setVersion as setPlaygroundVersion,
} from "./composables/use-version.js";
const props = defineProps({
version: { type: String, required: true },
});
const versionData = computed(() => {
const match = props.version.match(/^pr-(\d+)$/);
let href;
if (match) {
href = `pull/${match[1]}`;
} else if (/\.0$/.test(props.version)) {
href = `releases/tag/${props.version}`;
} else {
href = `blob/main/CHANGELOG.md#${props.version.replaceAll(".", "")}`;
}
return {
href,
formattedVersion: match ? `PR #${match[1]}` : `v${props.version}`,
};
version: { type: Object, required: true },
});
const updateTitle = () => {
document.title = `Prettier ${versionData.value.formattedVersion}`;
document.title = props.version.title;
};
watch(() => props.version, updateTitle);
watch(() => props.version.title, updateTitle);
onMounted(updateTitle);
</script>
<template>
<a
:href="`https://github.com/prettier/prettier/${versionData.href}`"
target="_blank"
rel="noreferrer noopener"
class="version"
>
{{ versionData.formattedVersion }}
</a>
<div class="version-wrapper">
<select
class="channel-select"
:value="playgroundVersion"
@change="
(event) => {
setPlaygroundVersion(event.target.value);
}
"
>
<option value="stable">stable</option>
<option value="next">next</option>
</select>
<a
class="version-link"
:href="version.link"
target="_blank"
rel="noopener noreferrer"
>
{{ version.text }}
</a>
</div>
</template>
<style>
.version {
font-size: 0.5em;
line-height: 0;
.version-wrapper {
display: flex;
align-items: center;
gap: 0.5em;
flex: 1;
}
.version-link {
opacity: 0.5;
}
</style>
+52 -47
View File
@@ -1,20 +1,8 @@
import prettierPackageManifest from "./lib/package-manifest.mjs";
import * as prettier from "./lib/prettier/standalone.mjs";
const builderNames = new Set(Object.keys(prettier.doc.builders));
const parserName = "doc-explorer";
const languageName = "Doc explorer";
const astFormat = parserName;
const expressionParserName = "__js_expression";
async function getJsExpressionParser() {
const plugin = prettierPackageManifest.plugins.find((plugin) =>
plugin.parsers?.includes(expressionParserName),
);
const pluginModule = await import(`./lib/${plugin.file}`);
return pluginModule.parsers[expressionParserName];
}
// `Symbol.for('description')`
function isSymbol(node) {
@@ -32,7 +20,7 @@ function isSymbol(node) {
);
}
function validateNode(node) {
function validateNode(node, builderNames) {
if (!node?.type) {
return;
}
@@ -54,7 +42,7 @@ function validateNode(node) {
continue;
}
validateNode(value);
validateNode(value, builderNames);
}
return;
}
@@ -67,44 +55,61 @@ function validateNode(node) {
const children = Array.isArray(value) ? value : [value];
for (const child of children) {
validateNode(child);
validateNode(child, builderNames);
}
}
}
let expressionParser;
async function validateDoc(text) {
expressionParser ??= await getJsExpressionParser();
export function createDocExplorerPlugin(
prettier,
prettierPackageManifest,
version,
) {
const builderNames = new Set(Object.keys(prettier.doc.builders));
const ast = expressionParser.parse(text);
if (ast.type !== "JsExpressionRoot") {
throw new Error("Invalid doc");
async function getJsExpressionParser() {
const plugin = prettierPackageManifest.plugins.find((plugin) =>
plugin.parsers?.includes(expressionParserName),
);
const pluginModule = await import(`./lib/${version}/${plugin.file}`);
return pluginModule.parsers[expressionParserName];
}
validateNode(ast.node);
let expressionParser;
async function validateDoc(text) {
expressionParser ??= await getJsExpressionParser();
const ast = expressionParser.parse(text);
if (ast.type !== "JsExpressionRoot") {
throw new Error("Invalid doc");
}
validateNode(ast.node, builderNames);
}
async function parse(text) {
await validateDoc(text);
const value = new Function(
`{ ${Object.keys(prettier.doc.builders)} }`,
`const result = (${text || "''"}\n); return result;`,
)(prettier.doc.builders);
return { value };
}
return {
parsers: {
[parserName]: {
parse,
astFormat,
},
},
printers: {
[astFormat]: {
print: ({ node }) => node.value,
},
},
languages: [{ name: languageName, parsers: [parserName] }],
};
}
async function parse(text) {
await validateDoc(text);
const value = new Function(
`{ ${Object.keys(prettier.doc.builders)} }`,
`const result = (${text || "''"}\n); return result;`,
)(prettier.doc.builders);
return { value };
}
export const parsers = {
[parserName]: {
parse,
astFormat,
},
};
export const printers = {
[astFormat]: {
print: ({ node }) => node.value,
},
};
export const languages = [{ name: languageName, parsers: [parserName] }];
+15 -7
View File
@@ -1,17 +1,25 @@
import "https://cdnjs.cloudflare.com/ajax/libs/sw-toolbox/3.6.0/sw-toolbox.js";
import prettierPackageManifest from "./lib/package-manifest.mjs";
import prettierPackageManifestNext from "./lib/next/package-manifest.mjs";
import prettierPackageManifestStable from "./lib/stable/package-manifest.mjs";
const { toolbox } = self;
const packageFiles = [
prettierPackageManifest.prettier,
...prettierPackageManifest.plugins,
].map(({ file }) => `./lib/${file}`);
function getPackageFiles(manifest) {
return [manifest.prettier, ...manifest.plugins].map(
({ file }) => `./lib/${manifest.version.name}/${file}`,
);
}
const stableFiles = getPackageFiles(prettierPackageManifestStable);
const nextFiles = getPackageFiles(prettierPackageManifestNext);
toolbox.precache([
// Scripts
"lib/package-manifest.mjs",
...packageFiles,
"lib/stable/package-manifest.mjs",
...stableFiles,
"lib/next/package-manifest.mjs",
...nextFiles,
"https://cdnjs.cloudflare.com/ajax/libs/sw-toolbox/3.6.0/sw-toolbox.js",
// Images
+66 -12
View File
@@ -1,22 +1,74 @@
import prettierPackageManifest from "./lib/package-manifest.mjs";
import * as prettier from "./lib/prettier/standalone.mjs";
import * as prettierPluginDocExplorer from "./prettier-plugin-doc-explorer.mjs";
import { createDocExplorerPlugin } from "./prettier-plugin-doc-explorer.mjs";
/**
@import {PlaygroundSettings} from "../playground/composables/playground-settings.js"
@typedef {{ type: "meta" }} MetaMessage
@typedef {{
type: "meta",
version: "stable" | "next",
}} MetaMessage
@typedef {{
type: "format",
code: string,
options: any,
settings: PlaygroundSettings
settings: PlaygroundSettings,
version: "stable" | "next",
}} FormatMessage
*/
const workerUrl = new URL(import.meta.url);
const version =
workerUrl.searchParams.get("version") === "next" ? "next" : "stable";
let prettierCache;
let prettierPackageManifestCache;
let prettierPluginDocExplorerCache;
let pluginsCache;
async function loadPrettier() {
if (!prettierCache) {
prettierCache = import(`./lib/${version}/prettier/standalone.mjs`);
}
return await prettierCache;
}
async function loadPrettierPackageManifest() {
if (!prettierPackageManifestCache) {
prettierPackageManifestCache = import(
`./lib/${version}/package-manifest.mjs`
).then((m) => m.default);
}
return await prettierPackageManifestCache;
}
async function loadPrettierPluginDocExplorer() {
if (!prettierPluginDocExplorerCache) {
const prettier = await loadPrettier();
const prettierPackageManifest = await loadPrettierPackageManifest();
prettierPluginDocExplorerCache = createDocExplorerPlugin(
prettier,
prettierPackageManifest,
version,
);
}
return prettierPluginDocExplorerCache;
}
async function loadPlugins() {
if (!pluginsCache) {
const prettierPackageManifest = await loadPrettierPackageManifest();
const prettierPluginDocExplorer = await loadPrettierPluginDocExplorer();
pluginsCache = [
...prettierPackageManifest.plugins.map((plugin) => createPlugin(plugin)),
prettierPluginDocExplorer,
];
}
return pluginsCache;
}
const pluginLoadPromises = new Map();
async function importPlugin(plugin) {
if (!pluginLoadPromises.has(plugin)) {
pluginLoadPromises.set(plugin, import(`./lib/${plugin.file}`));
pluginLoadPromises.set(plugin, import(`./lib/${version}/${plugin.file}`));
}
try {
@@ -52,11 +104,6 @@ function createPlugin(pluginManifest) {
return plugin;
}
const plugins = [
...prettierPackageManifest.plugins.map((plugin) => createPlugin(plugin)),
prettierPluginDocExplorer,
];
self.onmessage = async function (event) {
self.postMessage({
uid: event.data.uid,
@@ -113,13 +160,17 @@ function handleMessage(message) {
}
async function handleMetaMessage() {
const prettier = await loadPrettier();
const prettierPackageManifest = await loadPrettierPackageManifest();
const plugins = await loadPlugins();
const supportInfo = await prettier.getSupportInfo({ plugins });
return {
type: "meta",
// eslint-disable-next-line unicorn/prefer-structured-clone
supportInfo: JSON.parse(JSON.stringify(supportInfo)),
version: prettier.version,
version: prettierPackageManifest.version,
};
}
@@ -127,6 +178,8 @@ async function handleMetaMessage() {
@param {FormatMessage} message
*/
async function handleFormatMessage(message) {
const prettier = await loadPrettier();
const plugins = await loadPlugins();
let { options, code, settings } = message;
options = { ...options, plugins };
@@ -231,6 +284,7 @@ async function handleFormatMessage(message) {
@param {PlaygroundSettings} settings
*/
async function formatCode(text, options, settings = {}) {
const prettier = await loadPrettier();
if (options.parser === "doc-explorer") {
options = {
...options,
+5
View File
@@ -43,6 +43,11 @@ export default defineConfig({
outDir: OUT_DIRECTORY,
minify: IS_CI,
},
define: {
"import.meta.env.VITE_IS_PR": JSON.stringify(
Boolean(process.env.PULL_REQUEST),
),
},
});
function buildCdnAlias() {