sir_trevor_rails 0.5.0b1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +4 -0
  3. data/CHANGELOG +13 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +126 -0
  7. data/Rakefile +7 -0
  8. data/app/views/sir_trevor/_sir_trevor_block_array.html.erb +1 -0
  9. data/app/views/sir_trevor/blocks/_heading_block.html.erb +1 -0
  10. data/app/views/sir_trevor/blocks/_image_block.html.erb +5 -0
  11. data/app/views/sir_trevor/blocks/_list_block.html.erb +3 -0
  12. data/app/views/sir_trevor/blocks/_quote_block.html.erb +13 -0
  13. data/app/views/sir_trevor/blocks/_text_block.html.erb +3 -0
  14. data/app/views/sir_trevor/blocks/_tweet_block.html.erb +9 -0
  15. data/app/views/sir_trevor/blocks/videos/_vimeo.html.erb +4 -0
  16. data/app/views/sir_trevor/blocks/videos/_youtube.html.erb +4 -0
  17. data/config/initializers/validators.rb +12 -0
  18. data/config.ru +7 -0
  19. data/lib/generators/sir_trevor_rails/block/block_generator.rb +33 -0
  20. data/lib/generators/sir_trevor_rails/block/templates/_block.html.erb +3 -0
  21. data/lib/generators/sir_trevor_rails/block/templates/_block.js +203 -0
  22. data/lib/generators/sir_trevor_rails/block/templates/_block.rb +2 -0
  23. data/lib/generators/sir_trevor_rails/views/views_generator.rb +17 -0
  24. data/lib/sir_trevor_rails/block.rb +63 -0
  25. data/lib/sir_trevor_rails/block_array.rb +21 -0
  26. data/lib/sir_trevor_rails/blocks/tweet_block.rb +35 -0
  27. data/lib/sir_trevor_rails/blocks/video_block.rb +9 -0
  28. data/lib/sir_trevor_rails/engine.rb +34 -0
  29. data/lib/sir_trevor_rails/has_sir_trevor_content.rb +27 -0
  30. data/lib/sir_trevor_rails/helpers/view_helper.rb +26 -0
  31. data/lib/sir_trevor_rails/version.rb +3 -0
  32. data/lib/sir_trevor_rails/view_resolver.rb +13 -0
  33. data/lib/sir_trevor_rails.rb +30 -0
  34. data/sir_trevor_rails.gemspec +39 -0
  35. data/spec/internal/app/models/custom_block.rb +5 -0
  36. data/spec/internal/app/models/post.rb +2 -0
  37. data/spec/internal/config/database.yml +3 -0
  38. data/spec/internal/config/routes.rb +3 -0
  39. data/spec/internal/db/schema.rb +7 -0
  40. data/spec/internal/log/.gitignore +1 -0
  41. data/spec/internal/public/favicon.ico +0 -0
  42. data/spec/spec_helper.rb +16 -0
  43. data/spec/unit/block_array_spec.rb +66 -0
  44. data/spec/unit/block_spec.rb +66 -0
  45. data/spec/unit/custom_block_spec.rb +19 -0
  46. data/spec/unit/has_sir_trevor_content_spec.rb +38 -0
  47. metadata +254 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: e0440542cac7ceda76800ef5d839ce166aea6a96
4
+ data.tar.gz: 63bfbecf7f48260f978fd284bf773ec1cc8287c2
5
+ SHA512:
6
+ metadata.gz: 41c835b01d6f5fd0bf4540ba2a3c65d3fcf70c43de7586ab3048fae21025bd05045c70c4afca5a9671dbbfe3a774e8e9f7a97dd9c3b97ff1840d7bf281135a3f
7
+ data.tar.gz: 7621bdbeae052096553e9af079169a8f600aef8e8733acfdf02e0b3f91618455c8a44b3bcec27a0eb382fbb55fd52b1cfc0d32c9cd6e3f4d3cdf3c19821b9013
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .DS_Store
3
+ Gemfile.lock
4
+ spec/internal/db/combustion_test.sqlite
data/CHANGELOG ADDED
@@ -0,0 +1,13 @@
1
+ v0.4.0:
2
+ date: 2014-05-20
3
+ changes:
4
+ - Renamed gem sir_trevor_rails (used to be sir-trevor-rails)
5
+ - Removed sir trevor JS and all its dependencies (should install files manually or from bower from now on)
6
+ - Removed all the view helpers appart from sir_trevor_markdown (render_sir_trevor, render_sir_trevor_block, render_sir_trevor_image, sir_trevor_image_tag, parse_sir_trevor are all gone)
7
+ - Removed the form helper (no more sir_trevor_text_area)
8
+ - Added has_sir_trevor_content.rb as a concern for models with ST content
9
+ - Remove jQuery rails dependency
10
+ - Use view resolvers and to_partial_path to render ST content (instead of the view helper)
11
+ - Add block array class
12
+ - Add block classes
13
+ - Add lookup methods on the block array
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in sir_trevor_rails.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013-2014 by ITV plc - http://www.itv.com
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,126 @@
1
+ # Sir Trevor Rails
2
+
3
+ A Rails gem for integrating Sir Trevor JS into your Rails 3/4 application.
4
+
5
+ ## Upgrade guide from v0.4.0-rc.1
6
+
7
+ Version 0.4.0 represents a major refactor and contains significant API changes.
8
+
9
+ * The SirTrevor gem has been renamed from ``sir-trevor-rails`` to ``sir_trevor_rails`` you will need to update your Gemfile.
10
+ * There are no more form helpers or view helpers so relace ``f.sir_trevor_text_area :content`` with ``f.text_area :content``.
11
+ * SirTrevor JS and it's dependencies are no longer bundled with the gem and need to be downloaded and installed manually or with bower. [See the SirTrevor JS repo for more](https://github.com/madebymany/sir-trevor-js#plain-js).
12
+ * In your model, register your SirTrevor content like this ``sir_trevor_content :content`` where ``:content`` is the name of the field on your where you store SirTrevor content.
13
+ * In your views, you no longer need to use the ``render_sir_trevor`` helper. Instead, simply render your content like this ``<%= render @item.content %>``
14
+
15
+ ## Usage
16
+
17
+ Add Sir Trevor to your Gemfile
18
+
19
+ ```ruby
20
+ gem 'sir_trevor_rails'
21
+ ```
22
+
23
+ ```bash
24
+ bundle install
25
+ ```
26
+
27
+ Include Sir Trevor JS in your project following the instructions set out [here](http://madebymany.github.io/sir-trevor-js/docs.html)
28
+
29
+ ## Generators: Views
30
+
31
+ Grab all of the default block type partials by running the following generator command:
32
+
33
+ ```bash
34
+ rails g sir_trevor_rails:views
35
+ ```
36
+
37
+ This will copy all of the SirTrevor block partials into `app/views/sir_trevor/blocks/`
38
+
39
+ ## Rendering
40
+
41
+ In your models pass the attribute name of your Sir Trevor content to `sir_trevor_content`
42
+
43
+ ```ruby
44
+ sir_trevor_content :content
45
+ ```
46
+
47
+ In your view files, call render to display the Sir Trevor content
48
+
49
+ ```ruby
50
+ <%= render @item.content %>
51
+ ```
52
+
53
+ ## Handling image uploads
54
+
55
+ We don't provide a default image uploader out of the box, because everyone will have different requirements. To see an example of an image uploader, please refer to our Rails examples in the [Sir Trevor JS repository](https://github.com/madebymany/sir-trevor-js/tree/master/examples/rails/image-uploader).
56
+
57
+ ## Handling markdown
58
+
59
+ Use the ``sir_trevor_markdown`` method in your custom block partials to correctly parse the markdown in a block
60
+
61
+ ## Querying the block content
62
+
63
+ Use the following methods to query the Sir Trevor content
64
+
65
+ ```ruby
66
+ @item.content.has_block_of_type?(:image)
67
+ ```
68
+
69
+ Does this content have an image block?
70
+
71
+ ```ruby
72
+ @item.content.first_block_of_type(:video)
73
+ ```
74
+
75
+ Return the first video block in the content
76
+
77
+ ## Add custom methods for block content
78
+
79
+ Create an initializer ``config/initializers/sir_trevor_rails.rb``
80
+
81
+ Write your method in the initializer:
82
+
83
+ ```ruby
84
+ class SirTrevorRails::BlockArray
85
+ def your_custom_method_here
86
+ # some code
87
+ end
88
+ end
89
+ ```
90
+
91
+ Call your method on the ST content
92
+
93
+ ```ruby
94
+ @item.content.your_custom_method
95
+ ```
96
+
97
+ ## Generators: Blocks
98
+
99
+ Run the blocks generator to create templates for your custom blocks
100
+
101
+ ```bash
102
+ rails g sir_trevor_rails:block my_custom_block
103
+ ```
104
+
105
+ This will generate an html file for rendering the block, a javascript file for the editor and a ruby block class.
106
+
107
+ ## Block Classes
108
+
109
+ Ruby block classes can be used like decorators for the block content. See the [tweet block class](https://github.com/madebymany/sir-trevor-rails/blob/redesign-gem/lib/sir_trevor_rails/blocks/tweet_block.rb) for an example
110
+
111
+ ## Requirements
112
+
113
+
114
+ - Rails 3.x/4.x
115
+
116
+ ## To do
117
+
118
+ - Add tests
119
+
120
+ ## Licence
121
+
122
+ Sir Trevor Rails is released under the [MIT Licence](MIT-LICENSE)
123
+
124
+ ## Changelog
125
+
126
+ See the [CHANGELOG](CHANGELOG)
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rake/testtask'
3
+
4
+ Rake::TestTask.new do |t|
5
+ t.libs << 'spec'
6
+ t.pattern = 'spec/**/*_spec.rb'
7
+ end
@@ -0,0 +1 @@
1
+ <%= render sir_trevor_block_array.to_a %>
@@ -0,0 +1 @@
1
+ <h2><%= heading_block.text %></h2>
@@ -0,0 +1,5 @@
1
+ <% if image_block.file && image_block.file[:url] -%>
2
+ <figure class="st__content-block st__content-block--image">
3
+ <%= image_tag image_block.file[:url] %>
4
+ </figure>
5
+ <% end -%>
@@ -0,0 +1,3 @@
1
+ <div class="st__content-block st__content-block--list">
2
+ <%= sir_trevor_markdown list_block.text %>
3
+ </div>
@@ -0,0 +1,13 @@
1
+ <div class="st__content-block st__content-block--quote">
2
+ <div class="quote">
3
+ <div class="quote__content">
4
+ <%= sir_trevor_markdown quote_block.text %>
5
+ </div>
6
+
7
+ <% if quote_block.cite.present? %>
8
+ <div class="quote__cite">
9
+ <cite class="quote__cite-text">&ndash; <%= quote_block.cite %></cite>
10
+ </div>
11
+ <% end %>
12
+ </div>
13
+ </div>
@@ -0,0 +1,3 @@
1
+ <div class="st__content-block st__content-block--text">
2
+ <%= sir_trevor_markdown text_block.text %>
3
+ </div>
@@ -0,0 +1,9 @@
1
+ <div class="st__content-block st__content-block--tweet">
2
+ <%= link_to image_tag(tweet_block.profile_image_url, class: 'img'), tweet_block.screen_name %>
3
+ <p>
4
+ <%= tweet_block.render_tweet_body %>
5
+ </p>
6
+ <cite>From <%= link_to tweet_block.at_name, tweet_block.screen_name %> on Twitter:</cite>
7
+ <time datetime="<%= tweet_block.created_at %>">(<%= link_to Time.parse(tweet_block.created_at), tweet_block.status_url %>)</time>
8
+ </div>
9
+
@@ -0,0 +1,4 @@
1
+ <div class="st__content-block st__content-block--video">
2
+ <iframe src="//player.vimeo.com/video/<%= vimeo.remote_id %>?title=1&amp;byline=1&amp;portrait=1&amp;autoplay=0"
3
+ width="640" height="360" frameborder="0" allowfullscreen></iframe>
4
+ </div>
@@ -0,0 +1,4 @@
1
+ <div class="st__content-block st__content-block--video">
2
+ <iframe src="//www.youtube.com/embed/<%= youtube.remote_id %>?wmode=transparent"
3
+ width="640" height="360" frameborder="0" allowfullscreen></iframe>
4
+ </div>
@@ -0,0 +1,12 @@
1
+ require 'active_model/validator'
2
+
3
+ class IsJsonValidator < ActiveModel::EachValidator
4
+ def validate_each(record, attribute, value)
5
+ @json = MultiJson.load(value, symbolize_keys: true)
6
+ record.errors.add(attribute, "is empty") if @json.empty?
7
+ rescue TypeError => e
8
+ record.errors.add(attribute, "is not valid JSON: #{e.message}")
9
+ rescue JSON::JSONError => e
10
+ record.errors.add(attribute, "is not valid JSON: #{e.message}")
11
+ end
12
+ end
data/config.ru ADDED
@@ -0,0 +1,7 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+
4
+ Bundler.require :default, :development
5
+
6
+ Combustion.initialize! :all
7
+ run Combustion::Application
@@ -0,0 +1,33 @@
1
+ require 'rails/generators'
2
+
3
+ module SirTrevorRails
4
+ module Generators
5
+ class BlockGenerator < Rails::Generators::NamedBase
6
+
7
+ def self.source_root
8
+ @source_root ||= File.join(File.dirname(__FILE__), 'templates')
9
+ end
10
+
11
+ def create_block
12
+
13
+ # Copy the JS
14
+ copy_file "_block.js", "app/assets/javascripts/sir_trevor/blocks/#{name}.js"
15
+
16
+ gsub_file "app/assets/javascripts/sir_trevor/blocks/#{name}.js", /SirTrevor\.Blocks\.Example/, "SirTrevor.Blocks.#{name.capitalize}"
17
+ gsub_file "app/assets/javascripts/sir_trevor/blocks/#{name}.js", /return "Example"/, "return: '#{name.capitalize}'"
18
+ gsub_file "app/assets/javascripts/sir_trevor/blocks/#{name}.js", /type: 'example'/, "type: '#{name.downcase}'"
19
+
20
+ # Copy the HTML
21
+ copy_file "_block.html.erb", "app/views/sir_trevor/blocks/_#{name}_block.html.erb"
22
+ gsub_file "app/views/sir_trevor/blocks/_#{name}_block.html.erb", /\s(-block)/, " #{name}-block"
23
+ gsub_file "app/views/sir_trevor/blocks/_#{name}_block.html.erb", /\s(_block)/, " #{name}_block"
24
+
25
+ # Copy the BlockDecorator
26
+ copy_file "_block.rb", "app/sir_trevor_blocks/#{name}_block.rb"
27
+ gsub_file "app/sir_trevor_blocks/#{name}_block.rb", /ExampleBlock/, " #{name}Block"
28
+
29
+ end
30
+
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,3 @@
1
+ <div class="content-block example-block">
2
+ <%= example_block %>
3
+ </div>
@@ -0,0 +1,203 @@
1
+ /*
2
+ An example of a SirTrevor.Block
3
+ --
4
+ Author: C J Bell @ madebymany
5
+ */
6
+
7
+ SirTrevor.Blocks.Example = (function(){
8
+
9
+ return SirTrevor.Block.extend({
10
+
11
+ // String; Names the block
12
+ // Note – please use underscores when naming
13
+ // Eg example_block should be ExampleBlock
14
+ type: 'example',
15
+
16
+ // Function; the title displayed in the toolbar
17
+ // Can return a translated string (if required)
18
+ title: function() {
19
+ // return i18n.t('blocks:example:title');
20
+ return "Example";
21
+ },
22
+
23
+ // Boolean; show this blockType of the toolbar
24
+ toolbarEnabled: true,
25
+
26
+ // Block Mixins
27
+ // Allow different UI components / methods to be mixed into the block
28
+
29
+ // Enable drop functionality on the block
30
+ droppable: false,
31
+
32
+ // Enable paste functionality (to paste URLS etc)
33
+ pastable: false,
34
+
35
+ // Enable an upload button to be added
36
+ // Mixins Ajaxable automatically
37
+ // Exposes an uploader method
38
+ // Usage: this.uploader(file, success, failure)
39
+ uploadable: false,
40
+
41
+ // Enable queued remote fetching
42
+ // Exposes a small wrapper around the $.ajax method
43
+ // Usage: this.fetch(ajaxOptions, success, failure)
44
+ fetchable: false,
45
+
46
+ // Add an ajax queue to the block
47
+ // Added to uploadable & fetchable automatically
48
+ ajaxable: false,
49
+
50
+ // Overwritable mixin options:
51
+ // --
52
+ drop_options: {
53
+ // String; (can use underscore template tags)
54
+ // Defines the HTML for the dropzone template
55
+ html: "<div class='st-block__dropzone'></div>",
56
+ // Boolean;
57
+ // On re-order, should we re-render this item.
58
+ // Useful for when re-ordering iframes (like Twitter)
59
+ re_render_on_reorder: false
60
+ },
61
+
62
+ paste_options: {
63
+ // String; (can use underscore template tags)
64
+ // Defines the HTML for the paste template
65
+ html: "<input type=\"text\" class=\"st-paste-block\">"
66
+ },
67
+
68
+ upload_options: {
69
+ // String; (can use underscore template tags)
70
+ // Defines the HTML for the upload template
71
+ html: "<input type=\"file\" type=\"st-file-upload\">"
72
+ },
73
+
74
+ formattable: true,
75
+
76
+ // String or Function; The HTML for the inner portion of the editor block
77
+ // In this example, the editorHTML is an editable input div (like we use for a TextBlock)
78
+
79
+ // Classes:
80
+ // st-required – indicates this input must be present to pass validation
81
+ // st-text-block – gives the block the ability to use the formatting controls
82
+
83
+ editorHTML: function() {
84
+ return "<div class='st-text-block' contenteditable='true'></div>";
85
+ },
86
+
87
+ // Element shorthands
88
+ // --
89
+ // this.$el
90
+ // this.el
91
+ // this.$inner (the inner container for the block)
92
+ // this.$editor (contains all the UI inputs for the block)
93
+ // this.$inputs (contains all the UI inputs for blocks that are uploadable / droppable / pastable)
94
+ // this.getTextBlock() (shorthand for this.$el.find('.st-text-block'))
95
+ // this.$(selector) (shorthand for this.$el.find(selector))
96
+
97
+ // Validations
98
+ // --
99
+ // Required fields (with .st-required class) always get validted
100
+ // Called using the validateField method
101
+ // Set a data-st-name="Field Name" on your required inputs to use it in the validation fail message
102
+
103
+ // Array; defines custom validator methods to call
104
+ validations: ['myCustomValidator'],
105
+
106
+ // Example custom validator
107
+ myCustomValidator: function() {
108
+ var field = this.$('.a-field');
109
+
110
+ if (field.val() === 'herp derp') {
111
+ this.setError(field, "A validation fail message");
112
+ }
113
+ },
114
+
115
+ // Function; Executed on render of the block if some data is provided.
116
+ // LoadData gives us a means to convert JSON data into the editor dom
117
+ // In this example we convert the text from markdown to HTML and show it inside the element
118
+ loadData: function(data){
119
+ this.getTextBlock().html(SirTrevor.toHTML(data.text, this.type));
120
+ },
121
+
122
+ // Function; Executed on save of the block, once the block is validated
123
+ // toData expects a way for the block to be transformed from inputs into structured data
124
+ // The default toData function provides a pretty comprehensive way of turning data into JSON
125
+ // In this example we take the text data and save it to the data object on the block
126
+ toData: function(){
127
+ var dataObj = {};
128
+
129
+ var content = this.getTextBlock().html();
130
+ if (content.length > 0) {
131
+ dataObj.text = SirTrevor.toMarkdown(content, this.type);
132
+ }
133
+
134
+ this.setData(dataObj);
135
+ },
136
+
137
+ // Function; Returns true or false whether there is data in the block
138
+ isEmpty: function() {
139
+ return _.isEmpty(this.saveAndGetData()); // Default implementation
140
+ },
141
+
142
+ // Other data functions
143
+ // --
144
+ // getData – returns the data in the store
145
+ // save - Invokes the toData method
146
+ // saveAndReturnData - Saves and returns the entire store
147
+ // saveAndGetData - Save and only return the data part of the store
148
+
149
+
150
+ // Function; Hook executed at the end of the block rendering method.
151
+ // Useful for initialising extra pieces of UI or binding extra events.
152
+ // In this example we add an extra button, just because.
153
+ onBlockRender: function() {
154
+ this.$editor.append($('<button>', {
155
+ click: function() {
156
+ alert('Yo dawg, you clicked my button');
157
+ }
158
+ }));
159
+ },
160
+
161
+ // Function; Optional hook method executed before the rendering of a block
162
+ // Beware, $el and any shorthand element variables won't be setup here.
163
+ beforeBlockRender: function() {},
164
+
165
+ // Function; Executed once content has been dropped onto the dropzone of this block
166
+ // Only required if you have enabled dropping and have provided a dropzone for this block
167
+ // Always is passed the ev.transferData object from the drop
168
+ // Please see the image block (https://github.com/madebymany/sir-trevor-js/blob/master/src/blocks/image.js) for an example
169
+ onDrop: function(transferData) {},
170
+
171
+ // Function; executed once content has been pasted into a pastable block
172
+ // See the tweet block as an example (https://github.com/madebymany/sir-trevor-js/blob/master/src/blocks/tweet.js)
173
+ onContentPasted: function(event) {},
174
+
175
+ // Block level messages
176
+ // --
177
+ // addMessage(msg, additionalClass)
178
+ // Adds a new message onto the block
179
+
180
+ // resetMessages()
181
+ // Clears all existing messages
182
+
183
+ // Helper methods
184
+ // --
185
+ // loading()
186
+ // ready()
187
+ // hasTextBlock()
188
+ // remove()
189
+
190
+ // Function; Any extra markdown parsing can be defined in here.
191
+ // Returns; String (Required)
192
+ toMarkdown: function(markdown) {
193
+ return markdown.replace(/^(.+)$/mg,"> $1");
194
+ },
195
+
196
+ // Function; Any extra HTML parsing can be defined in here.
197
+ // Returns; String (Required)
198
+ toHTML: function(html) {
199
+ return html;
200
+ }
201
+ });
202
+
203
+ })();
@@ -0,0 +1,2 @@
1
+ class ExampleBlock < SirTrevorRails::Block
2
+ end
@@ -0,0 +1,17 @@
1
+ require 'rails/generators'
2
+
3
+ module SirTrevorRails
4
+ module Generators
5
+ class ViewsGenerator < Rails::Generators::Base
6
+
7
+ def self.source_root
8
+ @source_root ||= SirTrevorRails::Engine.root
9
+ end
10
+
11
+ def views
12
+ directory "app/views/sir_trevor"
13
+ end
14
+
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,63 @@
1
+ require 'ostruct'
2
+
3
+ module SirTrevorRails
4
+ class Block < OpenStruct
5
+
6
+ def self.from_hash(hash, parent)
7
+ hash = hash.deep_dup
8
+ self.type_klass(hash).new(hash, parent)
9
+ end
10
+
11
+ def initialize(hash, parent)
12
+ @as_json = hash
13
+ @parent = parent
14
+ @type = hash[:type].to_sym
15
+
16
+ super(hash[:data])
17
+ end
18
+
19
+ attr_reader :parent, :type, :as_json
20
+
21
+ def to_partial_path
22
+ "sir_trevor/blocks/" << self.class.name.demodulize.underscore
23
+ end
24
+
25
+ private
26
+
27
+ # Infers the block class.
28
+ # Safe lookup that tries to identify user created block class.
29
+ #
30
+ # @param [Symbol] type
31
+ def self.block_class(type)
32
+ block_name = "#{type.to_s.camelize}Block"
33
+ begin
34
+ block_name.constantize
35
+ rescue NameError
36
+ block_class!(block_name)
37
+ end
38
+ end
39
+
40
+ # Infers the block class.
41
+ # Failover from block_class.
42
+ # Safe lookup against the SirTevor::Blocks namespace
43
+ # If no block is found, create one with given name and inherit from Block class
44
+ #
45
+ # @param [Constant] block_name
46
+ def self.block_class!(block_name)
47
+ begin
48
+ SirTrevorRails::Blocks.const_get(block_name)
49
+ rescue NameError
50
+ SirTrevorRails::Blocks.const_set(block_name, Class.new(Block))
51
+ end
52
+ end
53
+
54
+ def self.type_klass(hash)
55
+ if self == Block
56
+ block_class(hash[:type].to_sym)
57
+ else
58
+ self
59
+ end
60
+ end
61
+
62
+ end
63
+ end
@@ -0,0 +1,21 @@
1
+ module SirTrevorRails
2
+ class BlockArray < Array
3
+
4
+ def self.from_json(str, parent = nil)
5
+ blocks = MultiJson.load(str, symbolize_keys: true)
6
+ blocks = blocks[:data] if blocks.is_a?(Hash)
7
+ blocks.map! { |block_obj| SirTrevorRails::Block.from_hash(block_obj, parent) }
8
+ new blocks
9
+ end
10
+
11
+ def has_block_of_type?(type)
12
+ klass = Block.block_class(type)
13
+ any? { |b| b.is_a? klass }
14
+ end
15
+
16
+ def first_block_of_type(type)
17
+ klass = Block.block_class(type)
18
+ detect { |b| b.is_a? klass }
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,35 @@
1
+ require 'twitter-text'
2
+
3
+ module SirTrevorRails
4
+ module Blocks
5
+ class TweetBlock < SirTrevorRails::Block
6
+
7
+ include ActionView::Helpers::SanitizeHelper
8
+
9
+ def render_tweet_body
10
+ sanitize Twitter::Autolink.auto_link(
11
+ self.text,
12
+ url_entities: (self.entities.values_at(:urls, :media).flatten.compact.uniq rescue nil)
13
+ ), tags: %w{a span}, attributes: %w{class href rel target}
14
+ end
15
+
16
+ def profile_url
17
+ "//twitter.com/" << self.user[:screen_name]
18
+ end
19
+
20
+ def screen_name
21
+ self.user[:screen_name]
22
+ end
23
+
24
+ def at_name
25
+ "@" << screen_name
26
+ end
27
+
28
+ def profile_image_url(size="bigger")
29
+ "//twitter.com/api/users/profile_image/" << self.user[:screen_name] <<
30
+ "?size=" << size
31
+ end
32
+
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,9 @@
1
+ module SirTrevorRails
2
+ module Blocks
3
+ class VideoBlock < SirTrevorRails::Block
4
+ def to_partial_path
5
+ "sir_trevor/blocks/videos/" << self.source
6
+ end
7
+ end
8
+ end
9
+ end