package main
import (
"log"
"fmt"
"strings"
"io/fs"
"path/filepath"
"os"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/template/html/v2"
"zedshaw.games/ssgod/config"
"github.com/yuin/goldmark"
)
func Fail ( err error , format string , v ... any ) error {
err_format := fmt . Sprintf ( "ERROR: %v; %s" , err , format )
log . Printf ( err_format , v ... )
return err
}
func RenderMarkdown ( target_path string , ext string , path string ) error {
// need to strip the .md and replace with .html
html_name , _ := strings . CutSuffix ( target_path , ext )
html_name = fmt . Sprintf ( "%s.html" , html_name )
log . Printf ( "MARKDOWN: %s -> %s" , path , html_name )
out , err := os . OpenFile ( html_name , os . O_RDWR | os . O_CREATE | os . O_TRUNC , 0644 )
defer out . Close ( )
if err != nil { return Fail ( err , "writing file %s" , target_path ) }
input_data , err := os . ReadFile ( path )
err = goldmark . Convert ( input_data , out )
return err ;
}
func RenderHTML ( engine * html . Engine , source_name string , target_path string , page_id string ) error {
log . Printf ( "RENDER: %s -> %s" , source_name , target_path )
out , err := os . OpenFile ( target_path , os . O_RDWR | os . O_CREATE | os . O_TRUNC , 0644 )
defer out . Close ( )
if err != nil { return Fail ( err , "writing file %s" , target_path ) }
err = engine . Render ( out , source_name , fiber . Map { "PageId" : page_id } , config . Settings . Layout )
return err ;
}
func MkdirPath ( target_path string ) error {
target_dir := filepath . Dir ( target_path )
_ , err := os . Stat ( target_dir )
if os . IsNotExist ( err ) {
log . Println ( "MAKING: " , target_dir )
err = os . MkdirAll ( target_dir , 0750 )
if err != nil { return Fail ( err , "making path to %s" , target_dir ) ; }
}
return nil ;
}
func SplitPathExt ( path string ) ( string , string , bool ) {
split_path := strings . Split ( path , string ( os . PathSeparator ) ) [ 1 : ]
source_name := strings . Join ( split_path , "/" ) // Render wants / even on windows
ext := filepath . Ext ( source_name )
source_name , found := strings . CutSuffix ( source_name , ext )
return source_name , ext , found
}
func RePrefixPath ( path string , new_prefix string ) string {
split_path := strings . Split ( path , string ( os . PathSeparator ) ) [ 1 : ]
prefixed_path := append ( [ ] string { new_prefix } , split_path ... )
return filepath . Join ( prefixed_path ... )
}
func ProcessDirEntry ( engine * html . Engine , path string , d fs . DirEntry , err error ) error {
settings := config . Settings
if ! d . IsDir ( ) {
if err != nil { return Fail ( err , "path: %s" , path ) ; }
source_name , ext , found := SplitPathExt ( path )
if found && source_name != settings . Layout {
target_path := RePrefixPath ( path , settings . Target )
err = MkdirPath ( target_path )
if err != nil { return Fail ( err , "making target path: %s" , target_path ) }
// generate a data-testid for all pages based on template name
page_id := strings . ReplaceAll ( source_name , "/" , "-" ) + "-page"
if ext == ".html" {
err = RenderHTML ( engine , source_name , target_path , page_id )
if err != nil { return Fail ( err , "failed to render %s" , path ) }
} else if ext == ".md" {
RenderMarkdown ( target_path , ext , path )
if err != nil { return Fail ( err , "failed to render markdown %s" , path ) }
}
}
}
return nil
}
func RenderPages ( ) {
engine := html . New ( config . Settings . Views , ".html" )
engine . Load ( )
err := filepath . WalkDir ( config . Settings . Views ,
func ( path string , d fs . DirEntry , err error ) error {
return ProcessDirEntry ( engine , path , d , err )
} )
if err != nil { log . Fatalf ( "can't walk content" ) }
}
func main ( ) {
config . Load ( "ssgod.toml" )
RenderPages ( )
}