Files
oddmu/static_cmd_common.go

90 lines
2.1 KiB
Go

//go:build !openbsd
package main
import (
"fmt"
"image/jpeg"
"io"
"io/fs"
"os"
"path/filepath"
"strings"
"github.com/disintegration/imaging"
"github.com/edwvee/exiffix"
"github.com/gen2brain/webp"
)
// staticFile is used to walk the file trees and do the right thing for the destination directory: create
// subdirectories, link files, render HTML files.
func staticFile(source, target string, info fs.FileInfo, shrink bool) error {
// render pages
if strings.HasSuffix(source, ".md") {
// target already has ".html" extension
p, err := staticPage(source[:len(source)-3], target)
if err != nil {
return err
}
return staticFeed(source[:len(source)-3], target[:len(target)-5]+".rss", p, info.ModTime())
}
if shrink {
switch filepath.Ext(source) {
case ".jpg", ".jpeg", ".webp":
return shrinkImage(source, target, info)
}
}
// delete before linking, ignore errors
os.Remove(target)
err := os.Link(source, target)
if err == nil {
return nil
}
// in case of invalid cross-device link error, copy file instead
src, err := os.Open(source)
if err != nil {
return err
}
defer src.Close()
dst, err := os.Create(target)
if err != nil {
return err
}
defer dst.Close()
_, err = io.Copy(dst, src)
return err
}
// shrink Image shrinks images down and reduces the quality dramatically.
func shrinkImage(source, target string, info fs.FileInfo) error {
file, err := os.Open(source)
if err != nil {
return err
}
defer file.Close()
img, _, err := exiffix.Decode(file)
if err != nil {
return fmt.Errorf("%s cannot be decoded", source)
}
if img.Bounds().Dx() > shrinkWidth {
res := imaging.Resize(img, shrinkWidth, 0, imaging.Lanczos) // preserve aspect ratio
// imaging functions don't return errors but empty images…
if res.Rect.Empty() {
return fmt.Errorf("%s cannot be resized", source)
}
img = res
}
dst, err := os.Create(target)
if err != nil {
return err
}
defer dst.Close()
switch filepath.Ext(source) {
case ".jpg", ".jpeg":
err = jpeg.Encode(dst, img, &jpeg.Options{Quality: shrinkQuality})
case ".webp":
err = webp.Encode(dst, img, webp.Options{Quality: shrinkQuality})
}
return err
}