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:
17 files changed
+412
-199
No files matched your search
@@ -77,6 +77,8 @@ const config = {
|
||||
path: "../docs",
|
||||
sidebarCollapsed: false,
|
||||
breadcrumbs: false,
|
||||
lastVersion:
|
||||
process.env.PULL_REQUEST === "true" ? "current" : undefined,
|
||||
versions: {
|
||||
current: {
|
||||
label: "next",
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -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 };
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
},
|
||||
};
|
||||
|
||||
@@ -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"),
|
||||
"",
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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>
|
||||
@@ -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] }];
|
||||
@@ -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
@@ -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,
|
||||
|
||||
@@ -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() {
|
||||
|
||||
Reference in new issue
Block a user