example-redirects.ts 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. import fs from "fs-extra";
  2. import type { Plugin } from "@docusaurus/types";
  3. export default function pluginExampleRedirectsPages(): Plugin<void> {
  4. return {
  5. name: "refine-plugin-handle-example-redirects",
  6. async postBuild() {
  7. const redirects: RedirectItem[] = collectRedirects();
  8. const redirectFiles = generateRedirectFiles(redirects);
  9. // Write files only at the end: make code more easy to test without IO
  10. await Promise.all(
  11. redirectFiles.map((file) => writeRedirectFile(file)),
  12. );
  13. },
  14. };
  15. }
  16. async function writeRedirectFile(file: RedirectFile): Promise<void> {
  17. try {
  18. // User-friendly security to prevent file overrides
  19. if (await fs.pathExists(file.fileAbsolutePath)) {
  20. throw new Error(
  21. "The redirect plugin is not supposed to override existing files.",
  22. );
  23. }
  24. await fs.outputFile(
  25. file.fileAbsolutePath,
  26. file.fileContent,
  27. // Hard security to prevent file overrides
  28. // See https://stackoverflow.com/a/34187712/82609
  29. { flag: "wx" },
  30. );
  31. } catch (err) {
  32. // logger.error`Redirect file creation error for path=${file.fileAbsolutePath}.`;
  33. throw err;
  34. }
  35. }
  36. const htmlTemplate = (to: string) => `
  37. <!DOCTYPE html>
  38. <html>
  39. <head>
  40. <meta charset="UTF-8">
  41. </head>
  42. <script>
  43. window.location.href = '${to}';
  44. </script>
  45. </html>
  46. `;
  47. const collectRedirects = () => {
  48. const redirects = fs.readJSONSync("./example-redirects.json");
  49. return redirects?.redirects ?? [];
  50. };
  51. const generateRedirectFiles = (redirects: RedirectItem[]) => {
  52. return redirects.map((redirect) => {
  53. const path = `${redirect.from}/index.html`;
  54. return {
  55. fileAbsolutePath: `./build/${path}`,
  56. fileContent: htmlTemplate(redirect.to),
  57. };
  58. });
  59. };
  60. type RedirectFile = {
  61. fileAbsolutePath: string;
  62. fileContent: string;
  63. };
  64. type RedirectItem = {
  65. from: string;
  66. to: string;
  67. };