vite-plugin-tailwind-source.ts 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. import path from 'path';
  2. import { Plugin } from 'vite';
  3. import { CompileResult } from './utils/compiler.js';
  4. import { ConfigLoaderApi, getConfigLoaderApi } from './vite-plugin-config-loader.js';
  5. /**
  6. * This Vite plugin transforms the `app/styles.css` file to include a `@source` directive
  7. * for each dashboard extension's source directory. This allows Tailwind CSS to
  8. * include styles from these extensions when processing the CSS.
  9. */
  10. export function dashboardTailwindSourcePlugin(): Plugin {
  11. let configLoaderApi: ConfigLoaderApi;
  12. let loadVendureConfigResult: CompileResult;
  13. return {
  14. name: 'vendure:dashboard-tailwind-source',
  15. // Ensure this plugin runs before Tailwind CSS processing
  16. enforce: 'pre',
  17. configResolved({ plugins }) {
  18. configLoaderApi = getConfigLoaderApi(plugins);
  19. },
  20. async transform(src, id) {
  21. if (/app\/styles.css$/.test(id)) {
  22. if (!loadVendureConfigResult) {
  23. loadVendureConfigResult = await configLoaderApi.getVendureConfig();
  24. }
  25. const { pluginInfo } = loadVendureConfigResult;
  26. const dashboardExtensionDirs =
  27. pluginInfo
  28. ?.flatMap(({ dashboardEntryPath, sourcePluginPath, pluginPath }) => {
  29. if (!dashboardEntryPath) {
  30. return [];
  31. }
  32. const sourcePaths = [];
  33. if (sourcePluginPath) {
  34. sourcePaths.push(
  35. path.join(
  36. path.dirname(sourcePluginPath),
  37. path.dirname(dashboardEntryPath),
  38. ),
  39. );
  40. }
  41. if (pluginPath) {
  42. sourcePaths.push(
  43. path.join(path.dirname(pluginPath), path.dirname(dashboardEntryPath)),
  44. );
  45. }
  46. return sourcePaths;
  47. })
  48. .filter(x => x != null) ?? [];
  49. const sources = dashboardExtensionDirs
  50. .map(extension => {
  51. return `@source '${extension}';`;
  52. })
  53. .join('\n');
  54. // Find the line with the specific comment and insert sources after it
  55. const lines = src.split('\n');
  56. const sourceCommentIndex = lines.findIndex(line =>
  57. line.includes(
  58. '/* @source rules from extensions will be added here by the dashboardTailwindSourcePlugin */',
  59. ),
  60. );
  61. if (sourceCommentIndex !== -1) {
  62. // Insert the sources after the comment line
  63. lines.splice(sourceCommentIndex + 1, 0, sources);
  64. const modifiedSrc = lines.join('\n');
  65. return {
  66. code: modifiedSrc,
  67. };
  68. }
  69. // If the comment is not found, append sources at the end
  70. return {
  71. code: src + '\n' + sources,
  72. };
  73. }
  74. },
  75. };
  76. }