marta 0.37396 → 0.41245

Sign up to get free protection for your applications and to get access to all the features.
@@ -158,7 +158,7 @@ div[martaclass=marta_div] {
158
158
  outline: 2px solid #bbbbbb;
159
159
  background-color: lightgray;
160
160
  position : relative;
161
- z-index : 150000;
161
+ z-index : 2147483647;
162
162
  padding: 0;
163
163
  margin: 0px 0px 0px 0px;
164
164
  overflow-y: scroll;
@@ -228,7 +228,7 @@ div[martastyle=at_large] {
228
228
  width: 100%;
229
229
  pointer-events: visible;
230
230
  display: block;
231
- z-index: 149000;
231
+ z-index: 2147483646;
232
232
  }
233
233
 
234
234
  div[martastyle=off] {
@@ -4,6 +4,7 @@ require 'marta/lightning'
4
4
  require 'marta/injector'
5
5
  require 'marta/public_methods'
6
6
  require 'marta/page_arithmetic'
7
+ require 'marta/element_information'
7
8
 
8
9
  module Marta
9
10
 
@@ -23,7 +24,7 @@ module Marta
23
24
  class MethodSpeaker
24
25
 
25
26
  include XPath, Lightning, Injector, PublicMethods, SimpleElementFinder,
26
- PageArithmetic
27
+ PageArithmetic, ElementInformation
27
28
 
28
29
  def initialize(method_name, requestor)
29
30
  @class_name = requestor.class_name
@@ -83,8 +84,7 @@ module Marta
83
84
  def attrs_plus_result
84
85
  if !attrs_exists?
85
86
  @attrs = @result
86
- elsif !@attrs['options']['collection'] or
87
- !@result['options']['collection']
87
+ elsif !@result['options']['collection']
88
88
  @attrs = @result
89
89
  else
90
90
  @attrs = make_collection(@attrs, @result)
@@ -93,7 +93,17 @@ module Marta
93
93
 
94
94
  # Asking: "What are you looking for?"
95
95
  def ask_for_elements
96
- ask 'element', "Found #{@found} elements for #{@title}", @attrs
96
+ answer = ask 'element', "Found #{@found} elements for #{@title}", @attrs
97
+ return answer.class == Hash ? answer_to_hash(answer) : answer
98
+ end
99
+
100
+ # Creating new fashioned hash out of data
101
+ def answer_to_hash(answer)
102
+ result = method_structure
103
+ result['options']['collection'] = answer['collection']
104
+ what = answer['exclude'] ? 'negative' : 'positive'
105
+ result[what] = get_attributes(answer['element'])
106
+ result
97
107
  end
98
108
 
99
109
  # Creating data to save when it is a basically defined element
@@ -173,8 +183,46 @@ module Marta
173
183
  def user_method_dialogs(method_name)
174
184
  dialog_master = MethodSpeaker.new(method_name, self)
175
185
  data = dialog_master.dialog
186
+ data['meths'][method_name] =
187
+ dynamise_method(data['vars'], data['meths'][method_name])
176
188
  file_write(self.class_name.to_s, data)
177
189
  data
178
190
  end
191
+
192
+ # Massive gsub for attribute
193
+ def dynamise(variable_name, what)
194
+ what.each do |entry|
195
+ entry.each do |value|
196
+ value.gsub!(self.instance_variable_get("@#{variable_name}"),
197
+ '#{@' + variable_name + '}')
198
+ end
199
+ end
200
+ end
201
+
202
+ # Marta will search for page variables in attributes of element in order
203
+ # to create dynamic element by itself. It must be splited. And moved.
204
+ def dynamise_method(vars, method)
205
+ vars.each_pair do |variable_name, variable|
206
+ if variable_name.include?('text')
207
+ dynamise variable_name, [method['positive']['self']['text'],
208
+ method['positive']['pappy']['text'],
209
+ method['positive']['granny']['text'],
210
+ method['negative']['self']['text'],
211
+ method['negative']['pappy']['text'],
212
+ method['negative']['granny']['text']]
213
+ else
214
+ [method['positive'], method['negative']].each do |method|
215
+ method.each_pair do |level, content|
216
+ content['attributes'].each_pair do |attribute_name, values|
217
+ if variable_name.include?(attribute_name)
218
+ dynamise variable_name, [values]
219
+ end
220
+ end
221
+ end
222
+ end
223
+ end
224
+ end
225
+ method
226
+ end
179
227
  end
180
228
  end
@@ -0,0 +1,86 @@
1
+ module Marta
2
+
3
+ # Marta is creating a hash of element data. For now it stores
4
+ # tag, text, and all the attributes.
5
+ module ElementInformation
6
+
7
+ private
8
+
9
+ #
10
+ # We are using helper class which can parse element attributes to our
11
+ # special hash format.
12
+ #
13
+ # @note It is believed that no user will use it
14
+ class ElementHelper
15
+
16
+ def initialize(requestor)
17
+ @engine = requestor.engine
18
+ end
19
+
20
+ # We can get data of the element or data of any parent.
21
+ def get_element_info(element, parent_count = 0)
22
+ parent = ''
23
+ parent_count.times do
24
+ parent = parent + '.parentElement'
25
+ end
26
+ result = Hash.new
27
+ attr_script = %Q[
28
+ var s = {};
29
+ var attrs = arguments[0]#{parent}.attributes;
30
+ for (var l = 0; l < attrs.length; ++l) {
31
+ var a = attrs[l]; s[a.name] = a.value.split(" ");
32
+ } ;
33
+ return s;]
34
+ tag_script = "return arguments[0]#{parent}.tagName"
35
+ text_script = %Q[
36
+ if (arguments[0]#{parent}.textContent == arguments[0]#{parent}.innerHTML)
37
+ {return arguments[0]#{parent}.textContent} else {return ''};]
38
+ result['tag'] = [@engine.execute_script(tag_script, element)]
39
+ txt = @engine.execute_script(text_script, element)
40
+ result['text'] = txt != '' ? [txt] : []
41
+ result['attributes'] = @engine.execute_script(attr_script, element)
42
+ result['attributes'].each_pair do |attribute, value|
43
+ value.uniq!
44
+ end
45
+ return result
46
+ end
47
+
48
+ # That class is also stores an empty special format hash.
49
+ def self.method_structure(collection = false)
50
+ return {'options' => {'collection' => collection},
51
+ 'positive' => {
52
+ 'self' => {
53
+ 'text'=>[], 'tag' => [], 'attributes' => {}},
54
+ 'pappy' => {
55
+ 'text'=>[], 'tag' => [], 'attributes' => {}},
56
+ 'granny' => {
57
+ 'text'=>[], 'tag' => [], 'attributes' => {}}},
58
+ 'negative' => {
59
+ 'self' => {
60
+ 'text'=>[], 'tag' => [], 'attributes' => {}},
61
+ 'pappy' => {
62
+ 'text'=>[], 'tag' => [], 'attributes' => {}},
63
+ 'granny' => {
64
+ 'text'=>[], 'tag' => [], 'attributes' => {}}}
65
+ }
66
+ end
67
+ end
68
+
69
+ # We are getting three levels of attributes of element,
70
+ # parent and grandparent
71
+ def get_attributes(element, requestor = self)
72
+ result = Hash.new
73
+ element_helper = ElementHelper.new requestor
74
+ result['self'] = element_helper.get_element_info element
75
+ result['pappy'] = element_helper.get_element_info element, 1
76
+ result['granny'] = element_helper.get_element_info element, 2
77
+ return result
78
+ end
79
+
80
+ # We can return the default structure of our special format
81
+ def method_structure(collection = false)
82
+ ElementHelper.method_structure collection
83
+ end
84
+
85
+ end
86
+ end
@@ -127,9 +127,9 @@ module Marta
127
127
  result = MartaServer.wait_user_dialog_response
128
128
  # We need double check for iframes here. It should be 100% changed.
129
129
  if !result
130
- result = engine.execute_script("return document.marta_confirm_mark")
130
+ result = @engine.execute_script("return document.marta_confirm_mark")
131
131
  end
132
- if (!result and !engine.element(id: 'marta_s_everything').exists?)
132
+ if (!result and !@engine.element(id: 'marta_s_everything').exists?)
133
133
  actual_injection
134
134
  end
135
135
  end
@@ -104,7 +104,7 @@ module Marta
104
104
 
105
105
  def build_method(name, content)
106
106
  define_singleton_method name.to_sym do
107
- learn_status ? method_edit(name) : marta_magic_finder(content)
107
+ learn_status ? method_edit(name) : marta_magic_finder(content, name)
108
108
  end
109
109
  exact = name + '_exact'
110
110
  define_singleton_method exact.to_sym do
@@ -21,6 +21,7 @@ module Marta
21
21
  end
22
22
  end
23
23
 
24
+ # Method to understand that something shouldn't be highlighted
24
25
  def is_here?(element)
25
26
  element.exists?
26
27
  rescue
@@ -6,6 +6,13 @@ async function port_set(value){
6
6
  });
7
7
  };
8
8
 
9
+ function getSelected(value){
10
+ document.getElementById('marta_show_html').setAttribute('tag', value.tagName);
11
+ const x = document.getElementsByTagName(value.tagName);
12
+ const index = Array.prototype.indexOf.call(x, value);
13
+ document.getElementById('marta_show_html').setAttribute('index', index);
14
+ };
15
+
9
16
  async function port_get(){
10
17
  await chrome.storage.sync.get(['port'], function(result) {
11
18
  port = result.port;
@@ -22,6 +29,7 @@ document.addEventListener("marta_send", async function(e) {
22
29
  //console.log(port);
23
30
  //console.log(e.detail.port);
24
31
  console.log("Marta is acting back. With port = " + port);
32
+ console.log("Marta is acting back. With mark = " + e.detail.mark);
25
33
  marta_real_send(e.detail.mark, port);
26
34
  });
27
35
 
@@ -0,0 +1 @@
1
+ <script src="devtools.js"></script>
@@ -0,0 +1,5 @@
1
+
2
+ setInterval(function(){
3
+
4
+ chrome.devtools.inspectedWindow.eval("getSelected($0)", { useContentScriptContext: true });
5
+ }, 100);
@@ -1,8 +1,9 @@
1
1
  {
2
2
  "name": "Marta app",
3
- "version": "0.37396",
3
+ "version": "0.41245",
4
4
  "description": "Messaging from browser to main app",
5
- "permissions": ["activeTab", "http://127.0.0.1*/*", "storage"],
5
+ "devtools_page": "devtools.html",
6
+ "permissions": ["activeTab", "http://127.0.0.1*/*", "storage", "contextMenus"],
6
7
  "background": {
7
8
  "scripts": ["background.js"],
8
9
  "persistent": true
@@ -158,7 +158,7 @@ module Marta
158
158
 
159
159
  # Marta uses simple rules to set the tolerancy value
160
160
  def self.set_tolerancy(value)
161
- @@tolerancy = parameter_set(@@tolerancy, value, 1024)
161
+ @@tolerancy = parameter_set(@@tolerancy, value, 100000)
162
162
  end
163
163
 
164
164
  def self.parameter_check_and_set(where, value, default, expected_class)
@@ -246,14 +246,5 @@ module Marta
246
246
  SettingMaster.port
247
247
  end
248
248
 
249
- # Marta can call server easily
250
- def server
251
- SettingMaster.server
252
- end
253
-
254
- # Marta knows was the browser started by she
255
- def correct_engine?
256
- SettingMaster.correct_engine?
257
- end
258
249
  end
259
250
  end
@@ -1,3 +1,4 @@
1
+ require 'marta/element_information'
1
2
  module Marta
2
3
 
3
4
  #
@@ -15,126 +16,107 @@ module Marta
15
16
  # @note It is believed that no user will use it
16
17
  # Now it has only one way to merge hashes
17
18
  # This method is getting common only of two methods in order to generate a
18
- # correct hash for collection element. Methods of the class are pretty
19
- # esoteric. Refactoring is a must here.
19
+ # correct hash for collection element.
20
20
  class MethodMerger
21
21
 
22
+ include ElementInformation
23
+
22
24
  # Class is taking two hashes. Sometimes order is valuable
23
25
  def initialize(main_hash, second_hash)
24
26
  @main_hash = main_hash
25
27
  @second_hash = second_hash
26
28
  end
27
29
 
28
- POSITIVE = ['self', 'pappy', 'granny']
29
- NEGATIVE = ['not_self', 'not_pappy', 'not_granny']
30
-
31
30
  # Main method for adding two elements into a large-wide collection
32
31
  def do_collection
33
- result = Hash.new
34
- result['options'] = options_merge
35
- NEGATIVE.each do |key|
36
- result[key] = all_of key
37
- end
38
- POSITIVE.each do |key|
39
- result[key], result["not_#{key}"] =
40
- passive_exclude(common_of(key), result["not_#{key}"])
32
+ result = method_structure
33
+ # Everything is simple for now with options)
34
+ result['options'] = @main_hash['options']
35
+ # If we are adding to collection
36
+ if @second_hash['positive']['self']['tag'] != []
37
+ result['positive'] = multiply(@main_hash['positive'],
38
+ @second_hash['positive'])
39
+ result['negative'] = extract(@main_hash['negative'],
40
+ @second_hash['positive'])
41
+ else # If we are excluding from collection
42
+ result['positive'] = @main_hash['positive']
43
+ uniqs = extract(@second_hash['negative'], @main_hash['positive'])
44
+ result['negative'] = summarize(uniqs, @main_hash['negative'])
41
45
  end
42
46
  result
43
47
  end
44
48
 
45
- # The most esoteric part of merging elements into collection
46
- # Now we are loosing nots tags if they are not good for us
47
- # As well we are loosing positive tags by merging them into alltags
48
- # symbol == *. The way out is to use arrays for tags.
49
- def options_merge
50
- temp = Hash.new
51
- temp['collection'] = @main_hash['options']['collection']
52
- POSITIVE.each do |key|
53
- value = @main_hash['options'][key]
54
- main_negative = @main_hash['options']["not_#{key}"]
55
- second_negative = @second_hash['options']["not_#{key}"]
56
- if (@second_hash['options'][key] == value) or
57
- ((@second_hash['options'][key].nil?) and (!value.nil?))
58
- temp[key] = value
59
- else
60
- temp[key] = "*"
61
- end
62
- if (second_negative != temp[key]) and
63
- ((second_negative == main_negative) or
64
- (main_negative.nil?))
65
- temp["not_#{key}"] = second_negative
66
- end
67
- end
68
- temp
49
+ # When black magic finds something
50
+ # she's not trusting dynamic attribute anymore. So she's forgetting
51
+ # unstable attributes and remembering stable and new ones
52
+ def forget_unstable
53
+ result = method_structure
54
+ result['options'] = @main_hash['options']
55
+ result['positive'] = merge(@main_hash['positive'],
56
+ @second_hash['positive'])
57
+ result['negative'] = extract(@main_hash['negative'],
58
+ @second_hash['positive'])
59
+ result
69
60
  end
70
61
 
71
- # This method will leave only common elements of both hashes
72
- def common_of(what)
73
- temp = Hash.new
74
- first, second = @main_hash[what], @second_hash[what]
75
- if !first.nil? and !second.nil?
76
- first.each_pair do |key, value|
77
- if second[key] == value
78
- temp[key] = value
79
- elsif second[key].class == Array and value.class == Array
80
- temp[key] = value & second[key]
62
+ # Recursive operations with method.
63
+ def do_arithmetic(first, second, what)
64
+ what == '+' ? result = second : result = Hash.new
65
+ first.each_pair do |key, value|
66
+ if value.is_a? Hash
67
+ result[key] = do_arithmetic(first[key], second[key], what)
68
+ elsif !second[key].nil? and !value.nil?
69
+ if what == '+'
70
+ result[key] = (first[key] + second[key]).uniq
71
+ elsif what == '&'
72
+ result[key] = first[key] & second[key]
73
+ elsif what == '-'
74
+ result[key] = first[key] - second[key]
75
+ elsif what == '*'
76
+ if (second[key] != [])
77
+ result[key] = first[key] & second[key]
78
+ end
81
79
  end
82
80
  end
83
- else
84
- temp = first
81
+ if (second[key] == [] or second[key].nil?) and
82
+ ((what == '+') or (what == '*'))
83
+ result[key] = first[key]
84
+ end
85
85
  end
86
- temp
86
+ result
87
87
  end
88
88
 
89
- # This method will leave all the elements of hashes. But if one attribute
90
- # is presented in both. Method will use the one from the main.
91
- # When it will be possible to use arrays for tags and attributes this
92
- # logic will be changed
93
- def all_of(what)
94
- temp = Hash.new
95
- first, second = @main_hash[what], @second_hash[what]
96
- if !first.nil?
97
- temp = first
98
- end
99
- if !second.nil? and !temp.nil?
100
- second.each_pair do |key, value|
101
- if (temp[key].nil?) or ((temp[key] != value) and
102
- (temp[key].class != Array) and (value.class != Array))
103
- temp[key] = value
104
- elsif (temp[key].class == Array) and (value.class == Array)
105
- temp[key] = (value + temp[key]).uniq
106
- end
107
- end
108
- if !first.nil?
109
- first.each_pair do |key, value|
110
- if second[key].nil? and !value.nil?
111
- temp[key] = nil
112
- end
113
- end
114
- end
115
- else
116
- temp = second
117
- end
118
- temp
89
+ # That is not a real merge. We are leaving everything that is the same
90
+ # or new and deleting everyting that is not the same
91
+ #
92
+ # Idea:
93
+ # merge({a:[1],b:[2],c:[3]},{a:[1],b:[2,3]}) #=> {a:[1],b:[2],c:[3]}
94
+ def merge(first, second)
95
+ do_arithmetic(second, first, '*')
119
96
  end
120
97
 
121
- # That is about excluding only attributes that are not presented as
122
- # positives.
123
- def passive_exclude(main, passive)
124
- temp = main
125
- not_temp = passive
126
- if !passive.nil?
127
- passive.each_pair do |key, value|
128
- if !main[key].nil?
129
- if main[key] == value
130
- not_temp[key] = value.class == Array ? []:nil
131
- elsif (value.class == Array) and (main[key].class == Array)
132
- not_temp[key] = value - main[key]
133
- end
134
- end
135
- end
136
- end
137
- return temp, not_temp
98
+ # Simple adding everyting to everything
99
+ #
100
+ # Idea:
101
+ # summarize({a:[1],c:[4]},{a:[2],b:[3]}) #=> {a:[1,2],b:[3],c:[4]}
102
+ def summarize(first, second)
103
+ do_arithmetic(second, do_arithmetic(first, second, '+'), '+')
104
+ end
105
+
106
+ # That will leave only the same options in the result
107
+ #
108
+ # Idea:
109
+ # multiply({a:[1,2],b:[2],c:[5]},{a:[1,3],b:[4],d:[0]}) #=> {a:[1],b:[2]}
110
+ def multiply(first, second)
111
+ do_arithmetic(first, second, '&')
112
+ end
113
+
114
+ # That will take out of the result all options of second
115
+ #
116
+ # Idea
117
+ # extract({a:[1,2],b:[2],c:[5]},{a:[2],c:[5],d:[0]}) #=> {a:[1],b:[2]}
118
+ def extract(first, second)
119
+ do_arithmetic(first, second, '-')
138
120
  end
139
121
  end
140
122
 
@@ -143,5 +125,11 @@ module Marta
143
125
  merger = MethodMerger.new(one, two)
144
126
  merger.do_collection
145
127
  end
128
+
129
+ # Forgetting unstable attributes leaving the same ones and new ones
130
+ def forget_unstable(old_one, new_one)
131
+ merger = MethodMerger.new(old_one, new_one)
132
+ merger.forget_unstable
133
+ end
146
134
  end
147
135
  end