Skip to content

Instantly share code, notes, and snippets.

@acao
Last active August 4, 2023 16:21
Show Gist options
  • Save acao/97caed0ccbdbb9240a37f758f4d7561b to your computer and use it in GitHub Desktop.
Save acao/97caed0ccbdbb9240a37f758f4d7561b to your computer and use it in GitHub Desktop.
Generate a GraphiQL HTML with specific releases.
import type { GraphiQLProps } from 'graphiql';
import type { FetcherOpts } from '@graphiql/toolkit';
export type GenerateGraphiQLOptions = {
plugins?: (
| '@graphiql/plugin-doc-explorer'
| '@graphiql/plugin-explorer'
| '@graphiql/plugin-code-exporter'
)[];
props?: GraphiQLProps;
fetcherOptions?: FetcherOpts;
releases?: Record<string, string>;
};
const capitalize = (str: string) => str[0].toUpperCase() + str.slice(1);
const camelizeString = (str: string) => {
return str.replaceAll(/(?:^\w|[A-Z]|\b\w)/g, (word, index) => {
return index === 0 ? word.toLowerCase() : word.toUpperCase();
});
};
export async function generateGraphiQLHTML(options: GenerateGraphiQLOptions) {
const plugins = options.plugins || [];
const camelizedPlugins = plugins?.filter(p =>
camelizeString(p.replace('@graphiql/plugin', '')),
);
const getPath = (project: string, type: 'css' | 'js' = 'js') => {
let basePath = `https://unpkg.com/${project}/`;
if (options?.releases && options.releases[project]) {
basePath += options.releases[project] + '/';
}
if (project === 'graphiql') {
if (type === 'css') {
basePath += 'graphiql.min.css';
}
basePath += 'graphiql.min.js';
} else if (project === '@graphiql/plugin-explorer') {
if (type === 'css') {
basePath += 'style.css';
}
basePath += 'index.umd.js';
}
return basePath;
};
return `<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>GraphiQL</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style>
html,
body {
height: 100%;
margin: 0;
overflow: hidden;
width: 100%;
#graphiql {
height: 100vh;
}
</style>
<link href="${getPath('graphiql', 'css')}}" rel="stylesheet"/>
${plugins?.map(
plugin =>
`<link href="${getPath(plugin, 'css')}" rel="stylesheet"></link>`,
)}
<script src="https://unpkg.com/react/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom/umd/react-dom.production.min.js"></script>
<script src="${getPath('graphiql', 'js')}"></script>
${plugins?.map(plugin => `<script src="${getPath(plugin)}"></script>`)}
<script>
const fetcher = GraphiQL.createFetcher(${JSON.stringify(
options.fetcherOptions,
null,
2,
)});
const plugins = []
${camelizedPlugins.map(
plugin =>
`const ${plugin} = GraphiQLPlugin${capitalize(
plugin,
)}.${plugin}Plugin();
plugins.push(${plugin})
`,
)}
const root = ReactDOM.createRoot(document.getElementById('graphiql'));
root.render(
React.createElement(GraphiQL, {
fetcher,
...${JSON.stringify(options?.props || {}, null, 2)},
plugins: plugins,
})
);
</script>
</head>
<body>
<div id="graphiql">Loading...</div>
</body>
</html>
`;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment