Files
sm-journal-plugin/console/image_variants.go
Jakub Zych 4f5bd190e5 feat: image variants job and variants in the post API
- golem15_journal_image_variants (migration 202610280002): a thumbnail
  per width of golem15.journal.image_widths (480, 800, 1200 by default,
  never wider than the original) and its WebP copy, with the original's
  size
- conga job golem15.journal.image_variants (three attempts), queued after
  a featured image upload and after an admin save of a post whose images
  lack a width; the upload request never encodes
- journal:image-variants [--all] backfills
- featured_images[].variants {width, height, url, webp_url, source_width,
  source_height} on the post answers (additive key)
2026-11-04 17:05:16 +01:00

68 lines
2.7 KiB
Go

package console
import (
"context"
"errors"
"fmt"
"git.golem15.com/golem15/sm-journal-plugin/classes"
"git.golem15.com/golem15/summercms/modules/backpack"
"git.golem15.com/golem15/summercms/modules/bonfire"
"gocloud.dev/blob"
)
// ImageVariants is journal:image-variants: it writes the thumbnails and
// WebP copies of the posts' featured images at golem15.journal.image_widths
// in this process (the backfill of the golem15.journal.image_variants job).
// Without --all it takes the images that lack a variant of some width.
func ImageVariants(app *backpack.App) bonfire.Command {
return bonfire.Command{
Name: "journal:image-variants",
Description: "Write the WebP and resized variants of featured images",
Long: `Writes, for every post's featured image, a thumbnail at each width of
golem15.journal.image_widths (480, 800 and 1200 by default) that is not
wider than the original, and a WebP copy of each next to it, and records
them in golem15_journal_image_variants. The Journal API lists them as
featured_images[].variants and the journal layer serves them through
<picture> with the original format as fallback.
New uploads get their variants from the golem15.journal.image_variants job,
queued after the upload commits. This command is the backfill: without
--all it takes the images that lack a variant of some width (for example
after adding a width), with --all it checks every featured image. A
variant that exists is never written again, so the command can run any
number of times.`,
Flags: []bonfire.Flag{
{Name: "all", Description: "Check every featured image (default: only those missing a width)", Bare: true},
},
Examples: []bonfire.Example{
{Command: "journal:image-variants", Description: "Write the variants images are missing"},
{Command: "journal:image-variants --all", Description: "Check every featured image"},
},
Run: func(ctx context.Context, in bonfire.Input, out bonfire.Output) error {
db := mustDB(app)
if db == nil {
return errors.New("journal: database is not configured")
}
bucket, ok := app.Lookup[*blob.Bucket]()
if !ok || bucket == nil {
return errors.New("journal: the uploads bucket is not configured")
}
ids, err := classes.FeaturedImageIDs(db.WithContext(ctx), appConfig(app), flagOn(in, "all"))
if err != nil {
return err
}
if len(ids) == 0 {
out.Info("Every featured image has its variants.")
return nil
}
res, err := classes.GenerateImageVariants(ctx, db, bucket, classes.ImageWidths(appConfig(app)), ids)
if err != nil {
return err
}
out.Success(fmt.Sprintf("Checked %d featured images, wrote %d variants, skipped %d.", res.Files, res.Written, res.Skipped))
return nil
},
}
}