/*** IMPORT ------------------------------------------- ***/ import { default as dedent } from "@netopwibby/dedent"; import { filterXSS } from "xss"; /*** UTILITY ------------------------------------------ ***/ const filter = (val: string) => filterXSS(val, { stripIgnoreTag: true, stripIgnoreTagBody: ["script"], whiteList: {} }); const buildAssetUrl = ({ cdnUrl, suffix, version }: { cdnUrl: string suffix: string version?: string }) => filter(`${cdnUrl}/@eeeooolll/graphiql${version ? `@${version}` : ""}/dist/${suffix}`); /*** EXPORT ------------------------------------------- ***/ export interface RenderPageOptions { /** Base CDN. Defaults to jsDelivr. */ cdnUrl?: string; /** GraphQL endpoint the embedded fetcher posts to. */ endpoint?: string; /** Optional ``. `null` skips, `undefined` falls back to default. */ faviconUrl?: string | null; /** Document ``. */ title?: string; /** Pin `@eeeooolll/graphiql` to a specific version on the CDN. */ version?: string; } /** * Renders the GraphiQL HTML shell. * * Loads the prebuilt IIFE bundle from `@eeeooolll/graphiql` (registered as * `window.EolGraphiQL`) and mounts it against `endpoint`. * * Usually called indirectly via `GraphQLHTTP({ graphiql: true })`; invoke it * directly if you need to embed GraphiQL in a custom route. */ export function renderPlaygroundPage(options: RenderPageOptions): string { const { cdnUrl = "//cdn.jsdelivr.net/npm", endpoint = "/graphql", faviconUrl, title = "GraphiQL", version } = options; const safeEndpoint = filter(endpoint); const safeTitle = filter(title); const scriptUrl = buildAssetUrl({ cdnUrl, suffix: "standalone.js", version }); const styleUrl = buildAssetUrl({ cdnUrl, suffix: "standalone.css", version }); const faviconLink = faviconUrl === null ? "" : typeof faviconUrl === "string" ? `<link rel="shortcut icon" href="${filter(faviconUrl)}"/>` : `<link rel="shortcut icon" href="${buildAssetUrl({ cdnUrl, suffix: "favicon.svg", version })}"/>`; return dedent` <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"/> <meta name="viewport" content="width=device-width, initial-scale=1"/> <title>${safeTitle} ${faviconLink}
`; }