agave-client 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (85) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +12 -0
  3. data/.travis.yml +14 -0
  4. data/CODE_OF_CONDUCT.md +49 -0
  5. data/CONTRIBUTORS.md +34 -0
  6. data/Gemfile +7 -0
  7. data/LICENSE.txt +29 -0
  8. data/README.md +41 -0
  9. data/Rakefile +7 -0
  10. data/agave-client.gemspec +63 -0
  11. data/bin/console +15 -0
  12. data/bin/setup +8 -0
  13. data/exe/agave +10 -0
  14. data/lib/agave.rb +11 -0
  15. data/lib/agave/api_client.rb +97 -0
  16. data/lib/agave/api_error.rb +23 -0
  17. data/lib/agave/cli.rb +93 -0
  18. data/lib/agave/dump/dsl/add_to_data_file.rb +14 -0
  19. data/lib/agave/dump/dsl/create_data_file.rb +14 -0
  20. data/lib/agave/dump/dsl/create_post.rb +33 -0
  21. data/lib/agave/dump/dsl/directory.rb +30 -0
  22. data/lib/agave/dump/dsl/root.rb +37 -0
  23. data/lib/agave/dump/format.rb +28 -0
  24. data/lib/agave/dump/format/json.rb +18 -0
  25. data/lib/agave/dump/format/toml.rb +31 -0
  26. data/lib/agave/dump/format/yaml.rb +55 -0
  27. data/lib/agave/dump/operation/add_to_data_file.rb +41 -0
  28. data/lib/agave/dump/operation/create_data_file.rb +28 -0
  29. data/lib/agave/dump/operation/create_post.rb +34 -0
  30. data/lib/agave/dump/operation/directory.rb +34 -0
  31. data/lib/agave/dump/operation/root.rb +27 -0
  32. data/lib/agave/dump/runner.rb +47 -0
  33. data/lib/agave/dump/ssg_detector.rb +36 -0
  34. data/lib/agave/json_api_deserializer.rb +38 -0
  35. data/lib/agave/json_api_serializer.rb +145 -0
  36. data/lib/agave/local/entities_repo.rb +46 -0
  37. data/lib/agave/local/field_type/boolean.rb +12 -0
  38. data/lib/agave/local/field_type/color.rb +63 -0
  39. data/lib/agave/local/field_type/date.rb +12 -0
  40. data/lib/agave/local/field_type/date_time.rb +12 -0
  41. data/lib/agave/local/field_type/file.rb +65 -0
  42. data/lib/agave/local/field_type/float.rb +12 -0
  43. data/lib/agave/local/field_type/gallery.rb +23 -0
  44. data/lib/agave/local/field_type/global_seo.rb +56 -0
  45. data/lib/agave/local/field_type/image.rb +82 -0
  46. data/lib/agave/local/field_type/integer.rb +12 -0
  47. data/lib/agave/local/field_type/json.rb +13 -0
  48. data/lib/agave/local/field_type/lat_lon.rb +30 -0
  49. data/lib/agave/local/field_type/link.rb +12 -0
  50. data/lib/agave/local/field_type/links.rb +21 -0
  51. data/lib/agave/local/field_type/rich_text.rb +21 -0
  52. data/lib/agave/local/field_type/seo.rb +33 -0
  53. data/lib/agave/local/field_type/slug.rb +12 -0
  54. data/lib/agave/local/field_type/string.rb +12 -0
  55. data/lib/agave/local/field_type/text.rb +12 -0
  56. data/lib/agave/local/field_type/theme.rb +43 -0
  57. data/lib/agave/local/field_type/video.rb +77 -0
  58. data/lib/agave/local/item.rb +179 -0
  59. data/lib/agave/local/items_repo.rb +210 -0
  60. data/lib/agave/local/json_api_entity.rb +78 -0
  61. data/lib/agave/local/loader.rb +60 -0
  62. data/lib/agave/local/site.rb +73 -0
  63. data/lib/agave/paginator.rb +33 -0
  64. data/lib/agave/repo.rb +93 -0
  65. data/lib/agave/site/client.rb +24 -0
  66. data/lib/agave/upload/file.rb +92 -0
  67. data/lib/agave/upload/image.rb +8 -0
  68. data/lib/agave/utils/favicon_tags_builder.rb +85 -0
  69. data/lib/agave/utils/locale_value.rb +15 -0
  70. data/lib/agave/utils/meta_tags/article_modified_time.rb +15 -0
  71. data/lib/agave/utils/meta_tags/article_publisher.rb +18 -0
  72. data/lib/agave/utils/meta_tags/base.rb +55 -0
  73. data/lib/agave/utils/meta_tags/description.rb +24 -0
  74. data/lib/agave/utils/meta_tags/image.rb +35 -0
  75. data/lib/agave/utils/meta_tags/og_locale.rb +15 -0
  76. data/lib/agave/utils/meta_tags/og_site_name.rb +18 -0
  77. data/lib/agave/utils/meta_tags/og_type.rb +18 -0
  78. data/lib/agave/utils/meta_tags/robots.rb +14 -0
  79. data/lib/agave/utils/meta_tags/title.rb +46 -0
  80. data/lib/agave/utils/meta_tags/twitter_card.rb +14 -0
  81. data/lib/agave/utils/meta_tags/twitter_site.rb +18 -0
  82. data/lib/agave/utils/seo_tags_builder.rb +45 -0
  83. data/lib/agave/version.rb +4 -0
  84. data/lib/agave/watch/site_change_watcher.rb +37 -0
  85. metadata +504 -0
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+ require 'agave/upload/file'
3
+
4
+ module Agave
5
+ module Upload
6
+ Image = Agave::Upload::File
7
+ end
8
+ end
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+ module Agave
3
+ module Utils
4
+ class FaviconTagsBuilder
5
+ attr_reader :theme_color, :site
6
+
7
+ APPLE_TOUCH_ICON_SIZES = [57, 60, 72, 76, 114, 120, 144, 152, 180].freeze
8
+ ICON_SIZES = [16, 32, 96, 192].freeze
9
+ WINDOWS_SIZES = [[70, 70], [150, 150], [310, 310], [310, 150]].freeze
10
+
11
+ def initialize(site, theme_color)
12
+ @site = site
13
+ @theme_color = theme_color
14
+ end
15
+
16
+ def meta_tags
17
+ [
18
+ build_icon_tags,
19
+ build_apple_icon_tags,
20
+ build_windows_tags,
21
+ build_color_tags,
22
+ build_app_name_tag
23
+ ].flatten.compact
24
+ end
25
+
26
+ def build_apple_icon_tags
27
+ return unless site.favicon
28
+
29
+ APPLE_TOUCH_ICON_SIZES.map do |size|
30
+ link_tag(
31
+ 'apple-touch-icon',
32
+ url(size),
33
+ sizes: "#{size}x#{size}"
34
+ )
35
+ end
36
+ end
37
+
38
+ def build_icon_tags
39
+ return unless site.favicon
40
+
41
+ ICON_SIZES.map do |size|
42
+ link_tag(
43
+ 'icon',
44
+ url(size),
45
+ sizes: "#{size}x#{size}",
46
+ type: "image/#{site.favicon.format}"
47
+ )
48
+ end
49
+ end
50
+
51
+ def build_windows_tags
52
+ return unless site.favicon
53
+
54
+ WINDOWS_SIZES.map do |(w, h)|
55
+ meta_tag("msapplication-square#{w}x#{h}logo", url(w, h))
56
+ end
57
+ end
58
+
59
+ def build_app_name_tag
60
+ meta_tag('application-name', site.name)
61
+ end
62
+
63
+ def build_color_tags
64
+ return unless theme_color
65
+
66
+ [
67
+ meta_tag('theme-color', theme_color),
68
+ meta_tag('msapplication-TileColor', theme_color)
69
+ ]
70
+ end
71
+
72
+ def url(width, height = width)
73
+ site.favicon.url(w: width, h: height)
74
+ end
75
+
76
+ def meta_tag(name, value)
77
+ { tag_name: 'meta', attributes: { name: name, content: value } }
78
+ end
79
+
80
+ def link_tag(rel, href, attrs = {})
81
+ { tag_name: 'link', attributes: attrs.merge(rel: rel, href: href) }
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+ require 'i18n/backend/fallbacks'
3
+
4
+ module Agave
5
+ module Utils
6
+ module LocaleValue
7
+ def self.find(obj)
8
+ locale_with_value = I18n.fallbacks[I18n.locale]
9
+ .find { |locale| obj[locale] }
10
+
11
+ obj[locale_with_value || I18n.locale]
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+ require 'agave/utils/meta_tags/base'
3
+ require 'time'
4
+
5
+ module Agave
6
+ module Utils
7
+ module MetaTags
8
+ class ArticleModifiedTime < Base
9
+ def build
10
+ og_tag('article:modified_time', item.updated_at.iso8601) if item
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+ require 'agave/utils/meta_tags/base'
3
+
4
+ module Agave
5
+ module Utils
6
+ module MetaTags
7
+ class ArticlePublisher < Base
8
+ def build
9
+ og_tag('article:publisher', facebook_page_url) if facebook_page_url
10
+ end
11
+
12
+ def facebook_page_url
13
+ site.global_seo && site.global_seo.facebook_page_url
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+ require 'forwardable'
3
+ require 'agave/local/field_type/seo'
4
+ require 'active_support/core_ext/object/blank'
5
+
6
+ module Agave
7
+ module Utils
8
+ module MetaTags
9
+ class Base
10
+ attr_reader :site, :item
11
+
12
+ def initialize(item, site)
13
+ @item = item
14
+ @site = site
15
+ end
16
+
17
+ def seo_field_with_fallback(attribute, alternative)
18
+ fallback_seo = site.global_seo && site.global_seo.fallback_seo
19
+
20
+ seo_field = item &&
21
+ item.fields.detect { |f| f.field_type == 'seo' }
22
+
23
+ item_seo_value = seo_field &&
24
+ item.send(seo_field.api_key) &&
25
+ item.send(seo_field.api_key).send(attribute)
26
+
27
+ fallback_seo_value = fallback_seo &&
28
+ fallback_seo.send(attribute)
29
+
30
+ item_seo_value || alternative || fallback_seo_value
31
+ end
32
+
33
+ def tag(tag_name, attributes)
34
+ { tag_name: tag_name, attributes: attributes }
35
+ end
36
+
37
+ def meta_tag(name, content)
38
+ tag('meta', name: name, content: content)
39
+ end
40
+
41
+ def og_tag(property, content)
42
+ tag('meta', property: property, content: content)
43
+ end
44
+
45
+ def card_tag(name, content)
46
+ meta_tag(name, content)
47
+ end
48
+
49
+ def content_tag(tag_name, content)
50
+ { tag_name: tag_name, content: content }
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+ require 'agave/utils/meta_tags/base'
3
+
4
+ module Agave
5
+ module Utils
6
+ module MetaTags
7
+ class Description < Base
8
+ def build
9
+ return unless description.present?
10
+
11
+ [
12
+ meta_tag('description', description),
13
+ og_tag('og:description', description),
14
+ card_tag('twitter:description', description)
15
+ ]
16
+ end
17
+
18
+ def description
19
+ @description ||= seo_field_with_fallback(:description, nil)
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+ require 'agave/utils/meta_tags/base'
3
+
4
+ module Agave
5
+ module Utils
6
+ module MetaTags
7
+ class Image < Base
8
+ def build
9
+ return unless image
10
+
11
+ [
12
+ og_tag('og:image', image.url),
13
+ card_tag('twitter:image', image.url)
14
+ ]
15
+ end
16
+
17
+ def image
18
+ @image ||= seo_field_with_fallback(:image, item_image)
19
+ end
20
+
21
+ def item_image
22
+ item && item.fields
23
+ .select { |field| field.field_type == 'image' }
24
+ .map { |field| item.send(field.api_key) }
25
+ .compact
26
+ .find do |image|
27
+
28
+ image.width && image.height &&
29
+ image.width >= 200 && image.height >= 200
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+ require 'agave/utils/meta_tags/base'
3
+
4
+ module Agave
5
+ module Utils
6
+ module MetaTags
7
+ class OgLocale < Base
8
+ def build
9
+ locale = I18n.locale
10
+ og_tag('og:locale', "#{locale}_#{locale.upcase}")
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+ require 'agave/utils/meta_tags/base'
3
+
4
+ module Agave
5
+ module Utils
6
+ module MetaTags
7
+ class OgSiteName < Base
8
+ def build
9
+ og_tag('og:site_name', site_name) if site_name
10
+ end
11
+
12
+ def site_name
13
+ site.global_seo && site.global_seo.site_name
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+ require 'agave/utils/meta_tags/base'
3
+
4
+ module Agave
5
+ module Utils
6
+ module MetaTags
7
+ class OgType < Base
8
+ def build
9
+ if !item || item.singleton?
10
+ og_tag('og:type', 'website')
11
+ else
12
+ og_tag('og:type', 'article')
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+ require 'agave/utils/meta_tags/base'
3
+
4
+ module Agave
5
+ module Utils
6
+ module MetaTags
7
+ class Robots < Base
8
+ def build
9
+ meta_tag('robots', 'noindex') if site.no_index
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+ require 'agave/utils/meta_tags/base'
3
+
4
+ module Agave
5
+ module Utils
6
+ module MetaTags
7
+ class Title < Base
8
+ def build
9
+ return unless item_title
10
+
11
+ [
12
+ content_tag('title', item_title_with_suffix),
13
+ og_tag('og:title', item_title),
14
+ card_tag('twitter:title', item_title)
15
+ ]
16
+ end
17
+
18
+ def title_field
19
+ item && item.fields.find do |field|
20
+ field.field_type == 'string' &&
21
+ field.appeareance[:type] == 'title'
22
+ end
23
+ end
24
+
25
+ def item_title
26
+ @item_title ||= seo_field_with_fallback(
27
+ :title,
28
+ title_field && item.send(title_field.api_key)
29
+ )
30
+ end
31
+
32
+ def suffix
33
+ (site.global_seo && site.global_seo.title_suffix) || ''
34
+ end
35
+
36
+ def item_title_with_suffix
37
+ if (item_title + suffix).size <= 60
38
+ item_title + suffix
39
+ else
40
+ item_title
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+ require 'agave/utils/meta_tags/base'
3
+
4
+ module Agave
5
+ module Utils
6
+ module MetaTags
7
+ class TwitterCard < Base
8
+ def build
9
+ card_tag('twitter:card', 'summary')
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+ require 'agave/utils/meta_tags/base'
3
+
4
+ module Agave
5
+ module Utils
6
+ module MetaTags
7
+ class TwitterSite < Base
8
+ def build
9
+ card_tag('twitter:site', twitter_account) if twitter_account
10
+ end
11
+
12
+ def twitter_account
13
+ site.global_seo && site.global_seo.twitter_account
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+ require 'agave/utils/meta_tags/title'
3
+ require 'agave/utils/meta_tags/description'
4
+ require 'agave/utils/meta_tags/image'
5
+ require 'agave/utils/meta_tags/robots'
6
+ require 'agave/utils/meta_tags/og_locale'
7
+ require 'agave/utils/meta_tags/og_type'
8
+ require 'agave/utils/meta_tags/og_site_name'
9
+ require 'agave/utils/meta_tags/article_modified_time'
10
+ require 'agave/utils/meta_tags/article_publisher'
11
+ require 'agave/utils/meta_tags/twitter_card'
12
+ require 'agave/utils/meta_tags/twitter_site'
13
+
14
+ module Agave
15
+ module Utils
16
+ class SeoTagsBuilder
17
+ META_TAGS = [
18
+ MetaTags::Title,
19
+ MetaTags::Description,
20
+ MetaTags::Image,
21
+ MetaTags::Robots,
22
+ MetaTags::OgLocale,
23
+ MetaTags::OgType,
24
+ MetaTags::OgSiteName,
25
+ MetaTags::ArticleModifiedTime,
26
+ MetaTags::ArticlePublisher,
27
+ MetaTags::TwitterCard,
28
+ MetaTags::TwitterSite
29
+ ].freeze
30
+
31
+ attr_reader :site, :item
32
+
33
+ def initialize(item, site)
34
+ @item = item
35
+ @site = site
36
+ end
37
+
38
+ def meta_tags
39
+ META_TAGS.map do |klass|
40
+ klass.new(item, site).build
41
+ end.flatten.compact
42
+ end
43
+ end
44
+ end
45
+ end