rdoc-generator-sixfish 0.3.1 → 0.5.0.pre20180710102525

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/.editorconfig +16 -0
  4. data/.ruby-gemset +1 -0
  5. data/.ruby-version +1 -0
  6. data/ChangeLog +675 -0
  7. data/History.md +20 -16
  8. data/Manifest.txt +29 -0
  9. data/README.md +24 -30
  10. data/data/rdoc-generator-sixfish/css/sixfish.css +1184 -2
  11. data/data/rdoc-generator-sixfish/css/sixfish.css.map +7 -1
  12. data/data/rdoc-generator-sixfish/fa/light.js +0 -0
  13. data/data/rdoc-generator-sixfish/fa/light.svg +0 -0
  14. data/data/rdoc-generator-sixfish/fa/loader.js +1 -0
  15. data/data/rdoc-generator-sixfish/fa/regular.js +1 -0
  16. data/data/rdoc-generator-sixfish/fa/regular.svg +662 -0
  17. data/data/rdoc-generator-sixfish/fa/solid.js +1 -0
  18. data/data/rdoc-generator-sixfish/fa/solid.svg +662 -0
  19. data/data/rdoc-generator-sixfish/images/glyphicons-28-search.png +0 -0
  20. data/data/rdoc-generator-sixfish/js/jquery-3.1.1.js +10220 -0
  21. data/data/rdoc-generator-sixfish/js/sixfish.min.js +99 -0
  22. data/data/rdoc-generator-sixfish/templates/class.tmpl +180 -179
  23. data/data/rdoc-generator-sixfish/templates/file.tmpl +16 -4
  24. data/data/rdoc-generator-sixfish/templates/index.tmpl +48 -77
  25. data/data/rdoc-generator-sixfish/templates/layout.tmpl +51 -71
  26. data/lib/rdoc/discover.rb +1 -1
  27. data/lib/rdoc/generator/sixfish.rb +66 -45
  28. data/lib/sixfish.rb +9 -10
  29. data/spec/rdoc/generator/sixfish_spec.rb +16 -22
  30. data/spec/sixfish_spec.rb +5 -1
  31. data.tar.gz.sig +3 -2
  32. metadata +163 -63
  33. metadata.gz.sig +0 -0
  34. data/data/rdoc-generator-sixfish/css/fa-solid-900.515704be.ttf +0 -0
  35. data/data/rdoc-generator-sixfish/css/fa-solid-900.7ba04835.svg +0 -1
  36. data/data/rdoc-generator-sixfish/css/fa-solid-900.8c589fd1.eot +0 -0
  37. data/data/rdoc-generator-sixfish/css/fa-solid-900.c7b072c6.woff +0 -0
  38. data/data/rdoc-generator-sixfish/css/fa-solid-900.f2049a98.woff2 +0 -0
  39. data/data/rdoc-generator-sixfish/js/sixfish.js +0 -39
  40. data/data/rdoc-generator-sixfish/js/sixfish.js.map +0 -1
  41. data/lib/inversion/template/striptag.rb +0 -42
  42. data/lib/sixfish/patches.rb +0 -73
@@ -1,96 +1,76 @@
1
1
  <!DOCTYPE html>
2
- <html>
2
+ <!--
3
+
4
+ Sixfish RDoc Generator
5
+ $Id$
6
+
7
+ Authors:
8
+ - Michael Granger <ged@FaerieMUD.org>
9
+
10
+ -->
11
+ <html lang="en">
3
12
  <head>
4
- <meta charset="utf-8">
5
13
 
6
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
14
+ <meta charset="utf-8">
7
15
 
8
16
  <title><?escape rdoc_options.title ?></title>
9
17
 
10
- <meta name="description" content="API documentation for [?escape rdoc_options.title ?]">
18
+ <meta name="description" content="">
11
19
  <meta name="author" content="">
12
20
 
13
21
  <meta name="viewport" content="width=device-width, initial-scale=1">
14
22
 
15
23
  <link rel="icon" type="image/png" href="[?attr rel_prefix ?]/images/favicon.png">
16
24
  <link rel="prefix" href="[?attr rel_prefix ?]" />
17
-
18
25
  <link rel="stylesheet" href="[?attr rel_prefix ?]/css/sixfish.css">
19
-
20
- <script src="[?attr rel_prefix ?]/js/sixfish.js"></script>
26
+ <?if rdoc_options.additional_stylesheet ?>
27
+ <link href="[?call rdoc_options.additional_stylesheet ?]" rel="stylesheet" title="Site Style" />
28
+ <?end if ?>
29
+
30
+ <script src="[?attr rel_prefix ?]/fa/light.js" type="text/javascript"
31
+ defer="defer" charset="utf-8"></script>
32
+ <script src="[?attr rel_prefix ?]/fa/loader.js" type="text/javascript"
33
+ defer="defer" charset="utf-8"></script>
34
+ <script src="[?attr rel_prefix ?]/js/jquery-3.1.1.min.js" type="text/javascript"
35
+ defer="defer" charset="utf-8"></script>
36
+ <script src="[?attr rel_prefix ?]/js/sixfish.min.js" type="text/javascript"
37
+ defer="defer" charset="utf-8" onload="initSixfish()"></script>
21
38
  </head>
22
- <body>
39
+ <body class="[?attr pageclass ?]">
23
40
 
24
- <main class="columns section">
41
+ <div class="container">
25
42
 
26
- <nav class="index column is-one-quarter">
27
-
28
- <div class="field">
29
- <p class="control has-icons-left">
30
- <input id="index-search" class="input is-rounded" type="text" placeholder="Search">
31
- <span class="icon is-small is-left">
32
- <i class="fas fa-solid fa-search"></i>
33
- </span>
34
- </p>
43
+ <nav id="topbar" class="row">
44
+ <div class="masthead one-half column">
45
+ <a href="[?attr rel_prefix ?]/index.html"><?escape rdoc_options.title ?></a>
35
46
  </div>
36
47
 
37
- <aside class="menu">
38
- <p class="menu-label">Files</p>
39
-
40
- <ul id="file-index" class="menu-list">
41
- <?if mainpage ?>
42
- <li class="file" data-search-term="[?attr mainpage.page_name ?]"><a
43
- href="[?attr rel_prefix ?]/[?call mainpage.path ?]"><?escape mainpage.page_name ?></a></li>
44
- <?end if ?>
45
- <?for file in files.select {|f| f.text? }.sort ?>
46
- <li class="file" data-search-term="[?attr file.page_name ?]"><a
47
- href="[?attr rel_prefix ?]/[?call file.path ?]"><?escape file.page_name ?></a></li>
48
- <?end for ?>
49
- </ul>
50
- </aside>
51
-
52
- <aside class="menu">
53
- <p class="menu-label">Classes/Modules</p>
54
-
55
- <ul id="class-index" class="menu-list">
56
- <?for index_class in modsort.select( &:documented? ).uniq {|c| c.path } ?>
57
- <li class="class" data-search-term="[?attr index_class.full_name ?]"><a
58
- href="[?attr rel_prefix ?]/[?call index_class.path ?]"><?call
59
- index_class.full_name ?></a></li>
60
- <?end for ?>
61
- </ul>
62
- </aside>
63
-
64
- <aside class="menu">
65
- <p class="menu-label">Methods</p>
66
-
67
- <ul id="method-index" class="menu-list">
68
- <?for method in methods.uniq {|m| m.path } ?>
69
- <li class="method" data-search-term="[?attr method.name ?]"><a
70
- title="[?call method.parent.full_name ?]"
71
- href="[?attr rel_prefix ?]/[?call method.path ?]"><?call method.pretty_name ?>
72
- <span class="method-parent">[<?call
73
- method.parent.full_name.sub(/.*(::)/, '\\1') ?>]</span>
74
- </a>
75
- </li>
76
- <?end for ?>
77
- </ul>
78
- </aside>
48
+ <div class="search one-half column">
49
+ <form>
50
+ <input class="u-full-width" type="text"
51
+ placeholder="Class, module, method name or description keyword" id="search-input" />
52
+ </form>
53
+ </div>
79
54
  </nav>
80
55
 
81
- <article class="description column">
82
- <div class="content container">
83
- <?attr contents ?>
84
- </div>
85
- </article>
56
+ <?attr contents ?>
86
57
 
87
- </main>
58
+ <div class="row">
59
+ <div class="column">
88
60
 
89
- <footer class="footer">
90
- <span id="rdoc-version">Generated by RDoc <?attr rdoc_version ?></span> using the
91
- <a id="generator-version"
92
- href="https://hg.sr.ht/~ged/Sixfish"><?attr sixfish_version ?></a> generator.
93
- </footer>
61
+ <hr>
62
+
63
+ <footer>
64
+ <div class="container">
65
+ <span id="rdoc-version">Generated by RDoc <?attr rdoc_version ?></span> using the
66
+ <a id="generator-version"
67
+ href="http://deveiate.org/sixfish"><?attr sixfish_version ?></a> generator.
68
+ </div>
69
+ </footer>
70
+
71
+ </div>
72
+ </div>
73
+ </div>
94
74
 
95
75
  </body>
96
76
  </html>
data/lib/rdoc/discover.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  # -*- ruby -*-
2
2
 
3
- $stderr.puts "Discovered Sixfish!" if $DEBUG
3
+ $stderr.puts "Discovered Darkfish!" if $DEBUG
4
4
 
5
5
  # RDoc plugin hook
6
6
  require 'sixfish'
@@ -3,6 +3,7 @@
3
3
  gem 'rdoc'
4
4
 
5
5
  require 'uri'
6
+ require 'yajl'
6
7
  require 'inversion'
7
8
  require 'loggability'
8
9
  require 'fileutils'
@@ -10,10 +11,6 @@ require 'pathname'
10
11
  require 'rdoc/rdoc'
11
12
  require 'rdoc/generator/json_index'
12
13
 
13
- require 'inversion/template/striptag'
14
-
15
- require 'sixfish'
16
-
17
14
  # The Sixfish generator class.
18
15
  class RDoc::Generator::Sixfish
19
16
  extend Loggability
@@ -26,12 +23,13 @@ class RDoc::Generator::Sixfish
26
23
 
27
24
  # The data directory in the project if that exists, otherwise the gem datadir
28
25
  DATADIR = if ENV['SIXFISH_DATADIR']
29
- Pathname( ENV['SIXFISH_DATADIR'] )
30
- elsif Gem.loaded_specs[ 'rdoc-generator-sixfish' ] &&
31
- File.exist?( Gem.loaded_specs['rdoc-generator-sixfish'].datadir )
32
- Pathname( Gem.loaded_specs['rdoc-generator-sixfish'].datadir )
26
+ Pathname( ENV['SIXFISH_DATADIR'] ).expand_path( Pathname.pwd )
27
+ elsif File.directory?( 'data/rdoc-generator-sixfish' )
28
+ Pathname( 'data/rdoc-generator-sixfish' ).expand_path( Pathname.pwd )
29
+ elsif path = Gem.latest_spec_for( 'rdoc-generator-sixfish' )&.datadir
30
+ Pathname( path )
33
31
  else
34
- Pathname( __FILE__ ).dirname.parent.parent.parent + 'data/rdoc-generator-sixfish'
32
+ raise ScriptError, "can't find the data directory!"
35
33
  end
36
34
 
37
35
  # Register with RDoc as an alternative generator
@@ -74,6 +72,7 @@ class RDoc::Generator::Sixfish
74
72
  @template_cache = {}
75
73
  @files = nil
76
74
  @classes = nil
75
+ @search_index = {}
77
76
 
78
77
  Inversion::Template.configure( :template_paths => [self.template_dir + 'templates'] )
79
78
  end
@@ -128,6 +127,8 @@ class RDoc::Generator::Sixfish
128
127
  self.generate_class_files
129
128
  self.generate_file_files
130
129
 
130
+ self.generate_search_index
131
+
131
132
  self.copy_static_assets
132
133
  end
133
134
 
@@ -145,16 +146,29 @@ class RDoc::Generator::Sixfish
145
146
  ### Generate an index page which lists all the classes which are documented.
146
147
  def generate_index_page
147
148
  self.log.debug "Generating index page"
149
+ layout = self.load_layout_template
148
150
  template = self.load_template( 'index.tmpl' )
149
- self.set_toplevel_variables( template )
150
-
151
151
  out_file = self.output_dir + 'index.html'
152
152
  out_file.dirname.mkpath
153
153
 
154
- template.rel_prefix = self.output_dir.relative_path_from( out_file.dirname )
155
- template.pageclass = 'index-page'
154
+ mainpage = nil
155
+ if mpname = self.options.main_page
156
+ mainpage = @files.find {|f| f.full_name == mpname }
157
+ else
158
+ mainpage = @files.find {|f| f.full_name =~ /\breadme\b/i }
159
+ end
160
+ self.log.debug " using main_page (%s)" % [ mainpage ]
161
+
162
+ if mainpage
163
+ template.mainpage = mainpage
164
+ template.synopsis = self.extract_synopsis( mainpage )
165
+ end
156
166
 
157
- out_file.open( 'w', 0644 ) {|io| io.print(template.render) }
167
+ layout.rel_prefix = self.output_dir.relative_path_from( out_file.dirname )
168
+ layout.contents = template
169
+ layout.pageclass = 'index-page'
170
+
171
+ out_file.open( 'w', 0644 ) {|io| io.print(layout.render) }
158
172
  end
159
173
 
160
174
 
@@ -216,6 +230,35 @@ class RDoc::Generator::Sixfish
216
230
  end
217
231
 
218
232
 
233
+ ### Generate a JSON search index for the quicksearch blank.
234
+ def generate_search_index
235
+ out_file = self.output_dir + 'js/searchindex.json'
236
+
237
+ self.log.debug "Generating search index (%s)." % [ out_file ]
238
+ index = []
239
+
240
+ objs = self.get_indexable_objects
241
+ objs.each do |codeobj|
242
+ self.log.debug " #{codeobj.name}..."
243
+ record = codeobj.search_record
244
+ index << {
245
+ name: record[2],
246
+ link: record[4],
247
+ snippet: record[6],
248
+ type: codeobj.class.name.downcase.sub( /.*::/, '' )
249
+ }
250
+ end
251
+
252
+ self.log.debug " dumping JSON..."
253
+ out_file.dirname.mkpath
254
+ ofh = out_file.open( 'w:utf-8', 0644 )
255
+
256
+ json = Yajl.dump( index, pretty: true, indent: "\t" )
257
+
258
+ ofh.puts( 'var SearchIndex = ', json, ';' )
259
+ end
260
+
261
+
219
262
  ### Copies static files from the static_path into the output directory
220
263
  def copy_static_assets
221
264
  asset_paths = self.find_static_assets
@@ -304,7 +347,14 @@ class RDoc::Generator::Sixfish
304
347
  def load_layout_template
305
348
  template = self.load_template( 'layout.tmpl' )
306
349
 
307
- self.set_toplevel_variables( template )
350
+ template.files = @files
351
+ template.classes = @classes
352
+ template.methods = @methods
353
+ template.modsort = @modsort
354
+ template.rdoc_options = @options
355
+
356
+ template.rdoc_version = RDoc::VERSION
357
+ template.sixfish_version = Sixfish.version_string
308
358
 
309
359
  return template
310
360
  end
@@ -322,35 +372,6 @@ class RDoc::Generator::Sixfish
322
372
  end
323
373
 
324
374
 
325
- ### If the "main" page was set in the options, set it in the template, otherwise set the
326
- ### main page to be the README if one exists.
327
- def set_toplevel_variables( template )
328
- mpname = self.options.main_page
329
- mainpage, files = @files.partition do |f|
330
- if mpname
331
- f.full_name == mpname
332
- else
333
- f.full_name =~ /\breadme\b/i
334
- end
335
- end
336
-
337
- template.files = files
338
- if mainpage.first
339
- template.mainpage = mainpage.first
340
- template.synopsis = self.extract_synopsis( mainpage.first )
341
- end
342
-
343
- template.classes = @classes
344
- template.methods = @methods
345
- template.modsort = @modsort
346
- template.rdoc_options = @options
347
-
348
- template.rdoc_version = RDoc::VERSION
349
- template.sixfish_version = Sixfish.version_string
350
-
351
- end
352
-
353
-
354
375
  ### Extract a synopsis for the project from the specified +mainpage+ and
355
376
  ### return it as a String.
356
377
  def extract_synopsis( mainpage )
@@ -363,7 +384,7 @@ class RDoc::Generator::Sixfish
363
384
  !( para.start_with?('<p><a') && para.end_with?('/a></p>') )
364
385
  end
365
386
 
366
- return first_para
387
+ return heading + first_para
367
388
  end
368
389
 
369
390
  end # class RDoc::Generator::Sixfish
data/lib/sixfish.rb CHANGED
@@ -1,31 +1,30 @@
1
1
  # -*- mode: ruby; ruby-indent-level: 4; tab-width: 4 -*-
2
2
 
3
+ require 'rdoc/rdoc'
4
+ require 'rdoc/generator/sixfish'
5
+
3
6
  # :title: Sixfish RDoc
4
7
  #
5
8
  # Toplevel namespace for Sixfish. The main goods are in RDoc::Generator::Sixfish.
6
9
  module Sixfish
7
10
 
8
11
  # Library version constant
9
- VERSION = '0.3.1'
12
+ VERSION = '0.4.0'
13
+
14
+ # Version-control revision constant
15
+ REVISION = %q$Revision: bd4700e71546 $
10
16
 
11
17
  # Fivefish project URL
12
- PROJECT_URL = 'https://hg.sr.ht/~ged/Sixfish'
18
+ PROJECT_URL = 'https://bitbucket.com/ged/fivefish'
13
19
 
14
20
 
15
21
  ### Get the library version. If +include_buildnum+ is true, the version string will
16
22
  ### include the VCS rev ID.
17
23
  def self::version_string( include_buildnum=false )
18
24
  vstring = "Sixfish RDoc %s" % [ VERSION ]
25
+ vstring << " (build %s)" % [ REVISION[/: ([[:xdigit:]]+)/, 1] || '0' ] if include_buildnum
19
26
  return vstring
20
27
  end
21
28
 
22
-
23
- autoload :Patches, 'sixfish/patches'
24
-
25
29
  end # module Sixfish
26
30
 
27
- require 'rdoc/rdoc'
28
- require 'rdoc/generator/sixfish'
29
-
30
- RDoc::Markup::ToHtml.prepend( Sixfish::Patches )
31
-
@@ -84,31 +84,27 @@ describe RDoc::Generator::Sixfish do
84
84
  end
85
85
 
86
86
 
87
- it "uses the index template to make the index page" do
87
+ it "combines an index template with the layout template to make the index page" do
88
+ layout_template = get_fixtured_layout_template_mock()
89
+
88
90
  index_template = double( "index template" )
89
91
  expect( Inversion::Template ).to receive( :load ).
90
92
  with( 'index.tmpl', encoding: 'utf-8' ).
91
93
  and_return( index_template )
92
94
 
93
95
  expect( index_template ).to receive( :dup ).and_return( index_template )
94
- expect( index_template ).to receive( :files= ).with( [@top_level] ).once
95
- expect( index_template ).to receive( :classes= ).
96
- with( @store.all_classes_and_modules.sort )
97
- expect( index_template ).to receive( :methods= ).
98
- with( @store.all_classes_and_modules.flat_map(&:method_list).sort )
99
- expect( index_template ).to receive( :modsort= ) do |sorted_mods|
100
- expect( sorted_mods ).to include( @store.find_class_named('Klass') )
101
- end
102
- expect( index_template ).to receive( :rdoc_options= ).with( @options )
103
- expect( index_template ).to receive( :rdoc_version= ).with( RDoc::VERSION )
104
- expect( index_template ).to receive( :sixfish_version= ).with( Sixfish.version_string )
105
96
  expect( index_template ).to receive( :mainpage= ).with( @readme )
106
97
  expect( index_template ).to receive( :synopsis= ).
107
- with( %{<p>This is a readme for testing.</p>} )
108
- expect( index_template ).to receive( :rel_prefix= ).with( Pathname('.') ).once
109
- expect( index_template ).to receive( :pageclass= ).with( 'index-page' )
98
+ with( %{<h1 id="label-Testing+README">Testing <a href="README_md} +
99
+ %{.html">README</a><span><a href="#label-Testing+README">} +
100
+ %{&para;</a> <a href="#top">&uarr;</a></span></h1>} +
101
+ %{<p>This is a readme for testing.</p>} )
110
102
 
111
- expect( index_template ).to receive( :render ).and_return( "Index page!" )
103
+ expect( layout_template ).to receive( :contents= ).with( index_template )
104
+ expect( layout_template ).to receive( :pageclass= ).with( 'index-page' )
105
+ expect( layout_template ).to receive( :rel_prefix= ).with( Pathname('.') )
106
+
107
+ expect( layout_template ).to receive( :render ).and_return( 'Index page!' )
112
108
 
113
109
  @generator.generate_index_page
114
110
  end
@@ -155,7 +151,8 @@ describe RDoc::Generator::Sixfish do
155
151
  expect( file_template ).to receive( :dup ).and_return( file_template )
156
152
  expect( file_template ).to receive( :header= ).
157
153
  with( %{<h1 id="label-Testing+README">Testing <a href="README_md} +
158
- %{.html">README</a></h1>} )
154
+ %{.html">README</a><span><a href="#label-Testing+README">} +
155
+ %{&para;</a> <a href="#top">&uarr;</a></span></h1>} )
159
156
  expect( file_template ).to receive( :description= ).
160
157
  with( %{\n<p>This is a readme for testing.</p>\n\n<p>It has some more} +
161
158
  %{ stuff</p>\n\n<p>And even more stuff.</p>\n} )
@@ -196,7 +193,7 @@ describe RDoc::Generator::Sixfish do
196
193
  top_level.add_constant( alias_constant )
197
194
 
198
195
  # ::A = ::Klass (?)
199
- klass.add_module_alias( klass, 'Klass', alias_constant, top_level )
196
+ klass.add_module_alias( klass, 'A', top_level )
200
197
 
201
198
  # Klass#method
202
199
  meth = RDoc::AnyMethod.new( nil, 'method' )
@@ -231,12 +228,10 @@ describe RDoc::Generator::Sixfish do
231
228
  with( 'layout.tmpl', encoding: 'utf-8' ).
232
229
  and_return( layout_template )
233
230
 
234
- allow( layout_template ).to receive( :synopsis= )
235
-
236
231
  # Work around caching
237
232
  expect( layout_template ).to receive( :dup ).and_return( layout_template )
238
233
 
239
- expect( layout_template ).to receive( :files= ).with( [@top_level] )
234
+ expect( layout_template ).to receive( :files= ).with( [@readme, @top_level] )
240
235
  expect( layout_template ).to receive( :classes= ).
241
236
  with( @store.all_classes_and_modules.sort )
242
237
  expect( layout_template ).to receive( :methods= ).
@@ -244,7 +239,6 @@ describe RDoc::Generator::Sixfish do
244
239
  expect( layout_template ).to receive( :modsort= ) do |sorted_mods|
245
240
  expect( sorted_mods ).to include( @store.find_class_named('Klass') )
246
241
  end
247
- expect( layout_template ).to receive( :mainpage= ).with( @readme )
248
242
  expect( layout_template ).to receive( :rdoc_options= ).with( @options )
249
243
  expect( layout_template ).to receive( :rdoc_version= ).with( RDoc::VERSION )
250
244
  expect( layout_template ).to receive( :sixfish_version= ).with( Sixfish.version_string )
data/spec/sixfish_spec.rb CHANGED
@@ -8,11 +8,15 @@ require 'sixfish'
8
8
  describe Sixfish do
9
9
 
10
10
  describe "version methods" do
11
-
12
11
  it "returns a version string if asked" do
13
12
  expect( described_class.version_string ).to match( /\w+ [\d.]+/ )
14
13
  end
15
14
 
15
+
16
+ it "returns a version string with a build number if asked" do
17
+ expect( described_class.version_string(true) ).
18
+ to match( /\w+ [\d.]+ \(build [[:xdigit:]]+\)/ )
19
+ end
16
20
  end
17
21
 
18
22
  end
data.tar.gz.sig CHANGED
@@ -1,2 +1,3 @@
1
- BRcb�?nZ�|m����]I\R����� �eV�(��~t��ŶԎP�'Y��~9�{d�$E��|W��ms��\�3�}�J Gܑ��-K1]��j���L��>GevH���X���H:,�����������GhGI�x
2
-
1
+ ���[jm��ev~�+&�Ӯ� م�[i郕u �?��9���%��x LoD ���g���;�&S�ab,��ӛ~ڮ�#�'-�y���މ�� +;�G�5��<�%��V�
2
+ �}3}?B<��v�bCHmHɔ���_�C� ilb��Ӝ_���j�
3
+ P��M��{TBi���ur����1a6���ۮ���T�3�1�r �\��+ n�Wգ���V�ٙ�qy��m���E˖zO��~�|`i