github.com/vulppine/fotoDen@v0.3.0/tool/web.go (about)

     1  package tool
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"html/template"
     7  	"io"
     8  	"net/url"
     9  	"os"
    10  	"path"
    11  	"path/filepath"
    12  	"strings"
    13  
    14  	"github.com/vulppine/fotoDen/generator"
    15  	"github.com/yuin/goldmark"
    16  	"github.com/yuin/goldmark/extension"
    17  	"github.com/yuin/goldmark/renderer/html"
    18  )
    19  
    20  // GenerateWebRoot generates the root of a fotoDen website in fpath.
    21  // Creates the folders for JS and CSS placement.
    22  //
    23  // It is up to the fotoDen tool to copy over the relevant files,
    24  // and folder configuration.
    25  func GenerateWebRoot(fpath string) error {
    26  	err := os.Mkdir(fpath, 0755)
    27  	if err != nil {
    28  		return err
    29  	}
    30  
    31  	err = os.Mkdir(filepath.Join(fpath, "js"), 0755)
    32  	if err != nil {
    33  		return err
    34  	}
    35  
    36  	err = os.Mkdir(filepath.Join(fpath, "theme"), 0755)
    37  	if err != nil {
    38  		return err
    39  	}
    40  
    41  	err = os.Mkdir(filepath.Join(fpath, "theme", "js"), 0755)
    42  	if err != nil {
    43  		return err
    44  	}
    45  
    46  	err = os.Mkdir(filepath.Join(fpath, "theme", "css"), 0755)
    47  	if err != nil {
    48  		return err
    49  	}
    50  
    51  	err = os.Mkdir(filepath.Join(fpath, "theme", "etc"), 0755)
    52  	if err != nil {
    53  		return err
    54  	}
    55  
    56  	return nil
    57  }
    58  
    59  // MakeAlbumDirectoryStructure makes a fotoDen-suitable album structure in the given rootDirectory (string).
    60  // The directory must exist beforehand.
    61  func MakeAlbumDirectoryStructure(rootDirectory string) error {
    62  
    63  	currentDirectory, _ := os.Getwd()
    64  
    65  	defer func() {
    66  		verbose("Changing back to " + currentDirectory)
    67  		os.Chdir(currentDirectory)
    68  	}()
    69  
    70  	verbose("Attempting to change to " + rootDirectory)
    71  	err := os.Chdir(rootDirectory)
    72  	if err != nil {
    73  		return err
    74  	}
    75  
    76  	verbose("Creating directories in " + rootDirectory)
    77  	os.Mkdir(generator.CurrentConfig.ImageRootDirectory, 0777)
    78  	os.Mkdir(path.Join(generator.CurrentConfig.ImageRootDirectory, generator.CurrentConfig.ImageSrcDirectory), 0777)
    79  	os.Mkdir(path.Join(generator.CurrentConfig.ImageRootDirectory, generator.CurrentConfig.ImageMetaDirectory), 0777)
    80  
    81  	for k := range generator.CurrentConfig.ImageSizes {
    82  		os.Mkdir(filepath.Join(generator.CurrentConfig.ImageRootDirectory, k), 0777)
    83  	}
    84  
    85  	return nil
    86  }
    87  
    88  // StaticWebVars are fields that a page can take in order to allow for static page generation.
    89  // If a folder is marked for dynamic generation, these will all automatically be blank.
    90  // Otherwise, these will have the relevant information inside. This only applies to folders.
    91  type StaticWebVars struct {
    92  	IsStatic   bool
    93  	PageName   string // the current name of the page, e.g. 'My album', or 'Photo name'
    94  	PageDesc   string // the current description of the page
    95  	PageFolder string // the folder this is contained in
    96  	PageAuthor string // the author of the page, i.e. the photographer
    97  }
    98  
    99  // ConfigureWebFile configures the web variables in a template by putting it through Go's template system.
   100  // Outputs to a destination location.
   101  // Can be used for any fotoDen-compatible web file.
   102  //
   103  // This should only be done once, ideally,
   104  // and copied over to a configuration directory
   105  // for fotoDen to use (in essence, CurrentConfig.WebSourceDirectory)
   106  func ConfigureWebFile(source string, dest string, vars interface{}) error {
   107  	webpage, err := template.ParseFiles(source)
   108  	if err != nil {
   109  		return err
   110  	}
   111  
   112  	file, err := os.OpenFile(dest, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0755) // just rewrite the entire thing
   113  	if err != nil {
   114  		return err
   115  	}
   116  	defer file.Close()
   117  
   118  	err = webpage.Execute(file, vars)
   119  	if err != nil {
   120  		return err
   121  	}
   122  
   123  	return nil
   124  }
   125  
   126  // GenerateWeb hooks into the fotoDen/generator package, and generates web pages for fotoDen folders/albums.
   127  // If a folder was marked as static, it will create a StaticWebVars object to put into the page, and generate
   128  // a more static page - otherwise, it will leave those fields blank, and leave it to the fotoDen front end
   129  // to generate the rest of the page.
   130  /*func GenerateWeb(m string, dest string, f *generator.Folder, opt GeneratorOptions) error {
   131  	verbose("Generating web pages...")
   132  	var err error
   133  	var pageOptions *StaticWebVars
   134  
   135  	if opt.Static || f.Static {
   136  		verbose("Folder/album is static, generating static web vars...")
   137  		pageOptions, err = NewWebVars(dest)
   138  		if checkError(err) {
   139  			return err
   140  		}
   141  	} else {
   142  		verbose("Folder/album is dynamic.")
   143  		pageOptions = new(StaticWebVars)
   144  		pageOptions.IsStatic = false
   145  	}
   146  
   147  	switch m {
   148  	case "album":
   149  		verbose("Album mode selected, generating album.")
   150  		err = ConfigureWebFile(path.Join(generator.CurrentConfig.WebSourceLocation, "html", "album-template.html"), path.Join(dest, "index.html"), pageOptions)
   151  		err = ConfigureWebFile(path.Join(generator.CurrentConfig.WebSourceLocation, "html", "photo-template.html"), path.Join(dest, "photo.html"), pageOptions)
   152  	case "folder":
   153  		verbose("Folder mode selected, generating folder.")
   154  		err = ConfigureWebFile(path.Join(generator.CurrentConfig.WebSourceLocation, "html", "folder-template.html"), path.Join(dest, "index.html"), pageOptions)
   155  	default:
   156  		return fmt.Errorf("mode was not passed to GenerateWeb")
   157  	}
   158  
   159  	if checkError(err) {
   160  		return err
   161  	}
   162  
   163  	return nil
   164  }*/
   165  
   166  // UpdateWeb takes a folder, and updates the webpages inside of that folder.
   167  func UpdateWeb(folder string) error {
   168  	verbose("Updating web pages...")
   169  	f := new(generator.Folder)
   170  
   171  	err := f.ReadFolderInfo(path.Join(folder, "folderInfo.json"))
   172  	if checkError(err) {
   173  		return err
   174  	}
   175  
   176  	err = currentTheme.generateWeb(f.Type, folder, nil)
   177  	if checkError(err) {
   178  		return err
   179  	}
   180  
   181  	return nil
   182  }
   183  
   184  // MARKDOWN SUPPORT //
   185  
   186  // GeneratePage generates a page using a markdown document as a source.
   187  // It will use the 'page' HTML template in the theme in order to generate
   188  // a web page. Takes a source location, and places it at the root of the current site.
   189  //
   190  // The page template must have {{.PageVars.PageContent}} in the location of where
   191  // you want the parsed document to go.
   192  func GeneratePage(src string, title string) error {
   193  	if title == "" {
   194  		return fmt.Errorf("you need to give the page a filename/title")
   195  	}
   196  
   197  	if CurrentConfig == nil {
   198  		return fmt.Errorf("you need to use this in conjunction with a valid fotoDen site")
   199  	}
   200  
   201  	f, err := os.Open(src)
   202  	if checkError(err) {
   203  		return err
   204  	}
   205  
   206  	r, err := io.ReadAll(f)
   207  	if checkError(err) {
   208  		return err
   209  	}
   210  
   211  	f.Close()
   212  
   213  	mdown := goldmark.New(
   214  		goldmark.WithExtensions(extension.GFM),
   215  		goldmark.WithRendererOptions(
   216  			html.WithHardWraps(),
   217  		),
   218  	)
   219  
   220  	var b bytes.Buffer
   221  	err = mdown.Convert(r, &b)
   222  	if checkError(err) {
   223  		return err
   224  	}
   225  
   226  	r, err = io.ReadAll(&b)
   227  	if checkError(err) {
   228  		return err
   229  	}
   230  
   231  	if currentTheme == nil {
   232  		err = openDefaultTheme()
   233  		if checkError(err) {
   234  			return err
   235  		}
   236  	}
   237  
   238  	v := map[string]string{
   239  		"pageContent": string(r),
   240  		"title":       title,
   241  	}
   242  
   243  	u, err := url.Parse(generator.CurrentConfig.WebBaseURL)
   244  	if checkError(err) {
   245  		return err
   246  	}
   247  
   248  	u.Path = path.Join(u.Path, strings.ToLower(strings.ReplaceAll(title, " ", "")))
   249  
   250  	err = currentTheme.generateWeb(
   251  		"page",
   252  		path.Base(u.Path),
   253  		v,
   254  	)
   255  
   256  	if checkError(err) {
   257  		return err
   258  	}
   259  
   260  	c := new(generator.WebConfig)
   261  	err = c.ReadWebConfig(filepath.Join(CurrentConfig.RootLocation, "config.json"))
   262  	if checkError(err) {
   263  		return err
   264  	}
   265  
   266  	c.Pages = append(c.Pages, generator.PageLink{Title: title, Location: u.String()})
   267  	err = c.WriteWebConfig(filepath.Join(CurrentConfig.RootLocation, "config.json"))
   268  	if checkError(err) {
   269  		return err
   270  	}
   271  
   272  	return nil
   273  }