Created
September 2, 2024 17:03
-
-
Save cognivore/d0680926e6c1d64c3277f1a9ca05be25 to your computer and use it in GitHub Desktop.
We heard you like static site generators so we put static site generator into your React website so that you can statically generate while you dynamically generate
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Plugin } from 'vite'; | |
import fs from 'fs'; | |
import path from 'path'; | |
import { execSync } from 'child_process'; | |
interface ZolaPluginOptions { | |
zolaOutputDir?: string; | |
componentDir: string; | |
manifestFile: string; | |
zolaBinaryPath?: string; | |
} | |
export default function zolaPlugin(options: ZolaPluginOptions): Plugin { | |
const { zolaOutputDir = "./src/html/zola", componentDir, manifestFile, zolaBinaryPath = './zola' } = options; | |
const zolaVersion = 'v0.16.1'; | |
const zolaDownloadUrl = `https://github.com/getzola/zola/releases/download/${zolaVersion}/zola-${zolaVersion}-x86_64-unknown-linux-gnu.tar.gz`; | |
const ensureZolaAvailable = () => { | |
if (!fs.existsSync(zolaBinaryPath)) { | |
console.log('Zola not found, downloading...'); | |
execSync(` | |
wget "${zolaDownloadUrl}" -O zola.tar.gz | |
tar xzvf zola.tar.gz | |
rm zola.tar.gz | |
chmod +x zola | |
`); | |
console.log('Zola downloaded and ready to use.'); | |
} | |
}; | |
const ensureDirectoryExists = (dir: string) => { | |
if (!fs.existsSync(dir)) { | |
fs.mkdirSync(dir, { recursive: true }); | |
console.log(`Created directory: ${dir}`); | |
} | |
}; | |
const calculateRelativeImportPath = (sourceDir: string, targetFile: string) => { | |
const relativePath = path.relative(sourceDir, targetFile); | |
return relativePath.split(path.sep).join('/'); | |
}; | |
return { | |
name: 'vite-plugin-zola', | |
async buildStart() { | |
ensureZolaAvailable(); | |
ensureDirectoryExists(zolaOutputDir); | |
console.log(`Building Zola site...`); | |
execSync(`yes | ${zolaBinaryPath} -c ./zola.toml build --output-dir ${zolaOutputDir}`); | |
ensureDirectoryExists(componentDir); | |
const files: { id: string, filePath: string }[] = []; | |
const collectFiles = (dir: string) => { | |
fs.readdirSync(dir).forEach(file => { | |
const fullPath = path.join(dir, file); | |
if (fs.statSync(fullPath).isDirectory()) { | |
collectFiles(fullPath); | |
} else if (file === 'index.html') { | |
const relativeDir = path.relative(zolaOutputDir, dir); | |
if (relativeDir && relativeDir !== '.' && relativeDir !== '404.html') { | |
files.push({ id: relativeDir, filePath: fullPath }); | |
} | |
} | |
}); | |
}; | |
collectFiles(zolaOutputDir); | |
console.log('Collected files:', files); | |
const manifest = files.map(({ id }) => id); | |
const manifestContent = ` | |
export default ${JSON.stringify(manifest, null, 2)}; | |
`; | |
fs.writeFileSync(manifestFile, manifestContent); | |
files.forEach(({ id, filePath }) => { | |
const componentFileName = id.replace(/[-/]/g, '_'); // Ensure valid JS identifier | |
const componentPath = path.resolve(componentDir, `${id}.tsx`); | |
const importPath = calculateRelativeImportPath(path.dirname(componentPath), filePath); | |
const reactComponent = ` | |
import React from 'react'; | |
import content from '${importPath}?raw'; | |
const ${componentFileName} = () => { | |
return ( | |
<div dangerouslySetInnerHTML={{ __html: content }} /> | |
); | |
}; | |
export default ${componentFileName}; | |
`; | |
fs.mkdirSync(path.dirname(componentPath), { recursive: true }); | |
fs.writeFileSync(componentPath, reactComponent); | |
console.log(`Generated component: ${componentFileName} at ${componentPath}`); | |
}); | |
console.log('Manifest and components have been generated.'); | |
}, | |
handleHotUpdate({ file, server }) { | |
if (file.endsWith('.md') || file.endsWith('.html')) { | |
console.log(`Rebuilding due to changes in ${file}`); | |
execSync(`yes | ${zolaBinaryPath} -c ./zola.toml build --output-dir ${zolaOutputDir}`); | |
server.restart(); | |
} | |
} | |
}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment