package caddyhugo
import (
"bytes"
"fmt"
"io"
"net/http"
"net/url"
"path"
"github.com/PuerkitoBio/goquery"
"github.com/gohugoio/hugo/resources/page"
"git.stephensearles.com/stephen/caddy-hugo2/media"
)
func ( ch * CaddyHugo ) ReferencedMedia ( ) map [ string ] map [ page . Page ] struct { } {
found := map [ string ] map [ page . Page ] struct { } { }
for _ , pg := range ch . HugoSites . Pages ( ) {
renderOutput , err := pg . Render ( )
if err != nil {
continue
}
r := bytes . NewBufferString ( string ( renderOutput ) )
doc , err := goquery . NewDocumentFromReader ( r )
if err != nil {
continue
}
doc . Find ( "img,video" ) . Map ( func ( i int , s * goquery . Selection ) string {
u , ok := s . Attr ( "src" )
if ok {
u = path . Base ( u )
if ud , err := url . QueryUnescape ( u ) ; err == nil {
u = ud
}
if m := found [ u ] ; m == nil {
found [ u ] = make ( map [ page . Page ] struct { } )
}
found [ u ] [ pg ] = struct { } { }
}
return ""
} )
}
return found
}
func ( ch * CaddyHugo ) uploadMedia ( w http . ResponseWriter , r * http . Request ) error {
if ch . Media == nil {
http . NotFound ( w , r )
return nil
}
mr , err := r . MultipartReader ( )
if err != nil {
http . Error ( w , err . Error ( ) , http . StatusBadRequest )
return nil
}
for {
part , err := mr . NextPart ( )
if err == io . EOF {
break
}
if err != nil {
http . Error ( w , err . Error ( ) , http . StatusBadRequest )
return err
}
name := part . FileName ( )
if name != "" {
err = ch . Media . ReceiveNewMedia ( name , part )
if err != nil {
http . Error ( w , err . Error ( ) , http . StatusInternalServerError )
return nil
}
}
}
return nil
}
func ( ch * CaddyHugo ) serveMediaPage ( w http . ResponseWriter , r * http . Request ) error {
if ch . Media == nil {
http . NotFound ( w , r )
return nil
}
referenced := ch . ReferencedMedia ( )
io . WriteString ( w , ` < html >
< head > < style >
iframe { height : 100 % ; }
. img { display : inline - block ; text - align : center ; max - width : 19.9 vw ; min - height : 120 px ; }
. img . selected { background - color : lightblue ; }
. copy { cursor : pointer ; }
@ media ( max - width : 800 px ) {
. img {
width : 50 % ;
max - width : 50 % ;
}
body {
min - height : 300 px ;
}
}
< / style > < / head >
< body >
< div style = "position: fixed; top: 0; height: 10vh; width: 100%; background-color: white;" >
` )
io . WriteString ( w , UploadPage ( "media" ) )
io . WriteString ( w , ` < / div >
< div style = "display: inline-block; width: 100%; height: 10vh;" > < / div >
` )
if ch . Media != nil {
mm , err := ch . Media . Walk ( )
if err != nil {
http . Error ( w , err . Error ( ) , http . StatusInternalServerError )
return err
}
for _ , m := range media . Set ( mm ) . ByDate ( ) {
size , err := ch . Media . ThumbMax ( * m , 100 )
if err != nil {
fmt . Fprintf ( w , ` <div class="img">error rendering %q: %v</div> ` , m . Name , err )
continue
}
refs := len ( referenced [ m . Name ] )
plural := "s"
if refs == 1 {
plural = ""
}
refLine := fmt . Sprintf ( "included on %d page%s" , refs , plural )
switch m . Type {
case media . TypeImage :
fmt . Fprintf ( w , ` <div class="img"><img width=%d height=%d src=%q data-filename=%q /><br /><input type="text" readonly value=%q /><span class="copy">📋</span><br />%s</div> ` , size . Dx ( ) , size . Dy ( ) , m . ThumbPath ( size ) , m . Name , m . ThumbPath ( size ) , refLine )
case media . TypeVideo :
// TODO: onmouseover sucks for mobile
fmt . Fprintf ( w , ` <div class="img"><video width=%d height=%d src=%q data-filename=%q onmouseover="this.play()" onmouseout="this.pause();this.currentTime=0;"></video><br /><input type="text" readonly value=%q /><span class="copy">📋</span><br />%s</div> ` , size . Dx ( ) , size . Dy ( ) , m . ThumbPath ( size ) , m . Name , m . ThumbPath ( size ) , refLine )
}
}
}
io . WriteString ( w , ` < script >
document . querySelector ( ' body ' ) . onclick = function ( evt ) {
if ( evt . target . tagName == = "INPUT" && evt . target . type == = "text" ) {
evt . target . select ( ) ;
}
if ( evt . target . tagName == = "SPAN" && evt . target . className == = "copy" ) {
evt . target . previousSibling . select ( ) ;
document . execCommand ( "copy" ) ;
}
if ( evt . target . tagName == = "IMG" || evt . target . tagName == = "VIDEO" ) {
var current = document . querySelector ( ".img.selected" ) ;
if ( current ) {
current . classList = "img" ;
}
evt . target . parentElement . classList = "img selected" ;
if ( window . parent ) {
window . parent . postMessage ( evt . target . dataset . filename , location . origin ) ;
}
}
}
document . querySelector ( ' body ' ) . onmouseup = function ( evt ) {
if ( evt . target . tagName == = "INPUT" && evt . target . type == = "text" ) {
return false ;
}
}
< / script > < / body > < html > ` )
return nil
}
func ( ch * CaddyHugo ) serveMedia ( w http . ResponseWriter , r * http . Request ) error {
if ch . Media == nil {
http . NotFound ( w , r )
return nil
}
ch . Media . ServeHTTP ( w , r )
return nil
}