From 4c6194c4c2b5506f6d482347b0c13033ef17b5c7 Mon Sep 17 00:00:00 2001 From: "netop://ウィビ" Date: Fri, 24 Apr 2026 07:43:33 -0700 Subject: initial commit --- source/graphiql/render.ts | 218 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 218 insertions(+) create mode 100755 source/graphiql/render.ts (limited to 'source/graphiql/render.ts') diff --git a/source/graphiql/render.ts b/source/graphiql/render.ts new file mode 100755 index 0000000..a0e4dc2 --- /dev/null +++ b/source/graphiql/render.ts @@ -0,0 +1,218 @@ + + + +/*** IMPORT ------------------------------------------- ***/ + +import { filterXSS } from "xss"; + +/*** UTILITY ------------------------------------------ ***/ + +import { getLoadingMarkup } from "./markup.ts"; + +const CONFIG_ID = "playground-config"; +const loading = getLoadingMarkup(); + +const filter = (val: string) => { + return filterXSS(val, { + stripIgnoreTag: true, + stripIgnoreTagBody: ["script"], + whiteList: {} + }); +} + +const getCdnMarkup = ({ cdnUrl = "//cdn.jsdelivr.net/npm", faviconUrl, version }: { + cdnUrl?: string + faviconUrl?: string | null + version?: string +}) => { + const buildCDNUrl = (packageName: string, suffix: string) => + filter(`${cdnUrl}/${packageName}${version ? `@${version}` : ""}/${suffix}` || ""); + + return ` + + ${typeof faviconUrl === "string" ? `` : ""} + ${faviconUrl === undefined ? `` : ""} + + `; +} + +const renderConfig = (config: unknown) => { + return filterXSS(`
${JSON.stringify(config)}
`, { + whiteList: { div: ["id"] } + }); +}; + +/*** EXPORT ------------------------------------------- ***/ + +export interface MiddlewareOptions { + codeTheme?: EditorColours; + config?: { [key: string]: unknown; }; + endpoint?: string; + env?: "electron" | "react"; + schema?: IntrospectionResult; + settings?: ISettings; + subscriptionEndpoint?: string; + tabs?: Tab[]; + workspaceName?: string; +} + +export type CursorShape = "line" | "block" | "underline"; +export type Theme = "dark" | "light"; + +export interface ISettings { + "editor.cursorShape": CursorShape; + "editor.fontFamily": string; + "editor.fontSize": number; + "editor.reuseHeaders": boolean; + "editor.theme": Theme; + "general.betaUpdates": boolean; + "request.credentials": string; + "request.globalHeaders": { [key: string]: string }; + "schema.polling.enable": boolean; + "schema.polling.endpointFilter": string; + "schema.polling.interval": number; + "tracing.hideTracingResponse": boolean; + "tracing.tracingSupported": boolean; +} + +export interface EditorColours { + atom: string; + attribute: string; + builtin: string; + comment: string; + cursorColor: string; + def: string; + editorBackground: string; + keyword: string; + leftDrawerBackground: string; + meta: string; + number: string; + property: string; + punctuation: string; + qualifier: string; + resultBackground: string; + rightDrawerBackground: string; + selection: string; + string: string; + string2: string; + variable: string; + ws: string; +} + +export interface IntrospectionResult { + __schema: { [key: string]: unknown; }; +} + +export interface RenderPageOptions extends MiddlewareOptions { + cdnUrl?: string; + env?: "electron" | "react"; + faviconUrl?: string | null; + title?: string; + version?: string; +} + +export interface Tab { + endpoint: string; + headers?: { [key: string]: string }; + name?: string; + query: string; + responses?: string[]; + variables?: string; +} + +/** + * Renders the GraphQL Playground HTML shell. + * + * Usually called indirectly via `GraphQLHTTP({ graphiql: true })`; invoke it + * directly if you need to embed the Playground in a custom route. + */ +export function renderPlaygroundPage(options: RenderPageOptions) { + const extendedOptions: + & Partial<{ + canSaveConfig: boolean + configString: string + }> + & RenderPageOptions = { + ...options, + canSaveConfig: false + }; + + if (options.config) + extendedOptions.configString = JSON.stringify(options.config, null, 2); + + if (!extendedOptions.endpoint && !extendedOptions.configString) + console.warn("WARNING: You did not provide an endpoint and do not have a .graphqlconfig. Make sure you have at least one of them."); + else if (extendedOptions.endpoint) + extendedOptions.endpoint = filter(extendedOptions.endpoint || ""); + + return ` + + + + + + + ${extendedOptions.title || "GraphQL Playground"} + ${extendedOptions.env === "react" || extendedOptions.env === "electron" ? "" : getCdnMarkup(extendedOptions)} + + + + + + ${loading.container} + ${renderConfig(extendedOptions)} +
+ + + + + `; +} -- cgit v1.2.3