github.com/gitbundle/modules@v0.0.0-20231025071548-85b91c5c3b01/markup/markdown/renderconfig.go (about)

     1  // Copyright 2023 The GitBundle Inc. All rights reserved.
     2  // Copyright 2017 The Gitea Authors. All rights reserved.
     3  // Use of this source code is governed by a MIT-style
     4  // license that can be found in the LICENSE file.
     5  
     6  package markdown
     7  
     8  import (
     9  	"fmt"
    10  	"strings"
    11  
    12  	"github.com/yuin/goldmark/ast"
    13  	east "github.com/yuin/goldmark/extension/ast"
    14  	"gopkg.in/yaml.v2"
    15  )
    16  
    17  // RenderConfig represents rendering configuration for this file
    18  type RenderConfig struct {
    19  	Meta string
    20  	Icon string
    21  	TOC  bool
    22  	Lang string
    23  }
    24  
    25  // ToRenderConfig converts a yaml.MapSlice to a RenderConfig
    26  func (rc *RenderConfig) ToRenderConfig(meta yaml.MapSlice) {
    27  	if meta == nil {
    28  		return
    29  	}
    30  	found := false
    31  	var giteaMetaControl yaml.MapItem
    32  	for _, item := range meta {
    33  		strKey, ok := item.Key.(string)
    34  		if !ok {
    35  			continue
    36  		}
    37  		strKey = strings.TrimSpace(strings.ToLower(strKey))
    38  		switch strKey {
    39  		case "gitea":
    40  			giteaMetaControl = item
    41  			found = true
    42  		case "include_toc":
    43  			val, ok := item.Value.(bool)
    44  			if !ok {
    45  				continue
    46  			}
    47  			rc.TOC = val
    48  		case "lang":
    49  			val, ok := item.Value.(string)
    50  			if !ok {
    51  				continue
    52  			}
    53  			val = strings.TrimSpace(val)
    54  			if len(val) == 0 {
    55  				continue
    56  			}
    57  			rc.Lang = val
    58  		}
    59  	}
    60  
    61  	if found {
    62  		switch v := giteaMetaControl.Value.(type) {
    63  		case string:
    64  			switch v {
    65  			case "none":
    66  				rc.Meta = "none"
    67  			case "table":
    68  				rc.Meta = "table"
    69  			default: // "details"
    70  				rc.Meta = "details"
    71  			}
    72  		case yaml.MapSlice:
    73  			for _, item := range v {
    74  				strKey, ok := item.Key.(string)
    75  				if !ok {
    76  					continue
    77  				}
    78  				strKey = strings.TrimSpace(strings.ToLower(strKey))
    79  				switch strKey {
    80  				case "meta":
    81  					val, ok := item.Value.(string)
    82  					if !ok {
    83  						continue
    84  					}
    85  					switch strings.TrimSpace(strings.ToLower(val)) {
    86  					case "none":
    87  						rc.Meta = "none"
    88  					case "table":
    89  						rc.Meta = "table"
    90  					default: // "details"
    91  						rc.Meta = "details"
    92  					}
    93  				case "details_icon":
    94  					val, ok := item.Value.(string)
    95  					if !ok {
    96  						continue
    97  					}
    98  					rc.Icon = strings.TrimSpace(strings.ToLower(val))
    99  				case "include_toc":
   100  					val, ok := item.Value.(bool)
   101  					if !ok {
   102  						continue
   103  					}
   104  					rc.TOC = val
   105  				case "lang":
   106  					val, ok := item.Value.(string)
   107  					if !ok {
   108  						continue
   109  					}
   110  					val = strings.TrimSpace(val)
   111  					if len(val) == 0 {
   112  						continue
   113  					}
   114  					rc.Lang = val
   115  				}
   116  			}
   117  		}
   118  	}
   119  }
   120  
   121  func (rc *RenderConfig) toMetaNode(meta yaml.MapSlice) ast.Node {
   122  	switch rc.Meta {
   123  	case "table":
   124  		return metaToTable(meta)
   125  	case "details":
   126  		return metaToDetails(meta, rc.Icon)
   127  	default:
   128  		return nil
   129  	}
   130  }
   131  
   132  func metaToTable(meta yaml.MapSlice) ast.Node {
   133  	table := east.NewTable()
   134  	alignments := []east.Alignment{}
   135  	for range meta {
   136  		alignments = append(alignments, east.AlignNone)
   137  	}
   138  	row := east.NewTableRow(alignments)
   139  	for _, item := range meta {
   140  		cell := east.NewTableCell()
   141  		cell.AppendChild(cell, ast.NewString([]byte(fmt.Sprintf("%v", item.Key))))
   142  		row.AppendChild(row, cell)
   143  	}
   144  	table.AppendChild(table, east.NewTableHeader(row))
   145  
   146  	row = east.NewTableRow(alignments)
   147  	for _, item := range meta {
   148  		cell := east.NewTableCell()
   149  		cell.AppendChild(cell, ast.NewString([]byte(fmt.Sprintf("%v", item.Value))))
   150  		row.AppendChild(row, cell)
   151  	}
   152  	table.AppendChild(table, row)
   153  	return table
   154  }
   155  
   156  func metaToDetails(meta yaml.MapSlice, icon string) ast.Node {
   157  	details := NewDetails()
   158  	summary := NewSummary()
   159  	summary.AppendChild(summary, NewIcon(icon))
   160  	details.AppendChild(details, summary)
   161  	details.AppendChild(details, metaToTable(meta))
   162  
   163  	return details
   164  }