You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

51 lines
1.2 KiB

  1. // Copyright 2020 The Gitea Authors. All rights reserved.
  2. // Use of this source code is governed by a MIT-style
  3. // license that can be found in the LICENSE file.
  4. package markdown
  5. import (
  6. "errors"
  7. "strings"
  8. "gopkg.in/yaml.v2"
  9. )
  10. func isYAMLSeparator(line string) bool {
  11. line = strings.TrimSpace(line)
  12. for i := 0; i < len(line); i++ {
  13. if line[i] != '-' {
  14. return false
  15. }
  16. }
  17. return len(line) > 2
  18. }
  19. // ExtractMetadata consumes a markdown file, parses YAML frontmatter,
  20. // and returns the frontmatter metadata separated from the markdown content
  21. func ExtractMetadata(contents string, out interface{}) (string, error) {
  22. var front, body []string
  23. lines := strings.Split(contents, "\n")
  24. for idx, line := range lines {
  25. if idx == 0 {
  26. // First line has to be a separator
  27. if !isYAMLSeparator(line) {
  28. return "", errors.New("frontmatter must start with a separator line")
  29. }
  30. continue
  31. }
  32. if isYAMLSeparator(line) {
  33. front, body = lines[1:idx], lines[idx+1:]
  34. break
  35. }
  36. }
  37. if len(front) == 0 {
  38. return "", errors.New("could not determine metadata")
  39. }
  40. if err := yaml.Unmarshal([]byte(strings.Join(front, "\n")), out); err != nil {
  41. return "", err
  42. }
  43. return strings.Join(body, "\n"), nil
  44. }