github.com/linchen2chris/hugo@v0.0.0-20230307053224-cec209389705/tpl/transform/transform.go (about) 1 // Copyright 2017 The Hugo Authors. All rights reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // http://www.apache.org/licenses/LICENSE-2.0 7 // 8 // Unless required by applicable law or agreed to in writing, software 9 // distributed under the License is distributed on an "AS IS" BASIS, 10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 // Package transform provides template functions for transforming content. 15 package transform 16 17 import ( 18 "context" 19 "html" 20 "html/template" 21 22 "github.com/gohugoio/hugo/cache/namedmemcache" 23 "github.com/gohugoio/hugo/markup/converter/hooks" 24 "github.com/gohugoio/hugo/markup/highlight" 25 "github.com/gohugoio/hugo/markup/highlight/chromalexers" 26 "github.com/gohugoio/hugo/tpl" 27 28 "github.com/gohugoio/hugo/deps" 29 "github.com/gohugoio/hugo/helpers" 30 "github.com/spf13/cast" 31 ) 32 33 // New returns a new instance of the transform-namespaced template functions. 34 func New(deps *deps.Deps) *Namespace { 35 cache := namedmemcache.New() 36 deps.BuildStartListeners.Add( 37 func() { 38 cache.Clear() 39 }) 40 41 return &Namespace{ 42 cache: cache, 43 deps: deps, 44 } 45 } 46 47 // Namespace provides template functions for the "transform" namespace. 48 type Namespace struct { 49 cache *namedmemcache.Cache 50 deps *deps.Deps 51 } 52 53 // Emojify returns a copy of s with all emoji codes replaced with actual emojis. 54 // 55 // See http://www.emoji-cheat-sheet.com/ 56 func (ns *Namespace) Emojify(s any) (template.HTML, error) { 57 ss, err := cast.ToStringE(s) 58 if err != nil { 59 return "", err 60 } 61 62 return template.HTML(helpers.Emojify([]byte(ss))), nil 63 } 64 65 // Highlight returns a copy of s as an HTML string with syntax 66 // highlighting applied. 67 func (ns *Namespace) Highlight(s any, lang string, opts ...any) (template.HTML, error) { 68 ss, err := cast.ToStringE(s) 69 if err != nil { 70 return "", err 71 } 72 73 var optsv any 74 if len(opts) > 0 { 75 optsv = opts[0] 76 } 77 78 hl := ns.deps.ContentSpec.Converters.GetHighlighter() 79 highlighted, _ := hl.Highlight(ss, lang, optsv) 80 return template.HTML(highlighted), nil 81 } 82 83 // HighlightCodeBlock highlights a code block on the form received in the codeblock render hooks. 84 func (ns *Namespace) HighlightCodeBlock(ctx hooks.CodeblockContext, opts ...any) (highlight.HightlightResult, error) { 85 var optsv any 86 if len(opts) > 0 { 87 optsv = opts[0] 88 } 89 90 hl := ns.deps.ContentSpec.Converters.GetHighlighter() 91 92 return hl.HighlightCodeBlock(ctx, optsv) 93 } 94 95 // CanHighlight returns whether the given code language is supported by the Chroma highlighter. 96 func (ns *Namespace) CanHighlight(language string) bool { 97 return chromalexers.Get(language) != nil 98 } 99 100 // HTMLEscape returns a copy of s with reserved HTML characters escaped. 101 func (ns *Namespace) HTMLEscape(s any) (string, error) { 102 ss, err := cast.ToStringE(s) 103 if err != nil { 104 return "", err 105 } 106 107 return html.EscapeString(ss), nil 108 } 109 110 // HTMLUnescape returns a copy of s with HTML escape requences converted to plain 111 // text. 112 func (ns *Namespace) HTMLUnescape(s any) (string, error) { 113 ss, err := cast.ToStringE(s) 114 if err != nil { 115 return "", err 116 } 117 118 return html.UnescapeString(ss), nil 119 } 120 121 // Markdownify renders s from Markdown to HTML. 122 func (ns *Namespace) Markdownify(ctx context.Context, s any) (template.HTML, error) { 123 124 home := ns.deps.Site.Home() 125 if home == nil { 126 panic("home must not be nil") 127 } 128 ss, err := home.RenderString(ctx, s) 129 if err != nil { 130 return "", err 131 } 132 133 // Strip if this is a short inline type of text. 134 bb := ns.deps.ContentSpec.TrimShortHTML([]byte(ss)) 135 136 return helpers.BytesToHTML(bb), nil 137 } 138 139 // Plainify returns a copy of s with all HTML tags removed. 140 func (ns *Namespace) Plainify(s any) (string, error) { 141 ss, err := cast.ToStringE(s) 142 if err != nil { 143 return "", err 144 } 145 146 return tpl.StripHTML(ss), nil 147 } 148 149 // For internal use. 150 func (ns *Namespace) Reset() { 151 ns.cache.Clear() 152 }