Move Mastodon theme handling to custom vite plugin (#34808)
Co-authored-by: Echo <ChaosExAnima@users.noreply.github.com>
This commit is contained in:
		
							
								
								
									
										58
									
								
								config/vite/plugin-mastodon-themes.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								config/vite/plugin-mastodon-themes.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,58 @@
 | 
			
		||||
/* This plugins handles Mastodon's theme system
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import fs from 'node:fs/promises';
 | 
			
		||||
import path from 'node:path';
 | 
			
		||||
 | 
			
		||||
import yaml from 'js-yaml';
 | 
			
		||||
import type { Plugin } from 'vite';
 | 
			
		||||
 | 
			
		||||
export function MastodonThemes(): Plugin {
 | 
			
		||||
  return {
 | 
			
		||||
    name: 'mastodon-themes',
 | 
			
		||||
    async config(userConfig) {
 | 
			
		||||
      if (!userConfig.root || !userConfig.envDir) {
 | 
			
		||||
        throw new Error('Unknown project directory');
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      const themesFile = path.resolve(userConfig.envDir, 'config/themes.yml');
 | 
			
		||||
      const entrypoints: Record<string, string> = {};
 | 
			
		||||
 | 
			
		||||
      // Get all files mentioned in the themes.yml file.
 | 
			
		||||
      const themesString = await fs.readFile(themesFile, 'utf8');
 | 
			
		||||
      const themes = yaml.load(themesString, {
 | 
			
		||||
        filename: 'themes.yml',
 | 
			
		||||
        schema: yaml.FAILSAFE_SCHEMA,
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      if (!themes || typeof themes !== 'object') {
 | 
			
		||||
        throw new Error('Invalid themes.yml file');
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      for (const themePath of Object.values(themes)) {
 | 
			
		||||
        if (
 | 
			
		||||
          typeof themePath !== 'string' ||
 | 
			
		||||
          themePath.split('.').length !== 2 || // Ensure it has exactly one period
 | 
			
		||||
          !themePath.endsWith('css')
 | 
			
		||||
        ) {
 | 
			
		||||
          console.warn(
 | 
			
		||||
            `Invalid theme path "${themePath}" in themes.yml, skipping`,
 | 
			
		||||
          );
 | 
			
		||||
          continue;
 | 
			
		||||
        }
 | 
			
		||||
        entrypoints[path.basename(themePath)] = path.resolve(
 | 
			
		||||
          userConfig.root,
 | 
			
		||||
          themePath,
 | 
			
		||||
        );
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      return {
 | 
			
		||||
        build: {
 | 
			
		||||
          rollupOptions: {
 | 
			
		||||
            input: entrypoints,
 | 
			
		||||
          },
 | 
			
		||||
        },
 | 
			
		||||
      };
 | 
			
		||||
    },
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
@@ -1,4 +1,3 @@
 | 
			
		||||
import fs from 'node:fs/promises';
 | 
			
		||||
import path from 'node:path';
 | 
			
		||||
 | 
			
		||||
import { optimizeLodashImports } from '@optimize-lodash/rollup-plugin';
 | 
			
		||||
@@ -9,7 +8,6 @@ import { visualizer } from 'rollup-plugin-visualizer';
 | 
			
		||||
import RailsPlugin from 'vite-plugin-rails';
 | 
			
		||||
import { VitePWA } from 'vite-plugin-pwa';
 | 
			
		||||
import tsconfigPaths from 'vite-tsconfig-paths';
 | 
			
		||||
import yaml from 'js-yaml';
 | 
			
		||||
import legacy from '@vitejs/plugin-legacy';
 | 
			
		||||
 | 
			
		||||
import { defineConfig, UserConfigFnPromise, UserConfig } from 'vite';
 | 
			
		||||
@@ -17,36 +15,11 @@ import postcssPresetEnv from 'postcss-preset-env';
 | 
			
		||||
 | 
			
		||||
import { MastodonServiceWorkerLocales } from './config/vite/plugin-sw-locales';
 | 
			
		||||
import { MastodonEmojiCompressed } from './config/vite/plugin-emoji-compressed';
 | 
			
		||||
import { MastodonThemes } from './config/vite/plugin-mastodon-themes';
 | 
			
		||||
 | 
			
		||||
const jsRoot = path.resolve(__dirname, 'app/javascript');
 | 
			
		||||
const themesFile = path.resolve(__dirname, 'config/themes.yml');
 | 
			
		||||
 | 
			
		||||
export const config: UserConfigFnPromise = async ({ mode, command }) => {
 | 
			
		||||
  const entrypoints: Record<string, string> = {}; // All JS entrypoints are taken care of by Vite Ruby
 | 
			
		||||
 | 
			
		||||
  // Get all files mentioned in the themes.yml file.
 | 
			
		||||
  const themesString = await fs.readFile(themesFile, 'utf8');
 | 
			
		||||
  const themes = yaml.load(themesString, {
 | 
			
		||||
    filename: 'themes.yml',
 | 
			
		||||
    schema: yaml.FAILSAFE_SCHEMA,
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  if (!themes || typeof themes !== 'object') {
 | 
			
		||||
    throw new Error('Invalid themes.yml file');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  for (const themePath of Object.values(themes)) {
 | 
			
		||||
    if (
 | 
			
		||||
      typeof themePath !== 'string' ||
 | 
			
		||||
      themePath.split('.').length !== 2 || // Ensure it has exactly one period
 | 
			
		||||
      !themePath.endsWith('css')
 | 
			
		||||
    ) {
 | 
			
		||||
      console.warn(`Invalid theme path "${themePath}" in themes.yml, skipping`);
 | 
			
		||||
      continue;
 | 
			
		||||
    }
 | 
			
		||||
    entrypoints[path.basename(themePath)] = path.resolve(jsRoot, themePath);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return {
 | 
			
		||||
    root: jsRoot,
 | 
			
		||||
    css: {
 | 
			
		||||
@@ -72,7 +45,6 @@ export const config: UserConfigFnPromise = async ({ mode, command }) => {
 | 
			
		||||
      chunkSizeWarningLimit: 1 * 1024 * 1024, // 1MB
 | 
			
		||||
      sourcemap: true,
 | 
			
		||||
      rollupOptions: {
 | 
			
		||||
        input: entrypoints,
 | 
			
		||||
        output: {
 | 
			
		||||
          chunkFileNames({ facadeModuleId, name }) {
 | 
			
		||||
            if (!facadeModuleId) {
 | 
			
		||||
@@ -113,6 +85,7 @@ export const config: UserConfigFnPromise = async ({ mode, command }) => {
 | 
			
		||||
          manifestPaths: ['.vite/manifest.json', '.vite/manifest-assets.json'],
 | 
			
		||||
        },
 | 
			
		||||
      }),
 | 
			
		||||
      MastodonThemes(),
 | 
			
		||||
      react({
 | 
			
		||||
        babel: {
 | 
			
		||||
          plugins: ['formatjs', 'transform-react-remove-prop-types'],
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user