@sctg/vite-plugin-github-pages-spa
Version:
Vite plugin to enable SPA (Single Page Application) support for GitHub Pages
121 lines (119 loc) • 3.94 kB
JavaScript
// src/index.ts
import { resolve } from "node:path";
import { writeFileSync, mkdirSync, existsSync } from "node:fs";
function githubPagesSpa(options = {}) {
const {
verbose = true,
injectScript = true,
custom404Html
} = options;
let config;
return {
name: "vite-plugin-github-pages-spa",
configResolved(resolvedConfig) {
config = resolvedConfig;
},
transformIndexHtml(html) {
const isGitHubPages = config.base.includes("github.io") || config.base !== "/";
if (!isGitHubPages || !injectScript) {
if (verbose && !isGitHubPages) {
console.warn("\nNot using GitHub Pages base URL. SPA redirection script not added.");
}
return html;
}
if (verbose) {
console.info("\nAdding GitHub Pages SPA redirection script to index.html");
}
return html.replace(
/<head>/,
`<head>
<script type="text/javascript">
// Single Page Apps Helper for GitHub Pages
// MIT License
// https://github.com/rafgraph/spa-github-pages
(function(l) {
if (l.search[1] === '/' ) {
var decoded = l.search.slice(1).split('&').map(function(s) {
return s.replace(/~and~/g, '&')
}).join('?');
window.history.replaceState(null, null,
l.pathname.slice(0, -1) + decoded + l.hash
);
}
}(window.location))
</script>`
);
},
closeBundle() {
const isGitHubPages = config.base.includes("github.io") || config.base !== "/";
if (!isGitHubPages) {
return;
}
const distPath = resolve(config.root, config.build.outDir);
if (!existsSync(distPath)) {
mkdirSync(distPath, { recursive: true });
}
const urlBase = new URL(config.base.startsWith("http") ? config.base : `http://example.com${config.base}`);
const urlPath = urlBase.pathname;
const pathSegmentsToKeep = urlPath.split("/").filter(Boolean).length;
let fileContent = custom404Html;
if (!fileContent) {
fileContent = `
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>404 - Page Not Found</title>
<script type="text/javascript">
// Single Page Apps for GitHub Pages
// MIT License
// https://github.com/rafgraph/spa-github-pages
var pathSegmentsToKeep = ${pathSegmentsToKeep}; // Number of path segments to keep in the URL
var l = window.location;
l.replace(
l.protocol + '//' + l.hostname + (l.port ? ':' + l.port : '') +
l.pathname.split('/').slice(0, 1 + pathSegmentsToKeep).join('/') + '/?/' +
l.pathname.slice(1).split('/').slice(pathSegmentsToKeep).join('/').replace(/&/g, '~and~') +
(l.search ? '&' + l.search.slice(1).replace(/&/g, '~and~') : '') +
l.hash
);
</script>
<style>
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
margin: 0;
padding: 20px;
text-align: center;
color: #333;
}
h1 {
margin-top: 50px;
font-size: 24px;
}
p {
margin: 20px 0;
font-size: 16px;
}
</style>
</head>
<body>
<h1>Page Not Found</h1>
<p>Redirecting to the home page...</p>
<p><a href="/">Click here if you are not redirected automatically</a></p>
</body>
</html>`;
}
const filePath = resolve(distPath, "404.html");
if (verbose) {
console.info(`
Creating 404.html in ${filePath} for GitHub Pages SPA support`);
}
writeFileSync(filePath, fileContent);
}
};
}
var index_default = githubPagesSpa;
export {
index_default as default,
githubPagesSpa
};