juice_extractor 0.0.0.4 → 0.0.1.1

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.
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm 1.8.7@juice_extractor --create
data/Rakefile CHANGED
@@ -1,2 +1,17 @@
1
1
  #!/usr/bin/env rake
2
2
  require "bundler/gem_tasks"
3
+ require "rubygems"
4
+ require "hanoi"
5
+
6
+ namespace :test do
7
+ desc "Runs all the JavaScript tests and collects the results"
8
+ JavaScriptTestTask.new(:js) do |t|
9
+ test_cases = ENV['TESTS'] && ENV['TESTS'].split(',')
10
+ browsers = ENV['BROWSERS'] && ENV['BROWSERS'].split(',')
11
+ # change this path according to your configuration,
12
+ # it should indicate the root directory of your JavaScript files
13
+ sources_directory = File.expand_path(File.dirname(__FILE__) + "/src")
14
+
15
+ t.setup(sources_directory, test_cases, browsers)
16
+ end
17
+ end
@@ -17,6 +17,9 @@ Gem::Specification.new do |gem|
17
17
 
18
18
  gem.add_dependency 'rmagick', "2.12.0"
19
19
  gem.add_dependency 'json'
20
-
20
+
21
21
  gem.add_development_dependency 'ruby-debug'
22
+ gem.add_development_dependency 'rspec'
23
+ gem.add_development_dependency 'mocha'
24
+ gem.add_development_dependency 'hanoi'
22
25
  end
@@ -0,0 +1,55 @@
1
+ module ColorExtractor
2
+ def self.implicit_colors(site_url, quantize = nil)
3
+ return [] if site_url.nil?
4
+ image_path = Base.screenshot(site_url)
5
+ img = Magick::ImageList.new(image_path)
6
+ img = img.quantize(quantize) if quantize
7
+ img.color_histogram.map{|pixel| pixel.first.to_color(Magick::AllCompliance, false, 8, true) }
8
+ end
9
+
10
+ def self.explicit_colors(site_url, attributes = ['background-color', "border-color", 'color'], quantize = nil)
11
+ return [] if site_url.nil?
12
+ val = Base.color_explicit_cmd(site_url, attributes)
13
+ Base.build_explicit_colors(val, attributes, quantize)
14
+ end
15
+
16
+ def self.from_image(image_url)
17
+ end
18
+
19
+ module Base
20
+ def self.screenshot(site_url, to_path = '/tmp')
21
+ Base.screenshot_cmd(site_url, to_path)
22
+ end
23
+
24
+ def self.build_explicit_colors(val, attributes, max = nil)
25
+ colors = JSON.parse(val)
26
+
27
+ attributes.each do |prop|
28
+ colors['containers'][prop] = colors['containers'][prop].compact.group_by.map{|e| [e, e.length]}.uniq.sort{|a,b| b[1] <=> a[1]}.map{|e| e[0].upcase }
29
+ colors['typography'][prop] = colors['typography'][prop].compact.group_by.map{|e| [e, e.length]}.uniq.sort{|a,b| b[1] <=> a[1]}.map{|e| e[0].upcase }
30
+
31
+ if max && max > 0
32
+ colors['containers'][prop] = colors['containers'][prop][0..max-1]
33
+ colors['typography'][prop] = colors['typography'][prop][0..max-1]
34
+ end
35
+ end
36
+
37
+ colors
38
+ end
39
+
40
+ def self.color_explicit_cmd(site_url, attributes)
41
+ phantom_script = File.expand_path(File.dirname(__FILE__) + "/../js/styles.phantom.js")
42
+ puts "Running command: phantomjs #{phantom_script} #{site_url} #{ File.dirname(__FILE__) }/../ '#{attributes.to_json}' "
43
+ `phantomjs #{phantom_script} #{site_url} #{ File.dirname(__FILE__) }/../ '#{attributes.to_json}'`
44
+ end
45
+
46
+ def self.screenshot_cmd(site_url, path)
47
+ image_name = "#{path}/#{rand(36**10).to_s(36)}.png"
48
+ phantom_script = File.expand_path(File.dirname(__FILE__) + "/../js/screenshot.phantom.js")
49
+ puts "Running command: phantomjs --load-images=no #{phantom_script} #{site_url} #{image_name} "
50
+ res = `phantomjs --load-images=no #{phantom_script} #{site_url} #{image_name}`
51
+ /.*.png/.match(res).to_s
52
+ end
53
+
54
+ end
55
+ end
@@ -6,6 +6,12 @@
6
6
  ("0" + parseInt(rgb[1],10).toString(16)).slice(-2) +
7
7
  ("0" + parseInt(rgb[2],10).toString(16)).slice(-2) +
8
8
  ("0" + parseInt(rgb[3],10).toString(16)).slice(-2);
9
- }
9
+ },
10
+
11
+ removeFromArray: function(value, arr) {
12
+ return $.grep(arr, function(elem, index) {
13
+ return elem !== value;
14
+ });
15
+ }
10
16
  });
11
17
  })(jQuery);
@@ -0,0 +1,55 @@
1
+ (function( $ ) {
2
+ var border_color_styles = ['border-top-color','border-left-color','border-bottom-color','border-right-color'];
3
+
4
+ var addBorderColor = function (attr){
5
+ //Remove 'border-color' attribute
6
+ attr = $.removeFromArray('border-color', attr);
7
+
8
+ // Add css styles
9
+ $.each(border_color_styles, function(key, ele) { attr.push(ele); });
10
+ return attr;
11
+ };
12
+
13
+ var buildStyleObject = function (obj){
14
+ var tmpObj = {};
15
+
16
+ $.each(obj, function(index, element){
17
+ if ($.inArray(index, border_color_styles) >= 0 ){
18
+ if (typeof tmpObj['border-color'] == 'undefined'){ tmpObj['border-color'] = []; }
19
+ $(element).each(function(){ $.merge(tmpObj['border-color'], element) });
20
+ return true;
21
+ }
22
+
23
+ if (typeof tmpObj[index] == 'undefined'){ tmpObj[index] = []; }
24
+ $.merge(tmpObj[index], element)
25
+ });
26
+
27
+ return tmpObj;
28
+ };
29
+
30
+ $.styleExtractor = function( el, styles ) {
31
+ var obj = {};
32
+
33
+ // Computed styles doesn't have border-color
34
+ if ($.inArray("border-color", styles) >= 0) {
35
+ styles = addBorderColor(styles);
36
+ }
37
+
38
+ var props = $(el).curStyles.apply($(el), styles)
39
+
40
+ $.each(props, function(element, key) {
41
+ if (key && key != undefined && key != ''){
42
+ if (typeof obj[element] == 'undefined'){
43
+ obj[element] = [];
44
+ }
45
+ obj[element].push($.rgb2Hex(key));
46
+ }
47
+ });
48
+
49
+ return buildStyleObject(obj);
50
+ };
51
+
52
+ $.fn.styleExtractor = function() {
53
+ return $.styleExtractor(this[0], $.makeArray(arguments));
54
+ };
55
+ })(jQuery)
@@ -3,6 +3,10 @@ var page = require('webpage').create(),
3
3
  url = system.args[1],
4
4
  filename = system.args[2];
5
5
 
6
+ if (system.args.length === 2) {
7
+ console.log("Usage: $ phantomjs screenshot.phantom.js <url> <filename>");
8
+ }
9
+
6
10
  page.onConsoleMessage = function(msg) {
7
11
  return console.log(msg);
8
12
  };
@@ -4,6 +4,11 @@ var page = require('webpage').create(),
4
4
  assets_path = system.args[2],
5
5
  args = system.args[3];
6
6
 
7
+
8
+ if (system.args.length === 3) {
9
+ console.log("Usage: $ phantomjs style.phantom.js <url> <js_lib_path> '[\"background-color\",\"border-color\",\"color\"]'");
10
+ }
11
+
7
12
  page.onConsoleMessage = function(msg) {
8
13
  //if (msg.match(/#/)){
9
14
  return console.log(msg);
@@ -13,55 +18,34 @@ page.onConsoleMessage = function(msg) {
13
18
  page.open(url, function(status) {
14
19
 
15
20
  if ( status === "success" ) {
16
- page.injectJs(assets_path + '/juice_extractor/includes/jquery.min.js');
17
- page.injectJs(assets_path + '/juice_extractor/includes/jquery.base.extend.js');
18
- page.injectJs(assets_path + '/juice_extractor/includes/jquery.curstyles.js');
21
+ page.injectJs(assets_path + '/includes/jquery.min.js');
22
+ page.injectJs(assets_path + '/includes/jquery.base.extend.js');
23
+ page.injectJs(assets_path + '/includes/jquery.curstyles.js');
24
+ page.injectJs(assets_path + '/includes/jquery.style.extractor.js');
19
25
 
20
26
  page.evaluate(function(args) {
21
27
  var styles = {'containers' : {}, 'typography' : {}},
22
- attributes = [],
28
+ attributes = eval(args),
23
29
  content_elements = ['header', 'footer', 'div', 'aside', 'article'],
24
- typography_elements = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p', 'a', 'span', 'small', 'em', 'blockquote', 'abbr'],
25
- border_colors = ['border-top-color','border-left-color','border-bottom-color','border-right-color'];
30
+ typography_elements = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p', 'a', 'span', 'small', 'em', 'blockquote', 'abbr'];
26
31
 
27
32
  // Create object to return
28
- $.each(eval(args), function(key, ele){ attributes.push(ele); })
29
33
  $.each(attributes, function(i,ele){ styles['containers'][ele] = []; styles['typography'][ele] = [];})
30
34
 
31
- // Handling different border color
32
- if ($.inArray("border-color", attributes) >= 0) {
33
- $.each(border_colors, function(key, ele) { attributes.push(ele); });
34
- }
35
-
36
35
  $.each(content_elements, function (i, element) {
37
36
  if ($(element).length > 0){
38
-
37
+ // Getting content elements
39
38
  $.each($(element).get(), function(i, single_element){
40
-
41
- // Handling the rest attributes
42
- var props = $(single_element).curStyles.apply($(single_element), attributes);
43
- $.each(props, function(element, key) {
44
- if ($.inArray(element, border_colors) >= 0){
45
- element = 'border-color';
46
- }
47
- if (key && key != undefined && key != ''){
48
- styles['containers'][element].push($.rgb2Hex(key));
49
- }
39
+ $.each($(single_element).styleExtractor.apply($(single_element), attributes), function(i, n){
40
+ $.merge(styles['containers'][i], n)
50
41
  });
51
42
 
43
+ // Getting typography elements
52
44
  $(single_element).find(typography_elements.join(',')).each(function(i, typo_element){
53
- // Handling the rest attributes
54
- var props = $(single_element).curStyles.apply($(single_element), attributes);
55
- $.each(props, function(element, key) {
56
- if ($.inArray(element, border_colors) >= 0){
57
- element = 'border-color';
58
- }
59
- if (key && key != undefined && key != ''){
60
- styles['typography'][element].push($.rgb2Hex(key));
61
- }
45
+ $.each($(typo_element).styleExtractor.apply($(typo_element), attributes), function(i, n){
46
+ $.merge(styles['typography'][i], n)
62
47
  });
63
- }); // End single_elements iteration
64
-
48
+ });
65
49
  });
66
50
  } //End length validation
67
51
  });
@@ -70,5 +54,4 @@ page.open(url, function(status) {
70
54
  }, args); //End evaluate
71
55
  phantom.exit();
72
56
  }
73
-
74
57
  });
@@ -4,6 +4,10 @@ var page = require('webpage').create(),
4
4
  url = system.args[1],
5
5
  assets_file = system.args[2];
6
6
 
7
+ if (system.args.length === 2) {
8
+ console.log("Usage: $ phantomjs typography.phantom.js <url> <js_lib_path>");
9
+ }
10
+
7
11
  page.onConsoleMessage = function(msg) {
8
12
  if (!msg.match(/(Unsafe|TypeError)/)){
9
13
  console.log(msg);
@@ -12,26 +16,28 @@ page.onConsoleMessage = function(msg) {
12
16
 
13
17
  page.open(url, function(status) {
14
18
  if ( status === "success" ) {
15
-
16
- page.includeJs( assets_file , function() {
17
- page.evaluate(function() {
18
-
19
- $(document).ready(function () {
20
- var styles = {},
21
- elements = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p', 'body', 'a', 'span', 'small', 'em', 'blockquote', 'abbr'],
22
- attributes = ['font-family', 'font-style', 'font-size', 'line-height', 'font-weight', 'letter-spacing'];
23
-
24
- $.map(elements, function (ele, i){
25
- styles[ele] = $(ele).curStyles('font-family', 'font-style', 'font-size', 'line-height', 'font-weight', 'letter-spacing');
26
- });
27
-
28
- // TODO: Check compatibility with ie browsers
29
- console.log($.CSSJsonDecode(styles));
19
+ page.injectJs(assets_path + '/includes/jquery.min.js');
20
+ page.injectJs(assets_path + '/includes/jquery.base.extend.js');
21
+ page.injectJs(assets_path + '/includes/jquery.curstyles.js');
22
+ page.injectJs(assets_path + '/includes/jquery.style.extractor.js');
23
+
24
+ page.evaluate(function() {
25
+
26
+ $(document).ready(function () {
27
+ var styles = {},
28
+ elements = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p', 'body', 'a', 'span', 'small', 'em', 'blockquote', 'abbr'],
29
+ attributes = ['font-family', 'font-style', 'font-size', 'line-height', 'font-weight', 'letter-spacing'];
30
+
31
+ $.map(elements, function (ele, i){
32
+ styles[ele] = $(ele).curStyles('font-family', 'font-style', 'font-size', 'line-height', 'font-weight', 'letter-spacing');
30
33
  });
31
34
 
35
+ // TODO: Check compatibility with ie browsers
36
+ console.log($.CSSJsonDecode(styles));
32
37
  });
33
- phantom.exit();
38
+
34
39
  });
40
+ phantom.exit();
35
41
 
36
42
  }
37
43
  });
@@ -1,3 +1,3 @@
1
1
  module JuiceExtractor
2
- VERSION = "0.0.0.4"
2
+ VERSION = "0.0.1.1"
3
3
  end
@@ -1,51 +1,10 @@
1
- require "juice_extractor/version"
2
1
  require "rmagick"
3
2
  require 'json'
4
3
 
4
+ require "juice_extractor/version"
5
+ require "juice_extractor/core/color_extractor"
6
+
5
7
  module JuiceExtractor
6
8
  # TODO: Extend other modules here
7
- #"[\"background-color\",\"border-color\",\"color\"]"
8
- end
9
-
10
- module ColorExtractor
11
- def self.implicit_colors(site_url, quantize = nil)
12
- return [] if site_url.nil?
13
- image_path = Base.screenshot(site_url)
14
- img = Magick::ImageList.new(image_path)
15
- img = img.quantize(quantize) if quantize
16
- img.color_histogram.map{|pixel| pixel.first.to_color(Magick::AllCompliance, false, 8, true) }
17
- end
18
-
19
- def self.explicit_colors(site_url, attributes = ['background-color', "border-color", 'color'], quantize = nil)
20
- return {} if site_url.nil?
21
- phantom_script = File.expand_path(File.dirname(__FILE__) + "/juice_extractor/js/styles.phantom.js")
22
- val = `phantomjs #{phantom_script} #{site_url} #{ File.dirname(__FILE__) } '#{attributes.to_json}'`
23
- colors= Base.build_explicit_colors(val, attributes, quantize)
24
- colors
25
- end
26
-
27
- module Base
28
- def self.screenshot(site_url, to_path = '/tmp/')
29
- image_name = "#{to_path}#{rand(36**10).to_s(36)}.png"
30
- phantom_script = File.expand_path(File.dirname(__FILE__) + "/juice_extractor/js/screenshot.phantom.js")
31
- `phantomjs --load-images=no #{phantom_script} #{site_url} #{image_name}`
32
- image_name
33
- end
34
-
35
- def self.build_explicit_colors(val, attributes, max = nil)
36
- colors = JSON.parse(val)
37
-
38
- attributes.each do |prop|
39
- colors['containers'][prop] = colors['containers'][prop].compact.group_by.map{|e| [e, e.length]}.uniq.sort{|a,b| b[1] <=> a[1]}.map{|e| e[0].upcase }
40
- colors['typography'][prop] = colors['typography'][prop].compact.group_by.map{|e| [e, e.length]}.uniq.sort{|a,b| b[1] <=> a[1]}.map{|e| e[0].upcase }
41
-
42
- if max && max > 0
43
- colors['containers'][prop] = colors['containers'][prop][0..max-1]
44
- colors['typography'][prop] = colors['typography'][prop][0..max-1]
45
- end
46
- end
47
-
48
- colors
49
- end
50
- end
51
- end
9
+ #"[\"background-color\",\"border-color\",\"color\"]"
10
+ end