link.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. package kinds
  2. import (
  3. "net/url"
  4. "strings"
  5. "errors"
  6. )
  7. type Link Dict
  8. // one of these should be omitted so
  9. // Link isn't Content
  10. func (l Link) Kind() (string, error) {
  11. return "link", nil
  12. }
  13. func (l Link) Category() string {
  14. return "link"
  15. }
  16. func (l Link) Supertype() (string, error) {
  17. mediaType, err := Get[string](l, "mediaType")
  18. return strings.Split(mediaType, "/")[0], err
  19. }
  20. func (l Link) Subtype() (string, error) {
  21. if mediaType, err := Get[string](l, "mediaType"); err != nil {
  22. return "", err
  23. } else if split := strings.Split(mediaType, "/"); len(split) < 2 {
  24. return "", errors.New("Media type " + mediaType + " lacks a subtype")
  25. } else {
  26. return split[1], nil
  27. }
  28. }
  29. func (l Link) URL() (*url.URL, error) {
  30. return GetURL(l, "href")
  31. }
  32. func (l Link) Alt() (string, error) {
  33. alt, err := Get[string](l, "name")
  34. return strings.TrimSpace(alt), err
  35. }
  36. func (l Link) Identifier() (*url.URL, error) {
  37. return nil, nil
  38. }
  39. // used for link prioritization, roughly
  40. // related to resolution
  41. func (l Link) rating() int {
  42. height, err := Get[int](l, "height")
  43. if err != nil { height = 1 }
  44. width, err := Get[int](l, "width")
  45. if err != nil { width = 1 }
  46. return height * width
  47. }
  48. // TODO: update of course to be nice markup of some sort
  49. func (l Link) String() (string, error) {
  50. output := ""
  51. if alt, err := l.Alt(); err == nil {
  52. output += alt
  53. } else if url, err := l.URL(); err == nil {
  54. output += url.String()
  55. }
  56. if Subtype, err := l.Subtype(); err == nil {
  57. output += " (" + Subtype + ")"
  58. }
  59. return output, nil
  60. }
  61. // TODO: must test when list only has 1 link (probably works)
  62. func SelectBestLink(links []Link, supertype string) (Link, error) {
  63. if len(links) == 0 {
  64. return nil, errors.New("Can't select best link of type " + supertype + "/* from an empty list")
  65. }
  66. bestLink := links[0]
  67. for _, thisLink := range links[1:] {
  68. var bestLinkSupertypeMatches bool
  69. if bestLinkSupertype, err := bestLink.Supertype(); err != nil {
  70. bestLinkSupertypeMatches = false
  71. } else {
  72. bestLinkSupertypeMatches = bestLinkSupertype == supertype
  73. }
  74. var thisLinkSuperTypeMatches bool
  75. if thisLinkSupertype, err := thisLink.Supertype(); err != nil {
  76. thisLinkSuperTypeMatches = false
  77. } else {
  78. thisLinkSuperTypeMatches = thisLinkSupertype == supertype
  79. }
  80. if thisLinkSuperTypeMatches && !bestLinkSupertypeMatches {
  81. bestLink = thisLink
  82. continue
  83. } else if !thisLinkSuperTypeMatches && bestLinkSupertypeMatches {
  84. continue
  85. } else if thisLink.rating() > bestLink.rating() {
  86. bestLink = thisLink
  87. continue
  88. }
  89. }
  90. return bestLink, nil
  91. }
  92. func SelectFirstLink(links []Link) (Link, error) {
  93. if len(links) == 0 {
  94. return nil, errors.New("can't select first Link from an empty list of links")
  95. } else {
  96. return links[0], nil
  97. }
  98. }