dato-rails 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +170 -0
  3. data/Rakefile +17 -0
  4. data/app/assets/config/dato_rails_manifest.js +0 -0
  5. data/app/components/dato/block.html.erb +13 -0
  6. data/app/components/dato/block.rb +7 -0
  7. data/app/components/dato/blockquote.html.erb +9 -0
  8. data/app/components/dato/blockquote.rb +7 -0
  9. data/app/components/dato/code.html.erb +1 -0
  10. data/app/components/dato/code.rb +11 -0
  11. data/app/components/dato/dast_node.html.erb +6 -0
  12. data/app/components/dato/dast_node.rb +17 -0
  13. data/app/components/dato/heading.rb +11 -0
  14. data/app/components/dato/link.html.erb +5 -0
  15. data/app/components/dato/link.rb +11 -0
  16. data/app/components/dato/list.rb +11 -0
  17. data/app/components/dato/list_item.rb +11 -0
  18. data/app/components/dato/live.html.erb +20 -0
  19. data/app/components/dato/live.rb +25 -0
  20. data/app/components/dato/node.rb +58 -0
  21. data/app/components/dato/not_rendered.rb +13 -0
  22. data/app/components/dato/paragraph.rb +11 -0
  23. data/app/components/dato/responsive_image.html.erb +10 -0
  24. data/app/components/dato/responsive_image.rb +8 -0
  25. data/app/components/dato/span.html.erb +5 -0
  26. data/app/components/dato/span.rb +41 -0
  27. data/app/components/dato/structured_text.html.erb +5 -0
  28. data/app/components/dato/structured_text.rb +25 -0
  29. data/app/components/dato/thematic_break.rb +11 -0
  30. data/app/components/dato/unknown_block.html.erb +17 -0
  31. data/app/components/dato/unknown_block.rb +9 -0
  32. data/app/components/dato/unknown_node.html.erb +15 -0
  33. data/app/components/dato/unknown_node.rb +9 -0
  34. data/app/controllers/dato/live_controller.rb +7 -0
  35. data/app/views/dato/live/show.html.erb +3 -0
  36. data/config/routes.rb +3 -0
  37. data/lib/dato/client.rb +23 -0
  38. data/lib/dato/config.rb +8 -0
  39. data/lib/dato/engine.rb +5 -0
  40. data/lib/dato/fragments/responsive_image.rb +13 -0
  41. data/lib/dato/version.rb +3 -0
  42. data/lib/dato.rb +7 -0
  43. data/lib/tasks/dato/rails_tasks.rake +4 -0
  44. metadata +214 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 02c359d5fbd1d6c3ec6aeb523e4e6cd363d76eeeec4045a195af8d89f62f59f8
4
+ data.tar.gz: 3a81c86545557254a92fe7b323bc241cac6b33051d619847d5e911f286cbb0ab
5
+ SHA512:
6
+ metadata.gz: 49b7857ed9358db19ea94a5c984250ec50b389bc806af3c6df8a7919504c8dbd6aa837c167bffed60f69c8cbd599ed86e03bbedbe721e39adf1b80a758a42adc
7
+ data.tar.gz: bcc954ba7e8606a5c807d0d3f1be11b1a82d0a3b065cfef77e051b7b481e3fe8b0f4f424738216ab0602a009446709c14b5d4133eef576e4960fa194fd1f4b4e
data/README.md ADDED
@@ -0,0 +1,170 @@
1
+ # Dato::Rails
2
+
3
+ Use [DatoCMS](https://www.datocms.com/) in your Rails application.
4
+
5
+ This gem allows you to fetch data using Dato GraphQL APIs and render the content in your Rails app.
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'dato-rails', require: 'dato'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle install
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install dato-rails
22
+
23
+ The gem is made of two parts:
24
+
25
+ ## GraphQL client
26
+
27
+ The GraphQL client based on [GQLi](https://github.com/contentful-labs/gqli.rb) allows to perform
28
+ queries to the GraphQL endpoint.
29
+ Look at GQLi documentation for more information about the syntax of queries.
30
+ You can also find some examples in specs of this library.
31
+
32
+ Set your api token as `DATO_API_TOKEN` environment variable.
33
+
34
+ ```ruby
35
+ client = Dato::Client.new # you can also pass the api token here.
36
+ query = GQLi::DSL.query {
37
+ homepage {
38
+ id
39
+ }
40
+ }
41
+ response = client.execute(query)
42
+
43
+ puts response.data.homepage.id
44
+ ```
45
+
46
+ We provide a fragment to extract a Responsive Image.
47
+
48
+ ```ruby
49
+ GQLi::DSL.query {
50
+ homepage {
51
+ id
52
+ content {
53
+ value
54
+ blocks {
55
+ __typename
56
+ id
57
+ image {
58
+ responsiveImage(imgixParams: {fm: __enum("png")}) {
59
+ ___ Dato::Fragments::ResponsiveImage
60
+ }
61
+ }
62
+ }
63
+ }
64
+ }
65
+ }
66
+ ```
67
+
68
+ ## View rendering
69
+
70
+ The library is also a Rails Engine and provides a whole set of ViewComponents to render your content.
71
+ The library aims to provide the most basic components and make it easy to create new one.
72
+
73
+ Once you fetched the response of a query, you can use the Dato ViewComponents to render the content.
74
+
75
+ If you have a StructuredText component, you can render it with:
76
+
77
+ ```ruby
78
+ render Dato::StructuredText.new(response.data.homepage.content)
79
+ ```
80
+
81
+ If you have a responsive image, you can render it with:
82
+
83
+ ```ruby
84
+ render Dato::ResponsiveImage.new(node.image.responsiveImage)
85
+ ```
86
+
87
+ To define a custom node, you can create a new `Dato::CustomNode` view component in your application and it will be automatically used.
88
+
89
+ You can also customize how each node type is rendered by specifying the mapping on the single render:
90
+
91
+ ```ruby
92
+ render Dato::StructuredText.new(response.data.homepage.content, overrides: { link: Dato::NotRendered })
93
+ ```
94
+
95
+ or globally:
96
+
97
+ ```
98
+ # config/initializers/dato.rb
99
+
100
+ Dato::Config.overrides = {
101
+ link: 'Dato::NotRendered'
102
+ }.with_indifferent_access
103
+ ```
104
+
105
+ # Preview and live
106
+
107
+ The `Dato::Client` supports both [preview](https://www.datocms.com/docs/pro-tips/how-to-manage-a-live-and-a-preview-site) and [live updates](https://www.datocms.com/docs/real-time-updates-api) features from Dato CMS.
108
+
109
+ ```ruby
110
+ Dato::Client.new(preview: true) # to fetch draft versions
111
+
112
+ client = Dato::Client.new(live: true) # => to fetch a live straming URL
113
+ client.live!(your_query)
114
+ # => { url: 'https://your_event_source_url' }
115
+ ```
116
+
117
+ A `ViewComponent` is provided to use both these features very easily!
118
+
119
+ Given that you have a `ViewComponent` that takes in input only the result of a dato query,
120
+ you probably have the following:
121
+
122
+ ```ruby
123
+ result = Dato::Client.new.execute!(my_query)
124
+ render(MyComponent.new(result))
125
+ ```
126
+
127
+ you can now wrap everything in a `Dato::Live` component like this:
128
+
129
+ ```ruby
130
+ render(Dato::Live.new(MyComponent, my_query, preview: true, live: true))
131
+ ```
132
+
133
+ and your component will come to life with live updates 🎉 (requires turbo).
134
+
135
+ ## Development
136
+
137
+ After checking out the repo, run `bin/setup` to install dependencies.
138
+
139
+ You can now clone the dato-rails project
140
+
141
+ [![Clone DatoCMS project](https://dashboard.datocms.com/clone/button.svg)](https://dashboard.datocms.com/clone?projectId=57262&name=dato-rails
142
+ )
143
+
144
+
145
+ You then need to set a `DATO_API_TOKEN=abcd123x` in the `.env` file on the root of your project
146
+ to consume data from your project.
147
+
148
+ Then, run `bundle exec rspec` to run the tests.
149
+
150
+ You can also run `bin/console` for an interactive prompt that will allow you to experiment.
151
+
152
+ To install this gem onto your local machine, run `bundle exec rake install`.
153
+ To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`,
154
+ which will create a git tag for the version, push git commits and the created tag,
155
+ and push the `.gem` file to [rubygems.org](https://rubygems.org).
156
+
157
+ ## Contributing
158
+
159
+ Bug reports and pull requests are welcome on GitHub at https://github.com/renuo/dato-rails.
160
+ This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to
161
+ adhere to the [code of conduct](https://github.com/renuo/dato-rails/blob/master/CODE_OF_CONDUCT.md).
162
+
163
+ ## License
164
+
165
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
166
+
167
+ ## Code of Conduct
168
+
169
+ Everyone interacting in the Dato::Rails project's codebases, issue trackers, chat rooms and mailing lists is
170
+ expected to follow the [code of conduct](https://github.com/renuo/dato-rails/blob/master/CODE_OF_CONDUCT.md).
data/Rakefile ADDED
@@ -0,0 +1,17 @@
1
+ require "bundler/setup"
2
+
3
+ APP_RAKEFILE = File.expand_path("test/dummy/Rakefile", __dir__)
4
+ load "rails/tasks/engine.rake"
5
+
6
+ load "rails/tasks/statistics.rake"
7
+
8
+ require "bundler/gem_tasks"
9
+ require "rake/testtask"
10
+
11
+ Rake::TestTask.new(:test) do |t|
12
+ t.libs << "test"
13
+ t.pattern = "test/**/*_test.rb"
14
+ t.verbose = false
15
+ end
16
+
17
+ task default: :test
File without changes
@@ -0,0 +1,13 @@
1
+ <% block = blocks.find { |b| b.id == @node.item } %>
2
+ <% if block.__typename.nil? %>
3
+ In order to render a block, you need to return its <code>__typename</code>.<br>
4
+ In your GraphQL query, add <code>__typename</code> to the list of fields returned for the blocks.<br>
5
+ For example:<br><br>
6
+ <code>
7
+ blocks {
8
+ __typename
9
+ }
10
+ </code>
11
+ <% else %>
12
+ <%=render class_for_block(block).new(block, root) %>
13
+ <% end %>
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Dato::Block < Dato::DastNode
4
+ def initialize(node, root)
5
+ super(node, "block", root)
6
+ end
7
+ end
@@ -0,0 +1,9 @@
1
+ <%= content_tag generated_tag, class: "dato-cms-#{@node.type}" do %>
2
+ <% @node.children&.each do |node| %>
3
+ <%= render_node(node) %>
4
+ <% end %>
5
+ <% end %>
6
+
7
+ <p class="dato-cms-attribution">
8
+ <%= @node.attribution %>
9
+ </p>
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Dato::Blockquote < Dato::DastNode
4
+ def initialize(node, root)
5
+ super(node, "blockquote", root)
6
+ end
7
+ end
@@ -0,0 +1 @@
1
+ <%= content_tag generated_tag, class: "dato-cms-#{@node.type}" do %><%= @node.code %><% end %>
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Dato::Code < Dato::DastNode
4
+ def initialize(node, root)
5
+ super(node, "code", root)
6
+ end
7
+
8
+ def generated_tag
9
+ "pre"
10
+ end
11
+ end
@@ -0,0 +1,6 @@
1
+ <%= content_tag generated_tag, class: "dato-cms-#{@node.type}" do %>
2
+ <%= @node.value %>
3
+ <% @node.children&.each do |node| %>
4
+ <%= render_node(node) %>
5
+ <% end %>
6
+ <% end %>
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dato
4
+ class DastNode < Node
5
+ def initialize(node, type, root = nil)
6
+ super(node, root)
7
+ unless node.type == type
8
+ raise ArgumentError.new("The node type is '#{node.type}' instead of '#{type}'")
9
+ end
10
+ @type = type
11
+ end
12
+
13
+ def generated_tag
14
+ @type
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Dato::Heading < Dato::DastNode
4
+ def initialize(node, root)
5
+ super(node, "heading", root)
6
+ end
7
+
8
+ def generated_tag
9
+ "h#{@node.level}"
10
+ end
11
+ end
@@ -0,0 +1,5 @@
1
+ <a href="<%=@node.url %>" class="dato-cms-<%=@node.type %>">
2
+ <% @node.children&.each do |node| %>
3
+ <%= render_node(node) %>
4
+ <% end %>
5
+ </a>
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Dato::Link < Dato::DastNode
4
+ def initialize(node, root)
5
+ super(node, "link", root)
6
+ end
7
+
8
+ def generated_tag
9
+ "a"
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Dato::List < Dato::DastNode
4
+ def initialize(node, root)
5
+ super(node, "list", root)
6
+ end
7
+
8
+ def generated_tag
9
+ @node.style == "bulleted" ? "ul" : "ol"
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Dato::ListItem < Dato::DastNode
4
+ def initialize(node, root)
5
+ super(node, "listItem", root)
6
+ end
7
+
8
+ def generated_tag
9
+ "li"
10
+ end
11
+ end
@@ -0,0 +1,20 @@
1
+ <% if @live %>
2
+ <script type="text/javascript">
3
+ const eventSourceUrl = '<%=@data.url %>';
4
+ const componentKlass = '<%=@component_klass%>';
5
+ const frameId = '<%=@frame_id%>';
6
+ const eventSource = new EventSource(eventSourceUrl);
7
+ eventSource.addEventListener("update", (event) => {
8
+ const params = new URLSearchParams({
9
+ component: componentKlass,
10
+ data: event.data,
11
+ frame_id: frameId
12
+ });
13
+ document.getElementById(frameId).src = `/dato/live?${params.toString()}`;
14
+ });
15
+ </script>
16
+
17
+ <%= turbo_frame_tag @frame_id %>
18
+ <% else %>
19
+ <%= render(@component_klass.new(@data)) %>
20
+ <% end %>
@@ -0,0 +1,25 @@
1
+ # This component can bring to life your dato components allowing peviews and live updates.
2
+ # Given that you have a component MyComponent that renders your page, you can would render your page with:
3
+ # render(MyComponent.new(@data_result_from_dato_query))
4
+ # you can now use this wrapper component to do:
5
+ # render(Dato::Live.new(MyComponent, query, preview: true, live: true)
6
+ module Dato
7
+ class Live < ViewComponent::Base
8
+ delegate :turbo_frame_tag, to: :helpers
9
+
10
+ def initialize(component_klass, query, preview: false, live: false)
11
+ @data = dato_fetch(query, preview: preview, live: live)
12
+ @component_klass = component_klass
13
+ @live = live
14
+ @frame_id = SecureRandom.hex(10)
15
+ end
16
+
17
+ private
18
+
19
+ def dato_fetch(query, preview: false, live: false)
20
+ client = Dato::Client.new(preview: preview, live: live)
21
+ response = live ? client.live!(query) : client.execute!(query)
22
+ response.data
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dato
4
+ class Node < ViewComponent::Base
5
+ attr_reader :root
6
+
7
+ def initialize(node, root = nil)
8
+ @node = node
9
+ @root = root
10
+ end
11
+
12
+ def render_node(node)
13
+ render class_for_node(node).new(node, root)
14
+ end
15
+
16
+ def blocks
17
+ root.blocks
18
+ end
19
+
20
+ def overrides
21
+ root.overrides
22
+ end
23
+
24
+ def debug_node
25
+ content_tag("pre", JSON.pretty_generate(@node))
26
+ end
27
+
28
+ private
29
+
30
+ def class_for_block(block)
31
+ class_name = (overrides[block.__typename] || Dato::Config.overrides[block.__typename])
32
+ if class_name.is_a?(String)
33
+ class_name = class_name.constantize
34
+ end
35
+ begin
36
+ class_name || class_by_type(block.__typename).constantize
37
+ rescue
38
+ Dato::UnknownBlock
39
+ end
40
+ end
41
+
42
+ def class_for_node(node)
43
+ class_name = (overrides[node.type] || Dato::Config.overrides[node.type])
44
+ if class_name.is_a?(String)
45
+ class_name = class_name.constantize
46
+ end
47
+ begin
48
+ class_name || class_by_type(node.type).constantize
49
+ rescue
50
+ Dato::UnknownNode
51
+ end
52
+ end
53
+
54
+ def class_by_type(type)
55
+ "Dato::#{type.classify}"
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dato
4
+ class NotRendered < DastNode
5
+ def initialize(node, root)
6
+ super(node, node.type, root)
7
+ end
8
+
9
+ def render?
10
+ false
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Dato::Paragraph < Dato::DastNode
4
+ def initialize(node, root)
5
+ super(node, "paragraph", root)
6
+ end
7
+
8
+ def generated_tag
9
+ "p"
10
+ end
11
+ end
@@ -0,0 +1,10 @@
1
+ <div class="dato-responsive-image <%= @custom_css_classes %>"
2
+ style="position: relative; background-image: url(<%= @node.base64 %>); background-size: cover;">
3
+ <div style="padding-top: <%= 100.0 / @node.aspectRatio %>%;">
4
+ <picture style="position: absolute; left: 0; top: 0; width: 100%">
5
+ <source srcset="<%= @node.webpSrcSet %>" type="image/webp">
6
+ <source srcset="<%= @node.srcSet %>">
7
+ <img src="<%= @node.src %>" alt="<%= @node.alt %>" title="<%= @node.title %>" loading="lazy" width="100%">
8
+ </picture>
9
+ </div>
10
+ </div>
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Dato::ResponsiveImage < Dato::Node
4
+ def initialize(node, root = nil, custom_css_classes: [])
5
+ super(node, root)
6
+ @custom_css_classes = custom_css_classes
7
+ end
8
+ end
@@ -0,0 +1,5 @@
1
+ <%= conditional_tag 'code', code_span?, class: "dato-cms-span-wrapper" do %>
2
+ <%= content_tag 'span', class: "dato-cms-span", style: styles do %>
3
+ <%= @node.value %>
4
+ <% end %>
5
+ <% end %>
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Dato::Span < Dato::DastNode
4
+ def initialize(node, root = nil)
5
+ super(node, "span", root)
6
+ end
7
+
8
+ def styles
9
+ return unless @node.marks.present?
10
+
11
+ mapping = {
12
+ emphasis: "font-style: italic",
13
+ strong: "font-weight: bold",
14
+ highlight: "background-color: #FFFF00"
15
+ }.with_indifferent_access
16
+
17
+ text_decoration_mappings = {
18
+ underline: "underline",
19
+ strikethrough: "line-through"
20
+ }.with_indifferent_access
21
+ styles = @node.marks.map { |m| mapping[m] }.compact
22
+ text_decorations = @node.marks.map { |m| text_decoration_mappings[m] }.compact
23
+ if text_decorations.any?
24
+ styles << "text-decoration: #{text_decorations.join(" ")}"
25
+ end
26
+
27
+ styles.join("; ")
28
+ end
29
+
30
+ def code_span?
31
+ @node.marks.present? && @node.marks.include?("code")
32
+ end
33
+
34
+ def conditional_tag(name, condition, options = nil, &block)
35
+ if condition
36
+ content_tag name, capture(&block), options
37
+ else
38
+ capture(&block)
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,5 @@
1
+ <div class="dato-cms-structured-text">
2
+ <% @structured_text_node.value.document.children.each do |node| %>
3
+ <%= render_node(node) %>
4
+ <% end %>
5
+ </div>
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Dato::StructuredText < Dato::Node
4
+ def initialize(structured_text_node, overrides: {})
5
+ unless structured_text_node.is_a?(Hashie::Mash)
6
+ raise ArgumentError.new("The parameter is not an instance of Hashie::Mash")
7
+ end
8
+
9
+ unless structured_text_node.value.schema == "dast"
10
+ raise ArgumentError.new("The node schema is '#{structured_text_node.value.schema}' instead of 'dast'")
11
+ end
12
+
13
+ @overrides = overrides.with_indifferent_access
14
+ @structured_text_node = structured_text_node
15
+ @blocks = structured_text_node.blocks
16
+ end
17
+
18
+ def root
19
+ self
20
+ end
21
+
22
+ attr_reader :blocks
23
+
24
+ attr_reader :overrides
25
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Dato::ThematicBreak < Dato::DastNode
4
+ def initialize(node, root)
5
+ super(node, "thematicBreak", root)
6
+ end
7
+
8
+ def generated_tag
9
+ "hr"
10
+ end
11
+ end
@@ -0,0 +1,17 @@
1
+ <div style="border: 3px dotted limegreen; display: inline-block; padding: 5px;">
2
+ <b>
3
+ This is an unknown block. Here is the content:<br>
4
+ <pre><%= JSON.pretty_generate(@node) %></pre>
5
+ In order to render it, you need to define a ViewComponent named <code><%=class_by_type(@node.__typename) %></code>.<br>
6
+ You can define this class in your <code>app/components/dato</code> folder. For example:<br><br>
7
+ <code>
8
+ class <%=class_by_type(@node.__typename) %> < Dato::DastNode<br>
9
+ ...<br>
10
+ end<br>
11
+ </code><br>
12
+ If you don't want to render this block you can:
13
+ * not return it in your GraphQL query
14
+ * the component when rendering the root <code>Dato::StructuredText</code> node.<br>
15
+ <code>Dato::StructuredText.new(content, overrides: { '<%=@node.__typename %>': Dato::NotRendered })</code>
16
+ </b>
17
+ </div>
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dato
4
+ class UnknownBlock < Node
5
+ def initialize(block, root)
6
+ super(block, root)
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,15 @@
1
+ <div style="border: 3px dotted limegreen; display: inline-block; padding: 5px;">
2
+ <b>
3
+ This is an unknown node of type <code><%=@type %></code>.<br>
4
+ In order to render it, you need to define a ViewComponent named <code><%=class_by_type(@node.type) %></code>.<br>
5
+ You can define this class in your <code>app/components/dato</code> folder. For example:<br><br>
6
+ <code>
7
+ class <%=class_by_type(@node.type) %> < Dato::DastNode<br>
8
+ ...<br>
9
+ end<br>
10
+ </code><br>
11
+ If you don't want to render this node, you can override the component when rendering the root <code>Dato::StructuredText</code> node.<br>
12
+ <code>Dato::StructuredText.new(content, overrides: { link: Dato::NotRendered })</code>
13
+ </b>
14
+ <%= debug_node %>
15
+ </div>
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dato
4
+ class UnknownNode < DastNode
5
+ def initialize(node, root)
6
+ super(node, node.type, root)
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,7 @@
1
+ module Dato
2
+ class LiveController < ActionController::Base
3
+ def show
4
+ @data = Hashie::Mash.new(JSON.parse(params[:data], symbolize_names: true).dig(:response, :data))
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,3 @@
1
+ <%= turbo_frame_tag params[:frame_id] do %>
2
+ <%= render params[:component].constantize.new(@data) %>
3
+ <% end %>
data/config/routes.rb ADDED
@@ -0,0 +1,3 @@
1
+ Dato::Engine.routes.draw do
2
+ get "live", to: "live#show"
3
+ end
@@ -0,0 +1,23 @@
1
+ module Dato
2
+ class Client < GQLi::Client
3
+ def initialize(api_token = ENV["DATO_API_TOKEN"], validate_query: false, preview: false, live: false)
4
+ super(
5
+ "https://graphql#{"-listen" if live}.datocms.com/#{"preview" if preview}",
6
+ headers: {
7
+ "Authorization" => api_token
8
+ },
9
+ validate_query: validate_query && !live
10
+ )
11
+ end
12
+
13
+ def live!(query)
14
+ http_response = request.post(@url, params: @params, json: {query: query.to_gql})
15
+
16
+ fail "Error: #{http_response.reason}\nBody: #{http_response.body}" if http_response.status >= 300
17
+
18
+ parsed_response = JSON.parse(http_response.to_s)
19
+ errors = parsed_response["errors"]
20
+ GQLi::Response.new(parsed_response, errors, query)
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,8 @@
1
+ module Dato
2
+ class Config
3
+ include ActiveSupport::Configurable
4
+
5
+ config_accessor(:overrides) { {} }
6
+ config_accessor(:blocks) { {} }
7
+ end
8
+ end
@@ -0,0 +1,5 @@
1
+ module Dato
2
+ class Engine < ::Rails::Engine
3
+ isolate_namespace Dato
4
+ end
5
+ end
@@ -0,0 +1,13 @@
1
+ Dato::Fragments::ResponsiveImage = GQLi::DSL.fragment("responsiveImageFragment", "ResponsiveImage") {
2
+ srcSet
3
+ webpSrcSet
4
+ sizes
5
+ src
6
+ width
7
+ height
8
+ aspectRatio
9
+ alt
10
+ title
11
+ bgColor
12
+ base64
13
+ }
@@ -0,0 +1,3 @@
1
+ module Dato
2
+ VERSION = "0.3.0"
3
+ end
data/lib/dato.rb ADDED
@@ -0,0 +1,7 @@
1
+ require "gqli"
2
+ require "view_component"
3
+ require "zeitwerk"
4
+ require "dato/engine"
5
+
6
+ loader = Zeitwerk::Loader.for_gem
7
+ loader.setup
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :dato_rails do
3
+ # # Task goes here
4
+ # end
metadata ADDED
@@ -0,0 +1,214 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dato-rails
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.3.0
5
+ platform: ruby
6
+ authors:
7
+ - Alessandro Rodi
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2022-04-04 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rspec-rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '3.0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '3.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: standard
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: dotenv
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: capybara
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: view_component
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '2.0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '2.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rails
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '4'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '4'
97
+ - !ruby/object:Gem::Dependency
98
+ name: turbo-rails
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '1'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '1'
111
+ - !ruby/object:Gem::Dependency
112
+ name: gqli
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '1'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '1'
125
+ - !ruby/object:Gem::Dependency
126
+ name: zeitwerk
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '1'
132
+ type: :runtime
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '1'
139
+ description: This gem allows you to fetch data using Dato GraphQL APIs and render
140
+ the content in your Rails app.
141
+ email:
142
+ - alessandro.rodi@renuo.ch
143
+ executables: []
144
+ extensions: []
145
+ extra_rdoc_files: []
146
+ files:
147
+ - README.md
148
+ - Rakefile
149
+ - app/assets/config/dato_rails_manifest.js
150
+ - app/components/dato/block.html.erb
151
+ - app/components/dato/block.rb
152
+ - app/components/dato/blockquote.html.erb
153
+ - app/components/dato/blockquote.rb
154
+ - app/components/dato/code.html.erb
155
+ - app/components/dato/code.rb
156
+ - app/components/dato/dast_node.html.erb
157
+ - app/components/dato/dast_node.rb
158
+ - app/components/dato/heading.rb
159
+ - app/components/dato/link.html.erb
160
+ - app/components/dato/link.rb
161
+ - app/components/dato/list.rb
162
+ - app/components/dato/list_item.rb
163
+ - app/components/dato/live.html.erb
164
+ - app/components/dato/live.rb
165
+ - app/components/dato/node.rb
166
+ - app/components/dato/not_rendered.rb
167
+ - app/components/dato/paragraph.rb
168
+ - app/components/dato/responsive_image.html.erb
169
+ - app/components/dato/responsive_image.rb
170
+ - app/components/dato/span.html.erb
171
+ - app/components/dato/span.rb
172
+ - app/components/dato/structured_text.html.erb
173
+ - app/components/dato/structured_text.rb
174
+ - app/components/dato/thematic_break.rb
175
+ - app/components/dato/unknown_block.html.erb
176
+ - app/components/dato/unknown_block.rb
177
+ - app/components/dato/unknown_node.html.erb
178
+ - app/components/dato/unknown_node.rb
179
+ - app/controllers/dato/live_controller.rb
180
+ - app/views/dato/live/show.html.erb
181
+ - config/routes.rb
182
+ - lib/dato.rb
183
+ - lib/dato/client.rb
184
+ - lib/dato/config.rb
185
+ - lib/dato/engine.rb
186
+ - lib/dato/fragments/responsive_image.rb
187
+ - lib/dato/version.rb
188
+ - lib/tasks/dato/rails_tasks.rake
189
+ homepage: https://github.com/renuo/dato-rails
190
+ licenses: []
191
+ metadata:
192
+ homepage_uri: https://github.com/renuo/dato-rails
193
+ source_code_uri: https://github.com/renuo/dato-rails
194
+ changelog_uri: https://github.com/renuo/dato-rails/CHANGELOG.md
195
+ post_install_message:
196
+ rdoc_options: []
197
+ require_paths:
198
+ - lib
199
+ required_ruby_version: !ruby/object:Gem::Requirement
200
+ requirements:
201
+ - - ">="
202
+ - !ruby/object:Gem::Version
203
+ version: '0'
204
+ required_rubygems_version: !ruby/object:Gem::Requirement
205
+ requirements:
206
+ - - ">="
207
+ - !ruby/object:Gem::Version
208
+ version: '0'
209
+ requirements: []
210
+ rubygems_version: 3.3.10
211
+ signing_key:
212
+ specification_version: 4
213
+ summary: Use Dato CMS in your Rails application.
214
+ test_files: []