middleman-dato 0.0.1.rc2 → 0.0.1.rc3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2662bb3c2b38f4f37124b6ea9eb18de9db52b121
4
- data.tar.gz: f798ff90cad69d1eb951dc3d95d345d9bc9b30a7
3
+ metadata.gz: 9e9b62c5c0b856590c2086fc8eb5f7c881fdee83
4
+ data.tar.gz: ada1e157192adfb35b34f62ddbfa89828c5afad0
5
5
  SHA512:
6
- metadata.gz: 935e93b6a99c6c7a244b7f48184f3af845f8252d04cf696d8a94c00971fbd8e1a5c906ead27407ca39e0fedc2a4ed91a6888e22d1f046e734d02de9bdbf41895
7
- data.tar.gz: 88393186cced3a657979a04fefafb21a482791dbfb4a5f060935f8c10d7286b9d43d7af4f45006729e79bb9617a2d511436da953e8cac65f00587d945cd5dedb
6
+ metadata.gz: a6929b598351b0a444326ccba3e879215f4594378559e17674f5ae691348f1d4db32d29b7a49ffa7d9595b8db20b1f781831c61be389066686b2398bfa132904
7
+ data.tar.gz: 25b452a1e01c2034d6d8c046f906baf42605ae598d41d26f806b011b2c8705433a55b2d607cf550bb595b51176cd809a76b90b4915173932e67ca300efbbbd61
data/Gemfile CHANGED
@@ -12,8 +12,5 @@ group :development do
12
12
  end
13
13
 
14
14
  group :test do
15
- gem 'cucumber'
16
- gem 'fivemat'
17
- gem 'aruba'
18
15
  gem 'rspec'
19
16
  end
@@ -0,0 +1,20 @@
1
+ require 'dato/meta_tags/og_meta_tag'
2
+ require 'time'
3
+
4
+ module Dato
5
+ module MetaTags
6
+ class ArticleModifiedTime < OgMetaTag
7
+ def buildable?
8
+ record && !record.singleton?
9
+ end
10
+
11
+ def name
12
+ "article:modified_time"
13
+ end
14
+
15
+ def value
16
+ record.updated_at.iso8601
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,21 @@
1
+ require 'dato/meta_tags/og_meta_tag'
2
+ require 'time'
3
+
4
+ module Dato
5
+ module MetaTags
6
+ class ArticlePublisher < OgMetaTag
7
+ def buildable?
8
+ record && !record.singleton? &&
9
+ global_seo_field(:facebook_page_url).present?
10
+ end
11
+
12
+ def name
13
+ "article:publisher"
14
+ end
15
+
16
+ def value
17
+ global_seo_field(:facebook_page_url)
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,80 @@
1
+ require 'forwardable'
2
+ require 'dato/seo'
3
+
4
+ module Dato
5
+ module MetaTags
6
+ class Base
7
+ attr_reader :builder, :base_url, :space, :content_type, :record
8
+
9
+ def initialize(builder, base_url, space, record)
10
+ @space = space
11
+ @base_url = base_url
12
+ @record = record
13
+ @builder = builder
14
+ end
15
+
16
+ def seo_field_with_fallback(attribute, alternative = nil, &block)
17
+ seo = first_record_field_of_type(:seo)
18
+
19
+ alternatives = []
20
+
21
+ alternatives << seo.send(attribute) if seo
22
+ alternatives << alternative if alternative
23
+ alternatives << fallback_seo.send(attribute) if fallback_seo
24
+
25
+ alternatives = alternatives.select(&:present?)
26
+ alternatives = alternatives.select(&block) if block
27
+
28
+ alternatives.first
29
+ end
30
+
31
+ def title_suffix
32
+ global_seo_field(:title_suffix)
33
+ end
34
+
35
+ def no_index?
36
+ space && space[:attributes][:no_index]
37
+ end
38
+
39
+ def global_seo_field(attribute)
40
+ if global_seo
41
+ global_seo[attribute]
42
+ end
43
+ end
44
+
45
+ def first_record_field_of_type(type)
46
+ return nil unless record
47
+
48
+ field = record.fields.find do |name, field|
49
+ field[:field_type] == type.to_s
50
+ end
51
+
52
+ if field
53
+ field_name = field.first
54
+ record.send(field_name)
55
+ end
56
+ end
57
+
58
+ def fallback_seo
59
+ @fallback_seo ||= begin
60
+ if global_seo
61
+ Seo.new(global_seo[:fallback_seo])
62
+ end
63
+ end
64
+ end
65
+
66
+ def global_seo
67
+ @global_seo ||= begin
68
+ if space && space[:attributes][:global_seo]
69
+ global_seo = space[:attributes][:global_seo]
70
+ if space[:attributes][:locales].size > 1
71
+ global_seo[I18n.locale]
72
+ else
73
+ global_seo
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,24 @@
1
+ require 'dato/meta_tags/base'
2
+
3
+ module Dato
4
+ module MetaTags
5
+ class Description < Base
6
+
7
+ def build
8
+ if description.present?
9
+ [
10
+ builder.tag(:meta, name: "description", content: description),
11
+ builder.tag(:meta, property: "og:description", content: description),
12
+ builder.tag(:meta, name: "twitter:description", content: description)
13
+ ]
14
+ end
15
+ end
16
+
17
+ def description
18
+ @description ||= seo_field_with_fallback(:description)
19
+ end
20
+ end
21
+ end
22
+ end
23
+
24
+
@@ -0,0 +1,33 @@
1
+ require 'dato/meta_tags/base'
2
+
3
+ module Dato
4
+ module MetaTags
5
+ class Image < Base
6
+
7
+ def build
8
+ if image.present?
9
+ [
10
+ builder.tag(:meta, property: "og:image", content: image),
11
+ builder.tag(:meta, name: "twitter:image", content: image)
12
+ ]
13
+ end
14
+ end
15
+
16
+ def image
17
+ image = seo_field_with_fallback(
18
+ :image,
19
+ first_record_field_of_type(:image)
20
+ ) do |image|
21
+ image.attributes[:width] >= 200 &&
22
+ image.attributes[:height] >= 200
23
+ end
24
+
25
+ if image
26
+ image.file.format("jpg").to_url
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+
33
+
@@ -0,0 +1,20 @@
1
+ require 'dato/meta_tags/og_meta_tag'
2
+
3
+ module Dato
4
+ module MetaTags
5
+ class OgLocale < OgMetaTag
6
+ def buildable?
7
+ true
8
+ end
9
+
10
+ def name
11
+ "og:locale"
12
+ end
13
+
14
+ def value
15
+ locale = I18n.locale
16
+ "#{locale}_#{locale.upcase}"
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,25 @@
1
+ require 'dato/meta_tags/base'
2
+
3
+ module Dato
4
+ module MetaTags
5
+ class OgMetaTag < Base
6
+ def buildable?
7
+ false
8
+ end
9
+
10
+ def build
11
+ if buildable?
12
+ builder.tag(:meta, property: name, content: value)
13
+ end
14
+ end
15
+
16
+ def name
17
+ raise NotImplementedError
18
+ end
19
+
20
+ def value
21
+ raise NotImplementedError
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,19 @@
1
+ require 'dato/meta_tags/og_meta_tag'
2
+
3
+ module Dato
4
+ module MetaTags
5
+ class OgSiteName < OgMetaTag
6
+ def buildable?
7
+ global_seo_field(:site_name).present?
8
+ end
9
+
10
+ def name
11
+ "og:site_name"
12
+ end
13
+
14
+ def value
15
+ global_seo_field(:site_name)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,25 @@
1
+ require 'dato/meta_tags/og_meta_tag'
2
+
3
+ module Dato
4
+ module MetaTags
5
+ class OgType < OgMetaTag
6
+ def buildable?
7
+ true
8
+ end
9
+
10
+ def name
11
+ "og:type"
12
+ end
13
+
14
+ def value
15
+ if !record
16
+ "website"
17
+ elsif record.singleton?
18
+ "website"
19
+ else
20
+ "article"
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,16 @@
1
+ require 'dato/meta_tags/base'
2
+
3
+ module Dato
4
+ module MetaTags
5
+ class Robots < Base
6
+ def build
7
+ if no_index?
8
+ builder.tag(:meta, name: "robots", content: "noindex")
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
14
+
15
+
16
+
@@ -0,0 +1,37 @@
1
+ require 'dato/meta_tags/base'
2
+
3
+ module Dato
4
+ module MetaTags
5
+ class Title < Base
6
+
7
+ def build
8
+ if title.present?
9
+ [
10
+ builder.content_tag(:title, title_with_suffix),
11
+ builder.tag(:meta, property: "og:title", content: title),
12
+ builder.tag(:meta, name: "twitter:title", content: title)
13
+ ]
14
+ end
15
+ end
16
+
17
+ def title
18
+ @title ||= seo_field_with_fallback(
19
+ :title,
20
+ first_record_field_of_type(:title)
21
+ )
22
+ end
23
+
24
+ def title_with_suffix
25
+ title_plus_suffix = title + title_suffix
26
+
27
+ if title_plus_suffix.size <= 60
28
+ title_plus_suffix
29
+ else
30
+ title
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+
37
+
@@ -0,0 +1,19 @@
1
+ require 'dato/meta_tags/twitter_meta_tag'
2
+
3
+ module Dato
4
+ module MetaTags
5
+ class TwitterCard < TwitterMetaTag
6
+ def buildable?
7
+ true
8
+ end
9
+
10
+ def name
11
+ "twitter:card"
12
+ end
13
+
14
+ def value
15
+ "summary"
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,26 @@
1
+ require 'dato/meta_tags/base'
2
+
3
+ module Dato
4
+ module MetaTags
5
+ class TwitterMetaTag < Base
6
+ def buildable?
7
+ false
8
+ end
9
+
10
+ def build
11
+ if buildable?
12
+ builder.tag(:meta, name: name, content: value)
13
+ end
14
+ end
15
+
16
+ def name
17
+ raise NotImplementedError
18
+ end
19
+
20
+ def value
21
+ raise NotImplementedError
22
+ end
23
+ end
24
+ end
25
+ end
26
+
@@ -0,0 +1,19 @@
1
+ require 'dato/meta_tags/twitter_meta_tag'
2
+
3
+ module Dato
4
+ module MetaTags
5
+ class TwitterSite < TwitterMetaTag
6
+ def buildable?
7
+ global_seo_field(:twitter_account).present?
8
+ end
9
+
10
+ def name
11
+ "twitter:site"
12
+ end
13
+
14
+ def value
15
+ global_seo_field(:twitter_account)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,24 @@
1
+ require 'dato/meta_tags/base'
2
+
3
+ module Dato
4
+ module MetaTags
5
+ class Url < Base
6
+
7
+ def build
8
+ if url.present?
9
+ [
10
+ builder.tag(:link, rel: "canonical", href: url),
11
+ builder.tag(:meta, property: "og:url", content: url),
12
+ builder.tag(:meta, name: "twitter:url", content: url)
13
+ ]
14
+ end
15
+ end
16
+
17
+ def url
18
+ base_url + builder.current_page.url
19
+ end
20
+ end
21
+ end
22
+ end
23
+
24
+
@@ -0,0 +1,41 @@
1
+ require 'dato/meta_tags/title'
2
+ require 'dato/meta_tags/description'
3
+ require 'dato/meta_tags/image'
4
+ require 'dato/meta_tags/url'
5
+ require 'dato/meta_tags/robots'
6
+ require 'dato/meta_tags/og_locale'
7
+ require 'dato/meta_tags/og_type'
8
+ require 'dato/meta_tags/og_site_name'
9
+ require 'dato/meta_tags/article_modified_time'
10
+ require 'dato/meta_tags/article_publisher'
11
+ require 'dato/meta_tags/twitter_card'
12
+ require 'dato/meta_tags/twitter_site'
13
+
14
+ module Dato
15
+ class MetaTagsBuilder
16
+ META_TAGS = [
17
+ MetaTags::Title,
18
+ MetaTags::Description,
19
+ MetaTags::Image,
20
+ MetaTags::Url,
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
+ ]
30
+
31
+ def initialize(*args)
32
+ @args = args
33
+ end
34
+
35
+ def meta_tags
36
+ META_TAGS.map do |klass|
37
+ klass.new(*@args).build
38
+ end.flatten.compact.join("\n")
39
+ end
40
+ end
41
+ end
@@ -1,5 +1,6 @@
1
1
  require 'middleman-core'
2
2
  require 'dato/repo'
3
+ require 'dato/meta_tags_builder'
3
4
  require 'ostruct'
4
5
 
5
6
  module Dato
@@ -7,6 +8,7 @@ module Dato
7
8
  option :domain, nil, 'Space domain'
8
9
  option :token, nil, 'Space API token'
9
10
  option :api_host, 'http://dato-api.herokuapp.com', 'Space API token'
11
+ option :base_url, nil, 'Website base URL'
10
12
 
11
13
  attr_reader :records
12
14
 
@@ -38,6 +40,21 @@ module Dato
38
40
  def dato
39
41
  OpenStruct.new(Repo.instance.records_per_content_type)
40
42
  end
43
+
44
+ def dato_meta_tags(record)
45
+ begin
46
+ builder = MetaTagsBuilder.new(
47
+ self,
48
+ Repo.instance.connection_options[:base_url],
49
+ Repo.instance.space,
50
+ record
51
+ )
52
+ builder.meta_tags
53
+ rescue Exception => e
54
+ puts e.message
55
+ puts e.backtrace.join("\n")
56
+ end
57
+ end
41
58
  end
42
59
  end
43
60
  end
data/lib/dato/record.rb CHANGED
@@ -1,15 +1,21 @@
1
1
  require "dato/file"
2
+ require "dato/seo"
3
+ require "time"
2
4
 
3
5
  module Dato
4
6
  class Record
5
- attr_reader :attributes, :fields, :singleton
7
+ attr_reader :attributes, :fields, :content_type
6
8
 
7
9
  def initialize(attributes, content_type)
8
10
  @attributes = attributes.with_indifferent_access
9
- @singleton = content_type[:singleton]
11
+ @content_type = content_type
10
12
  @fields = content_type[:fields].with_indifferent_access
11
13
  end
12
14
 
15
+ def singleton?
16
+ @singleton = content_type[:singleton]
17
+ end
18
+
13
19
  def respond_to?(method, include_private = false)
14
20
  if @attributes.has_key?(method)
15
21
  true
@@ -27,10 +33,14 @@ module Dato
27
33
  attribute
28
34
  end
29
35
 
36
+ return nil if !attribute
37
+
30
38
  if %w(image file).include? fields[name][:field_type]
31
39
  Dato::File.new(attribute)
32
40
  elsif fields[name][:field_type] == "date"
33
41
  Date.parse(attribute)
42
+ elsif fields[name][:field_type] == "seo"
43
+ Dato::Seo.new(attribute)
34
44
  else
35
45
  attribute
36
46
  end
@@ -40,6 +50,10 @@ module Dato
40
50
  @attributes[:id]
41
51
  end
42
52
 
53
+ def updated_at
54
+ Time.parse(@attributes[:updated_at])
55
+ end
56
+
43
57
  def method_missing(method, *arguments, &block)
44
58
  if @attributes.has_key?(method) && arguments.size == 0
45
59
  read_attribute(method.to_sym)
data/lib/dato/repo.rb CHANGED
@@ -7,9 +7,11 @@ module Dato
7
7
  class Repo
8
8
  include Singleton
9
9
 
10
- attr_reader :client, :content_types, :records_per_content_type
10
+ attr_reader :client, :space, :content_types, :records_per_content_type,
11
+ :connection_options
11
12
 
12
13
  def connection_options=(options)
14
+ @connection_options = options
13
15
  @client = Client.new(
14
16
  options[:api_host],
15
17
  options[:domain],
@@ -18,7 +20,9 @@ module Dato
18
20
  end
19
21
 
20
22
  def sync!
21
- @content_types = prepare_content_types(client.space)
23
+ space_response = client.space.with_indifferent_access
24
+ @space = space_response[:data]
25
+ @content_types = prepare_content_types(space_response)
22
26
  @records_per_content_type = group_by_content_type(client.records)
23
27
  end
24
28
 
data/lib/dato/seo.rb ADDED
@@ -0,0 +1,31 @@
1
+ require "imgix"
2
+
3
+ module Dato
4
+ class Seo
5
+ attr_reader :attributes
6
+
7
+ def initialize(data)
8
+ @attributes = data.with_indifferent_access
9
+ end
10
+
11
+ def image
12
+ @attributes[:image] && File.new(@attributes[:image])
13
+ end
14
+
15
+ def respond_to?(method, include_private = false)
16
+ if @attributes.has_key?(method)
17
+ true
18
+ else
19
+ super
20
+ end
21
+ end
22
+
23
+ def method_missing(method, *arguments, &block)
24
+ if @attributes.has_key?(method) && arguments.size == 0
25
+ @attributes[method.to_sym]
26
+ else
27
+ super
28
+ end
29
+ end
30
+ end
31
+ end
@@ -3,7 +3,7 @@ $:.push File.expand_path("../lib", __FILE__)
3
3
 
4
4
  Gem::Specification.new do |s|
5
5
  s.name = "middleman-dato"
6
- s.version = "0.0.1.rc2"
6
+ s.version = "0.0.1.rc3"
7
7
  s.platform = Gem::Platform::RUBY
8
8
  s.authors = ["Stefano Verna"]
9
9
  s.email = ["s.verna@cantierecreativo.net"]
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+
3
+ module Dato::MetaTags
4
+ RSpec.describe ArticleModifiedTime do
5
+ subject(:meta_tag) { described_class.new(builder, space, record) }
6
+ let(:builder) { MockBuilder.new }
7
+ let(:space) { nil }
8
+ let(:record) do
9
+ double("Record", updated_at: Time.now, singleton?: false)
10
+ end
11
+
12
+ describe '.value' do
13
+ context 'if record is not singleton' do
14
+ it 'returns an ISO 8601 time representation' do
15
+ expect(meta_tag.value).not_to be_nil
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+
@@ -0,0 +1,18 @@
1
+ require 'spec_helper'
2
+
3
+ module Dato::MetaTags
4
+ RSpec.describe OgLocale do
5
+ subject(:meta_tag) { described_class.new(builder, space, record) }
6
+ let(:builder) { MockBuilder.new }
7
+ let(:space) { nil }
8
+ let(:record) { nil }
9
+
10
+ describe '.value' do
11
+ it "returns the current locale" do
12
+ I18n.with_locale(:it) do
13
+ expect(meta_tag.value).to eq "it_IT"
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,31 @@
1
+ require 'active_support/dependencies'
2
+
3
+ require 'i18n'
4
+
5
+ I18n.available_locales = [:it, :en]
6
+
7
+ ActiveSupport::Dependencies.autoload_paths.unshift(
8
+ File.join(__dir__, "../lib")
9
+ )
10
+
11
+ Dir["spec/support/**/*.rb"].each do |f|
12
+ require_relative "../" + f
13
+ end
14
+
15
+ RSpec.configure do |config|
16
+ config.expect_with :rspec do |expectations|
17
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
18
+ end
19
+
20
+ config.mock_with :rspec do |mocks|
21
+ mocks.verify_partial_doubles = true
22
+ end
23
+
24
+ config.filter_run :focus
25
+ config.run_all_when_everything_filtered = true
26
+ config.disable_monkey_patching!
27
+
28
+ config.order = :random
29
+
30
+ Kernel.srand config.seed
31
+ end
@@ -0,0 +1,5 @@
1
+ class MockBuilder
2
+ def tag(*args)
3
+ args
4
+ end
5
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: middleman-dato
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1.rc2
4
+ version: 0.0.1.rc3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stefano Verna
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-05-25 00:00:00.000000000 Z
11
+ date: 2015-05-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: middleman-core
@@ -78,12 +78,33 @@ files:
78
78
  - Rakefile
79
79
  - lib/dato/client.rb
80
80
  - lib/dato/file.rb
81
+ - lib/dato/meta_tags/article_modified_time.rb
82
+ - lib/dato/meta_tags/article_publisher.rb
83
+ - lib/dato/meta_tags/base.rb
84
+ - lib/dato/meta_tags/description.rb
85
+ - lib/dato/meta_tags/image.rb
86
+ - lib/dato/meta_tags/og_locale.rb
87
+ - lib/dato/meta_tags/og_meta_tag.rb
88
+ - lib/dato/meta_tags/og_site_name.rb
89
+ - lib/dato/meta_tags/og_type.rb
90
+ - lib/dato/meta_tags/robots.rb
91
+ - lib/dato/meta_tags/title.rb
92
+ - lib/dato/meta_tags/twitter_card.rb
93
+ - lib/dato/meta_tags/twitter_meta_tag.rb
94
+ - lib/dato/meta_tags/twitter_site.rb
95
+ - lib/dato/meta_tags/url.rb
96
+ - lib/dato/meta_tags_builder.rb
81
97
  - lib/dato/middleman_extension.rb
82
98
  - lib/dato/record.rb
83
99
  - lib/dato/repo.rb
100
+ - lib/dato/seo.rb
84
101
  - lib/middleman-dato.rb
85
102
  - lib/middleman_extension.rb
86
103
  - middleman-dato.gemspec
104
+ - spec/dato/meta_tags/article_modified_time_spec.rb
105
+ - spec/dato/meta_tags/og_locale_spec.rb
106
+ - spec/spec_helper.rb
107
+ - spec/support/mock_builder.rb
87
108
  homepage: http://cantierecreativo.net
88
109
  licenses: []
89
110
  metadata: {}
@@ -107,5 +128,9 @@ rubygems_version: 2.2.2
107
128
  signing_key:
108
129
  specification_version: 4
109
130
  summary: Fetches data from a Dato space
110
- test_files: []
131
+ test_files:
132
+ - spec/dato/meta_tags/article_modified_time_spec.rb
133
+ - spec/dato/meta_tags/og_locale_spec.rb
134
+ - spec/spec_helper.rb
135
+ - spec/support/mock_builder.rb
111
136
  has_rdoc: