link.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  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. func SelectBestLink(links []Link, supertype string) (Link, error) {
  62. if len(links) == 0 {
  63. return nil, errors.New("Can't select best link of type " + supertype + "/* from an empty list")
  64. }
  65. bestLink := links[0]
  66. for _, thisLink := range links[1:] {
  67. var bestLinkSupertypeMatches bool
  68. if bestLinkSupertype, err := bestLink.Supertype(); err != nil {
  69. bestLinkSupertypeMatches = false
  70. } else {
  71. bestLinkSupertypeMatches = bestLinkSupertype == supertype
  72. }
  73. var thisLinkSuperTypeMatches bool
  74. if thisLinkSupertype, err := thisLink.Supertype(); err != nil {
  75. thisLinkSuperTypeMatches = false
  76. } else {
  77. thisLinkSuperTypeMatches = thisLinkSupertype == supertype
  78. }
  79. if thisLinkSuperTypeMatches && !bestLinkSupertypeMatches {
  80. bestLink = thisLink
  81. continue
  82. } else if !thisLinkSuperTypeMatches && bestLinkSupertypeMatches {
  83. continue
  84. } else if thisLink.rating() > bestLink.rating() {
  85. bestLink = thisLink
  86. continue
  87. }
  88. }
  89. return bestLink, nil
  90. }
  91. func SelectFirstLink(links []Link) (Link, error) {
  92. if len(links) == 0 {
  93. return nil, errors.New("can't select first Link from an empty list of links")
  94. } else {
  95. return links[0], nil
  96. }
  97. }