Skip to content

Commit

Permalink
feat(playground): playground backend v2 (#12136)
Browse files Browse the repository at this point in the history
* feat(playground): render html in back-end
* fullscreen warning
* use hash as subdomain
* add content asset proxy
* use about:blank for iframe

---------

Co-authored-by: Leo McArdle <[email protected]>
  • Loading branch information
fiji-flo and LeoMcA authored Nov 22, 2024
1 parent 10a819c commit f1417ae
Show file tree
Hide file tree
Showing 22 changed files with 662 additions and 394 deletions.
167 changes: 0 additions & 167 deletions client/public/runner.html

This file was deleted.

17 changes: 8 additions & 9 deletions client/src/document/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ export function useCollectSample(doc: any) {
export function useRunSample(doc: Doc | undefined) {
const isServer = useIsServer();
const locale = useLocale();
const { hash } = useLocation();

useEffect(() => {
if (isServer) {
Expand All @@ -61,18 +62,15 @@ export function useRunSample(doc: Doc | undefined) {
return;
}
document.querySelectorAll("iframe").forEach((iframe) => {
const src = new URL(iframe.src || "", "https://example.com");
if (!(src && src.pathname.toLowerCase().endsWith(`/runner.html`))) {
return null;
}
const id = src.searchParams.get("id");
const id = iframe.getAttribute("data-live-id") || null;
const path = iframe.getAttribute("data-live-path") || "/";
if (!id) {
return null;
}

const r =
getCodeAndNodesForIframeBySampleClass(id, src.pathname) ||
getCodeAndNodesForIframe(id, iframe, src.pathname);
getCodeAndNodesForIframeBySampleClass(id, path) ||
getCodeAndNodesForIframe(id, iframe, path);
if (r === null) {
return null;
}
Expand All @@ -91,9 +89,10 @@ export function useRunSample(doc: Doc | undefined) {
code,
locale
);
initPlayIframe(iframe, code);
const fullscreen = hash === `#livesample_fullscreen=${id}`;
initPlayIframe(iframe, code, fullscreen);
});
}, [doc, isServer, locale]);
}, [doc, isServer, locale, hash]);
}

export function useDecorateCodeExamples(doc: Doc | undefined) {
Expand Down
75 changes: 39 additions & 36 deletions client/src/playground/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import prettierPluginHTML from "prettier/plugins/html";
import { Button } from "../ui/atoms/button";
import Editor, { EditorHandle } from "./editor";
import { SidePlacement } from "../ui/organisms/placement";
import { EditorContent, SESSION_KEY, updatePlayIframe } from "./utils";
import { compressAndBase64Encode, EditorContent, SESSION_KEY } from "./utils";

import "./index.scss";
import { PLAYGROUND_BASE_HOST } from "../env";
Expand Down Expand Up @@ -107,6 +107,17 @@ export default function Playground() {
const iframe = useRef<HTMLIFrameElement | null>(null);
const diaRef = useRef<HTMLDialogElement | null>(null);

const updateWithCode = async (code: EditorContent) => {
const { state } = await compressAndBase64Encode(JSON.stringify(code));
const sp = new URLSearchParams([["state", state]]);

if (iframe.current) {
const url = new URL(iframe.current.src);
url.search = sp.toString();
iframe.current.src = url.href;
}
};

useEffect(() => {
if (initialCode) {
store(SESSION_KEY, initialCode);
Expand All @@ -127,33 +138,28 @@ export default function Playground() {
return code;
}, [initialCode?.src]);

let messageListener = useCallback(
({ data: { typ, prop, message } }) => {
if (typ === "console") {
if (prop === "clear") {
setVConsole([]);
} else if (
(prop === "log" || prop === "error" || prop === "warn") &&
typeof message === "string"
) {
setVConsole((vConsole) => [...vConsole, { prop, message }]);
} else {
const warning = "[Playground] Unsupported console message";
setVConsole((vConsole) => [
...vConsole,
{
prop: "warn",
message: `${warning} (see browser console)`,
},
]);
console.warn(warning, { prop, message });
}
} else if (typ === "ready") {
updatePlayIframe(iframe.current, getEditorContent());
let messageListener = useCallback(({ data: { typ, prop, message } }) => {
if (typ === "console") {
if (prop === "clear") {
setVConsole([]);
} else if (
(prop === "log" || prop === "error" || prop === "warn") &&
typeof message === "string"
) {
setVConsole((vConsole) => [...vConsole, { prop, message }]);
} else {
const warning = "[Playground] Unsupported console message";
setVConsole((vConsole) => [
...vConsole,
{
prop: "warn",
message: `${warning} (see browser console)`,
},
]);
console.warn(warning, { prop, message });
}
},
[getEditorContent]
);
}
}, []);

const setEditorContent = ({ html, css, js, src }: EditorContent) => {
htmlRef.current?.setContent(html);
Expand All @@ -169,6 +175,10 @@ export default function Playground() {
if (state === State.initial || state === State.remote) {
if (initialCode && Object.values(initialCode).some(Boolean)) {
setEditorContent(initialCode);
if (!gistId) {
// don't auto run shared code
updateWithCode(initialCode);
}
} else {
setEditorContent({
html: HTML_DEFAULT,
Expand All @@ -178,7 +188,7 @@ export default function Playground() {
}
setState(State.ready);
}
}, [initialCode, state]);
}, [initialCode, state, gistId]);

useEffect(() => {
window.addEventListener("message", messageListener);
Expand Down Expand Up @@ -237,14 +247,7 @@ export default function Playground() {
iterations: 1,
};
document.getElementById("run")?.firstElementChild?.animate(loading, timing);
iframe.current?.contentWindow?.postMessage(
{
typ: "reload",
},
{
targetOrigin: "*",
}
);
updateWithCode({ html, css, js });
};

const format = async () => {
Expand Down
Loading

0 comments on commit f1417ae

Please sign in to comment.