github.com/lmorg/murex@v0.0.0-20240217211045-e081c89cd4ef/utils/docgen/api/functions.go (about)

     1  package docgen
     2  
     3  import (
     4  	"bytes"
     5  	"errors"
     6  	"fmt"
     7  	"os"
     8  	"regexp"
     9  	"sort"
    10  	"strconv"
    11  	"strings"
    12  	"text/template"
    13  	"time"
    14  
    15  	"github.com/lmorg/murex/utils/envvars"
    16  )
    17  
    18  var funcMap = template.FuncMap{
    19  	"md":         funcMarkdown,
    20  	"quote":      funcQuote,
    21  	"trim":       strings.TrimSpace,
    22  	"doc":        funcRenderedDocuments,
    23  	"cat":        funcRenderedCategories,
    24  	"link":       funcLink,
    25  	"linkbm":     funcLinkBookmark,
    26  	"file":       funcFile,
    27  	"notanindex": funcNotAnIndex,
    28  	"date":       funcDate,
    29  	"time":       funcTime,
    30  	"doct":       funcDocT,
    31  	"othercats":  funcOtherCats,
    32  	"otherdocs":  funcOtherDocs,
    33  	"env":        funcEnv,
    34  }
    35  
    36  /************
    37   * Markdown *
    38   ************/
    39  
    40  // Takes: string (contents as read from YAML in a machine readable subset of markdown)
    41  // Returns: markdown contents cleaned up for printing
    42  func funcMarkdown(s string) string {
    43  	s = strings.ReplaceAll(s, "\r", "")
    44  	s = strings.TrimSuffix(s, "\n")
    45  	return s
    46  }
    47  
    48  /************
    49   *   Quote  *
    50   ************/
    51  
    52  // Takes: strings (contents)
    53  // Returns: contents with some characters escaped for printing in source code (eg \")
    54  func funcQuote(s ...string) string {
    55  	return strconv.Quote(funcMarkdown(strings.Join(s, "")))
    56  }
    57  
    58  /************
    59   *    Doc   *
    60   ************/
    61  
    62  // Takes: string (category name), string (document name), int (index of rendered document template)
    63  // Returns: contents of rendered document template
    64  func funcRenderedDocuments(cat, doc string, index int) (string, error) {
    65  	if len(Config.renderedDocuments[cat]) == 0 {
    66  		return "", errors.New("category does not exist, doesn't have any documents, or hasn't yet been parsed")
    67  	}
    68  
    69  	if len(Config.renderedDocuments[cat][doc]) <= index {
    70  		return "", errors.New("index greater than number of templates currently parsed for that document")
    71  	}
    72  
    73  	return Config.renderedDocuments[cat][doc][index], nil
    74  }
    75  
    76  /************
    77   *    Cat   *
    78   ************/
    79  
    80  // Takes: string (category name) and int (index of rendered category template)
    81  // Returns: contents of rendered category template
    82  func funcRenderedCategories(cat string, index int) (string, error) {
    83  	if len(Config.renderedCategories[cat]) == 0 {
    84  		return "", errors.New("category does not exist or hasn't yet been parsed")
    85  	}
    86  
    87  	if len(Config.renderedCategories[cat]) <= index {
    88  		return "", errors.New("index greater than number of templates currently parsed for that category")
    89  	}
    90  
    91  	return Config.renderedCategories[cat][index], nil
    92  }
    93  
    94  /************
    95   *   Link   *
    96   ************/
    97  
    98  // Takes: string (doc, description, relativePath prefix...)
    99  // Returns: URL to document
   100  func funcLink(description, docId string, relativePath ...string) string {
   101  	return funcLinkBookmark(description, docId, "", relativePath...)
   102  }
   103  
   104  /************
   105   *  LinkBM  *
   106   ************/
   107  
   108  // Takes: string (doc, description, bookmark (w/o hash), relativePath prefix...)
   109  // Returns: URL to document
   110  func funcLinkBookmark(description, docId, bookmark string, relativePath ...string) string {
   111  	doc := Documents.ByID("", "???", docId)
   112  	if doc == nil {
   113  		panic(fmt.Sprintf("nil document (%s)", docId))
   114  	}
   115  
   116  	cat := Config.Categories.ByID(doc.CategoryID)
   117  	path := cat.Templates[0].DocumentFilePath(doc)
   118  
   119  	if bookmark != "" {
   120  		path += "#" + bookmark
   121  	}
   122  
   123  	//if len(relativePath) > 0 {
   124  	path = strings.Join(relativePath, "/") + "/" + path
   125  	//}
   126  
   127  	if os.Getenv("DOCGEN_TARGET") == "vuepress" {
   128  		path = strings.Replace(path, "/docs", "", 1)
   129  	}
   130  
   131  	return fmt.Sprintf("[%s](%s)", description, path)
   132  }
   133  
   134  /************
   135   *  Include *
   136   ************/
   137  
   138  // Takes: string (contents)
   139  // Looks for: {{ include "filename" }}
   140  // Returns: document with search string replaced with contents of filename
   141  func funcInclude(s string) string {
   142  	rx := regexp.MustCompile(`\{\{ include "([-_/.a-zA-Z0-9]+)" \}\}`)
   143  	if !rx.MatchString(s) {
   144  		return s
   145  	}
   146  
   147  	match := rx.FindAllStringSubmatch(s, -1)
   148  	for i := range match {
   149  		path := match[i][1]
   150  		f := fileReader(path)
   151  		b := bytes.TrimSpace(readAll(f))
   152  
   153  		w := bytes.NewBuffer([]byte{})
   154  
   155  		t := template.Must(template.New(path).Funcs(funcMap).Parse(string(b)))
   156  		if err := t.Execute(w, nil); err != nil {
   157  			panic(err.Error())
   158  		}
   159  
   160  		s = strings.Replace(s, match[i][0], w.String(), -1)
   161  	}
   162  
   163  	return s
   164  }
   165  
   166  /************
   167   *   File   *
   168   ************/
   169  
   170  // Takes: slice of strings (file path)
   171  // Returns: contents of file based on a concatenation of the slice
   172  func funcFile(path ...string) string {
   173  	f := fileReader(strings.Join(path, ""))
   174  	b := readAll(f)
   175  	return string(b)
   176  }
   177  
   178  func init() {
   179  	funcMap["include"] = funcInclude
   180  }
   181  
   182  /************
   183   *NotAnIndex*
   184   ************/
   185  
   186  // Takes: number (eg variable)
   187  // Returns: number incremented by 1
   188  func funcNotAnIndex(i int) int {
   189  	return i + 1
   190  }
   191  
   192  /************
   193   *   Date   *
   194   ************/
   195  
   196  // Takes: DateTime (time.Time)
   197  // Returns: Date as string
   198  func funcDate(dt time.Time) string {
   199  	return dt.Format("02.01.2006")
   200  }
   201  
   202  /************
   203   *   Time   *
   204   ************/
   205  
   206  // Takes: DateTime (time.Time)
   207  // Returns: Time as string
   208  func funcTime(dt time.Time) string {
   209  	return dt.Format("15:04")
   210  }
   211  
   212  /************
   213   *   doct   *
   214   ************/
   215  
   216  // Takes: string (category, document ID)
   217  // Returns: document type
   218  func funcDocT(cat, doc string) *document {
   219  	return Documents.ByID("!!!", cat, doc)
   220  }
   221  
   222  /************
   223   * OtherCats*
   224   ************/
   225  
   226  // Returns: list of documents in that category
   227  func funcOtherCats() []category {
   228  	return Config.Categories
   229  }
   230  
   231  /************
   232   * OtherDocs*
   233   ************/
   234  
   235  // Takes: string (category ID)
   236  // Returns: list of documents in that category
   237  func funcOtherDocs(id string) (d documents) {
   238  	for i := range Documents {
   239  		if Documents[i].CategoryID == id {
   240  			d = append(d, Documents[i])
   241  		}
   242  	}
   243  
   244  	sort.Sort(d)
   245  	return
   246  }
   247  
   248  /************
   249   *    Env   *
   250   ************/
   251  
   252  // Takes: string (env, formatted: `key=val`)
   253  // Returns: true or false if the env matches systems env
   254  func funcEnv(env string) any {
   255  	if !strings.Contains(env, "=") {
   256  		s := os.Getenv(env)
   257  		if s == "" {
   258  			s = "undef"
   259  		}
   260  		return s
   261  	}
   262  
   263  	key, value := envvars.Split(env)
   264  	v := make(map[string]interface{})
   265  	envvars.All(v)
   266  	s, _ := v[key].(string)
   267  	return s == value
   268  }