caboose-cms 0.8.79 → 0.8.80

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: cbd447044fa644c9f566598042ea9b67b7f23faa
4
- data.tar.gz: 4cf0ab42e9c3abb072dbb4a6a738d8a1026b2292
3
+ metadata.gz: bd650e7422bd0162938f8d1478473b941330e299
4
+ data.tar.gz: b90ef95467affa299943c9d950b232f288944630
5
5
  SHA512:
6
- metadata.gz: 28d6a8ae3983ca9b3856ce3951878223c5789794c06d1aa949bf577513fa167e505852d5cd47e29e632127b3ef7e9099cb7204e5963e337d3b7418f800a7e354
7
- data.tar.gz: 7e958ad18045db7b8b6dadf7fca9e12b13ee00a59ad2784ad0335a182f9ba128f2b582f988fda26a885646e9daa9eb204dc7f90a30dca6a7e77ac0cbe8c33490
6
+ metadata.gz: 0410f10cb892116bdbe0b19746b11841dfcf1f21e2c16237f29815755353ff6588d954bc6f9cb047d3207d85043494ceb66c54fc3d91515465b226d16af19729
7
+ data.tar.gz: e07c5de3582548172e8b0fc9ac65fd3b35a19bfc8ac313849ca423c29509a92c11fa0e1b5d47becce4752e943f26173318088b9ae9fe3fbcc3512bacdbce88af
@@ -0,0 +1,157 @@
1
+
2
+ var AdminBlockTypeParserController = function(params) { this.init(params); };
3
+
4
+ AdminBlockTypeParserController.prototype = {
5
+
6
+ container: 'block_type_parser',
7
+ authenticity_token: false,
8
+ //original_html: "<div data-num='30' data-thumb='assets/minimalist-basic/thumbnails/p02.png' data-cat='0,13'>\n <div class='row clearfix'>\n <div class='column half'>\n <div class='display'>\n <h1>Beautiful content. Responsive.</h1>\n <p>Lorem Ipsum is simply dummy text.</p>\n <div style='margin:1em 0 2.5em;'>\n <a href='#' class='btn btn-primary edit'>Read More</a>\n </div>\n </div>\n </div>\n <div class='column half'>\n <img src='assets/minimalist-basic/p02-1.jpg'>\n </div>\n </div>\n</div>\n",
9
+ //original_html: "<div data-num='1' data-thumb='assets/minimalist-basic/thumbnails/a01.png' data-cat='1'>\n <div class='row clearfix'>\n <div class='column full'>\n <h1 class='size-96 is-title1-96 is-title-lite'>Lorem Ipsum</h1>\n </div>\n </div>\n</div>\n",
10
+ original_html: "" +
11
+ "<div data-num='30' data-thumb='assets/minimalist-basic/thumbnails/p02.png' data-cat='0,13'>\n" +
12
+ " <div class='row clearfix'>\n" +
13
+ " <div class='column half'>\n" +
14
+ " <div class='display'>\n" +
15
+ " <h1>Beautiful content. Responsive.</h1>\n" +
16
+ " <p>Lorem Ipsum is simply dummy text.</p>\n" +
17
+ " <div style='margin:1em 0 2.5em;'>\n" +
18
+ " <a href='#' class='btn btn-primary edit'>Read More</a>\n" +
19
+ " </div>\n" +
20
+ " </div>\n" +
21
+ " </div>\n" +
22
+ " <div class='column half'>\n" +
23
+ " <img src='assets/minimalist-basic/p02-1.jpg'>\n" +
24
+ " </div>\n" +
25
+ " </div>\n" +
26
+ "</div>\n",
27
+ parsable_tags: { heading: 'Headings' , richtext: 'Rich Text' , img: 'Images' , link: 'Links' },
28
+ tags_to_parse: { heading: true , richtext: true , img: true , link: true },
29
+ render_function: false,
30
+ children: false,
31
+
32
+ init: function(params) {
33
+ var that = this;
34
+ for (var i in params)
35
+ this[i] = params[i];
36
+
37
+ that.print_step1();
38
+ },
39
+
40
+ print_step1: function()
41
+ {
42
+ var that = this;
43
+
44
+ var tr = $('<tr/>');
45
+ var all_checked = true;
46
+ $.each(that.parsable_tags, function(tag, name) { if (!that.tags_to_parse[tag]) { all_checked = false; return false; }});
47
+ tr.append($('<td/>').append($('<input/>').attr('type', 'checkbox').attr('id', 'all').prop('checked', all_checked).click(function() {
48
+ var checked = $(this).is(':checked');
49
+ $.each(that.parsable_tags, function(tag, name) { $('#'+tag).prop('checked', checked); });
50
+ })))
51
+ .append($('<td/>').append($('<label/>').attr('for', 'all').append('All')));
52
+ $.each(that.parsable_tags, function(tag, name) {
53
+ tr.append($('<td/>').append($('<input/>').attr('type', 'checkbox').attr('id', tag).val('1').prop('checked', that.tags_to_parse[tag])))
54
+ .append($('<td/>').append($('<label/>').attr('for', tag).append(name)));
55
+ });
56
+ var tags_table = $('<table/>').append($('<tbody/>').append(tr));
57
+
58
+ var div = $('<div/>')
59
+ .append(tags_table)
60
+ .append($('<p/>').append($('<textarea/>').attr('id', 'html').css('width', '90%').css('height', '400px').attr('placeholder', 'HTML to Parse').html(that.original_html)))
61
+ .append($('<div/>').attr('id', 'message'))
62
+ .append($('<p/>').append($('<input/>').attr('type', 'button').val("Parse!").click(function() {
63
+ that.original_html = $('#html').val();
64
+ $.each(that.parsable_tags, function(tag, name) { that.tags_to_parse[tag] = $('#'+tag).is(':checked'); });
65
+ that.parse_tags();
66
+ })));
67
+ $('#'+that.container).empty().append(div);
68
+ },
69
+
70
+ parse_tags: function(show_json)
71
+ {
72
+ var that = this;
73
+
74
+ var tags = [];
75
+ $.each(that.tags_to_parse, function(tag, checked) { if (checked) tags.push(tag); });
76
+ $.ajax({
77
+ url: '/admin/block-types/parse-tags',
78
+ type: 'post',
79
+ data: {
80
+ html: that.original_html,
81
+ tags: tags,
82
+ children: that.children
83
+ },
84
+ success: function(resp) {
85
+ that.last_response = resp;
86
+ that.original_html = resp.original_html;
87
+ that.render_function = resp.render_function;
88
+ that.children = resp.children;
89
+ },
90
+ async: false
91
+ });
92
+
93
+ if (show_json)
94
+ {
95
+ $('#'+that.container).empty()
96
+ .append($('<textarea/>').attr('id', 'json').css('width', '90%').css('height', '400px').html(JSON.stringify(that.last_response)))
97
+ .append($('<p/>')
98
+ .append($('<input/>').attr('type', 'button').val("< Back to HTML").click(function() { that.print_step1(); })).append(' ')
99
+ .append($('<input/>').attr('type', 'button').val("Show Parsed").click(function() { that.parse_tags(); }))
100
+ );
101
+ return;
102
+ }
103
+
104
+ var tbody = $('<tbody/>')
105
+ .append($('<tr/>')
106
+ .append($('<th/>').append('Field Type'))
107
+ .append($('<th/>').append('Name'))
108
+ .append($('<th/>').append('Description'))
109
+ .append($('<th/>').append('Default Value'))
110
+ .append($('<th/>').attr('colspan', '2').append('Child Values'))
111
+ );
112
+
113
+ var field_types = {
114
+ heading: 'Heading',
115
+ image2: 'Image',
116
+ button: 'Link',
117
+ richtext: 'Rich Text'
118
+ };
119
+ $.each(that.children, function(i, v) {
120
+
121
+ var tr = $('<tr/>')
122
+ .append(field_types[v.field_type])
123
+ .append($('<td/>').attr('valign', 'top').append($('<input/>').data('i', i).val(v.name ).on('keyup', function(e) { var x = $(this).val().toLowerCase().replace(' ', '_'); $(this).val(x); that.children[parseInt($(this).data('i'))].name = x; })))
124
+ .append($('<td/>').attr('valign', 'top').append($('<input/>').data('i', i).val(v.description ).on('keyup', function(e) { that.children[parseInt($(this).data('i'))].description = $(this).val(); })))
125
+ .append($('<td/>').attr('valign', 'top').append($('<input/>').data('i', i).val(v.default ).on('keyup', function(e) { that.children[parseInt($(this).data('i'))].default = $(this).val(); })));
126
+
127
+ if (v.child_values)
128
+ {
129
+ j = 0;
130
+ $.each(v.child_values, function(k,v) {
131
+ if (j > 0)
132
+ tr.append($('<td/>').attr('colspan', '4').html("&nbsp;"));
133
+ tr.append($('<td/>').attr('align', 'right').append(k))
134
+ .append($('<td/>').append($('<input/>').data('i', i).data('k', k).val(v).on('keyup', function(e) { that.children[parseInt($(this).data('i'))].child_values[$(this).data('k')] = $(this).val(); })));
135
+ tbody.append(tr);
136
+ tr = $('<tr/>');
137
+ j++;
138
+ });
139
+ }
140
+ else
141
+ tbody.append(tr);
142
+ });
143
+ var vars_table = $('<table/>').append(tbody);
144
+
145
+ $('#'+that.container).empty()
146
+ .append(vars_table)
147
+ .append($('<textarea/>').attr('id', 'parsed').css('width', '90%').css('height', '400px').html(that.render_function))
148
+ .append($('<p/>')
149
+ .append($('<input/>').attr('type', 'button').val("< Back to HTML").click(function() { that.print_step1(); })).append(' ')
150
+ .append($('<input/>').attr('type', 'button').val("Re-parse with Updated Variables").click(function() { that.parse_tags(); })).append(' ')
151
+ .append($('<input/>').attr('type', 'button').val("Show JSON").click(function() { that.parse_tags(true); }))
152
+ );
153
+ },
154
+ };
155
+
156
+
157
+
@@ -47,6 +47,20 @@ module Caboose
47
47
  block_type = BlockType.find(params[:id])
48
48
  render :json => block_type.as_json(:include => :sites)
49
49
  end
50
+
51
+ # @route GET /admin/block-types/parse
52
+ def admin_parse_form
53
+ return if !user_is_allowed('pages', 'view')
54
+ render :layout => 'caboose/admin'
55
+ end
56
+
57
+ # @route POST /admin/block-types/parse-tags
58
+ def admin_parse_tags
59
+ return if !user_is_allowed('pages', 'view')
60
+ children = params[:children] && params[:children] != 'false' ? params[:children] : nil
61
+ resp = BlockTypeParser.parse_html(params[:html], params[:tags], children)
62
+ render :json => resp
63
+ end
50
64
 
51
65
  # @route GET /admin/block-types/new
52
66
  # @route GET /admin/block-types/:id/new
@@ -0,0 +1,211 @@
1
+ require 'nokogiri'
2
+ require 'nokogiri-styles'
3
+
4
+ module Caboose
5
+ class BlockTypeParser
6
+
7
+ def BlockTypeParser.parse_html(str, tags, children = nil)
8
+
9
+ doc = Nokogiri::HTML.fragment(str)
10
+ doc.children.first.set_attribute('id', "block_<%= block.id %>")
11
+
12
+ count = 0
13
+ rf_header = []
14
+ rf_body = "#{doc.to_html}"
15
+ new_children = []
16
+ tags.each do |tag|
17
+ case tag
18
+ when 'heading'
19
+
20
+ headings = doc.search('h1') + doc.search('h2') + doc.search('h3') + doc.search('h4') + doc.search('h5') + doc.search('h6')
21
+ headings.each_with_index do |h, i|
22
+
23
+ info = children ? (children[count] ? children[count] : (children[count.to_s] ? children[count.to_s] : nil)) : nil
24
+ description = info && info['description'] ? info['description'] : "#{(i+1).ordinalize} Heading"
25
+ name = info && info['name'] ? info['name'] : description.downcase.gsub(' ', '_')
26
+
27
+ cv = StdClass.new
28
+ cv.heading_text = h.text
29
+ cv.size = h.name.gsub('h','').to_i
30
+ cv.align = h.attributes['align'].to_s if h.attributes['align']
31
+ cv.extra_classes = h.attributes['class'].to_s if h.attributes['class']
32
+ if h['style']
33
+ cv.align = h.styles['text-align'] if h.styles['text-align']
34
+ cv.color = h.styles['color'] if h.styles['color']
35
+ cv.margin_bottom = h.styles['margin-bottom'] if h.styles['margin-bottom']
36
+ cv.margin_top = h.styles['margin-top'] if h.styles['margin-top']
37
+ cv.underline = true if h.styles['text-decoration']
38
+ end
39
+
40
+ v = StdClass.new({
41
+ :name => name,
42
+ :description => description,
43
+ :field_type => 'heading',
44
+ :child_values => cv
45
+ })
46
+
47
+ rf_body.gsub!(h.to_s, "<%= block.render('#{name}') %>")
48
+ new_children << v
49
+
50
+ count = count + 1
51
+ end
52
+
53
+ when 'link'
54
+
55
+ links = doc.search('a')
56
+ links.each_with_index do |link, i|
57
+
58
+ info = children ? (children[count] ? children[count] : (children[count.to_s] ? children[count.to_s] : nil)) : nil
59
+ description = info && info['description'] ? info['description'] : "#{(i+1).ordinalize} Link"
60
+ name = info && info['name'] ? info['name'] : description.downcase.gsub(' ', '_')
61
+
62
+ cv = StdClass.new
63
+ cv.text = link.text
64
+ cv.align = link.attributes['align' ].to_s if link.attributes['align' ]
65
+ cv.target = link.attributes['target' ].to_s if link.attributes['target' ]
66
+ cv.url = link.attributes['href' ].to_s if link.attributes['href' ]
67
+ cv.extra_classes = link.attributes['class' ].to_s if link.attributes['class' ]
68
+ if link['style']
69
+ cv.align = link.styles['text-align' ] if link.styles['text-align' ]
70
+ cv.color = link.styles['color' ] if link.styles['color' ]
71
+ cv.margin = link.styles['margin' ] if link.styles['margin-bottom' ]
72
+ cv.margin_top = link.styles['margin-top' ] if link.styles['margin-top' ]
73
+ cv.margin_bottom = link.styles['margin-bottom'] if link.styles['margin-bottom' ]
74
+ cv.margin_left = link.styles['margin-left' ] if link.styles['margin-left' ]
75
+ cv.margin_right = link.styles['margin-right' ] if link.styles['margin-right' ]
76
+ end
77
+
78
+ v = StdClass.new({
79
+ :name => name,
80
+ :description => description,
81
+ :field_type => 'button',
82
+ :child_values => cv
83
+ })
84
+
85
+ rf_body.gsub!(link.to_s, "<%= block.render('#{name}') %>")
86
+ new_children << v
87
+
88
+ count = count + 1
89
+ end
90
+
91
+ when 'richtext'
92
+
93
+ paragraphs = doc.search('p')
94
+ paragraphs.each_with_index do |p, i|
95
+
96
+ info = children ? (children[count] ? children[count] : (children[count.to_s] ? children[count.to_s] : nil)) : nil
97
+ description = info && info['description'] ? info['description'] : "#{(i+1).ordinalize} Richtext"
98
+ name = info && info['name'] ? info['name'] : description.downcase.gsub(' ', '_')
99
+
100
+ v = StdClass.new({
101
+ :name => name,
102
+ :description => description,
103
+ :field_type => 'richtext',
104
+ :default => p.text
105
+ })
106
+
107
+ rf_body.gsub!(p.to_s, "<%= block.render('#{name}') %>")
108
+ new_children << v
109
+
110
+ count = count + 1
111
+ end
112
+
113
+ when 'img'
114
+
115
+ images = doc.search('img')
116
+ images.each_with_index do |img, i|
117
+
118
+ info = children ? (children[count] ? children[count] : (children[count.to_s] ? children[count.to_s] : nil)) : nil
119
+ description = info && info['description'] ? info['description'] : "#{(i+1).ordinalize} Image"
120
+ name = info && info['name'] ? info['name'] : description.downcase.gsub(' ', '_')
121
+
122
+ cv = StdClass.new
123
+ cv.image_src = img.attributes['src' ].to_s
124
+ cv.alt_text = img.attributes['alt' ].to_s if img.attributes['alt' ]
125
+ cv.width = img.attributes['width' ].to_s if img.attributes['width' ]
126
+ cv.height = img.attributes['height' ].to_s if img.attributes['height' ]
127
+ cv.width = img.styles['width' ] if img.styles['width' ]
128
+ cv.height = img.styles['height' ] if img.styles['height' ]
129
+ cv.align = img.styles['float' ] if img.styles['float' ]
130
+ cv.margin_bottom = img.styles['margin-bottom' ] if img.styles['margin-bottom' ]
131
+ cv.margin_left = img.styles['margin-left' ] if img.styles['margin-left' ]
132
+ cv.margin_right = img.styles['margin-right' ] if img.styles['margin-right' ]
133
+ cv.margin_top = img.styles['margin-top' ] if img.styles['margin-top' ]
134
+
135
+ Caboose.log(cv)
136
+
137
+ v = StdClass.new({
138
+ :name => name,
139
+ :description => description,
140
+ :field_type => 'image2',
141
+ :child_values => cv
142
+ })
143
+
144
+ rf_body.gsub!(img.to_s, "<%= block.render('#{name}') %>")
145
+ new_children << v
146
+
147
+ count = count + 1
148
+ end
149
+
150
+ end
151
+ end
152
+
153
+ render_function = ""
154
+ render_function << "<%\n#{rf_header.join("\n")}\n%>\n" if rf_header.count > 0
155
+ render_function << rf_body
156
+
157
+ return {
158
+ :original_html => str,
159
+ :render_function => render_function,
160
+ :children => new_children
161
+ }
162
+ end
163
+
164
+ def BlockTypeParser.parse(str)
165
+
166
+ vars = {}
167
+ pattern = /<%= \|(.*?)\| %>/
168
+ new_lines = []
169
+ lines = str.split("\n")
170
+ lines.each do |line|
171
+ matches = line.to_enum(:scan, pattern).map{$&}
172
+ if matches
173
+ matches.each do |match|
174
+ next if match.nil? || match.length == 0
175
+ arr = match[5..-5].split('|')
176
+
177
+ name = arr.count > 0 ? arr[0] : nil
178
+ description = arr.count > 1 ? arr[1] : nil
179
+ field_type = arr.count > 2 ? arr[2] : nil
180
+ default = arr.count > 3 ? arr[3] : nil
181
+ default = default && ((default.starts_with?('"') && default.ends_with?('"')) || (default.starts_with?("'") && default.ends_with?("'"))) ? default[1..-2] : nil
182
+
183
+ if vars[name.to_sym].nil?
184
+ vars[name.to_sym] = StdClass.new({
185
+ :name => name ,
186
+ :description => description ,
187
+ :field_type => field_type ,
188
+ :default => default
189
+ })
190
+ end
191
+ line.gsub!(match, "<%= #{name} %>")
192
+ end
193
+ end
194
+ new_lines << line
195
+ end
196
+
197
+ str2 = "<%\n"
198
+ vars.each do |k,var|
199
+ str2 << "#{var.name} = block.child_value('#{var.name}')\n"
200
+ end
201
+ str2 << "\n"
202
+ vars.each do |k,var|
203
+ str2 << "#{var.name} = \"#{var.default.gsub('"', '\"')}\" if #{var.name}.nil? || #{var.name}.length == 0\n" if var.default
204
+ end
205
+ str2 << "%>\n"
206
+ str2 << new_lines.join("\n")
207
+ return str2
208
+ end
209
+
210
+ end
211
+ end
@@ -4,7 +4,12 @@
4
4
  </div>
5
5
 
6
6
  <h1>Block Types</h1>
7
+
8
+ <!--
7
9
  <p><a href='/admin/block-types/store'>Block Type Store</a></p>
10
+ -->
11
+ <p><a href='/admin/block-types/parse'>Block Type Parser</a></p>
12
+
8
13
  <div id='block_types'></div>
9
14
  <% (0..100).each do |i| %><p>&nbsp;</p><% end %>
10
15
 
@@ -0,0 +1,35 @@
1
+ <div id='crumbtrail'>
2
+ <a href='/admin'>Admin</a> >
3
+ <a href='/admin/block-types'>Block Types</a> >
4
+ Parser
5
+ </div>
6
+
7
+ <h1>Block Type Parser</h1>
8
+ <p>
9
+ <a href='/admin/block-types'>Block Types List</a> |
10
+ <a href='/admin/block-types/parse'>Parser</a>
11
+ </p>
12
+
13
+ <div id='block_type_parser'></div>
14
+
15
+ <% content_for :caboose_js do %>
16
+ <%= javascript_include_tag 'caboose/model/all' %>
17
+ <%= javascript_include_tag 'caboose/admin_block_type_parser_controller' %>
18
+ <script type='text/javascript'>
19
+
20
+ var controller = false;
21
+ $(document).ready(function() {
22
+ controller = new AdminBlockTypeParserController({
23
+ form_authenticity_token: '<%= form_authenticity_token %>'
24
+ });
25
+ });
26
+
27
+ </script>
28
+ <% end %>
29
+ <% content_for :caboose_css do %>
30
+ <style type='text/css'>
31
+
32
+ textarea { font-family: Courier; font-size: 10pt; white-space: pre; overflow-wrap: normal; overflow-x: scroll; }
33
+
34
+ </style>
35
+ <% end %>
@@ -1,3 +1,3 @@
1
1
  module Caboose
2
- VERSION = '0.8.79'
2
+ VERSION = '0.8.80'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: caboose-cms
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.79
4
+ version: 0.8.80
5
5
  platform: ruby
6
6
  authors:
7
7
  - William Barry
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-10-14 00:00:00.000000000 Z
11
+ date: 2016-10-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: pg
@@ -220,6 +220,20 @@ dependencies:
220
220
  - - ">="
221
221
  - !ruby/object:Gem::Version
222
222
  version: '0'
223
+ - !ruby/object:Gem::Dependency
224
+ name: nokogiri-styles
225
+ requirement: !ruby/object:Gem::Requirement
226
+ requirements:
227
+ - - ">="
228
+ - !ruby/object:Gem::Version
229
+ version: '0'
230
+ type: :runtime
231
+ prerelease: false
232
+ version_requirements: !ruby/object:Gem::Requirement
233
+ requirements:
234
+ - - ">="
235
+ - !ruby/object:Gem::Version
236
+ version: '0'
223
237
  - !ruby/object:Gem::Dependency
224
238
  name: delayed_job_active_record
225
239
  requirement: !ruby/object:Gem::Requirement
@@ -513,6 +527,7 @@ files:
513
527
  - app/assets/images/caboose/search.png
514
528
  - app/assets/javascripts/caboose/admin.js
515
529
  - app/assets/javascripts/caboose/admin_block_edit.js
530
+ - app/assets/javascripts/caboose/admin_block_type_parser_controller.js
516
531
  - app/assets/javascripts/caboose/admin_edit_invoice.js
517
532
  - app/assets/javascripts/caboose/admin_edit_modifications.js
518
533
  - app/assets/javascripts/caboose/admin_main.js
@@ -841,6 +856,7 @@ files:
841
856
  - app/models/caboose/block_type.rb
842
857
  - app/models/caboose/block_type_category.rb
843
858
  - app/models/caboose/block_type_icons.rb
859
+ - app/models/caboose/block_type_parser.rb
844
860
  - app/models/caboose/block_type_site_membership.rb
845
861
  - app/models/caboose/block_type_source.rb
846
862
  - app/models/caboose/block_type_summary.rb
@@ -956,6 +972,7 @@ files:
956
972
  - app/views/caboose/block_types/admin_edit_icon.html.erb
957
973
  - app/views/caboose/block_types/admin_index.html.erb
958
974
  - app/views/caboose/block_types/admin_new.html.erb
975
+ - app/views/caboose/block_types/admin_parse_form.html.erb
959
976
  - app/views/caboose/blocks/_block.html.erb
960
977
  - app/views/caboose/blocks/_checkbox.html.erb
961
978
  - app/views/caboose/blocks/_controller_view_content.html.erb