link.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  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. if alt == "" || err != nil {
  35. alt, err = Get[string](l, "href")
  36. }
  37. return strings.TrimSpace(alt), err
  38. }
  39. func (l Link) Identifier() (*url.URL, error) {
  40. return nil, nil
  41. }
  42. // used for link prioritization, roughly
  43. // related to resolution
  44. func (l Link) rating() int {
  45. height, err := Get[int](l, "height")
  46. if err != nil { height = 1 }
  47. width, err := Get[int](l, "width")
  48. if err != nil { width = 1 }
  49. return height * width
  50. }
  51. // TODO: update of course to be nice markup of some sort
  52. func (l Link) String() (string, error) {
  53. output := ""
  54. if alt, err := l.Alt(); err == nil {
  55. output += alt
  56. } else if url, err := l.URL(); err == nil {
  57. output += url.String()
  58. }
  59. if Subtype, err := l.Subtype(); err == nil {
  60. output += " (" + Subtype + ")"
  61. }
  62. return output, nil
  63. }
  64. // TODO: must test when list only has 1 link (probably works)
  65. func SelectBestLink(links []Link, supertype string) (Link, error) {
  66. if len(links) == 0 {
  67. return nil, errors.New("Can't select best link of type " + supertype + "/* from an empty list")
  68. }
  69. bestLink := links[0]
  70. for _, thisLink := range links[1:] {
  71. var bestLinkSupertypeMatches bool
  72. if bestLinkSupertype, err := bestLink.Supertype(); err != nil {
  73. bestLinkSupertypeMatches = false
  74. } else {
  75. bestLinkSupertypeMatches = bestLinkSupertype == supertype
  76. }
  77. var thisLinkSuperTypeMatches bool
  78. if thisLinkSupertype, err := thisLink.Supertype(); err != nil {
  79. thisLinkSuperTypeMatches = false
  80. } else {
  81. thisLinkSuperTypeMatches = thisLinkSupertype == supertype
  82. }
  83. if thisLinkSuperTypeMatches && !bestLinkSupertypeMatches {
  84. bestLink = thisLink
  85. continue
  86. } else if !thisLinkSuperTypeMatches && bestLinkSupertypeMatches {
  87. continue
  88. } else if thisLink.rating() > bestLink.rating() {
  89. bestLink = thisLink
  90. continue
  91. }
  92. }
  93. return bestLink, nil
  94. }
  95. func SelectFirstLink(links []Link) (Link, error) {
  96. if len(links) == 0 {
  97. return nil, errors.New("can't select first Link from an empty list of links")
  98. } else {
  99. return links[0], nil
  100. }
  101. }