sharp-asset-preview-strategy.ts 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. import { AssetType } from '@vendure/common/lib/generated-types';
  2. import { AssetPreviewStrategy, getAssetType, RequestContext } from '@vendure/core';
  3. import path from 'path';
  4. import sharp from 'sharp';
  5. export class SharpAssetPreviewStrategy implements AssetPreviewStrategy {
  6. constructor(
  7. private config: {
  8. maxHeight: number;
  9. maxWidth: number;
  10. },
  11. ) {}
  12. async generatePreviewImage(ctx: RequestContext, mimeType: string, data: Buffer): Promise<Buffer> {
  13. const assetType = getAssetType(mimeType);
  14. const { maxWidth, maxHeight } = this.config;
  15. if (assetType === AssetType.IMAGE) {
  16. const image = sharp(data);
  17. const metadata = await image.metadata();
  18. const width = metadata.width || 0;
  19. const height = metadata.height || 0;
  20. if (maxWidth < width || maxHeight < height) {
  21. return image.resize(maxWidth, maxHeight, { fit: 'inside' }).toBuffer();
  22. } else {
  23. if (mimeType === 'image/svg+xml') {
  24. // Convert the SVG to a raster for the preview
  25. return image.toBuffer();
  26. } else {
  27. return data;
  28. }
  29. }
  30. } else {
  31. return sharp(path.join(__dirname, 'file-icon.png'))
  32. .resize(800, 800, { fit: 'outside' })
  33. .composite([
  34. {
  35. input: this.generateMimeTypeOverlay(mimeType),
  36. gravity: sharp.gravity.center,
  37. },
  38. ])
  39. .toBuffer();
  40. }
  41. }
  42. private generateMimeTypeOverlay(mimeType: string): Buffer {
  43. return Buffer.from(`
  44. <svg xmlns="http://www.w3.org/2000/svg" height="150" width="800">
  45. <style>
  46. text {
  47. font-size: 64px;
  48. font-family: Arial, sans-serif;
  49. fill: #666;
  50. }
  51. </style>
  52. <text x="400" y="110" text-anchor="middle" width="800">${mimeType}</text>
  53. </svg>`);
  54. }
  55. }