github.com/phsym/gomarkdoc@v0.5.4/format/devops.go (about)

     1  package format
     2  
     3  import (
     4  	"fmt"
     5  	"net/url"
     6  	"path/filepath"
     7  	"regexp"
     8  	"strings"
     9  
    10  	"github.com/phsym/gomarkdoc/format/formatcore"
    11  	"github.com/phsym/gomarkdoc/lang"
    12  )
    13  
    14  // AzureDevOpsMarkdown provides a Format which is compatible with Azure
    15  // DevOps's syntax and semantics. See the Azure DevOps documentation for more
    16  // details about their markdown format:
    17  // https://docs.microsoft.com/en-us/azure/devops/project/wiki/markdown-guidance?view=azure-devops
    18  type AzureDevOpsMarkdown struct{}
    19  
    20  // Bold converts the provided text to bold
    21  func (f *AzureDevOpsMarkdown) Bold(text string) (string, error) {
    22  	return formatcore.Bold(text), nil
    23  }
    24  
    25  // CodeBlock wraps the provided code as a code block and tags it with the
    26  // provided language (or no language if the empty string is provided).
    27  func (f *AzureDevOpsMarkdown) CodeBlock(language, code string) (string, error) {
    28  	return formatcore.GFMCodeBlock(language, code), nil
    29  }
    30  
    31  // Header converts the provided text into a header of the provided level. The
    32  // level is expected to be at least 1.
    33  func (f *AzureDevOpsMarkdown) Header(level int, text string) (string, error) {
    34  	return formatcore.Header(level, formatcore.Escape(text))
    35  }
    36  
    37  // RawHeader converts the provided text into a header of the provided level
    38  // without escaping the header text. The level is expected to be at least 1.
    39  func (f *AzureDevOpsMarkdown) RawHeader(level int, text string) (string, error) {
    40  	return formatcore.Header(level, text)
    41  }
    42  
    43  var devOpsWhitespaceRegex = regexp.MustCompile(`\s`)
    44  
    45  // LocalHref generates an href for navigating to a header with the given
    46  // headerText located within the same document as the href itself. Link
    47  // generation follows the guidelines here:
    48  // https://docs.microsoft.com/en-us/azure/devops/project/wiki/markdown-guidance?view=azure-devops#anchor-links
    49  func (f *AzureDevOpsMarkdown) LocalHref(headerText string) (string, error) {
    50  	result := strings.ToLower(headerText)
    51  	result = strings.TrimSpace(result)
    52  	result = devOpsWhitespaceRegex.ReplaceAllString(result, "-")
    53  	result = url.PathEscape(result)
    54  	// We also have to escape the `:` character if present
    55  	result = strings.ReplaceAll(result, ":", "%3A")
    56  
    57  	return fmt.Sprintf("#%s", result), nil
    58  }
    59  
    60  // CodeHref generates an href to the provided code entry.
    61  func (f *AzureDevOpsMarkdown) CodeHref(loc lang.Location) (string, error) {
    62  	// If there's no repo, we can't compute an href
    63  	if loc.Repo == nil {
    64  		return "", nil
    65  	}
    66  
    67  	var (
    68  		relative string
    69  		err      error
    70  	)
    71  	if filepath.IsAbs(loc.Filepath) {
    72  		relative, err = filepath.Rel(loc.WorkDir, loc.Filepath)
    73  		if err != nil {
    74  			return "", err
    75  		}
    76  	} else {
    77  		relative = loc.Filepath
    78  	}
    79  
    80  	full := filepath.Join(loc.Repo.PathFromRoot, relative)
    81  	p, err := filepath.Rel(string(filepath.Separator), full)
    82  	if err != nil {
    83  		return "", err
    84  	}
    85  
    86  	return fmt.Sprintf(
    87  		"%s?path=%s&version=GB%s&lineStyle=plain&line=%d&lineEnd=%d&lineStartColumn=%d&lineEndColumn=%d",
    88  		loc.Repo.Remote,
    89  		url.PathEscape(filepath.ToSlash(p)),
    90  		loc.Repo.DefaultBranch,
    91  		loc.Start.Line,
    92  		loc.End.Line,
    93  		loc.Start.Col,
    94  		loc.End.Col,
    95  	), nil
    96  }
    97  
    98  // Link generates a link with the given text and href values.
    99  func (f *AzureDevOpsMarkdown) Link(text, href string) (string, error) {
   100  	return formatcore.Link(text, href), nil
   101  }
   102  
   103  // ListEntry generates an unordered list entry with the provided text at the
   104  // provided zero-indexed depth. A depth of 0 is considered the topmost level of
   105  // list.
   106  func (f *AzureDevOpsMarkdown) ListEntry(depth int, text string) (string, error) {
   107  	return formatcore.ListEntry(depth, text), nil
   108  }
   109  
   110  // Accordion generates a collapsible content. The accordion's visible title
   111  // while collapsed is the provided title and the expanded content is the body.
   112  func (f *AzureDevOpsMarkdown) Accordion(title, body string) (string, error) {
   113  	return formatcore.GFMAccordion(title, body), nil
   114  }
   115  
   116  // AccordionHeader generates the header visible when an accordion is collapsed.
   117  //
   118  // The AccordionHeader is expected to be used in conjunction with
   119  // AccordionTerminator() when the demands of the body's rendering requires it to
   120  // be generated independently. The result looks conceptually like the following:
   121  //
   122  //	accordion := format.AccordionHeader("Accordion Title") + "Accordion Body" + format.AccordionTerminator()
   123  func (f *AzureDevOpsMarkdown) AccordionHeader(title string) (string, error) {
   124  	return formatcore.GFMAccordionHeader(title), nil
   125  }
   126  
   127  // AccordionTerminator generates the code necessary to terminate an accordion
   128  // after the body. It is expected to be used in conjunction with
   129  // AccordionHeader(). See AccordionHeader for a full description.
   130  func (f *AzureDevOpsMarkdown) AccordionTerminator() (string, error) {
   131  	return formatcore.GFMAccordionTerminator(), nil
   132  }
   133  
   134  // Paragraph formats a paragraph with the provided text as the contents.
   135  func (f *AzureDevOpsMarkdown) Paragraph(text string) (string, error) {
   136  	return formatcore.Paragraph(text), nil
   137  }
   138  
   139  // Escape escapes special markdown characters from the provided text.
   140  func (f *AzureDevOpsMarkdown) Escape(text string) string {
   141  	return formatcore.Escape(text)
   142  }