caption.go 1.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. package parser
  2. import (
  3. "bytes"
  4. )
  5. // caption checks for a caption, it returns the caption data and a potential "headingID".
  6. func (p *Parser) caption(data, caption []byte) ([]byte, string, int) {
  7. if !bytes.HasPrefix(data, caption) {
  8. return nil, "", 0
  9. }
  10. j := len(caption)
  11. data = data[j:]
  12. end := LinesUntilEmpty(data)
  13. data = data[:end]
  14. id, start := captionID(data)
  15. if id != "" {
  16. return data[:start], id, end + j
  17. }
  18. return data, "", end + j
  19. }
  20. // LinesUntilEmpty scans lines up to the first empty line.
  21. func LinesUntilEmpty(data []byte) int {
  22. line, i := 0, 0
  23. for line < len(data) {
  24. i++
  25. // find the end of this line
  26. for i < len(data) && data[i-1] != '\n' {
  27. i++
  28. }
  29. if IsEmpty(data[line:i]) == 0 {
  30. line = i
  31. continue
  32. }
  33. break
  34. }
  35. return i
  36. }
  37. // captionID checks if the caption *ends* in {#....}. If so the text after {# is taken to be
  38. // the ID/anchor of the entire figure block.
  39. func captionID(data []byte) (string, int) {
  40. end := len(data)
  41. j, k := 0, 0
  42. // find start/end of heading id
  43. for j = 0; j < end-1 && (data[j] != '{' || data[j+1] != '#'); j++ {
  44. }
  45. for k = j + 1; k < end && data[k] != '}'; k++ {
  46. }
  47. // remains must be whitespace.
  48. for l := k + 1; l < end; l++ {
  49. if !IsSpace(data[l]) {
  50. return "", 0
  51. }
  52. }
  53. if j > 0 && k > 0 && j+2 < k {
  54. return string(data[j+2 : k]), j
  55. }
  56. return "", 0
  57. }