marta 0.37396 → 0.41245

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.
@@ -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