dato-rails 0.3.0

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.
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: []