juice_extractor 0.0.0.4 → 0.0.1.1

Sign up to get free protection for your applications and to get access to all the features.
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