github.com/wheelercj/pm2md@v0.0.11/cmd/func_map.go (about) 1 // Copyright 2023 Chris Wheeler 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 7 // http://www.apache.org/licenses/LICENSE-2.0 8 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package cmd 16 17 import ( 18 "encoding/json" 19 "fmt" 20 "html/template" 21 "slices" 22 "strings" 23 ) 24 25 var funcMap = template.FuncMap{ 26 "formatHeaderLink": formatHeaderLink, 27 "add": func(a, b int) int { 28 return a + b 29 }, 30 "join": func(elems []any, sep string) string { 31 strElems := make([]string, len(elems)) 32 for i, e := range elems { 33 strElems[i] = fmt.Sprint(e) 34 } 35 return strings.Join(strElems, sep) 36 }, 37 "allowJsonOrPlaintext": func(s string) any { 38 if json.Valid([]byte(s)) { 39 return template.HTML(s) 40 } 41 return s 42 }, 43 // "assumeSafeHtml": func(s string) template.HTML { 44 // // This prevents HTML escaping. Never run this with untrusted input. 45 // return template.HTML(s) 46 // }, 47 } 48 49 var headerPathCache = make([]string, 0, 10) 50 51 // formatHeaderLink formats a markdown header body as a markdown link to the header 52 // compatible with GitHub's markdown rendering. When GitHub and this function find 53 // duplicate headers, they append `-1` to the header link for the second occurence, `-2` 54 // for the third, and so on. 55 func formatHeaderLink(headerBody string) string { 56 headerPath := formatHeaderPath(headerBody) 57 uniqueHeaderPath := headerPath 58 for i := 1; slices.Contains(headerPathCache, uniqueHeaderPath); i++ { 59 uniqueHeaderPath = fmt.Sprintf("%s-%d", headerPath, i) 60 } 61 headerPathCache = append(headerPathCache, uniqueHeaderPath) 62 return fmt.Sprintf("[%s](%s)", headerBody, uniqueHeaderPath) 63 } 64 65 // formatHeaderPath formats a markdown header body as a relative link path compatible 66 // with GitHub's markdown rendering. Letters are lowercased, leading spaces are removed, 67 // remaining spaces are replaced with dashes, special characters except dashes and 68 // underscores are removed, and one `#` will be prepended. Current limitation: 69 // formatHeaderPath ignores all emoji whereas GitHub removes some emoji. 70 func formatHeaderPath(headerBody string) string { 71 headerBody = strings.ReplaceAll( 72 strings.TrimLeft(strings.ToLower(headerBody), " "), " ", "-", 73 ) 74 toRemove := "=+!@#$%^&*()|\\'\";:/?.,<>[]{}`~" 75 result := make([]rune, 0, len(headerBody)/2) 76 result = append(result, '#') 77 for _, ch := range headerBody { 78 if !strings.Contains(toRemove, string(ch)) { 79 result = append(result, ch) 80 } 81 } 82 83 return string(result) 84 }