glimmer-dsl-opal 0.2.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (94) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +47 -0
  3. data/README.md +1022 -190
  4. data/VERSION +1 -1
  5. data/app/assets/images/glimmer/images/calendar.gif +0 -0
  6. data/app/assets/images/glimmer/images/ui-icons_222222_256x240.png +0 -0
  7. data/app/assets/images/glimmer/images/ui-icons_444444_256x240.png +0 -0
  8. data/app/assets/images/glimmer/images/ui-icons_555555_256x240.png +0 -0
  9. data/app/assets/images/glimmer/images/ui-icons_777620_256x240.png +0 -0
  10. data/app/assets/images/glimmer/images/ui-icons_777777_256x240.png +0 -0
  11. data/app/assets/images/glimmer/images/ui-icons_cc0000_256x240.png +0 -0
  12. data/app/assets/images/glimmer/images/ui-icons_ffffff_256x240.png +0 -0
  13. data/app/assets/stylesheets/glimmer.css +15 -0
  14. data/app/assets/stylesheets/glimmer/jquery-ui.css +1312 -0
  15. data/app/assets/stylesheets/glimmer/jquery-ui.structure.css +886 -0
  16. data/app/assets/stylesheets/glimmer/jquery-ui.theme.css +443 -0
  17. data/app/assets/stylesheets/glimmer/jquery.ui.timepicker.css +57 -0
  18. data/lib/glimmer-dsl-opal.rb +23 -8
  19. data/lib/glimmer-dsl-opal/ext/date.rb +48 -0
  20. data/lib/glimmer-dsl-opal/samples/hello/hello_checkbox.rb +85 -0
  21. data/lib/glimmer-dsl-opal/samples/hello/hello_checkbox_group.rb +68 -0
  22. data/lib/glimmer-dsl-opal/samples/hello/hello_combo.rb +5 -5
  23. data/lib/glimmer-dsl-opal/samples/hello/hello_custom_shell.rb +3 -3
  24. data/lib/glimmer-dsl-opal/samples/hello/hello_custom_widget.rb +3 -3
  25. data/lib/glimmer-dsl-opal/samples/hello/hello_date_time.rb +63 -0
  26. data/lib/glimmer-dsl-opal/samples/hello/hello_group.rb +104 -0
  27. data/lib/glimmer-dsl-opal/samples/hello/hello_list_single_selection.rb +1 -1
  28. data/lib/glimmer-dsl-opal/samples/hello/hello_radio.rb +108 -0
  29. data/lib/glimmer-dsl-opal/samples/hello/hello_radio_group.rb +84 -0
  30. data/lib/glimmer-dsl-opal/vendor/jquery-ui-timepicker/GPL-LICENSE.txt +278 -0
  31. data/lib/glimmer-dsl-opal/vendor/jquery-ui-timepicker/MIT-LICENSE.txt +20 -0
  32. data/lib/glimmer-dsl-opal/vendor/jquery-ui-timepicker/jquery.ui.timepicker.css +57 -0
  33. data/lib/glimmer-dsl-opal/vendor/jquery-ui-timepicker/jquery.ui.timepicker.js +1496 -0
  34. data/lib/glimmer-dsl-opal/vendor/jquery-ui/AUTHORS.txt +333 -0
  35. data/lib/glimmer-dsl-opal/vendor/jquery-ui/LICENSE.txt +43 -0
  36. data/lib/glimmer-dsl-opal/vendor/jquery-ui/images/ui-icons_444444_256x240.png +0 -0
  37. data/lib/glimmer-dsl-opal/vendor/jquery-ui/images/ui-icons_555555_256x240.png +0 -0
  38. data/lib/glimmer-dsl-opal/vendor/jquery-ui/images/ui-icons_777620_256x240.png +0 -0
  39. data/lib/glimmer-dsl-opal/vendor/jquery-ui/images/ui-icons_777777_256x240.png +0 -0
  40. data/lib/glimmer-dsl-opal/vendor/jquery-ui/images/ui-icons_cc0000_256x240.png +0 -0
  41. data/lib/glimmer-dsl-opal/vendor/jquery-ui/images/ui-icons_ffffff_256x240.png +0 -0
  42. data/lib/glimmer-dsl-opal/vendor/jquery-ui/jquery-ui.min.css +7 -0
  43. data/lib/glimmer-dsl-opal/vendor/jquery-ui/jquery-ui.min.js +13 -0
  44. data/lib/glimmer-dsl-opal/vendor/jquery-ui/jquery-ui.structure.min.css +5 -0
  45. data/lib/glimmer-dsl-opal/vendor/jquery-ui/jquery-ui.theme.min.css +5 -0
  46. data/lib/glimmer-dsl-opal/vendor/jquery-ui/package.json +74 -0
  47. data/lib/glimmer-dsl-swt.rb +37 -0
  48. data/lib/glimmer/data_binding/element_binding.rb +2 -1
  49. data/lib/glimmer/dsl/opal/async_exec_expression.rb +23 -7
  50. data/lib/glimmer/dsl/opal/checkbox_group_selection_data_binding_expression.rb +61 -0
  51. data/lib/glimmer/dsl/opal/custom_widget_expression.rb +42 -5
  52. data/lib/glimmer/dsl/opal/display_expression.rb +40 -0
  53. data/lib/glimmer/dsl/opal/dsl.rb +7 -0
  54. data/lib/glimmer/dsl/opal/exec_expression.rb +55 -0
  55. data/lib/glimmer/dsl/opal/layout_expression.rb +1 -1
  56. data/lib/glimmer/dsl/opal/property_expression.rb +4 -3
  57. data/lib/glimmer/dsl/opal/radio_group_selection_data_binding_expression.rb +61 -0
  58. data/lib/glimmer/dsl/opal/shell_expression.rb +23 -1
  59. data/lib/glimmer/dsl/opal/swt_expression.rb +1 -1
  60. data/lib/glimmer/dsl/opal/sync_exec_expression.rb +33 -0
  61. data/lib/glimmer/dsl/opal/widget_expression.rb +5 -0
  62. data/lib/glimmer/engine.rb +9 -0
  63. data/lib/glimmer/swt.rb +3 -3
  64. data/lib/glimmer/swt/button_proxy.rb +15 -1
  65. data/lib/glimmer/swt/checkbox_proxy.rb +81 -0
  66. data/lib/glimmer/swt/combo_proxy.rb +4 -4
  67. data/lib/glimmer/swt/custom/checkbox_group.rb +142 -0
  68. data/lib/glimmer/swt/custom/radio_group.rb +143 -0
  69. data/lib/glimmer/swt/date_time_proxy.rb +144 -0
  70. data/lib/glimmer/swt/display_proxy.rb +55 -1
  71. data/lib/glimmer/swt/fill_layout_proxy.rb +2 -2
  72. data/lib/glimmer/swt/grid_layout_proxy.rb +21 -10
  73. data/lib/glimmer/swt/group_proxy.rb +38 -0
  74. data/lib/glimmer/swt/label_proxy.rb +27 -7
  75. data/lib/glimmer/swt/layout_data_proxy.rb +59 -6
  76. data/lib/glimmer/swt/layout_proxy.rb +2 -1
  77. data/lib/glimmer/swt/list_proxy.rb +2 -2
  78. data/lib/glimmer/swt/make_shift_shell_proxy.rb +38 -0
  79. data/lib/glimmer/swt/message_box_proxy.rb +7 -7
  80. data/lib/glimmer/swt/radio_proxy.rb +82 -0
  81. data/lib/glimmer/swt/row_layout_proxy.rb +35 -12
  82. data/lib/glimmer/swt/scrolled_composite_proxy.rb +20 -0
  83. data/lib/glimmer/swt/shell_proxy.rb +25 -10
  84. data/lib/glimmer/swt/styled_text_proxy.rb +44 -0
  85. data/lib/glimmer/swt/tab_folder_proxy.rb +3 -3
  86. data/lib/glimmer/swt/table_proxy.rb +10 -10
  87. data/lib/glimmer/swt/text_proxy.rb +2 -2
  88. data/lib/glimmer/swt/widget_proxy.rb +67 -33
  89. data/lib/glimmer/ui/custom_shell.rb +21 -2
  90. data/lib/glimmer/ui/custom_widget.rb +3 -1
  91. data/lib/{glimmer-dsl-opal/missing/net → net}/http.rb +0 -0
  92. data/lib/uri.rb +64 -0
  93. metadata +57 -4
  94. data/lib/glimmer-dsl-opal/missing/uri.rb +0 -26
@@ -2,7 +2,7 @@ require 'glimmer/swt/widget_proxy'
2
2
 
3
3
  module Glimmer
4
4
  module SWT
5
- class TabFolderProxy < WidgetProxy
5
+ class TabFolderProxy < WidgetProxy
6
6
  attr_reader :tabs
7
7
 
8
8
  def initialize(parent, args)
@@ -10,9 +10,9 @@ module Glimmer
10
10
  @tabs = []
11
11
  end
12
12
 
13
- def add_child(child)
13
+ def post_initialize_child(child)
14
14
  unless @children.include?(child)
15
- @children << child
15
+ @children << child
16
16
  tabs_dom_element.append(child.tab_dom)
17
17
  child.render
18
18
  end
@@ -16,11 +16,11 @@ module Glimmer
16
16
  end
17
17
 
18
18
  # Only table_columns may be added as children
19
- def add_child(child)
19
+ def post_initialize_child(child)
20
20
  if child.is_a?(TableColumnProxy)
21
21
  @columns << child
22
22
  else
23
- @children << child
23
+ @children << child
24
24
  end
25
25
  child.redraw
26
26
  end
@@ -36,14 +36,14 @@ module Glimmer
36
36
  changed.each(&:redraw)
37
37
  end
38
38
 
39
- def items=(new_items)
39
+ def items=(new_items)
40
40
  @children = new_items
41
41
  redraw
42
42
  end
43
43
 
44
44
  def search(&condition)
45
45
  items.select {|item| condition.nil? || condition.call(item)}
46
- end
46
+ end
47
47
 
48
48
  def index_of(item)
49
49
  items.index(item)
@@ -84,9 +84,9 @@ module Glimmer
84
84
  event.singleton_class.send(:define_method, :column_index) do
85
85
  (table_data || event.target).attr('data-column-index')
86
86
  end
87
- event_listener.call(event)
87
+ event_listener.call(event)
88
88
  }
89
- }
89
+ }
90
90
 
91
91
  {
92
92
  'on_mouse_down' => {
@@ -102,7 +102,7 @@ module Glimmer
102
102
 
103
103
  def redraw
104
104
  super()
105
- @columns.to_a.each(&:redraw)
105
+ @columns.to_a.each(&:redraw)
106
106
  end
107
107
 
108
108
  def element
@@ -125,7 +125,7 @@ module Glimmer
125
125
  Document.find(items_path)
126
126
  end
127
127
 
128
- def columns_dom
128
+ def columns_dom
129
129
  tr {
130
130
  }
131
131
  end
@@ -134,9 +134,9 @@ module Glimmer
134
134
  thead {
135
135
  columns_dom
136
136
  }
137
- end
137
+ end
138
138
 
139
- def items_dom
139
+ def items_dom
140
140
  tbody {
141
141
  }
142
142
  end
@@ -21,12 +21,12 @@ module Glimmer
21
21
  event_handler: -> (event_listener) {
22
22
  -> (event) {
23
23
  @text = event.target.value
24
- event_listener.call(event)
24
+ event_listener.call(event)
25
25
  }
26
26
  }
27
27
  }
28
28
  }
29
- end
29
+ end
30
30
 
31
31
  def dom
32
32
  text_text = @text
@@ -1,5 +1,5 @@
1
1
  # Copyright (c) 2020 Andy Maleh
2
- #
2
+ #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
5
5
  # "Software"), to deal in the Software without restriction, including
@@ -7,10 +7,10 @@
7
7
  # distribute, sublicense, and/or sell copies of the Software, and to
8
8
  # permit persons to whom the Software is furnished to do so, subject to
9
9
  # the following conditions:
10
- #
10
+ #
11
11
  # The above copyright notice and this permission notice shall be
12
12
  # included in all copies or substantial portions of the Software.
13
- #
13
+ #
14
14
  # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
15
  # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
16
  # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
@@ -29,13 +29,13 @@ module Glimmer
29
29
  include Glimmer
30
30
  include PropertyOwner
31
31
 
32
- attr_reader :parent, :args, :path, :children, :enabled, :foreground, :background, :font
32
+ attr_reader :parent, :args, :path, :children, :enabled, :foreground, :background, :font, :focus
33
33
 
34
34
  class << self
35
35
  # Factory Method that translates a Glimmer DSL keyword into a WidgetProxy object
36
36
  def for(keyword, parent, args)
37
37
  the_widget_class = widget_class(keyword)
38
- the_widget_class.new(parent, args)
38
+ the_widget_class.respond_to?(:create) ? the_widget_class.create(keyword, parent, args) : the_widget_class.new(parent, args)
39
39
  end
40
40
 
41
41
  def widget_class(keyword)
@@ -69,7 +69,7 @@ module Glimmer
69
69
 
70
70
  def underscored_widget_name(widget_proxy)
71
71
  widget_proxy.class.name.split(/::|\./).last.sub(/Proxy$/, '').underscore
72
- end
72
+ end
73
73
  end
74
74
 
75
75
  DEFAULT_INITIALIZERS = {
@@ -95,27 +95,38 @@ module Glimmer
95
95
  # "group" => lambda do |group_proxy|
96
96
  # group_proxy.layout = GridLayoutProxy.new(group_proxy, []) if group.layout.nil?
97
97
  # end,
98
- }
98
+ }
99
99
 
100
100
  def initialize(parent, args)
101
- @parent = parent
101
+ @parent = parent
102
102
  @args = args
103
103
  @children = Set.new # TODO consider moving to composite
104
104
  @enabled = true
105
105
  DEFAULT_INITIALIZERS[self.class.underscored_widget_name(self)]&.call(self)
106
- @parent.add_child(self) # TODO rename to post_initialize_child to be closer to glimmer-dsl-swt terminology
106
+ @parent.post_initialize_child(self) # TODO rename to post_initialize_child to be closer to glimmer-dsl-swt terminology
107
+ end
108
+
109
+ # Executes for the parent of a child that just got added
110
+ def post_initialize_child(child)
111
+ @children << child
112
+ child.render
113
+ end
114
+
115
+ # Executes at the closing of a parent widget curly braces after all children/properties have been added/set
116
+ def post_add_content
117
+ # No Op by default
107
118
  end
108
119
 
109
120
  def css_classes
110
121
  dom_element.attr('class').to_s.split
111
- end
122
+ end
112
123
 
113
124
  def dispose
114
125
  Document.find(path).remove
115
126
  end
116
127
 
117
128
  def path
118
- "#{parent_path} > #{element}##{id}.#{name}"
129
+ "#{parent_path} #{element}##{id}.#{name}"
119
130
  end
120
131
 
121
132
  # Root element representing widget. Must be overridden by subclasses if different from div
@@ -123,11 +134,6 @@ module Glimmer
123
134
  'div'
124
135
  end
125
136
 
126
- def add_child(child)
127
- @children << child
128
- child.render
129
- end
130
-
131
137
  def enabled=(value)
132
138
  @enabled = value
133
139
  dom_element.prop('disabled', !@enabled)
@@ -151,6 +157,16 @@ module Glimmer
151
157
  dom_element.css('font-size', "#{@font.height}px") unless @font.nil?
152
158
  end
153
159
 
160
+ def focus=(value)
161
+ @focus = value
162
+ dom_element.focus # TODO consider if a delay or async_exec is needed here
163
+ end
164
+
165
+ def set_focus
166
+ self.focus = true
167
+ end
168
+ alias setFocus set_focus
169
+
154
170
  def parent_path
155
171
  @parent.path
156
172
  end
@@ -172,14 +188,14 @@ module Glimmer
172
188
  end
173
189
  children.each do |child|
174
190
  child.render
175
- end
191
+ end
176
192
  end
177
193
  alias redraw render
178
194
 
179
195
  def build_dom
180
196
  @dom = nil
181
197
  @dom = dom
182
- @dom = @parent.layout.dom(@dom) if @parent.respond_to?(:layout) && @parent.layout
198
+ @dom = @parent.layout.dom(@dom) if @parent.respond_to?(:layout) && @parent.layout
183
199
  end
184
200
 
185
201
  def content(&block)
@@ -234,9 +250,12 @@ module Glimmer
234
250
  end
235
251
 
236
252
  def dom_element
253
+ # TODO consider making this pick an element in relation to its parent, allowing unhooked dom elements to be built if needed (unhooked to the visible page dom)
237
254
  Document.find(path)
238
255
  end
239
256
 
257
+ # TODO consider adding a default #dom method implementation for the common case, automatically relying on #element and other methods to build the dom html
258
+
240
259
  def style_element
241
260
  style_element_id = "#{id}-style"
242
261
  style_element_selector = "style##{style_element_id}"
@@ -259,7 +278,11 @@ module Glimmer
259
278
  path
260
279
  end
261
280
 
262
- def can_handle_observation_request?(observation_request)
281
+ def listener_dom_element
282
+ Document.find(listener_path)
283
+ end
284
+
285
+ def can_handle_observation_request?(observation_request)
263
286
  # TODO sort this out for Opal
264
287
  observation_request = observation_request.to_s
265
288
  if observation_request.start_with?('on_swt_')
@@ -270,7 +293,7 @@ module Glimmer
270
293
  # can_add_listener?(event) || can_handle_drag_observation_request?(observation_request) || can_handle_drop_observation_request?(observation_request)
271
294
  true # TODO filter by valid listeners only in the future
272
295
  end
273
- end
296
+ end
274
297
 
275
298
  def handle_observation_request(keyword, &event_listener)
276
299
  return unless observation_request_to_event_mapping.keys.include?(keyword)
@@ -284,7 +307,7 @@ module Glimmer
284
307
  event_handler = mapping[:event_handler]
285
308
  potential_event_listener = event_handler&.call(event_listener)
286
309
  event_listener = potential_event_listener || event_listener
287
- delegate = Document.find(listener_path).on(event, &event_listener)
310
+ delegate = listener_dom_element.on(event, &event_listener)
288
311
  end
289
312
  # TODO update code below for new WidgetProxy API
290
313
  EventListenerProxy.new(element_proxy: self, event: event, selector: selector, delegate: delegate)
@@ -352,9 +375,6 @@ module Glimmer
352
375
  # else
353
376
  # value
354
377
  # end
355
- # end,
356
- # :items => lambda do |value|
357
- # value.to_java :string
358
378
  # end,
359
379
  :text => lambda do |value|
360
380
  # if swt_widget.is_a?(Browser)
@@ -366,8 +386,8 @@ module Glimmer
366
386
  # :visible => lambda do |value|
367
387
  # !!value
368
388
  # end,
369
- }
370
- end
389
+ }
390
+ end
371
391
 
372
392
  def widget_property_listener_installers
373
393
  @swt_widget_property_listener_installers ||= {
@@ -446,13 +466,20 @@ module Glimmer
446
466
  # }
447
467
  # end,
448
468
  # },
449
- # Button => { #radio?
450
- # :selection => lambda do |observer|
451
- # on_widget_selected { |selection_event|
452
- # observer.call(getSelection)
453
- # }
454
- # end
455
- # },
469
+ DateTimeProxy => { #radio?
470
+ :date_time => lambda do |observer|
471
+ on_widget_selected { |selection_event|
472
+ observer.call(date_time)
473
+ }
474
+ end
475
+ },
476
+ RadioProxy => { #radio?
477
+ :selection => lambda do |observer|
478
+ on_widget_selected { |selection_event|
479
+ observer.call(selection)
480
+ }
481
+ end
482
+ },
456
483
  # Java::OrgEclipseSwtWidgets::MenuItem => {
457
484
  # :selection => lambda do |observer|
458
485
  # on_widget_selected { |selection_event|
@@ -477,14 +504,21 @@ end
477
504
  require 'glimmer/swt/browser_proxy'
478
505
  require 'glimmer/swt/button_proxy'
479
506
  require 'glimmer/swt/combo_proxy'
507
+ require 'glimmer/swt/checkbox_proxy'
480
508
  require 'glimmer/swt/composite_proxy'
509
+ require 'glimmer/swt/date_time_proxy'
510
+ require 'glimmer/swt/group_proxy'
481
511
  require 'glimmer/swt/label_proxy'
482
512
  require 'glimmer/swt/list_proxy'
513
+ require 'glimmer/swt/radio_proxy'
483
514
  require 'glimmer/swt/tab_folder_proxy'
484
515
  require 'glimmer/swt/tab_item_proxy'
485
516
  require 'glimmer/swt/table_column_proxy'
486
517
  require 'glimmer/swt/table_item_proxy'
487
518
  require 'glimmer/swt/table_proxy'
488
519
  require 'glimmer/swt/text_proxy'
520
+ require 'glimmer/swt/radio_proxy'
521
+ require 'glimmer/swt/scrolled_composite_proxy'
522
+ require 'glimmer/swt/styled_text_proxy'
489
523
 
490
524
  require 'glimmer/dsl/opal/widget_expression'
@@ -19,6 +19,8 @@
19
19
  # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
20
  # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
21
 
22
+ require 'glimmer/ui/custom_widget'
23
+ require 'glimmer/swt/display_proxy'
22
24
  require 'glimmer/error'
23
25
 
24
26
  module Glimmer
@@ -32,15 +34,32 @@ module Glimmer
32
34
  klass.include(Glimmer)
33
35
  Glimmer::UI::CustomWidget.add_custom_widget_namespaces_for(klass)
34
36
  end
37
+
38
+ def request_parameter_string
39
+ URI.decode_www_form_component(`document.location.href`.match(/\?(.*)$/).to_a[1].to_s)
40
+ end
41
+
42
+ def encoded_request_parameter_string
43
+ `document.location.href`.match(/\?(.*)$/).to_a[1].to_s
44
+ end
45
+
46
+ def requested_and_not_handled?
47
+ requested? && !request_parameter_string.include?('custom_shell_handled=true')
48
+ end
49
+
50
+ def requested?
51
+ request_parameter_string.include?('custom_shell=')
52
+ end
35
53
  end
36
54
 
37
55
  def initialize(parent, args, options, &content)
38
- super
39
- raise Error, 'Invalid custom shell body root! Must be a shell or another custom shell.' unless body_root.is_a?(Glimmer::SWT::ShellProxy)
56
+ super(parent, args, options, &content)
57
+ raise Error, 'Invalid custom shell body root! Must be a shell or another custom shell.' unless body_root.is_a?(Glimmer::SWT::ShellProxy) || body_root.is_a?(Glimmer::UI::CustomShell)
40
58
  end
41
59
 
42
60
  # Classes may override
43
61
  def open
62
+ # TODO consider the idea of delaying rendering till the open method
44
63
  body_root.open
45
64
  end
46
65
 
@@ -157,8 +157,10 @@ module Glimmer
157
157
  options = args
158
158
  args = []
159
159
  end
160
+ options ||= {}
161
+ args = options.delete('swt_style').split(',').map(&:to_sym) if options['swt_style']
160
162
  @args = args
161
- @swt_style = SWT::SWTProxy[*args]
163
+ @swt_style = SWT::SWTProxy[*@args]
162
164
  options ||= {}
163
165
  @options = self.class.options.merge(options)
164
166
  @content = Util::ProcTracker.new(content) if content
@@ -0,0 +1,64 @@
1
+ # Missing URI module class features
2
+
3
+ module URI
4
+ class HTTP
5
+ REGEX = /([^:]+):\/\/([^\/])\/([^?]*)\??(.*)/
6
+
7
+ def initialize(url)
8
+ @url = url
9
+ uri_match = url.match(REGEX)
10
+ @scheme = uri_match[1]
11
+ @host = uri_match[2]
12
+ @path = uri_match[3]
13
+ @query = uri_match[4]
14
+ # TODO fragment
15
+ end
16
+
17
+ def to_s
18
+ url
19
+ end
20
+ end
21
+
22
+ TBLENCWWWCOMP_ = {"\u0000"=>"%00", "\u0001"=>"%01", "\u0002"=>"%02", "\u0003"=>"%03", "\u0004"=>"%04", "\u0005"=>"%05", "\u0006"=>"%06", "\a"=>"%07", "\b"=>"%08", "\t"=>"%09", "\n"=>"%0A", "\v"=>"%0B", "\f"=>"%0C", "\r"=>"%0D", "\u000E"=>"%0E", "\u000F"=>"%0F", "\u0010"=>"%10", "\u0011"=>"%11", "\u0012"=>"%12", "\u0013"=>"%13", "\u0014"=>"%14", "\u0015"=>"%15", "\u0016"=>"%16", "\u0017"=>"%17", "\u0018"=>"%18", "\u0019"=>"%19", "\u001A"=>"%1A", "\e"=>"%1B", "\u001C"=>"%1C", "\u001D"=>"%1D", "\u001E"=>"%1E", "\u001F"=>"%1F", " "=>"+", "!"=>"%21", "\""=>"%22", "#"=>"%23", "$"=>"%24", "%"=>"%25", "&"=>"%26", "'"=>"%27", "("=>"%28", ")"=>"%29", "*"=>"%2A", "+"=>"%2B", ","=>"%2C", "-"=>"%2D", "."=>"%2E", "/"=>"%2F", "0"=>"%30", "1"=>"%31", "2"=>"%32", "3"=>"%33", "4"=>"%34", "5"=>"%35", "6"=>"%36", "7"=>"%37", "8"=>"%38", "9"=>"%39", ":"=>"%3A", ";"=>"%3B", "<"=>"%3C", "="=>"%3D", ">"=>"%3E", "?"=>"%3F", "@"=>"%40", "A"=>"%41", "B"=>"%42", "C"=>"%43", "D"=>"%44", "E"=>"%45", "F"=>"%46", "G"=>"%47", "H"=>"%48", "I"=>"%49", "J"=>"%4A", "K"=>"%4B", "L"=>"%4C", "M"=>"%4D", "N"=>"%4E", "O"=>"%4F", "P"=>"%50", "Q"=>"%51", "R"=>"%52", "S"=>"%53", "T"=>"%54", "U"=>"%55", "V"=>"%56", "W"=>"%57", "X"=>"%58", "Y"=>"%59", "Z"=>"%5A", "["=>"%5B", "\\"=>"%5C", "]"=>"%5D", "^"=>"%5E", "_"=>"%5F", "`"=>"%60", "a"=>"%61", "b"=>"%62", "c"=>"%63", "d"=>"%64", "e"=>"%65", "f"=>"%66", "g"=>"%67", "h"=>"%68", "i"=>"%69", "j"=>"%6A", "k"=>"%6B", "l"=>"%6C", "m"=>"%6D", "n"=>"%6E", "o"=>"%6F", "p"=>"%70", "q"=>"%71", "r"=>"%72", "s"=>"%73", "t"=>"%74", "u"=>"%75", "v"=>"%76", "w"=>"%77", "x"=>"%78", "y"=>"%79", "z"=>"%7A", "{"=>"%7B", "|"=>"%7C", "}"=>"%7D", "~"=>"%7E", "\u007F"=>"%7F", "\u0080"=>"%80", "\u0081"=>"%81", "\u0082"=>"%82", "\u0083"=>"%83", "\u0084"=>"%84", "\u0085"=>"%85", "\u0086"=>"%86", "\u0087"=>"%87", "\u0088"=>"%88", "\u0089"=>"%89", "\u008A"=>"%8A", "\u008B"=>"%8B", "\u008C"=>"%8C", "\u008D"=>"%8D", "\u008E"=>"%8E", "\u008F"=>"%8F", "\u0090"=>"%90", "\u0091"=>"%91", "\u0092"=>"%92", "\u0093"=>"%93", "\u0094"=>"%94", "\u0095"=>"%95", "\u0096"=>"%96", "\u0097"=>"%97", "\u0098"=>"%98", "\u0099"=>"%99", "\u009A"=>"%9A", "\u009B"=>"%9B", "\u009C"=>"%9C", "\u009D"=>"%9D", "\u009E"=>"%9E", "\u009F"=>"%9F", "\u00A0"=>"%A0", "\u00A1"=>"%A1", "\u00A2"=>"%A2", "\u00A3"=>"%A3", "\u00A4"=>"%A4", "\u00A5"=>"%A5", "\u00A6"=>"%A6", "\u00A7"=>"%A7", "\u00A8"=>"%A8", "\u00A9"=>"%A9", "\u00AA"=>"%AA", "\u00AB"=>"%AB", "\u00AC"=>"%AC", "\u00AD"=>"%AD", "\u00AE"=>"%AE", "\u00AF"=>"%AF", "\u00B0"=>"%B0", "\u00B1"=>"%B1", "\u00B2"=>"%B2", "\u00B3"=>"%B3", "\u00B4"=>"%B4", "\u00B5"=>"%B5", "\u00B6"=>"%B6", "\u00B7"=>"%B7", "\u00B8"=>"%B8", "\u00B9"=>"%B9", "\u00BA"=>"%BA", "\u00BB"=>"%BB", "\u00BC"=>"%BC", "\u00BD"=>"%BD", "\u00BE"=>"%BE", "\u00BF"=>"%BF", "\u00C0"=>"%C0", "\u00C1"=>"%C1", "\u00C2"=>"%C2", "\u00C3"=>"%C3", "\u00C4"=>"%C4", "\u00C5"=>"%C5", "\u00C6"=>"%C6", "\u00C7"=>"%C7", "\u00C8"=>"%C8", "\u00C9"=>"%C9", "\u00CA"=>"%CA", "\u00CB"=>"%CB", "\u00CC"=>"%CC", "\u00CD"=>"%CD", "\u00CE"=>"%CE", "\u00CF"=>"%CF", "\u00D0"=>"%D0", "\u00D1"=>"%D1", "\u00D2"=>"%D2", "\u00D3"=>"%D3", "\u00D4"=>"%D4", "\u00D5"=>"%D5", "\u00D6"=>"%D6", "\u00D7"=>"%D7", "\u00D8"=>"%D8", "\u00D9"=>"%D9", "\u00DA"=>"%DA", "\u00DB"=>"%DB", "\u00DC"=>"%DC", "\u00DD"=>"%DD", "\u00DE"=>"%DE", "\u00DF"=>"%DF", "\u00E0"=>"%E0", "\u00E1"=>"%E1", "\u00E2"=>"%E2", "\u00E3"=>"%E3", "\u00E4"=>"%E4", "\u00E5"=>"%E5", "\u00E6"=>"%E6", "\u00E7"=>"%E7", "\u00E8"=>"%E8", "\u00E9"=>"%E9", "\u00EA"=>"%EA", "\u00EB"=>"%EB", "\u00EC"=>"%EC", "\u00ED"=>"%ED", "\u00EE"=>"%EE", "\u00EF"=>"%EF", "\u00F0"=>"%F0", "\u00F1"=>"%F1", "\u00F2"=>"%F2", "\u00F3"=>"%F3", "\u00F4"=>"%F4", "\u00F5"=>"%F5", "\u00F6"=>"%F6", "\u00F7"=>"%F7", "\u00F8"=>"%F8", "\u00F9"=>"%F9", "\u00FA"=>"%FA", "\u00FB"=>"%FB", "\u00FC"=>"%FC", "\u00FD"=>"%FD", "\u00FE"=>"%FE", "\u00FF"=>"%FF"}
23
+ TBLDECWWWCOMP_ = TBLENCWWWCOMP_.invert
24
+
25
+ # Encodes given +str+ to URL-encoded form data.
26
+ #
27
+ # This method doesn't convert *, -, ., 0-9, A-Z, _, a-z, but does convert SP
28
+ # (ASCII space) to + and converts others to %XX.
29
+ #
30
+ # If +enc+ is given, convert +str+ to the encoding before percent encoding.
31
+ #
32
+ # This is an implementation of
33
+ # https://www.w3.org/TR/2013/CR-html5-20130806/forms.html#url-encoded-form-data.
34
+ #
35
+ # See URI.decode_www_form_component, URI.encode_www_form.
36
+ def self.encode_www_form_component(str, enc=nil)
37
+ str = str.to_s.dup
38
+ if str.encoding != Encoding::ASCII_8BIT
39
+ if enc && enc != Encoding::ASCII_8BIT
40
+ str.encode!(Encoding::UTF_8, invalid: :replace, undef: :replace)
41
+ str.encode!(enc, fallback: ->(x){"&##{x.ord};"})
42
+ end
43
+ str.force_encoding(Encoding::ASCII_8BIT)
44
+ end
45
+ str = str.gsub(/[^*\-.0-9A-Z_a-z]/, TBLENCWWWCOMP_)
46
+ str.force_encoding(Encoding::US_ASCII)
47
+ end
48
+
49
+ # Decodes given +str+ of URL-encoded form data.
50
+ #
51
+ # This decodes + to SP.
52
+ #
53
+ # See URI.encode_www_form_component, URI.decode_www_form.
54
+ def self.decode_www_form_component(str, enc=Encoding::UTF_8)
55
+ raise ArgumentError, "invalid %-encoding (#{str})" if /%(?![0-9a-fA-F][0-9a-fA-F])/ =~ str
56
+ str.b.gsub(/\+|%[0-9a-fA-F][0-9a-fA-F]/, TBLDECWWWCOMP_).force_encoding(enc)
57
+ end
58
+ end
59
+
60
+ module Kernel
61
+ def URI(url)
62
+ URI::HTTP.new(url)
63
+ end
64
+ end