github.com/gitbundle/modules@v0.0.0-20231025071548-85b91c5c3b01/markup/markdown/meta.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  	"errors"
    10  	"strings"
    11  
    12  	"gopkg.in/yaml.v2"
    13  )
    14  
    15  func isYAMLSeparator(line string) bool {
    16  	line = strings.TrimSpace(line)
    17  	for i := 0; i < len(line); i++ {
    18  		if line[i] != '-' {
    19  			return false
    20  		}
    21  	}
    22  	return len(line) > 2
    23  }
    24  
    25  // ExtractMetadata consumes a markdown file, parses YAML frontmatter,
    26  // and returns the frontmatter metadata separated from the markdown content
    27  func ExtractMetadata(contents string, out interface{}) (string, error) {
    28  	var front, body []string
    29  	lines := strings.Split(contents, "\n")
    30  	for idx, line := range lines {
    31  		if idx == 0 {
    32  			// First line has to be a separator
    33  			if !isYAMLSeparator(line) {
    34  				return "", errors.New("frontmatter must start with a separator line")
    35  			}
    36  			continue
    37  		}
    38  		if isYAMLSeparator(line) {
    39  			front, body = lines[1:idx], lines[idx+1:]
    40  			break
    41  		}
    42  	}
    43  
    44  	if len(front) == 0 {
    45  		return "", errors.New("could not determine metadata")
    46  	}
    47  
    48  	if err := yaml.Unmarshal([]byte(strings.Join(front, "\n")), out); err != nil {
    49  		return "", err
    50  	}
    51  	return strings.Join(body, "\n"), nil
    52  }