intranet-core 2.3.2 → 2.4.3

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c7e47a94a48b6d2b3f4c65189c7fc94327e5f53de9a899bcb28da2258e6070fb
4
- data.tar.gz: add7936f6332a55e6c941a921d6640f1cbfdaab2cb898f5379ee00a22a64d518
3
+ metadata.gz: 1ec24599dbce60c41fef56f0b85a08c58ee76643bae4b3248841e699ebd90d0a
4
+ data.tar.gz: 93d61e93f4af53fbe8edad6f7a61f15d6161e9cdaf4406cce50f40a09f857a90
5
5
  SHA512:
6
- metadata.gz: 88b987f64a395931ef5da9cd12988d6b0d798428511cda1e23b10ae36ed8f7e50460fc2ccfb1faf89aaa8f6c2e36f97ccb730d0be7f6b401df6ceb61e93b6981
7
- data.tar.gz: eaf83db0c2c7a1c1692659a3a2442741972fbf75248da2bbd6ef012d37be3dc1434d1155099fc9767f318373802490eaf8c11dd4ef881b21440586e52d2b1a2a
6
+ metadata.gz: 7bfb357b1734def2604f7a5cfc0e5829e0418b213cf52e7e5eaf1a3e9cf43ad1640cb5144748b924ce435e4ce389224def7a8bfa332682c3891428803e7708b5
7
+ data.tar.gz: a233871543d39b35eeda9c88464a0798b4b77936fac200b1f268ffaa59d40d6e4facf4a926c585d2baac472f72c277347497575c3e3be7b6429f39ac865c7889
@@ -37,30 +37,44 @@ module Intranet
37
37
  # nothing to do
38
38
  end
39
39
 
40
- # Generates the HTML content associated to the given +path+ and +query+.
40
+ # Generates the HTML answer (HTTP return code, MIME type and body) associated to the given
41
+ # +path+ and +query+.
42
+ #
43
+ # The function may return a partial content, in which case the HTTP return code must be 206 and
44
+ # the answer body is expected to be a +Hash+ with the following keys:
45
+ # * +:title+ (mandatory): the page title
46
+ # * +:content+ (mandatory): the partial content
47
+ # * +:stylesheets+ (optional): an array of the required Cascade Style Sheets (CSS) files, either
48
+ # absolute or relative to the module root
49
+ # * +:scripts+ (optional): an array of hashes, each representing a <script> element to be
50
+ # included in the generated page. Keys are the one accepted by the HTML <script> tag. The
51
+ # +:src+ key may be either absolute or relative to the module root
41
52
  # @param path [String] The requested URI, relative to that module root URI
42
53
  # @param query [Hash] The URI variable/value pairs, if any
43
- # @return [Array] The HTTP return code, the MIME type and the answer body.
54
+ # @return [Array<Integer, String, String> or Array<Integer, String, Hash>] The HTTP return code,
55
+ # the MIME type and the answer body (partial if return code is 206).
44
56
  def generate_page(path, query)
45
57
  [404, '', '']
46
58
  end
47
59
 
48
60
  # Provides the list of Cascade Style Sheets (CSS) dependencies for this module, either using
49
61
  # absolute or relative (from the module root) paths.
50
- # If redefined, this method should probably append dependencies rather than overwriting them.
62
+ # @deprecated Use {generate_page} partial content feature, setting +:stylesheets+ attribute of
63
+ # the returned body.
51
64
  # @return [Array] The list of CSS dependencies, as absolute path or relative to the module root
52
65
  # URL.
53
66
  def css_dependencies
54
- ['/design/style.css']
67
+ []
55
68
  end
56
69
 
57
70
  # Provides the list of Javascript files (JS) dependencies for this module, either using
58
71
  # absolute or relative (from the module root) paths.
59
- # If redefined, this method should probably append dependencies rather than overwriting them.
72
+ # @deprecated Use {generate_page} partial content feature, setting +:scripts+ attribute of the
73
+ # returned body.
60
74
  # @return [Array] The list of JS dependencies, as absolute path or relative to the module root
61
75
  # URL.
62
76
  def js_dependencies
63
- ['/design/nav.js']
77
+ []
64
78
  end
65
79
  end
66
80
  end
@@ -117,8 +117,9 @@ module Intranet
117
117
  # @param responder [Intranet::AbstractResponder] The responder that produced the body
118
118
  # @param path [String] The path to the responder
119
119
  def add_header_and_footer(body, responder, path)
120
- to_markup('skeleton', body: body, css: responder.css_dependencies,
121
- js: responder.js_dependencies, current_path: path)
120
+ body[:stylesheets] ||= responder.css_dependencies
121
+ body[:scripts] ||= responder.js_dependencies.map { |url| { src: url, defer: 'defer' } }
122
+ to_markup('skeleton', body: body, current_path: path)
122
123
  end
123
124
 
124
125
  # Check whether a path is valid. In particular, this function excludes a path containing an
@@ -6,7 +6,7 @@ module Intranet
6
6
  NAME = 'intranet-core'
7
7
 
8
8
  # The version of the gem, according to semantic versionning.
9
- VERSION = '2.3.2'
9
+ VERSION = '2.4.3'
10
10
 
11
11
  # The URL of the gem homepage.
12
12
  HOMEPAGE_URL = 'https://rubygems.org/gems/intranet-core'
data/lib/intranet/core.rb CHANGED
@@ -91,10 +91,11 @@ module Intranet
91
91
  # See https://github.com/nahi/webrick/blob/master/lib/webrick/accesslog.rb#L69
92
92
  ACCESSLOG_FMT = "%h '%r' -> %s (%b bytes in %Ts)"
93
93
 
94
- def load_http_server(preferred_port)
94
+ def load_http_server(preferred_port) # rubocop:disable Metrics/MethodLength
95
95
  @port = preferred_port
96
96
  begin
97
- WEBrick::HTTPServer.new(Port: @port, Logger: @logger, AccessLog: [[@logger, ACCESSLOG_FMT]])
97
+ WEBrick::HTTPServer.new(Port: @port, Logger: @logger, AccessLog: [[@logger, ACCESSLOG_FMT]],
98
+ ServerSoftware: nil)
98
99
  rescue Errno::EACCES # not enough permission to use port 80
99
100
  @port = 8080
100
101
  retry
@@ -3,24 +3,23 @@
3
3
  %head
4
4
  %title= Socket.gethostname.capitalize + ' | ' + body[:title]
5
5
  %meta{charset: 'utf-8'}
6
+ %meta{name: 'viewport', content: 'width=device-width, initial-scale=1.0'}
6
7
  %link{rel: 'icon', type: 'image/x-icon', href: '/design/favicon.ico'}
7
- - css.each do |url|
8
- - if url.start_with?('/')
9
- %link{rel: 'stylesheet', type: 'text/css', href: url}
10
- - else
11
- %link{rel: 'stylesheet', type: 'text/css', href: current_path + '/' + url}
12
- - js.each do |url|
13
- - if url.start_with?('/')
14
- %script{src: url, defer: 'defer'}
15
- - else
16
- %script{src: current_path + '/' + url, defer: 'defer'}
8
+ %link{rel: 'stylesheet', type: 'text/css', href: '/design/style.css'}
9
+ - body[:stylesheets].each do |url|
10
+ - url = current_path + '/' + url unless url.start_with?('/')
11
+ %link{rel: 'stylesheet', type: 'text/css', href: url}
12
+ %script{type: 'module', src: '/design/nav.js'}
13
+ - body[:scripts].each do |script|
14
+ - script[:src] = current_path + '/' + script[:src] unless script[:src].start_with?('/')
15
+ %script{script}
17
16
  %body
18
17
  %header
19
- %a{id: 'openmenu', onclick: 'openNavMenu();'}= '&#9776;'
18
+ %a{id: 'openmenu'}= '&#9776;'
20
19
  %h1
21
20
  %a{href: '/index.html', title: I18n.t('nav.back.home')}= Socket.gethostname.capitalize
22
21
  %nav
23
- %a{id: 'closemenu', onclick: 'closeNavMenu();'}= '&times;'
22
+ %a{id: 'closemenu'}= '&times;'
24
23
  %ul
25
24
  - responders.children_nodes.each do |path, node|
26
25
  - if node.children?
@@ -48,7 +47,7 @@
48
47
  = ' ' + I18n.t('nav.generated.on_date') + ' ' + Time.now.strftime(I18n.t('date_format'))
49
48
  = ' ' + I18n.t('date_time_separator') + Time.now.strftime(I18n.t('time_format'))
50
49
  %br
51
- %a{onclick: 'openModal();'}= I18n.t('nav.about')
50
+ %a{id: 'openmodal'}= I18n.t('nav.about')
52
51
  %aside#modal
53
52
  %div#modal-content
54
53
  %h2= 'Intranet'
@@ -4,23 +4,13 @@
4
4
  * and for the modal box.
5
5
  */
6
6
 
7
+ const openMenu = document.getElementById('openmenu');
8
+ const closeMenu = document.getElementById('closemenu');
9
+ const navMenu = document.querySelectorAll('header nav')[0];
10
+ openMenu.addEventListener('click', function() { navMenu.style.width = 'auto'; });
11
+ closeMenu.addEventListener('click', function() { navMenu.style.width = ''; });
7
12
 
8
- function openNavMenu() {
9
- document.querySelectorAll('header nav')[0].style.width = 'auto';
10
- }
11
-
12
- function closeNavMenu() {
13
- /* Remove value property set in openNavMenu() */
14
- document.querySelectorAll('header nav')[0].style.width = '';
15
- }
16
-
17
- function openModal() {
18
- document.getElementById('modal').style.display = 'block';
19
- }
20
-
21
- window.onclick = function(event) {
22
- if (event.target == document.getElementById('modal')) {
23
- document.getElementById('modal').style.display = 'none';
24
- }
25
- }
26
-
13
+ const openModal = document.getElementById('openmodal');
14
+ const modal = document.getElementById('modal');
15
+ openModal.addEventListener('click', function() { modal.style.display = 'block'; });
16
+ modal.addEventListener('click', function() { modal.style.display = 'none'; });
@@ -21,7 +21,7 @@ body, html {
21
21
  height: 100%;
22
22
  }
23
23
  body {
24
- background: #1e262b;
24
+ background: #f7f8fa;
25
25
  font-family: "Source Sans Pro", Cantarell, sans-serif;
26
26
  color: black;
27
27
  font-size: 1.0rem;
@@ -30,12 +30,6 @@ body {
30
30
  -ms-text-size-adjust: none;
31
31
  font-size-adjust: none;
32
32
  }
33
- /* Mobile devices only */
34
- @media only screen and (max-width: 600px), only screen and (max-device-width: 600px) {
35
- body {
36
- font-size: 1.8rem;
37
- }
38
- }
39
33
 
40
34
  a {
41
35
  color: inherit;
@@ -45,67 +39,67 @@ a {
45
39
 
46
40
  /******************************************* Navigation *******************************************/
47
41
 
48
- header {
42
+ body > header {
49
43
  position: fixed;
50
44
  top: 0px;
51
45
  width: 100%;
52
46
  margin: auto;
53
47
  background-color: #1e262b;
54
48
  color: white;
55
- z-index: 2;
49
+ z-index: 10;
56
50
  }
57
- header h1 {
51
+ body > header h1 {
58
52
  float: left;
59
53
  font-size: 2.25em;
60
54
  font-weight: 500;
61
55
  margin: 0px;
62
56
  padding: 5px 20px 8px; /* top sides bottom */
63
57
  }
64
- header nav {
58
+ body > header nav {
65
59
  float: right;
66
60
  padding: 0px 20px;
67
61
  }
68
- header nav ul {
62
+ body > header nav ul {
69
63
  margin: 0px;
70
64
  padding: 0px;
71
65
  }
72
- header nav > ul > li {
66
+ body > header nav > ul > li {
73
67
  display: inline-block;
74
68
  }
75
- header nav > ul > li a, header a#closemenu {
69
+ body > header nav > ul > li a {
76
70
  display: block;
77
71
  padding: 16px 20px;
78
72
  margin: 0px;
79
73
  font-size: 1.25em;
80
74
  color: rgba(255, 255, 255, 0.7);
81
75
  }
82
- header nav > ul > li a:hover {
76
+ body > header nav > ul > li a:hover {
83
77
  color: rgba(255, 255, 255, 1.0);
84
78
  }
85
79
 
86
80
  /* dropdown menus */
87
- header nav > ul > li > ul {
81
+ body > header nav > ul > li > ul {
88
82
  display: none;
89
83
  background-color: #1e262b;
90
84
  position: absolute;
91
85
  }
92
- header nav > ul > li > ul > li {
86
+ body > header nav > ul > li > ul > li {
93
87
  display: block;
94
88
  }
95
- header nav > ul > li > ul > li a {
89
+ body > header nav > ul > li > ul > li a {
96
90
  padding: 8px 20px;
97
91
  }
98
- header nav > ul > li:hover > ul, header nav > ul > li:active > ul {
92
+ body > header nav > ul > li:hover > ul, body > header nav > ul > li:active > ul {
99
93
  display: block;
100
94
  }
101
95
 
102
- header a#openmenu, header a#closemenu {
96
+ body > header a#openmenu, body > header a#closemenu {
103
97
  display: none;
104
98
  }
105
99
 
106
100
  /* Mobile devices only */
107
101
  @media only screen and (max-width: 600px), only screen and (max-device-width: 600px) {
108
- header a#openmenu {
102
+ body > header a#openmenu {
109
103
  display: block;
110
104
  position: absolute;
111
105
  top: 12%;
@@ -114,7 +108,7 @@ header a#openmenu, header a#closemenu {
114
108
  font-weight: bold;
115
109
  color: white;
116
110
  }
117
- header nav a#closemenu {
111
+ body > header nav a#closemenu {
118
112
  display: block;
119
113
  font-size: 2.5em;
120
114
  font-weight: bold;
@@ -122,48 +116,40 @@ header a#openmenu, header a#closemenu {
122
116
  text-align: right;
123
117
  margin-right: 0.5em;
124
118
  }
125
- header h1 {
119
+ body > header h1 {
126
120
  float: none;
127
121
  text-align: center;
128
122
  }
129
- header nav {
123
+ body > header nav {
130
124
  position: fixed;
131
125
  top: 0;
132
126
  left: 0;
133
127
  height: 100%;
134
128
  padding: 0;
135
- z-index: 1;
129
+ z-index: 20;
136
130
  background: inherit;
137
131
  font-size: 1.25em;
138
132
  overflow-y: scroll;
139
133
  width: 0;
140
134
  max-width: 100%;
141
135
  }
142
- header nav > ul {
136
+ body > header nav > ul {
143
137
  height: auto;
144
- margin: 0px 0px 50px; /* top sides bottom */
145
138
  }
146
- header nav > ul > li {
139
+ body > header nav > ul > li {
147
140
  display: block;
148
141
  }
149
- header nav > ul > li a {
150
- color: rgba(255, 255, 255, 1.0);
151
- margin-top: 35px;
142
+ body > header nav > ul > li a {
152
143
  padding: 10px 150px 10px 40px; /* top right bottom left */
153
144
  }
154
- header nav > ul > li > ul {
145
+ body > header nav > ul > li > ul {
155
146
  display: block;
156
147
  position: static; /* reset absolute positionning */
157
148
  }
158
- header nav > ul > li > ul > li a {
159
- color: rgba(255, 255, 255, 0.7);
149
+ body > header nav > ul > li > ul > li a {
160
150
  margin: 0px;
161
151
  padding: 10px 100px 10px 90px; /* top right bottom left */
162
152
  }
163
- header nav li a:hover {
164
- color: inherit;
165
- background-color: #c2c2c2;
166
- }
167
153
  }
168
154
 
169
155
  /* breadcrumb navigation menu */
@@ -180,7 +166,7 @@ ul.breadcrumb li+li:before {
180
166
  padding: 4px;
181
167
  content: "/\00a0";
182
168
  }
183
- ul.breadcrumb li a, main article a {
169
+ main a {
184
170
  color: #748ea3;
185
171
  }
186
172
 
@@ -191,18 +177,16 @@ ul.breadcrumb li a, main article a {
191
177
  }
192
178
  }
193
179
 
194
- /******************************** Main content *******************************/
180
+ /****************************************** Main content ******************************************/
195
181
 
196
182
  body > main {
197
- background: #f7f8fa;
198
- padding: 57px 0px; /* height of the navigation bar */
199
- }
200
-
201
- body > main section, body > main article, body > main hr, body > footer p {
202
- width: 75%;
203
- max-width: 1200px;
183
+ padding: 58px 0px; /* height of the navigation bar */
184
+ width: 85%;
185
+ max-width: 1366px;
204
186
  margin: auto;
187
+ min-height: calc(100vh - 2*58px - 66px); /* 2*height of nav bar + height of footer */
205
188
  }
189
+
206
190
  body > main hr {
207
191
  height: 2px;
208
192
  border: 0px;
@@ -213,10 +197,7 @@ body > main hr {
213
197
 
214
198
  /* Mobile devices only */
215
199
  @media only screen and (max-width: 600px), only screen and (max-device-width: 600px) {
216
- body > main {
217
- padding: 100px 0px;
218
- }
219
- body > main section, main hr, footer p {
200
+ body > main section, body > main hr, body > footer p {
220
201
  width: 90%;
221
202
  }
222
203
  }
@@ -248,19 +229,23 @@ body > main div.loading {
248
229
  100% { transform: rotate(360deg); }
249
230
  }
250
231
 
232
+ /********************************************* Footer *********************************************/
233
+
251
234
  body > footer {
252
235
  background: #1e262b;
253
236
  text-align: center;
254
237
  color: white;
255
- padding: 15px 0px; /* top sides */
238
+ padding: 0px;
256
239
  }
257
240
  body > footer p {
258
241
  font-size: 0.85em;
242
+ padding: 15px 0px; /* top sides */
243
+ margin: 0px;
259
244
  }
260
245
  body > footer aside#modal { /* modal box container */
261
246
  display: none;
262
247
  position: fixed;
263
- z-index: 10;
248
+ z-index: 1000;
264
249
  left: 0;
265
250
  top: 0;
266
251
  width: 100%;
@@ -276,7 +261,9 @@ body > footer aside#modal #modal-content { /* modal box */
276
261
  transform: translateY(-50%);
277
262
  padding: 20px 25px 40px; /* top sides bottom */
278
263
  border: 1px solid #1e262b;
279
- width: 425px;
264
+ width: 25%;
265
+ max-width: 425px;
266
+ min-width: 375px;
280
267
  }
281
268
  body > footer aside#modal #modal-content dl {
282
269
  display: grid;
@@ -308,4 +295,3 @@ section#error p img {
308
295
  section#error a {
309
296
  color: #748ea3;
310
297
  }
311
-
@@ -61,6 +61,31 @@ RSpec.describe Intranet::Core do
61
61
  thread&.join
62
62
  end
63
63
 
64
+ it 'should not advertise server version in HTTP response headers' do
65
+ @intranet = described_class.new(Intranet::Logger.new(Intranet::Logger::FATAL))
66
+ thread = Thread.new { @intranet.start }
67
+ while @intranet.instance_variable_get(:@server).status != :Running
68
+ end
69
+
70
+ socket = TCPSocket.new('localhost', @intranet.port)
71
+ socket.puts("GET /design/favicon.ico HTTP/1.1\r\nHost: localhost:#{@intranet.port}\r\n\r\n")
72
+ server_identification = ''
73
+ expect(socket.gets).to include('HTTP/1.1 200 OK') # pre-requisite
74
+ while (line = socket.gets.chomp) # look for Server response header
75
+ break if line.empty?
76
+
77
+ if line.start_with?('Server: ')
78
+ server_identification = line[8..-1]
79
+ break
80
+ end
81
+ end
82
+ expect(server_identification).to be_empty
83
+ socket.close
84
+
85
+ @intranet.stop
86
+ thread&.join
87
+ end
88
+
64
89
  context 'when no module is registered' do
65
90
  it 'should return HTTP error 404 when requested for /index.html' do
66
91
  @intranet = described_class.new(Intranet::Logger.new(Intranet::Logger::FATAL))
@@ -219,13 +244,21 @@ RSpec.describe Intranet::Core do
219
244
  it 'should be called to retrieve the body of the page' do
220
245
  @intranet = described_class.new(Intranet::Logger.new(Intranet::Logger::FATAL))
221
246
 
222
- responder = Intranet::TestResponder.new(
223
- {
224
- '/index.html' => [206, 'text/html', { content: 'PARTIAL_CONTENT', title: 'MyTitle' }]
225
- },
226
- ['/responder.css', 'nav.css'],
227
- ['module.js', '/js/interactive.js']
228
- )
247
+ responder = Intranet::TestResponder.new({
248
+ '/index.html' => [
249
+ 206,
250
+ 'text/html',
251
+ {
252
+ content: 'PARTIAL_CONTENT',
253
+ title: 'MyTitle',
254
+ stylesheets: ['/resp.css', 'nav.css'],
255
+ scripts: [
256
+ { src: 'module.js', type: 'module' },
257
+ { src: '/js/interactive.js', defer: 'defer' }
258
+ ]
259
+ }
260
+ ]
261
+ })
229
262
  @intranet.register_module(responder, ['r'], responder.resources_dir)
230
263
 
231
264
  thread = Thread.new { @intranet.start }
@@ -255,11 +288,11 @@ RSpec.describe Intranet::Core do
255
288
  expect(html).to match(%r{<footer>.*#{hostname}.*</footer>}m)
256
289
 
257
290
  # Returned HTML document: includes all CSS dependencies, relative or absolute path
258
- expect(html).to match(%r{<link href='/responder.css' rel='stylesheet' type='text/css'})
291
+ expect(html).to match(%r{<link href='/resp.css' rel='stylesheet' type='text/css'})
259
292
  expect(html).to match(%r{<link href='/r/nav.css' rel='stylesheet' type='text/css'})
260
293
 
261
294
  # Returned HTML document: includes all JS dependencies
262
- expect(html).to match(%r{<script defer='defer' src='/r/module.js'></script>})
295
+ expect(html).to match(%r{<script src='/r/module.js' type='module'></script>})
263
296
  expect(html).to match(%r{<script defer='defer' src='/js/interactive.js'></script>})
264
297
 
265
298
  # Returned HTML document: includes Intranet Core name, version and URL
@@ -281,7 +314,7 @@ RSpec.describe Intranet::Core do
281
314
  responder = Intranet::TestResponder.new(
282
315
  '/index.html' => [206, 'text/html', { content: 'PARTIAL_CONTENT', title: 'MyTitle' }]
283
316
  )
284
- other_responder = Intranet::TestResponder.new({}, [], [], true)
317
+ other_responder = Intranet::TestResponder.new({}, true)
285
318
  @intranet.register_module(responder, %w[r], responder.resources_dir)
286
319
  @intranet.register_module(responder, %w[dep_th1], responder.resources_dir)
287
320
  @intranet.register_module(responder, %w[depth2 res_p1], responder.resources_dir)
@@ -6,10 +6,8 @@ module Intranet
6
6
  class TestResponder < AbstractResponder
7
7
  attr_reader :finalized
8
8
 
9
- def initialize(responses = {}, extra_css = [], extra_js = [], hide_from_menu = false) # rubocop:disable Metrics/ParameterLists
9
+ def initialize(responses = {}, hide_from_menu = false)
10
10
  @responses = responses
11
- @extra_css = extra_css
12
- @extra_js = extra_js
13
11
  @finalized = false
14
12
  @hide_from_menu = hide_from_menu
15
13
  end
@@ -47,14 +45,6 @@ module Intranet
47
45
  super(path, query)
48
46
  end
49
47
 
50
- def css_dependencies
51
- super + @extra_css
52
- end
53
-
54
- def js_dependencies
55
- super + @extra_js
56
- end
57
-
58
48
  private
59
49
 
60
50
  def dump_with_encoding(path, query)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: intranet-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.2
4
+ version: 2.4.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ebling Mis
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-05-26 00:00:00.000000000 Z
11
+ date: 2022-02-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: haml
@@ -84,44 +84,44 @@ dependencies:
84
84
  name: rake
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - ">="
87
+ - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: '0'
89
+ version: '13.0'
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
- - - ">="
94
+ - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: '0'
96
+ version: '13.0'
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: rspec
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
- - - ">="
101
+ - - "~>"
102
102
  - !ruby/object:Gem::Version
103
- version: '0'
103
+ version: '3.0'
104
104
  type: :development
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
- - - ">="
108
+ - - "~>"
109
109
  - !ruby/object:Gem::Version
110
- version: '0'
110
+ version: '3.0'
111
111
  - !ruby/object:Gem::Dependency
112
112
  name: rubocop
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
- - - ">="
115
+ - - "~>"
116
116
  - !ruby/object:Gem::Version
117
- version: '0'
117
+ version: '1.0'
118
118
  type: :development
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
- - - ">="
122
+ - - "~>"
123
123
  - !ruby/object:Gem::Version
124
- version: '0'
124
+ version: '1.0'
125
125
  - !ruby/object:Gem::Dependency
126
126
  name: simplecov
127
127
  requirement: !ruby/object:Gem::Requirement
@@ -140,16 +140,16 @@ dependencies:
140
140
  name: yard
141
141
  requirement: !ruby/object:Gem::Requirement
142
142
  requirements:
143
- - - ">="
143
+ - - "~>"
144
144
  - !ruby/object:Gem::Version
145
- version: '0'
145
+ version: '0.0'
146
146
  type: :development
147
147
  prerelease: false
148
148
  version_requirements: !ruby/object:Gem::Requirement
149
149
  requirements:
150
- - - ">="
150
+ - - "~>"
151
151
  - !ruby/object:Gem::Version
152
- version: '0'
152
+ version: '0.0'
153
153
  description:
154
154
  email: ebling.mis@protonmail.com
155
155
  executables: []
@@ -211,8 +211,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
211
211
  - !ruby/object:Gem::Version
212
212
  version: '0'
213
213
  requirements: []
214
- rubyforge_project:
215
- rubygems_version: 2.7.6.2
214
+ rubygems_version: 3.2.5
216
215
  signing_key:
217
216
  specification_version: 4
218
217
  summary: Core component to build a custom intranet.