intranet-core 1.0.2 → 1.1.1

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
  SHA1:
3
- metadata.gz: 16bba6e4fbd42e10c7c782d5171b4092f5d116a0
4
- data.tar.gz: ac817457c107a692555ae55af7bd98337094c778
3
+ metadata.gz: bf5a56e43b31aff50e2987cb337fdca3308f5444
4
+ data.tar.gz: c319c8fa7398563f469bb403edb7fff1923c126c
5
5
  SHA512:
6
- metadata.gz: 4446887c3d60d16dbacea6820f17f4679490ee0bb83b20cbd5c12d2c9c5e5f98d60e21df0126632539d6789f92a9723bec7ff6a8b7c34d32197ed07e73c9cea4
7
- data.tar.gz: 6708f510f4beeb3dc7bb2d981dd2ce49292f602b23489bf9a6c177829ef04040f5f3fe0dba129c9480723f7131dbee754dafa82d9d76e8c496b345450f1f7304
6
+ metadata.gz: 0cd16c07120e3a5f3996a9b186d69c40a5816ad58b3852b988d334a82a18637bf2f130dc098ce7d465976a4148b412cbb1955e001cad546ccf5c77d2d23b7599
7
+ data.tar.gz: a280390146e29d0fa3be5c44faebdc6f72b54d4c7e4599dd81ae94bde5c15e4481ece613c236d777522433beae0c9cb16dd92842488318a109b712f7ef2b9a8d
@@ -3,6 +3,18 @@
3
3
  module Intranet
4
4
  # The default implementation and interface of an Intranet module.
5
5
  class AbstractResponder
6
+ # Returns the name of the module.
7
+ # @return [String] The name of the module
8
+ def self.module_name; end
9
+
10
+ # The version of the module, according to semantic versionning.
11
+ # @return [String] The version of the module
12
+ def self.module_version; end
13
+
14
+ # The homepage of the module, if any.
15
+ # @return [String/Nil] The homepage URL of the module, or nil if no homepage is available.
16
+ def self.module_homepage; end
17
+
6
18
  # Destroys the responder instance.
7
19
  # This method gets called when server is shut down.
8
20
  def finalize
@@ -16,11 +16,16 @@ module Intranet
16
16
  # @return [CoreExtensions::Tree]
17
17
  attr_reader :responders
18
18
 
19
+ # The metadata concerning all registered modules (for Haml)
20
+ # @return [Hash]
21
+ attr_reader :modules
22
+
19
23
  # Initializes a new builder.
20
24
  # @param logger [Object] The logger.
21
25
  def initialize(logger)
22
26
  @logger = logger
23
27
  @responders = CoreExtensions::Tree.new
28
+ @modules = { NAME => { version: VERSION, homepage: HOMEPAGE_URL } }
24
29
  end
25
30
 
26
31
  # Finalizes the builder. Each registered responder is called for +finalize+.
@@ -63,17 +68,14 @@ module Intranet
63
68
  # directory. If empty, the responder will be registered as Home responder
64
69
  # (to serve /index.html in particular). Subdirectories are allowed using
65
70
  # an array element for each directory level.
71
+ # @raise [ArgumentError] If the +responder+ is not a valid responder instance.
66
72
  # @raise [ArgumentError] If one of the element of the +path+ contains invalid characters.
67
73
  def register(responder, path = [])
74
+ raise ArgumentError unless responder.class.superclass.to_s == 'Intranet::AbstractResponder'
68
75
  raise ArgumentError unless path.all?(&:urlized?)
69
76
 
70
- current_node = @responders
71
- path.each do |part|
72
- next if part.empty? || part == '.'
73
-
74
- current_node = current_node.add_child_node(part)
75
- end
76
- current_node.value = responder
77
+ insert_responder(responder, path)
78
+ store_module_metadata(responder)
77
79
  end
78
80
 
79
81
  private
@@ -93,6 +95,29 @@ module Intranet
93
95
 
94
96
  [current_treenode.value, '/' + relative_path.join('/')]
95
97
  end
98
+
99
+ # Inserts a responder instance in the appropriate Tree node according the given +path+.
100
+ # Missing Tree nodes are created.
101
+ # @param responder [Intranet::AbstractResponder] The responder instance of the module.
102
+ # @param path [Array] See Intranet::Builder::register().
103
+ def insert_responder(responder, path)
104
+ current_node = @responders
105
+ path.each do |part|
106
+ next if part.empty? || part == '.'
107
+
108
+ current_node = current_node.add_child_node(part)
109
+ end
110
+ current_node.value = responder
111
+ end
112
+
113
+ # Stores the module name, version and homepage URL. These information are used to display the
114
+ # 'about' modal window when partial content is returned by a module. The hash structure
115
+ # ensures that each module metadata are stored once only.
116
+ # @param responder [Intranet::AbstractResponder] The responder instance of the module.
117
+ def store_module_metadata(responder)
118
+ @modules[responder.class.module_name] = { version: responder.class.module_version,
119
+ homepage: responder.class.module_homepage }
120
+ end
96
121
  end
97
122
  end
98
123
  end
@@ -2,7 +2,16 @@
2
2
 
3
3
  module Intranet
4
4
  class Core
5
- # The version of the Intranet core, according to semantic versionning.
6
- VERSION = '1.0.2'
5
+ # The name of the gem.
6
+ NAME = 'intranet-core'
7
+
8
+ # The version of the gem, according to semantic versionning.
9
+ VERSION = '1.1.1'
10
+
11
+ # The URL of the gem homepage.
12
+ HOMEPAGE_URL = 'https://rubygems.org/gems/intranet-core'
13
+
14
+ # The URL of the gem source code.
15
+ SOURCES_URL = 'https://bitbucket.org/ebling-mis/intranet-core'
7
16
  end
8
17
  end
@@ -45,8 +45,11 @@
45
45
  %aside#modal
46
46
  %div#modal-content
47
47
  %h2= 'Intranet'
48
- %p
49
- %strong
50
- %a{href: 'https://rubygems.org/gems/intranet-core', target: '_blank'}= 'core'
51
- = '  '
52
- = Intranet::Core::VERSION
48
+ %dl
49
+ - modules.each do |name, metadata|
50
+ %dt
51
+ - if metadata[:homepage].nil?
52
+ = name
53
+ - else
54
+ %a{href: metadata[:homepage], target: '_blank'}= name
55
+ %dd= metadata[:version]
@@ -3,7 +3,7 @@
3
3
  * Design for the IntraNet core.
4
4
  */
5
5
 
6
- /******************************* External Fonts *******************************/
6
+ /***************************************** External Fonts *****************************************/
7
7
 
8
8
  @font-face {
9
9
  font-family: "Source Sans Pro";
@@ -13,7 +13,7 @@
13
13
  unicode-range: U+0-FF, U+131, U+152-153, U+2C6, U+2DA, U+2DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215;
14
14
  }
15
15
 
16
- /******************************* General design *******************************/
16
+ /***************************************** General design *****************************************/
17
17
 
18
18
  body, html {
19
19
  padding: 0px;
@@ -21,7 +21,7 @@ body, html {
21
21
  height: 100%;
22
22
  }
23
23
  body {
24
- background: #1e262b url('background.jpg') fixed top right no-repeat;
24
+ background: #1e262b;
25
25
  font-family: "Source Sans Pro", Cantarell, sans-serif;
26
26
  color: black;
27
27
  }
@@ -38,7 +38,7 @@ a {
38
38
  cursor: pointer;
39
39
  }
40
40
 
41
- /********************************* Navigation *********************************/
41
+ /******************************************* Navigation *******************************************/
42
42
 
43
43
  header {
44
44
  position: fixed;
@@ -193,6 +193,7 @@ ul.breadcrumb li a, main article a {
193
193
  /******************************** Main content *******************************/
194
194
 
195
195
  body > aside {
196
+ background: url('background.jpg') fixed top right no-repeat;
196
197
  height: 45%;
197
198
  min-height: 350px;
198
199
  max-height: 500px; /* less than height of background.jpg */
@@ -280,6 +281,19 @@ body > footer aside#modal #modal-content { /* modal box */
280
281
  width: 400px;
281
282
  font-size: 125%;
282
283
  }
284
+ body > footer aside#modal #modal-content dl {
285
+ display: grid;
286
+ grid-template-columns: repeat(2, 50%);
287
+ grid-gap: 5px 25px;
288
+ }
289
+ body > footer aside#modal #modal-content dl dt {
290
+ font-weight: bold;
291
+ text-align: right;
292
+ }
293
+ body > footer aside#modal #modal-content dl dd {
294
+ text-align: left;
295
+ margin-left: 0;
296
+ }
283
297
  /* Mobile devices only */
284
298
  @media only screen and (max-width: 600px), only screen and (max-device-width: 600px) {
285
299
  body > footer {
@@ -288,7 +302,7 @@ body > footer aside#modal #modal-content { /* modal box */
288
302
  }
289
303
 
290
304
 
291
- /********************************* Error pages *********************************/
305
+ /******************************************* Error pages ******************************************/
292
306
 
293
307
  section#error h2 {
294
308
  color: #ff3333;
@@ -109,26 +109,9 @@ RSpec.describe Intranet::Core do
109
109
  end
110
110
 
111
111
  context 'registering an invalid module' do
112
- it 'should succeed but accesses to the module URL should return HTTP error 404' do
113
- begin
114
- @intranet = described_class.new(Intranet::Logger.new(Intranet::Logger::FATAL))
115
- @intranet.register_module(nil, [], '')
116
- thread = Thread.new do
117
- @intranet.start
118
- end
119
- while @intranet.instance_variable_get(:@server).status != :Running
120
- end
121
-
122
- socket = TCPSocket.new('localhost', @intranet.port)
123
- socket.puts("GET /index.html HTTP/1.1\r\n" \
124
- "Host: localhost:#{@intranet.port}\r\n\r\n")
125
- expect(socket.gets).to include('HTTP/1.1 404 Not Found')
126
- socket.close
127
- ensure
128
- socket.close
129
- Thread.kill(thread)
130
- thread.join
131
- end
112
+ it 'should fail' do
113
+ @intranet = described_class.new(Intranet::Logger.new(Intranet::Logger::FATAL))
114
+ expect { @intranet.register_module(nil, [], '') }.to raise_error ArgumentError
132
115
  end
133
116
  end
134
117
 
@@ -315,9 +298,15 @@ RSpec.describe Intranet::Core do
315
298
  expect(html).to match(%r{<script defer='defer' src='module.js'></script>})
316
299
  expect(html).to match(%r{<script defer='defer' src='/js/interactive.js'></script>})
317
300
 
318
- # Returned HTML document: includes Intranet Core Version
319
- expect(html).to match(%r{<footer>.*#{Intranet::Core::VERSION}.*</footer>}m)
320
- expect(html).to match(%r{<footer>.*https://rubygems.org/gems/intranet-core.*</footer>}m)
301
+ # Returned HTML document: includes Intranet Core name, version and URL
302
+ expect(html).to match(
303
+ %r{<footer>.*<a href='#{Intranet::Core::HOMEPAGE_URL}'.*>#{Intranet::Core::NAME}</a>.*#{Intranet::Core::VERSION}.*</footer>}m # rubocop:disable Metrics/LineLength
304
+ )
305
+
306
+ # Returned HTML document: includes all registered modules version name, version and URL
307
+ expect(html).to match(
308
+ %r{<footer>.*<a href='http://nil/'.*>test-responder</a>.*0.0.0.*</footer>}m
309
+ )
321
310
  ensure
322
311
  socket.close
323
312
  Thread.kill(thread)
@@ -15,6 +15,19 @@ module Intranet
15
15
 
16
16
  def finalize
17
17
  @finalized = true
18
+ super
19
+ end
20
+
21
+ def self.module_name
22
+ 'test-responder'
23
+ end
24
+
25
+ def self.module_version
26
+ '0.0.0'
27
+ end
28
+
29
+ def self.module_homepage
30
+ 'http://nil/'
18
31
  end
19
32
 
20
33
  def resources_dir
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: 1.0.2
4
+ version: 1.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ebling Mis
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-12-24 00:00:00.000000000 Z
11
+ date: 2019-02-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: haml
@@ -191,10 +191,11 @@ files:
191
191
  - spec/spec_helper.rb
192
192
  - spec/test_responder/responder.rb
193
193
  - spec/test_responder/www/style.css
194
- homepage: https://bitbucket.org/ebling-mis/intranet-core
194
+ homepage: https://rubygems.org/gems/intranet-core
195
195
  licenses:
196
196
  - MIT
197
- metadata: {}
197
+ metadata:
198
+ source_code_uri: https://bitbucket.org/ebling-mis/intranet-core
198
199
  post_install_message:
199
200
  rdoc_options: []
200
201
  require_paths: