html_slicer 0.0.7 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,3 +1,9 @@
1
+ == 0.1.0
2
+
3
+ * The big changes. :)
4
+ * Code has been optimized and rewritten by ~70%.
5
+ * Caching option provided.
6
+
1
7
  == 0.0.7
2
8
 
3
9
  * Code refactoring.
data/README.rdoc CHANGED
@@ -65,6 +65,7 @@ where:
65
65
  * <tt>:as</tt> is a name of basic accessor for result.
66
66
  * <tt>:slice</tt> is a hash of <tt>slicing options</tt> as a part of configuration.
67
67
  * <tt>:resize</tt> is a hash of <tt>resizing options</tt> as a part of configuration.
68
+ * <tt>:cache_to</tt> is an accessor name used to store the cache. +True+ value make it by default.
68
69
 
69
70
  You can define any configuration key you want. Otherwise, default configuration options (if available) will be picked up automatically.
70
71
 
@@ -198,7 +199,7 @@ you can override/complete any configuration.
198
199
  By applying +:config+ key you can use one of stylized configurations:
199
200
 
200
201
  class Post < ActiveRecord::Base
201
- slice :content, :config => :paged, :slice = {:complete => /\s+/, :maximum => 3000}
202
+ slice :content, :config => :paged, :slice => {:complete => /\s+/, :maximum => 3000}
202
203
  end
203
204
 
204
205
  Through passing the block you get a more flexible approach to configure slicer:
@@ -304,6 +305,52 @@ Examples:
304
305
  :param_name => [:article, :page]
305
306
  # means you define params[:article][:page] as a slice key.
306
307
 
308
+ == Caching
309
+
310
+ Caching implies that resizing/slicing procedures is both time-consuming processes will be started only at once, and once again will be launched only if the target content has been changed or resizing/slicing options has been modified.
311
+
312
+ For caching, pass the option: <tt>:cache_to => true</tt> or <tt>:cache_to => :any_other_accessor</tt> within your config definition.
313
+
314
+ === ActiveRecord model
315
+
316
+ Example:
317
+
318
+ class Article < ActiveRecord::Base
319
+ slice :content, :as => :paged, :slice => {:maximum => 1000, :complete => /\s+|\z/}, :cache_to => :content_page_cache
320
+ end
321
+
322
+ Accessor method <tt>.content_page_cache=</tt> used for caching here.
323
+ The first time when resizing and slicing procedures is called, generated maps will be cached and assigned to <tt>.content_page_cache</tt> accessor. Before the article saves itself, assigned dump stuff is recorded like any other attribute of article (callback <tt>before_save</tt> is set up).
324
+
325
+ Of course, attribute is recorded only as a column of the database :), So, before, add the column to a model:
326
+
327
+ <tt>% rails generate migration AddContentPageCacheToArticle content_page_cache:text</tt>
328
+
329
+ <tt>% rake db:migrate </tt>
330
+
331
+ Slicing/resizing procedures repeat again only if target content has been changed or options has been modified.
332
+
333
+ === ActiveModel
334
+
335
+ Example:
336
+
337
+ class TextModel
338
+ attr_accessor :text, :paged_cache
339
+
340
+ extend HtmlSlicer::Installer
341
+
342
+ slice :text, :as => :paged, :slice => {:complete => /\s+/, :maximum => 300}, :cache_to => true
343
+
344
+ def initialize(text)
345
+ @text = text
346
+ end
347
+
348
+ end
349
+
350
+ +True+ value of <tt>:cache_to</tt> option set default cache accessor name consisted of basic accessor name + <tt>_page</tt>.
351
+
352
+ In fact, caching ActiveModel not so significant in most cases, but still works. The next time you call slicing method, the cached resizing/slicing map(s) will be used.
353
+
307
354
  == More
308
355
 
309
356
  === Slicing a general String or ActiveModel (or any other) object
@@ -0,0 +1,70 @@
1
+ require 'digest/sha1'
2
+
3
+ module HtmlSlicer
4
+ # Object to be serialized and dumped as cache storage.
5
+ # Include +resizing+ and +slicing+ objects, and original text's hexdigest hash value to provide authenticity.
6
+ # During the runtime object is used as an +maps+ accessor too.
7
+
8
+ class CachedStuff
9
+ attr_reader :hexdigest, :resizing, :slicing
10
+ attr_accessor :changed, :time
11
+
12
+ def initialize(text = nil)
13
+ @changed = false
14
+ self.hexdigest_for = text if text
15
+ end
16
+
17
+ def hexdigest_for=(text)
18
+ hex = Digest::SHA1.hexdigest(text)
19
+ unless hex == @hexdigest
20
+ @changed = true
21
+ @hexdigest = hex
22
+ end
23
+ hex
24
+ end
25
+
26
+ def slicing=(object)
27
+ case object
28
+ when HtmlSlicer::Mappers::Slicing, nil then
29
+ @changed = true unless object.try(:options).try(:hexdigest) == @slicing.try(:options).try(:hexdigest)
30
+ @slicing = object
31
+ else
32
+ raise(TypeError, "HtmlSlicer::Mappers::Slicing or nil expected, '#{object.class}' passed")
33
+ end
34
+ end
35
+
36
+ def resizing=(object)
37
+ case object
38
+ when HtmlSlicer::Mappers::Resizing, nil then
39
+ @changed = true unless object.try(:options).try(:hexdigest) == @slicing.try(:options).try(:hexdigest)
40
+ @resizing = object
41
+ else
42
+ raise(TypeError, "HtmlSlicer::Mappers::Resizing or nil expected, '#{object.class}' passed")
43
+ end
44
+ end
45
+
46
+ def valid_text?(text)
47
+ Digest::SHA1.hexdigest(text) == @hexdigest
48
+ end
49
+
50
+ def valid_resizing_options?(options)
51
+ options.try(:hexdigest) == @resizing.try(:options).try(:hexdigest)
52
+ end
53
+
54
+ def valid_slicing_options?(options)
55
+ options.try(:hexdigest) == @slicing.try(:options).try(:hexdigest)
56
+ end
57
+
58
+ def changed?
59
+ @changed
60
+ end
61
+
62
+ # Serialize self, using Marshal and Base64 encoding
63
+ def to_dump
64
+ @time = Time.now
65
+ Base64.encode64(Marshal.dump(self))
66
+ end
67
+
68
+ end
69
+
70
+ end
@@ -39,7 +39,7 @@ module HtmlSlicer
39
39
 
40
40
  # Config accessor for HtmlSlicer. Accepts argument as a +style+.
41
41
  def self.config(style = nil)
42
- eval("@config#{"_#{style}" if style}")
42
+ eval("@config#{"_#{style}" if style}") || raise("Config style '#{style}' is invalid.")
43
43
  end
44
44
 
45
45
  # need a Class for 3.0
@@ -57,6 +57,7 @@ module HtmlSlicer
57
57
  config_accessor :left
58
58
  config_accessor :right
59
59
  config_accessor :param_name
60
+ config_accessor :cache_to
60
61
 
61
62
  def slice # Ugly coding. Override Hash::slice method
62
63
  config[:slice]
@@ -105,12 +105,18 @@ module HtmlSlicer
105
105
  end
106
106
  end
107
107
  method_name = config.as||"#{attr_name}_slice"
108
- class_exec do
108
+ config.cache_to = "#{method_name}_cache" if config.cache_to == true
109
+ class_eval do
109
110
  define_method method_name do
110
111
  var_name = "@_#{method_name}"
111
112
  instance_variable_get(var_name)||instance_variable_set(var_name, HtmlSlicer::Interface.new(self, attr_name, config.config))
112
113
  end
113
114
  end
115
+ if config.cache_to && self.superclass == ActiveRecord::Base
116
+ before_save do
117
+ send(method_name).load!
118
+ end
119
+ end
114
120
  end
115
121
 
116
122
  end
@@ -1,3 +1,9 @@
1
+ require 'html_slicer/options'
2
+ require 'html_slicer/processor'
3
+ require 'html_slicer/cached_stuff'
4
+ require 'html_slicer/mappers/slicing'
5
+ require 'html_slicer/mappers/resizing'
6
+
1
7
  module HtmlSlicer
2
8
 
3
9
  # Interface code.
@@ -10,17 +16,75 @@ module HtmlSlicer
10
16
  #
11
17
 
12
18
  class Interface # General accessor instance
13
- attr_reader :options, :current_slice, :document
14
-
15
- delegate :sliced?, :resized?, :slice_number, :to => :document
16
-
19
+ include HtmlSlicer::Mappers
20
+
21
+ attr_reader :options, :document, :current_slice, :cached_stuff
22
+
23
+ delegate :slicing, :resizing, :to => :cached_stuff
24
+
17
25
  def initialize(env, method_name, options = {})
26
+ @env, @method_name = env, method_name
18
27
  @options = options
19
- @document = Document.new(env, method_name, options)
28
+ @resizing_options = ResizingOptions.new(options[:resize]) if options[:resize]
29
+ @slicing_options = SlicingOptions.new(options[:slice]) if options[:slice]
20
30
  @current_slice = 1
31
+ load!
32
+ end
33
+
34
+ # Getting source content
35
+ def source
36
+ case options[:processors].present?
37
+ when true then HtmlSlicer::Process.iterate(@env.send(@method_name), options[:processors])
38
+ else
39
+ @env.send(@method_name)
40
+ end
21
41
  end
22
42
 
23
- # General slicing method. Passing the argument changes the slice.
43
+ # Process initializer
44
+ def load!
45
+ text = source
46
+ @cached_stuff ||=
47
+ begin
48
+ if options[:cache_to] # Getting recorded hash dump
49
+ Marshal.load(Base64.decode64(@env.send(options[:cache_to])))
50
+ else
51
+ raise Exception
52
+ end
53
+ rescue Exception, TypeError, NoMethodError # New cache object otherwise
54
+ CachedStuff.new
55
+ end
56
+ if @document.blank? || !@cached_stuff.valid_text?(text) # Initialize new @document if not exist or content has been changed
57
+ @document = HTML::Document.new(text)
58
+ @cached_stuff.hexdigest_for = text
59
+ end
60
+ if @cached_stuff.changed? || !@cached_stuff.valid_resizing_options?(@resizing_options) # Initialize new resizing process if the content or options has been changed
61
+ if @resizing_options
62
+ @cached_stuff.resizing = Resizing.new(@document, @resizing_options)
63
+ else
64
+ @cached_stuff.resizing = nil
65
+ end
66
+ end
67
+ if @cached_stuff.changed? || !@cached_stuff.valid_slicing_options?(@slicing_options) # Initialize new slicing process if the content or options has been changed
68
+ if @slicing_options
69
+ @cached_stuff.slicing = Slicing.new(@document, @slicing_options)
70
+ else
71
+ @cached_stuff.slicing = nil
72
+ end
73
+ end
74
+ if @cached_stuff.changed? # Serialize and dump the cache if any changes provided
75
+ @cached_stuff.changed = false
76
+ if options[:cache_to]
77
+ @env.send("#{options[:cache_to]}=", @cached_stuff.to_dump)
78
+ end
79
+ end
80
+ end
81
+
82
+ # Return number of slices.
83
+ def slice_number
84
+ sliced? ? slicing.slice_number : 1
85
+ end
86
+
87
+ # General slicing method. Passing the argument changes the +current_slice+.
24
88
  def slice!(slice = nil)
25
89
  raise(Exception, "Slicing unavailable!") unless sliced?
26
90
  if slice.present?
@@ -32,10 +96,10 @@ module HtmlSlicer
32
96
  end
33
97
  self
34
98
  end
35
-
36
- # Textual representation according to a current slice.
99
+
37
100
  def to_s
38
- document.to_s(current_slice)
101
+ load!
102
+ view(document.root, @current_slice)
39
103
  end
40
104
 
41
105
  def inspect
@@ -45,10 +109,66 @@ module HtmlSlicer
45
109
  def method_missing(*args, &block)
46
110
  to_s.send(*args, &block)
47
111
  end
112
+
113
+ # True if any HTML tag has been resized
114
+ def resized?
115
+ resizing ? resizing.map.any? : false
116
+ end
48
117
 
118
+ # True if any part of document has been sliced
119
+ def sliced?
120
+ slicing ? slicing.map.any? : false
121
+ end
122
+
49
123
  # Return the current slice is a last or not?
50
124
  def last_slice?
51
125
  current_slice == slice_number
126
+ end
127
+
128
+ private
129
+
130
+ # Return a textual representation of the node including all children.
131
+ def view(node, slice)
132
+ slice = slice.to_i
133
+ case node
134
+ when HTML::Tag then
135
+ children_view = node.children.collect {|child| view(child, slice)}.compact.join
136
+ if resized?
137
+ resizing.resize_node(node)
138
+ end
139
+ if sliced?
140
+ if slicing.map.get(node, slice) || children_view.present?
141
+ if node.closing == :close
142
+ "</#{node.name}>"
143
+ else
144
+ s = "<#{node.name}"
145
+ node.attributes.each do |k,v|
146
+ s << " #{k}"
147
+ s << "=\"#{v}\"" if String === v
148
+ end
149
+ s << " /" if node.closing == :self
150
+ s << ">"
151
+ s += children_view
152
+ s << "</#{node.name}>" if node.closing != :self && !node.children.empty?
153
+ s
154
+ end
155
+ end
156
+ else
157
+ node.to_s
158
+ end
159
+ when HTML::Text then
160
+ if sliced?
161
+ if range = slicing.map.get(node, slice)
162
+ "#{node.content[Range.new(*range)]}#{slicing.options.text_break unless range.last == -1}"
163
+ end
164
+ else
165
+ node.to_s
166
+ end
167
+ when HTML::CDATA then
168
+ node.to_s
169
+ when HTML::Node then
170
+ node.children.collect {|child| view(child, slice)}.compact.join
171
+ end
52
172
  end
53
173
 
54
174
  end
@@ -1,17 +1,38 @@
1
1
  module HtmlSlicer
2
- module Makers
2
+ module Mappers
3
3
 
4
- class Resizing # Resizing engine
5
- attr_reader :options
6
-
7
- def initialize(document, options = {})
4
+ class Resizing # Resizing engine, generate and store slicing Map (hash)
5
+ attr_reader :options, :map
6
+
7
+ class Map < Hash #:nodoc:
8
+ include HtmlSlicer::Utilities::NodeIdent
9
+
10
+ def commit(node, width, height)
11
+ self[node_identify(node)] = [width, height]
12
+ end
13
+ def width(node)
14
+ self[node_identify(node)].try(:first)
15
+ end
16
+ def height(node)
17
+ self[node_identify(node)].try(:last)
18
+ end
19
+ end
20
+
21
+ def initialize(document, options)
8
22
  raise(TypeError, "HTML::Document expected, '#{document.class}' passed") unless document.is_a?(HTML::Document)
9
- @options = ResizeOptions.new(options)
10
- resize_document!(document.root)
23
+ raise(TypeError, "HtmlSlicer::Options expected, '#{options.class}' passed") unless options.is_a?(HtmlSlicer::Options)
24
+ @options = options
25
+ @map = Map.new
26
+ process!(document.root)
11
27
  end
12
-
13
- def did?
14
- @did||false
28
+
29
+ def resize_node(node)
30
+ if w = @map.width(node)
31
+ width(node) { w.to_s }
32
+ end
33
+ if h = @map.height(node)
34
+ height(node) { h.to_s }
35
+ end
15
36
  end
16
37
 
17
38
  private
@@ -19,9 +40,18 @@ module HtmlSlicer
19
40
  include HtmlSlicer::Utilities::ParseNode
20
41
  include HtmlSlicer::Utilities::NodeMatchExtension
21
42
 
22
- def resize_document!(root)
43
+ def process!(root)
23
44
  parse(root) do |node|
24
- resize!(node) if node.is_a?(HTML::Tag) && resizeable?(node)
45
+ if node.is_a?(HTML::Tag) && resizeable?(node)
46
+ target_width = node.parent.is_a?(HTML::Tag) ? @map.width(node.parent)||@options.width : @options.width
47
+ if target_width.present? && node_width = width(node)
48
+ node_height = height(node)
49
+ if node_width > target_width
50
+ ratio = node_width.to_f/target_width
51
+ @map.commit(node, target_width, node_height ? (node_height/ratio).round : nil)
52
+ end
53
+ end
54
+ end
25
55
  end
26
56
  end
27
57
 
@@ -31,7 +61,7 @@ module HtmlSlicer
31
61
 
32
62
  def width(node)
33
63
  values = []
34
- if block_given?
64
+ if block_given? && node.attributes.has_key?("width")
35
65
  node.attributes["width"] = yield
36
66
  else
37
67
  values << absolute_resolution(node.attributes["width"])
@@ -53,7 +83,7 @@ module HtmlSlicer
53
83
 
54
84
  def height(node)
55
85
  values = []
56
- if block_given?
86
+ if block_given? && node.attributes.has_key?("height")
57
87
  node.attributes["height"] = yield
58
88
  else
59
89
  values << absolute_resolution(node.attributes["height"])
@@ -73,19 +103,6 @@ module HtmlSlicer
73
103
  values.compact.min
74
104
  end
75
105
 
76
- def resize!(node)
77
- target_width = node.parent.is_a?(HTML::Tag) ? width(node.parent)||@options.width : nil
78
- if target_width.present? && node_width = width(node)
79
- node_height = height(node)
80
- if node_width > target_width
81
- ratio = node_width.to_f/target_width
82
- width(node) { target_width.to_s }
83
- height(node) { (node_height/ratio).round.to_s } if node_height
84
- @did = true
85
- end
86
- end
87
- end
88
-
89
106
  def absolute_resolution(value)
90
107
  (value.present? && value.last != "%") ? value.to_i : nil
91
108
  end
@@ -1,19 +1,28 @@
1
1
  module HtmlSlicer
2
- module Makers
2
+ module Mappers
3
3
 
4
- class Slicing # Slicing engine
5
- attr_reader :options, :map
4
+ class Slicing # Slicing engine, generate and store resizing Map (hash)
5
+ attr_reader :options, :map, :slice_number
6
+
7
+ class Map < Hash #:nodoc:
8
+ include HtmlSlicer::Utilities::NodeIdent
6
9
 
7
- def initialize(document, options = {})
8
- raise(TypeError, "HTML::Document expected, '#{document.class}' passed") unless document.is_a?(HTML::Document)
9
- @options = SliceOptions.new(options)
10
- @map = [Hash.new]
11
- @options.unit.is_a?(Hash) ? slice_document_by_node!(document.root) : slice_document_by_text!(document.root)
10
+ def commit(node, number, value)
11
+ self[node_identify(node)] ||= {}
12
+ self[node_identify(node)].merge!(number => value)
13
+ end
14
+ def get(node, number)
15
+ self[node_identify(node)] ? self[node_identify(node)][number] : nil
16
+ end
12
17
  end
13
18
 
14
- # Resturn number of slices.
15
- def slice_number
16
- @map.size
19
+ def initialize(document, options)
20
+ raise(TypeError, "HTML::Document expected, '#{document.class}' passed") unless document.is_a?(HTML::Document)
21
+ raise(TypeError, "HtmlSlicer::Options expected, '#{options.class}' passed") unless options.is_a?(HtmlSlicer::Options)
22
+ @options = options
23
+ @map = Map.new
24
+ @slice_number = 1
25
+ @options.unit.is_a?(Hash) ? process_by_node!(document.root) : process_by_text!(document.root)
17
26
  end
18
27
 
19
28
  private
@@ -21,7 +30,7 @@ module HtmlSlicer
21
30
  include HtmlSlicer::Utilities::ParseNode
22
31
  include HtmlSlicer::Utilities::NodeMatchExtension
23
32
 
24
- def slice_document_by_text!(root)
33
+ def process_by_text!(root)
25
34
  units_count = 0
26
35
  parse(root) do |node|
27
36
  if node.is_a?(HTML::Text)
@@ -36,48 +45,48 @@ module HtmlSlicer
36
45
  if units_count == @options.maximum
37
46
  units_count = 0
38
47
  index = complete!(content, match.end(0))
39
- @map.last[node.object_id] = Range.new(last_index, index-1)
48
+ @map.commit(node, @slice_number, [last_index, index-1])
40
49
  last_index = index
41
- limited? ? raise(Exception) : @map << Hash.new
50
+ limited? ? raise(Exception) : @slice_number += 1
42
51
  else
43
52
  index = match.end(0)
44
53
  end
45
54
  if units_count > 0
46
- @map.last[node.object_id] = Range.new(last_index, -1)
55
+ @map.commit(node, @slice_number, [last_index, -1])
47
56
  end
48
57
  end
49
58
  rescue Exception
50
59
  break
51
60
  end
52
61
  else
53
- @map.last[node.object_id] = Range.new(0, -1)
62
+ @map.commit(node, @slice_number, [0, -1])
54
63
  end
55
64
  else
56
- @map.last[node.object_id] = true
65
+ @map.commit(node, @slice_number, true)
57
66
  end
58
67
  end
59
68
  end
60
69
 
61
- def slice_document_by_node!(root)
70
+ def process_by_node!(root)
62
71
  units_count = 0
63
72
  parse(root) do |node|
64
73
  if node.is_a?(HTML::Text)
65
- @map.last[node.object_id] = Range.new(0, -1)
74
+ @map.commit(node, @slice_number, [0, -1])
66
75
  else
67
- @map.last[node.object_id] = true
76
+ @map.commit(node, @slice_number, true)
68
77
  end
69
78
  if node.match(@options.unit) && sliceable?(node)
70
79
  units_count += 1
71
80
  if units_count == @options.maximum
72
81
  units_count = 0
73
- limited? ? break : @map << Hash.new
82
+ limited? ? break : @slice_number += 1
74
83
  end
75
84
  end
76
85
  end
77
86
  end
78
87
 
79
88
  def limited?
80
- @options.limit && slice_number >= @options.limit
89
+ @options.limit && @slice_number >= @options.limit
81
90
  end
82
91
 
83
92
  def sanitize_content!(node)
@@ -1,3 +1,5 @@
1
+ require 'digest/sha1'
2
+
1
3
  module HtmlSlicer
2
4
 
3
5
  # Make options adjective and convinient for processing needs.
@@ -5,15 +7,26 @@ module HtmlSlicer
5
7
  class Options #:nodoc:
6
8
  # Superclass
7
9
  attr_reader :only, :except
10
+
8
11
  def initialize(options)
9
12
  options ||= {}
10
13
  @only = options[:only]
11
14
  @except = options[:except]
12
15
  end
16
+
17
+ def hexdigest
18
+ Digest::SHA1.hexdigest(string_value)
19
+ end
20
+
21
+ def string_value
22
+ instance_variables.collect {|name| name.to_s + ":" + instance_variable_get(name).to_s}.join
23
+ end
24
+
13
25
  end
14
26
 
15
- class SliceOptions < Options #:nodoc:
27
+ class SlicingOptions < Options #:nodoc:
16
28
  attr_reader :unit, :maximum, :complete, :text_break, :limit
29
+
17
30
  def initialize(options)
18
31
  super(options)
19
32
  @unit = case options[:unit]
@@ -47,14 +60,17 @@ module HtmlSlicer
47
60
  end
48
61
  @text_break = options[:text_break]
49
62
  end
63
+
50
64
  end
51
65
 
52
- class ResizeOptions < Options
66
+ class ResizingOptions < Options
53
67
  attr_reader :width
68
+
54
69
  def initialize(options)
55
70
  super(options)
56
- @width = options[:width]
71
+ @width = options[:width].to_i
57
72
  end
73
+
58
74
  end
59
75
 
60
76
  end
@@ -5,11 +5,19 @@ module HtmlSlicer
5
5
  def parse(node, &block)
6
6
  node.children.each do |node|
7
7
  yield node if block_given?
8
- parse(node, &block) if node.is_a?(HTML::Tag)
8
+ if node.is_a?(HTML::Tag)
9
+ parse(node, &block)
10
+ end
9
11
  end
10
12
  end
11
13
  end
12
14
 
15
+ module NodeIdent
16
+ def node_identify(node)
17
+ [node.line, node.position]
18
+ end
19
+ end
20
+
13
21
  module Deepcopy
14
22
  # Return the 'deep' brand new copy of Hash or Array. All nested hashes/arrays rebuilded at the same way.
15
23
  def deepcopy(object)
@@ -1,3 +1,3 @@
1
1
  module HtmlSlicer
2
- VERSION = "0.0.7"
2
+ VERSION = "0.1.0"
3
3
  end
data/lib/html_slicer.rb CHANGED
@@ -7,9 +7,6 @@ module HtmlSlicer
7
7
  def self.load!
8
8
  require 'html_slicer/utilities'
9
9
  require 'html_slicer/config'
10
- require 'html_slicer/options'
11
- require 'html_slicer/processor'
12
- require 'html_slicer/document'
13
10
  require 'html_slicer/interface'
14
11
  require 'html_slicer/engine'
15
12
  require 'html_slicer/helpers/action_view_extension'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: html_slicer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.7
4
+ version: 0.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-06-22 00:00:00.000000000 Z
12
+ date: 2012-07-09 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: actionpack
@@ -82,8 +82,8 @@ files:
82
82
  - config/locales/html_slicer.yml
83
83
  - html_slicer.gemspec
84
84
  - lib/html_slicer.rb
85
+ - lib/html_slicer/cached_stuff.rb
85
86
  - lib/html_slicer/config.rb
86
- - lib/html_slicer/document.rb
87
87
  - lib/html_slicer/engine.rb
88
88
  - lib/html_slicer/helpers/action_view_extension.rb
89
89
  - lib/html_slicer/helpers/slicer.rb
@@ -91,8 +91,8 @@ files:
91
91
  - lib/html_slicer/helpers/tags.rb
92
92
  - lib/html_slicer/installer.rb
93
93
  - lib/html_slicer/interface.rb
94
- - lib/html_slicer/makers/resizing.rb
95
- - lib/html_slicer/makers/slicing.rb
94
+ - lib/html_slicer/mappers/resizing.rb
95
+ - lib/html_slicer/mappers/slicing.rb
96
96
  - lib/html_slicer/models/active_record_extension.rb
97
97
  - lib/html_slicer/options.rb
98
98
  - lib/html_slicer/processor.rb
@@ -1,107 +0,0 @@
1
- require 'html_slicer/makers/slicing'
2
- require 'html_slicer/makers/resizing'
3
-
4
- module HtmlSlicer
5
-
6
- class Document # Framework
7
- include HtmlSlicer::Makers
8
-
9
- attr_reader :options, :document, :slicing, :resizing
10
-
11
- delegate :root, :to => :document
12
-
13
- def initialize(env, method_name, options = {})
14
- @options = options
15
- @source = Proc.new do
16
- if options[:processors].present?
17
- HtmlSlicer::Process.iterate(env.send(method_name), options[:processors])
18
- else
19
- env.send(method_name)
20
- end
21
- end
22
- prepare!
23
- end
24
-
25
- # Resturn number of slices.
26
- def slice_number
27
- sliced? ? @slicing.slice_number : 1
28
- end
29
-
30
- def to_s(slice = 1)
31
- prepare! if changed?
32
- if sliced? && map = slicing.map[slice-1]
33
- view(root, map, slicing.options.text_break)
34
- else
35
- root
36
- end
37
- end
38
-
39
- def inspect
40
- to_s
41
- end
42
-
43
- def method_missing(*args, &block)
44
- to_s.send(*args, &block)
45
- end
46
-
47
- def resized?
48
- resizing.try(:did?)||false
49
- end
50
-
51
- def sliced?
52
- slicing.present?
53
- end
54
-
55
- def changed?
56
- @source_hash != @source.call.hash
57
- end
58
-
59
- private
60
-
61
- # Return a textual representation of the node including all children assigned to a +map+.
62
- def view(node, map = {}, text_break = nil)
63
- case node
64
- when HTML::Tag then
65
- children_view = node.children.collect {|child| view(child, map, text_break)}.compact.join
66
- if map[node.object_id] || children_view.present?
67
- if node.closing == :close
68
- "</#{node.name}>"
69
- else
70
- s = "<#{node.name}"
71
- node.attributes.each do |k,v|
72
- s << " #{k}"
73
- s << "=\"#{v}\"" if String === v
74
- end
75
- s << " /" if node.closing == :self
76
- s << ">"
77
- s += children_view
78
- s << "</#{node.name}>" if node.closing != :self && !node.children.empty?
79
- s
80
- end
81
- end
82
- when HTML::Text then
83
- if range = map[node.object_id]
84
- "#{node.content[range]}#{text_break unless range.last == -1}"
85
- end
86
- when HTML::CDATA then
87
- node.to_s
88
- when HTML::Node then
89
- node.children.collect {|child| view(child, map, text_break)}.compact.join
90
- end
91
- end
92
-
93
- # Mapping the original source.
94
- def prepare!
95
- @source_hash = @source.call.hash
96
- @document = HTML::Document.new(@source.call)
97
- if options[:resize]
98
- @resizing = Resizing.new(document, options[:resize])
99
- end
100
- if options[:slice]
101
- @slicing = Slicing.new(document, options[:slice])
102
- end
103
- end
104
-
105
- end
106
-
107
- end