constants.go raw
1 // Package variants provides responsive image variant definitions per NIP-XX.
2 //
3 // Variant sizes are designed for modern device widths with the "next-larger"
4 // selection rule: clients should pick the smallest variant >= target width
5 // for minimal client-side downscaling.
6 package variants
7
8 // VariantConfig holds the target width and quality for a variant.
9 type VariantConfig struct {
10 Width int
11 Quality int // JPEG quality 0-100
12 }
13
14 // VariantName is the identifier for a variant size category.
15 type VariantName string
16
17 const (
18 Thumb VariantName = "thumb"
19 MobileSm VariantName = "mobile-sm"
20 MobileLg VariantName = "mobile-lg"
21 DesktopSm VariantName = "desktop-sm"
22 DesktopMd VariantName = "desktop-md"
23 DesktopLg VariantName = "desktop-lg"
24 Original VariantName = "original"
25 )
26
27 // VariantSizes maps variant names to their configuration.
28 // These are ordered from smallest to largest.
29 var VariantSizes = map[VariantName]VariantConfig{
30 Thumb: {Width: 128, Quality: 70},
31 MobileSm: {Width: 512, Quality: 75},
32 MobileLg: {Width: 1024, Quality: 80},
33 DesktopSm: {Width: 1536, Quality: 85},
34 DesktopMd: {Width: 2048, Quality: 88},
35 DesktopLg: {Width: 2560, Quality: 90},
36 }
37
38 // OriginalQuality is the JPEG quality for the EXIF-stripped original.
39 const OriginalQuality = 92
40
41 // VariantOrder defines the order from smallest to largest.
42 var VariantOrder = []VariantName{
43 Thumb,
44 MobileSm,
45 MobileLg,
46 DesktopSm,
47 DesktopMd,
48 DesktopLg,
49 Original,
50 }
51
52 // FileMetadataKind is the event kind for NIP-94 file metadata events.
53 const FileMetadataKind = 1063
54
55 // GetVariantsToGenerate returns the list of variants to generate
56 // based on the original image width (no upscaling).
57 func GetVariantsToGenerate(originalWidth int) []VariantName {
58 variants := []VariantName{Original}
59
60 for _, name := range VariantOrder[:len(VariantOrder)-1] { // Exclude Original
61 config := VariantSizes[name]
62 if config.Width < originalWidth {
63 variants = append(variants, name)
64 }
65 }
66
67 // Sort by variant order (already in order due to iteration)
68 result := make([]VariantName, 0, len(variants))
69 for _, name := range VariantOrder {
70 for _, v := range variants {
71 if v == name {
72 result = append(result, v)
73 break
74 }
75 }
76 }
77
78 return result
79 }
80