github.com/aldelo/common@v1.5.1/wrapper/gin/gintemplate.go (about) 1 package gin 2 3 /* 4 * Copyright 2020-2023 Aldelo, LP 5 * 6 * Licensed under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 19 import ( 20 "fmt" 21 util "github.com/aldelo/common" 22 "github.com/gin-contrib/multitemplate" 23 "path/filepath" 24 ) 25 26 // NewTemplate creates new html template render worker object 27 // 28 // templateBaseDir = (required) base directory that contains template files 29 // templateLayoutPath = (required) relative page layout folder path, layout defines site theme and common base pages 30 // 1. to use page parts, use {{ template "xyz" }} 31 // 2. see golang html page template rules for more information 32 // 33 // templatePagePath = (optional) relative page part folder path, pages define portion of html to be inserted into layout themes 34 // 1. to define page part with named template, use {{ define "xyz" }} {{ end }} 35 // 2. see golang html page template rules for more information 36 // 37 // notes 38 // 1. c.HTML name = page html name, such as home.html, if there is no page name, then use layout name 39 // 2. if c.HTML name cannot find target in renderer, error 500 will be encountered 40 // 3. layout file should not contain page parts may not be rendered in c.HTML call 41 // 4. basic info about html templates = https://blog.gopheracademy.com/advent-2017/using-go-templates/ 42 func NewTemplate(templateBaseDir string, templateLayoutPath string, templatePagePath string) *GinTemplate { 43 return &GinTemplate{ 44 TemplateBaseDir: templateBaseDir, 45 Templates: []TemplateDefinition{ 46 { 47 LayoutPath: templateLayoutPath, 48 PagePath: templatePagePath, 49 }, 50 }, 51 } 52 } 53 54 // GinTemplate defines the struct for working with html template renderer 55 type GinTemplate struct { 56 TemplateBaseDir string 57 Templates []TemplateDefinition 58 59 _htmlrenderer multitemplate.Renderer 60 _htmlTemplatesCount int 61 } 62 63 // TemplateDefinition defines an unit of template render target 64 type TemplateDefinition struct { 65 LayoutPath string 66 PagePath string 67 } 68 69 // LoadHtmlTemplates will load html templates and set renderer into struct internal var 70 func (t *GinTemplate) LoadHtmlTemplates() error { 71 t._htmlTemplatesCount = 0 72 73 if util.LenTrim(t.TemplateBaseDir) == 0 { 74 return fmt.Errorf("Html Template Base Dir is Required") 75 } 76 77 if len(t.Templates) == 0 { 78 return fmt.Errorf("Html Template Definition is Required") 79 } 80 81 r := multitemplate.NewRenderer() 82 83 if util.Right(t.TemplateBaseDir, 1) == "/" { 84 t.TemplateBaseDir = util.Left(t.TemplateBaseDir, len(t.TemplateBaseDir)-1) 85 } 86 87 for _, td := range t.Templates { 88 if util.LenTrim(td.LayoutPath) > 0 { 89 layout := td.LayoutPath 90 page := td.PagePath 91 92 if util.Left(layout, 1) != "/" { 93 layout = "/" + layout 94 } 95 96 if util.LenTrim(page) > 0 { 97 if util.Left(page, 1) != "/" { 98 page = "/" + page 99 } 100 } 101 102 // get all files matching layout pattern 103 layoutFiles, err := filepath.Glob(t.TemplateBaseDir + layout) 104 105 if err != nil { 106 continue 107 } 108 109 if len(layoutFiles) == 0 { 110 continue 111 } 112 113 if util.LenTrim(page) == 0 { 114 // only layout files to add to renderer 115 // template name is not important for 'AddFromFiles' (based on AddFromFiles source) 116 if tp := r.AddFromFiles(filepath.Base(layoutFiles[0]), layoutFiles...); tp != nil { 117 t._htmlTemplatesCount = len(layoutFiles) 118 } 119 } else { 120 // has layout and page files to add to renderer 121 pageFiles, err := filepath.Glob(t.TemplateBaseDir + page) 122 123 if err != nil { 124 continue 125 } 126 127 if len(pageFiles) == 0 { 128 continue 129 } 130 131 // layout with page files to add to renderer 132 // template name is not important for 'AddFromFiles' (based on AddFromFiles source) 133 for _, f := range pageFiles { 134 layoutCopy := make([]string, len(layoutFiles)) 135 copy(layoutCopy, layoutFiles) 136 files := append(layoutCopy, f) 137 138 if tp := r.AddFromFiles(filepath.Base(f), files...); tp != nil { 139 t._htmlTemplatesCount++ 140 } 141 } 142 } 143 } 144 } 145 146 if t._htmlTemplatesCount <= 0 { 147 t._htmlrenderer = nil 148 return fmt.Errorf("No Html Templates Loaded Into Renderer") 149 } else { 150 t._htmlrenderer = r 151 return nil 152 } 153 } 154 155 // SetHtmlRenderer will set the existing html renderer into gin engine's HTMLRender property 156 func (t *GinTemplate) SetHtmlRenderer(g *Gin) error { 157 if t._htmlrenderer == nil { 158 return fmt.Errorf("Html Template Renderer is Required") 159 } 160 161 if g == nil { 162 return fmt.Errorf("Gin Wrapper is Required") 163 } 164 165 if g._ginEngine == nil { 166 return fmt.Errorf(("Gin Engine is Required")) 167 } 168 169 if t._htmlTemplatesCount <= 0 { 170 return fmt.Errorf("No Html Templates Loaded Into Renderer") 171 } 172 173 if t._htmlrenderer == nil { 174 return fmt.Errorf("Html Renderer Must Not Be Nil") 175 } 176 177 g._ginEngine.HTMLRender = t._htmlrenderer 178 return nil 179 }