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 }