natour 0.2.0 → 0.6.0

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: eb00323054987bfbb4e15631640c781d2e44f1c1a86dae3d7fafca37ecdfe0d8
4
- data.tar.gz: 99cb9c130f9aefaecb5c68684b1e52ccd12628ae2b1d0e4e316a485a304ce761
3
+ metadata.gz: 8c599b25a1b97e3eb894161d80065d2359a7530371e40335702100b79510b013
4
+ data.tar.gz: '0892297dde6afb7de1a193d0bfe903ce6810d17b5a10c23bd5d0433b4cbde702'
5
5
  SHA512:
6
- metadata.gz: 35670a2a3872135b9cad97eac2c27af4205aaea5cf1db6b38c8757589e281061ad6b22b3469e2c4ae0c350701541fdea92170d837ed4e931445f26d2f2bb7aa7
7
- data.tar.gz: a784e70dba0803b538a58676f143e38f93b9d252d706ae470bb91bc90caef687c86464179ae2d53d20522595af02e0aadfb1cdc7b89b60f1d36449547e7b7e92
6
+ metadata.gz: ce5fd7ebedd87c7c4dcf529a90878cdeab5dac805362407b9be3becee524aaa3d616d44f62f6bf4d4d8fc694741f607cdff2bb69a134407cbe7d4ac9c70330bf
7
+ data.tar.gz: 6f92ed19ec2f32eb4933630937ecb2d0fe597e466b6c3057aacfe070f971820d0e03a0dff28eb3d61e1ffea4db6bfd61091da8830c005a7cc8f3a184e450612a
data/CHANGELOG.adoc CHANGED
@@ -6,6 +6,49 @@ The format is based on https://keepachangelog.com/en/1.0.0/[Keep a Changelog^],
6
6
 
7
7
  == Unreleased
8
8
 
9
+ == 0.6.0 - 2021-11-20
10
+
11
+ === Fixed
12
+
13
+ - Support GPX files containing only mandatory elements (i.e. no extensions)
14
+ - Consider also the image dimensions to determine the orientation, even if the tag is present
15
+
16
+ == 0.5.0 - 2021-08-16
17
+
18
+ === Added
19
+
20
+ - Reflect the date of the last update in the revision date
21
+ - Add captions to species lists in the AsciiDoc output
22
+ - Group species lists by taxonomic groups in the AsciiDoc output
23
+
24
+ === Fixed
25
+
26
+ - Support species lists of Flora Helvetica exported from Favoriten
27
+ - Consider botanical names with the authority name preceding the subspecies
28
+
29
+ == 0.4.0 - 2021-05-02
30
+
31
+ === Added
32
+
33
+ - Show date/time of images in draft output
34
+ - Support preferred conversion backend for draft output
35
+
36
+ === Changed
37
+
38
+ - Remove redundant method `Image.portrait?`
39
+
40
+ == 0.3.0 - 2021-03-07
41
+
42
+ === Changed
43
+
44
+ - Sort the reports according to their GPS track
45
+ - Bump minimum required Ruby version to 2.5
46
+ - Change font in PDF output to support ♀ and ♂ symbols
47
+
48
+ === Fixed
49
+
50
+ - Make source code compatible with Ruby version 2.5
51
+
9
52
  == 0.2.0 - 2021-01-24
10
53
 
11
54
  === Added
data/README.adoc CHANGED
@@ -45,7 +45,7 @@ sudo apt install build-essential patch ruby-dev zlib1g-dev liblzma-dev
45
45
  +
46
46
  [source,shell]
47
47
  ----
48
- sudo apt install libvips42
48
+ sudo apt install libvips
49
49
  ----
50
50
 
51
51
  . Install https://www.google.com/chrome/[Google Chrome-Webbroser^]
data/bin/natour CHANGED
@@ -17,6 +17,7 @@ config = Natour::Config.load_file(
17
17
  'adoc-author' => nil,
18
18
  'backend' => 'pdf',
19
19
  'draft' => false,
20
+ 'draft-backend' => nil,
20
21
  'image-maxdim' => 1800
21
22
  }
22
23
  )
@@ -69,6 +70,9 @@ option_parser = OptionParser.new do |opts|
69
70
  opts.on('--[no-]draft', 'Show additional information (e.g. image paths)') do |value|
70
71
  config['draft'] = value
71
72
  end
73
+ opts.on('--draft-backend BACKEND', 'Preferred conversion backend for draft (pdf, html5 ...)') do |value|
74
+ config['draft-backend'] = value
75
+ end
72
76
  opts.on('--image-maxdim DIM', 'Shrink oversized images (PDF only)') do |value|
73
77
  config['image-maxdim'] = value.to_i
74
78
  end
@@ -106,6 +110,7 @@ else
106
110
  overwrite: config['overwrite'],
107
111
  backend: config['backend'],
108
112
  draft: config['draft'],
113
+ draft_backend: config['draft-backend'],
109
114
  image_maxdim: config['image-maxdim']
110
115
  )
111
116
  end
@@ -30,9 +30,10 @@ module Natour
30
30
  doc << "= #{title}"
31
31
  if author
32
32
  doc << author
33
- doc << Date.today.strftime('%d.%m.%Y')
33
+ doc << ':revdate: {docdate}'
34
34
  end
35
35
  doc << ':figure-caption!:'
36
+ doc << ':table-caption!:'
36
37
  doc << ':pdf-page-mode: none'
37
38
  doc << ':title-page:'
38
39
  if title_image
@@ -77,10 +78,10 @@ module Natour
77
78
  doc << '== Bilder'
78
79
  doc << ''
79
80
  images.each do |image|
80
- width = if image.portrait?
81
- '40%'
82
- else
81
+ width = if image.landscape?
83
82
  '80%'
83
+ else
84
+ '40%'
84
85
  end
85
86
  doc << '.Abbildung {counter:image}'
86
87
  doc << "image::#{Pathname(doc_root).join(image.path)}[width=#{width}]"
@@ -88,35 +89,45 @@ module Natour
88
89
  end
89
90
  end
90
91
  unless species_lists.empty?
91
- birds_info = OpenStruct.new(
92
- title: 'Vogelarten',
93
- headers: %w[Deutscher\ Name Wissenschaftlicher\ Name],
94
- columns: %i[name_de name]
95
- )
96
- plants_info = OpenStruct.new(
97
- title: 'Pflanzenarten',
98
- headers: %w[Wissenschaftlicher\ Name Deutscher\ Name],
99
- columns: %i[name name_de]
100
- )
101
92
  doc << '<<<'
102
93
  doc << ''
103
94
  doc << '== Artenlisten'
104
95
  doc << ''
105
- species_lists.each.with_index(1) do |species_list, index|
106
- info = {
107
- birds: birds_info,
108
- plants: plants_info
109
- }[species_list.group]
96
+ index = 1
97
+ groups = species_lists.group_by(&:group)
98
+ [
99
+ OpenStruct.new(
100
+ group: :plants,
101
+ title: 'Pflanzenarten',
102
+ headers: %w[Wissenschaftlicher\ Name Deutscher\ Name],
103
+ columns: %i[name name_de]
104
+ ),
105
+ OpenStruct.new(
106
+ group: :birds,
107
+ title: 'Vogelarten',
108
+ headers: %w[Deutscher\ Name Wissenschaftlicher\ Name],
109
+ columns: %i[name_de name]
110
+ )
111
+ ].each do |info|
112
+ group = groups.fetch(info.group, [])
113
+ next if group.empty?
114
+
110
115
  doc << "=== #{info.title}"
111
116
  doc << ''
112
- doc << '[cols="1,5,5",options=header]'
113
- doc << '|==='
114
- doc << "|Nr.|#{info.headers.join('|')}"
115
- species_list.each do |species|
116
- doc << "|{counter:species_list#{index}}|#{info.columns.map { |method| species.send(method) }.join('|')}"
117
+ group.each do |species_list|
118
+ caption = '.Tabelle {counter:species_lists}'
119
+ caption << ": #{species_list.description}" if species_list.description
120
+ doc << caption
121
+ doc << '[cols="1,5,5",options=header]'
122
+ doc << '|==='
123
+ doc << "|Nr.|#{info.headers.join('|')}"
124
+ species_list.each do |species|
125
+ doc << "|{counter:species_list#{index}}|#{info.columns.map { |method| species.send(method) }.join('|')}"
126
+ end
127
+ doc << '|==='
128
+ doc << ''
129
+ index += 1
117
130
  end
118
- doc << '|==='
119
- doc << ''
120
131
  end
121
132
  end
122
133
  doc.join("\n")
data/lib/natour/config.rb CHANGED
@@ -5,14 +5,12 @@ module Natour
5
5
  class Config
6
6
  def self.load_file(filename, default: {}, dirs: [Dir.home, Dir.pwd])
7
7
  dirs.map do |dir|
8
- begin
9
- YAML.safe_load(
10
- File.read(Pathname(dir).join(filename)),
11
- permitted_classes: [Symbol]
12
- )
13
- rescue Errno::ENOENT
14
- {}
15
- end
8
+ YAML.safe_load(
9
+ File.read(Pathname(dir).join(filename)),
10
+ [Symbol]
11
+ )
12
+ rescue Errno::ENOENT
13
+ {}
16
14
  end.reduce(default, &:merge)
17
15
  end
18
16
  end
@@ -3,12 +3,19 @@ require 'pathname'
3
3
  require 'asciidoctor'
4
4
  require 'asciidoctor-pdf'
5
5
  require 'vips'
6
+ require 'time'
6
7
 
7
8
  module Natour
8
9
  module_function
9
10
 
10
11
  def convert(filename, out_dir: nil, out_file: nil, overwrite: false,
11
- backend: 'pdf', draft: false, image_maxdim: 16000)
12
+ backend: 'pdf', draft: false, draft_backend: nil, image_maxdim: 16000)
13
+ backend = if draft
14
+ draft_backend || backend
15
+ else
16
+ backend
17
+ end
18
+
12
19
  doc = Asciidoctor.load_file(
13
20
  filename,
14
21
  backend: backend,
@@ -16,7 +23,8 @@ module Natour
16
23
  standalone: true,
17
24
  attributes: {
18
25
  'pdf-theme' => 'natour',
19
- 'pdf-themesdir' => "#{__dir__}/data/themes"
26
+ 'pdf-themesdir' => "#{__dir__}/data/themes",
27
+ 'pdf-fontsdir' => "#{__dir__}/data/fonts"
20
28
  }
21
29
  )
22
30
 
@@ -28,7 +36,28 @@ module Natour
28
36
 
29
37
  if draft
30
38
  doc.find_by(context: :image).each do |node|
31
- node.title = "#{node.title} [#{node.attr('target')}]"
39
+ target = node.attr('target')
40
+ image = Image.load_file(dir.join(target).to_s)
41
+ node.title = "#{node.title} [#{[target, image.date_time].compact.join('|')}]"
42
+ end
43
+ end
44
+
45
+ %w[
46
+ revdate
47
+ docdate
48
+ doctime
49
+ docdatetime
50
+ localdate
51
+ localtime
52
+ localdatetime
53
+ ].each do |attr_name|
54
+ date_time = Time.parse(doc.attr(attr_name))
55
+ if attr_name.end_with?('datetime')
56
+ doc.set_attr(attr_name, date_time.strftime('%d.%m.%Y %H:%M:%S'))
57
+ elsif attr_name.end_with?('date')
58
+ doc.set_attr(attr_name, date_time.strftime('%d.%m.%Y'))
59
+ elsif attr_name.end_with?('time')
60
+ doc.set_attr(attr_name, date_time.strftime('%H:%M:%S'))
32
61
  end
33
62
  end
34
63
 
@@ -39,25 +68,17 @@ module Natour
39
68
  title_logo_image = doc.attr('title-logo-image')
40
69
  if title_logo_image
41
70
  target = title_logo_image[/^image:{1,2}(.*?)\[(.*?)\]$/, 1]
42
- options = {}
43
- options[:autorotate] = true if target =~ /\.jpe?g$/i
44
- image = Vips::Image.new_from_file(dir.join(target).to_s, options)
45
- scale = image_maxdim / image.size.max.to_f
46
- image = image.resize(scale) if scale < 1.0
71
+ image = Image.load_file(dir.join(target).to_s).autorotate.shrink_to(image_maxdim)
47
72
  new_target = tmp_dir.join("title_logo_image_#{Pathname(target).basename}").to_s
48
- suppress_output { image.write_to_file(new_target) }
73
+ image.save_as(new_target)
49
74
  doc.set_attr('title-logo-image', title_logo_image.gsub(target, new_target))
50
75
  end
51
76
 
52
77
  doc.find_by(context: :image).each.with_index do |node, index|
53
78
  target = node.attr('target')
54
- options = {}
55
- options[:autorotate] = true if target =~ /\.jpe?g$/i
56
- image = Vips::Image.new_from_file(dir.join(target).to_s, options)
57
- scale = image_maxdim / image.size.max.to_f
58
- image = image.resize(scale) if scale < 1.0
79
+ image = Image.load_file(dir.join(target).to_s).autorotate.shrink_to(image_maxdim)
59
80
  new_target = tmp_dir.join("image#{index}_#{Pathname(target).basename}").to_s
60
- suppress_output { image.write_to_file(new_target) }
81
+ image.save_as(new_target)
61
82
  node.set_attr('target', new_target)
62
83
  end
63
84
 
@@ -1,5 +1,14 @@
1
1
  ---
2
2
  extends: default
3
+ font:
4
+ catalog:
5
+ DejaVu Serif Condensed:
6
+ normal: dejavuserifcondensed-normal.ttf
7
+ italic: dejavuserifcondensed-italic.ttf
8
+ bold: dejavuserifcondensed-bold.ttf
9
+ bold_italic: dejavuserifcondensed-bold_italic.ttf
10
+ base:
11
+ font-family: DejaVu Serif Condensed
3
12
  footer:
4
13
  recto:
5
14
  left:
@@ -71,10 +71,14 @@ module Natour
71
71
  end
72
72
 
73
73
  def round_duration(duration, hours: 0, minutes: 0, seconds: 0)
74
+ return unless duration
75
+
74
76
  Duration.new(round_multiple_of(duration.to_i, (hours * 60 + minutes) * 60 + seconds))
75
77
  end
76
78
 
77
79
  def round_time(time, hours: 0, minutes: 0, seconds: 0)
80
+ return unless time
81
+
78
82
  Time.at(round_multiple_of(time.to_i, (hours * 60 + minutes) * 60 + seconds))
79
83
  end
80
84
  end
@@ -1,26 +1,29 @@
1
1
  require 'nokogiri'
2
2
  require 'duration'
3
- require 'date'
4
- require 'time'
3
+ require 'timeliness'
5
4
 
6
5
  module Natour
7
6
  class GPXFile < GPSTrack
7
+ GPX_XMLNS = {
8
+ 'xmlns' => 'http://www.topografix.com/GPX/1/1',
9
+ 'xmlns:gpxtrkx' => 'http://www.garmin.com/xmlschemas/TrackStatsExtension/v1'
10
+ }.freeze
11
+
8
12
  def initialize(filename)
9
13
  @doc = Nokogiri.XML(File.read(filename, mode: 'r:utf-8'))
10
14
 
11
- date = Date.parse(@doc.at('/xmlns:gpx/xmlns:metadata/xmlns:time').text)
12
- stats = @doc.at('/xmlns:gpx/xmlns:trk/xmlns:extensions/gpxtrkx:TrackStatsExtension')
15
+ stats = @doc.at('/xmlns:gpx/xmlns:trk/xmlns:extensions/gpxtrkx:TrackStatsExtension', GPX_XMLNS)
13
16
  if stats
14
- ascent = stats.at('./gpxtrkx:Ascent').text.to_i
15
- descent = stats.at('./gpxtrkx:Descent').text.to_i
16
- distance = stats.at('./gpxtrkx:Distance').text.to_i
17
- duration = Duration.new(stats.at('./gpxtrkx:TotalElapsedTime').text.to_i)
17
+ ascent = stats.at('./gpxtrkx:Ascent', GPX_XMLNS).text.to_i
18
+ descent = stats.at('./gpxtrkx:Descent', GPX_XMLNS).text.to_i
19
+ distance = stats.at('./gpxtrkx:Distance', GPX_XMLNS).text.to_i
20
+ duration = Duration.new(stats.at('./gpxtrkx:TotalElapsedTime', GPX_XMLNS).text.to_i)
18
21
  end
19
22
 
20
- start_point = to_track_point(@doc.at('/xmlns:gpx/xmlns:trk/xmlns:trkseg[1]/xmlns:trkpt[1]'))
21
- end_point = to_track_point(@doc.at('/xmlns:gpx/xmlns:trk/xmlns:trkseg[last()]/xmlns:trkpt[last()]'))
23
+ start_point = to_track_point(@doc.at('/xmlns:gpx/xmlns:trk/xmlns:trkseg[1]/xmlns:trkpt[1]', GPX_XMLNS))
24
+ end_point = to_track_point(@doc.at('/xmlns:gpx/xmlns:trk/xmlns:trkseg[last()]/xmlns:trkpt[last()]', GPX_XMLNS))
22
25
 
23
- super(filename, date, ascent, descent, distance, duration, start_point, end_point)
26
+ super(filename, start_point.time&.to_date, ascent, descent, distance, duration, start_point, end_point)
24
27
  end
25
28
 
26
29
  def to_gpx
@@ -33,8 +36,8 @@ module Natour
33
36
  GPSTrackPoint.new(
34
37
  trkpt['lat'].to_f,
35
38
  trkpt['lon'].to_f,
36
- trkpt.at('./xmlns:ele').text.to_f,
37
- Time.parse(trkpt.at('./xmlns:time').text)
39
+ trkpt.at('./xmlns:ele')&.text&.to_f,
40
+ Timeliness.parse(trkpt.at('./xmlns:time')&.text)
38
41
  )
39
42
  end
40
43
  end
data/lib/natour/image.rb CHANGED
@@ -1,29 +1,54 @@
1
1
  require 'vips'
2
2
  require 'timeliness'
3
+ require 'fileutils'
4
+ require 'pathname'
3
5
 
4
6
  module Natour
5
7
  class Image
6
8
  attr_reader :path
7
9
  attr_reader :date_time
8
10
 
9
- def initialize(path)
11
+ def initialize(path, image)
10
12
  @path = path
11
- image = Vips::Image.new_from_file(path)
12
- width, height = image.size
13
- @portrait = width < height
14
- get_field = ->(name) { image.get(name) if image.get_fields.include?(name) }
15
- orientation = get_field.call('exif-ifd0-Orientation')
16
- @portrait = orientation[/^(\d) \(/, 1].to_i.between?(5, 8) if orientation
17
- date_time = get_field.call('exif-ifd0-DateTime')
13
+ @image = image
14
+ @landscape = image.width >= image.height
15
+ orientation = get_field('exif-ifd0-Orientation')
16
+ @landscape = !@landscape if orientation && orientation[/^(\d) \(/, 1].to_i.between?(5, 8)
17
+ date_time = get_field('exif-ifd0-DateTime')
18
18
  @date_time = Timeliness.parse(date_time[/^(.*?) \(/, 1], format: 'yyyy:mm:dd hh:nn:ss') if date_time
19
19
  end
20
20
 
21
- def portrait?
22
- @portrait
21
+ def self.load_file(filename)
22
+ Image.new(filename, Vips::Image.new_from_file(filename))
23
23
  end
24
24
 
25
25
  def landscape?
26
- !portrait?
26
+ @landscape
27
+ end
28
+
29
+ def autorotate
30
+ Image.new(@path, @image.autorot)
31
+ end
32
+
33
+ def shrink_to(maxdim)
34
+ scale = maxdim / @image.size.max.to_f
35
+ image = if scale < 1.0
36
+ @image.resize(scale)
37
+ else
38
+ @image.copy
39
+ end
40
+ Image.new(@path, image)
41
+ end
42
+
43
+ def save_as(filename)
44
+ FileUtils.mkdir_p(Pathname(filename).dirname)
45
+ StdoutUtils.suppress_output { @image.write_to_file(filename) }
46
+ end
47
+
48
+ private
49
+
50
+ def get_field(name)
51
+ @image.get(name) if @image.get_fields.include?(name)
27
52
  end
28
53
  end
29
54
  end
data/lib/natour/report.rb CHANGED
@@ -35,7 +35,7 @@ module Natour
35
35
  title = Pathname.pwd.basename.to_s.encode('utf-8')
36
36
  .gsub(/^\d{4}-\d{2}-\d{2}( |_|-)?/, '')
37
37
  images = Pathname.glob('**/*.{jpg,jpeg}', File::FNM_CASEFOLD)
38
- .map { |filename| Image.new(filename.to_s) }
38
+ .map { |filename| Image.load_file(filename.to_s) }
39
39
  .sort_by { |image| [image.date_time ? 0 : 1, image.date_time, image.path] }
40
40
  species_lists =
41
41
  Pathname.glob('**/*.{csv,kml}', File::FNM_CASEFOLD)
@@ -47,6 +47,7 @@ module Natour
47
47
  else
48
48
  Pathname.glob("**/*.{#{track_formats.join(',')}}", File::FNM_CASEFOLD)
49
49
  .map { |filename| GPSTrack.load_file(filename.to_s) }
50
+ .sort_by { |gps_track| [gps_track.date, gps_track.path] }
50
51
  end
51
52
 
52
53
  if create_map
@@ -57,7 +58,7 @@ module Natour
57
58
  gps_track.save_gpx(track, overwrite: true)
58
59
  filename = Pathname(gps_track.path).sub_ext('.jpg')
59
60
  map.save_image(filename, tracks: [track], layers: map_layers)
60
- Image.new(filename.to_s)
61
+ Image.load_file(filename.to_s)
61
62
  end
62
63
  end
63
64
  end
@@ -34,13 +34,13 @@ module Natour
34
34
  case header
35
35
  when /^Primary/
36
36
  CSV.open(filename, 'r:windows-1252:utf-8', headers: true, liberal_parsing: true) do |csv|
37
- date = DateParser.parse(Pathname(filename).basename).compact.first
37
+ date = DateUtils.parse(Pathname(filename).basename).compact.first
38
38
  items = csv.map { |row| Species.new(row[1], row[0]) }
39
39
  .sort_by(&:name_de).uniq
40
40
  [SpeciesList.new(filename, date, :kosmos_vogelfuehrer, :birds, nil, nil, items)]
41
41
  end
42
42
  when /^<\?xml.*?www\.ornitho\.ch/m
43
- date = DateParser.parse(Pathname(filename).basename).compact.first
43
+ date = DateUtils.parse(Pathname(filename).basename).compact.first
44
44
  doc = Nokogiri.XML(File.read(filename, mode: 'r:utf-8'))
45
45
  folder = doc.at('/xmlns:kml/xmlns:Document/xmlns:Folder/xmlns:Folder/xmlns:Folder')
46
46
  name = folder.at('./xmlns:name').text
@@ -49,16 +49,16 @@ module Natour
49
49
  .map { |description| Species.new(*description.scan(/&gt;([^&(]+)&lt;/).flatten.reverse) }
50
50
  .sort_by(&:name_de).uniq
51
51
  [SpeciesList.new(filename, date, :ornitho_ch, :birds, name, nil, items)]
52
- when /^Favoriten/
52
+ when /^(Favoriten|NUMMER_FLORA)/
53
53
  CSV.open(filename, 'r:bom|utf-8', col_sep: ';', skip_blanks: true) do |csv|
54
- chunks = csv.reject { |row| row.count == 1 && row[0] != 'Favoriten' }
55
- .reject { |row| row.count == 4 && row[0] == 'NUMMER_FLORA' }
54
+ chunks = csv.reject { |row| row.count == 1 }
55
+ .map { |row| row[0] == 'NUMMER_FLORA' ? ['Favoriten'] : row }
56
56
  .slice_before { |row| row.count == 1 || row.count == 3 }
57
57
  .reject { |rows| rows.count == 1 }
58
58
  chunks.map do |rows|
59
59
  name, description = rows.shift
60
- date = DateParser.parse(name, Pathname(filename).basename).compact.first
61
- items = rows.map { |row| Species.new(row[1][/^(([^ ]+ [^ ]+)(( aggr\.)|( subsp\. [^ ]+))?)/, 1], row[2]) }
60
+ date = DateUtils.parse(name, Pathname(filename).basename).compact.first
61
+ items = rows.map { |row| Species.new(BotanicalNameUtils.parse(row[1]), row[2]) }
62
62
  .sort_by(&:name).uniq
63
63
  SpeciesList.new(
64
64
  filename,
@@ -73,9 +73,9 @@ module Natour
73
73
  end
74
74
  when /^obs_id/
75
75
  CSV.open(filename, 'r:bom|utf-16le:utf-8', col_sep: "\t", headers: true) do |csv|
76
- date = DateParser.parse(Pathname(filename).basename).compact.first
76
+ date = DateUtils.parse(Pathname(filename).basename).compact.first
77
77
  items = csv.select { |row| row[0] }
78
- .map { |row| Species.new(row[11][/^(([^ ]+ [^ ]+)(( aggr\.)|( subsp\. [^ ]+))?)/, 1], nil) }
78
+ .map { |row| Species.new(BotanicalNameUtils.parse(row[11]), nil) }
79
79
  .sort_by(&:name).uniq
80
80
  [SpeciesList.new(filename, date, :info_flora, :plants, nil, nil, items)]
81
81
  end
@@ -0,0 +1,12 @@
1
+ module Natour
2
+ module BotanicalNameUtils
3
+ module_function
4
+
5
+ def parse(name)
6
+ result = name.match(/^([^ ]+ [^ ]+)(( aggr\.)|(.*( subsp\. [^ ]+)))?.*$/)
7
+ return unless result
8
+
9
+ "#{result[1]}#{result[3]}#{result[5]}"
10
+ end
11
+ end
12
+ end
@@ -1,7 +1,7 @@
1
1
  require 'timeliness'
2
2
 
3
3
  module Natour
4
- module DateParser
4
+ module DateUtils
5
5
  module_function
6
6
 
7
7
  def parse(*args)
@@ -0,0 +1,16 @@
1
+ module Natour
2
+ module StdoutUtils
3
+ module_function
4
+
5
+ def suppress_output
6
+ orig_stdout = $stdout.clone
7
+ orig_stderr = $stderr.clone
8
+ $stdout.reopen(File.new(File::NULL, 'w'))
9
+ $stderr.reopen(File.new(File::NULL, 'w'))
10
+ yield
11
+ ensure
12
+ $stdout.reopen(orig_stdout)
13
+ $stderr.reopen(orig_stderr)
14
+ end
15
+ end
16
+ end
data/lib/natour.rb CHANGED
@@ -1,5 +1,6 @@
1
- require 'natour/helpers/date_parser'
2
- require 'natour/helpers/suppress_output'
1
+ require 'natour/utils/botanical_name_utils'
2
+ require 'natour/utils/date_utils'
3
+ require 'natour/utils/stdout_utils'
3
4
  require 'natour/convert'
4
5
  require 'natour/create'
5
6
  require 'natour/asciinurse'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: natour
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Simon Gysi
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-01-24 00:00:00.000000000 Z
11
+ date: 2021-11-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: asciidoctor
@@ -70,14 +70,14 @@ dependencies:
70
70
  name: fit4ruby
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - "~>"
73
+ - - '='
74
74
  - !ruby/object:Gem::Version
75
75
  version: '3.7'
76
76
  type: :runtime
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - "~>"
80
+ - - '='
81
81
  - !ruby/object:Gem::Version
82
82
  version: '3.7'
83
83
  - !ruby/object:Gem::Dependency
@@ -180,6 +180,10 @@ files:
180
180
  - lib/natour/config.rb
181
181
  - lib/natour/convert.rb
182
182
  - lib/natour/create.rb
183
+ - lib/natour/data/fonts/dejavuserifcondensed-bold.ttf
184
+ - lib/natour/data/fonts/dejavuserifcondensed-bold_italic.ttf
185
+ - lib/natour/data/fonts/dejavuserifcondensed-italic.ttf
186
+ - lib/natour/data/fonts/dejavuserifcondensed-normal.ttf
183
187
  - lib/natour/data/js/bootstrap.min.js
184
188
  - lib/natour/data/js/jquery-3.5.1.slim.min.js
185
189
  - lib/natour/data/js/loader.js
@@ -188,8 +192,6 @@ files:
188
192
  - lib/natour/gps_track.rb
189
193
  - lib/natour/gps_track_point.rb
190
194
  - lib/natour/gpx_file.rb
191
- - lib/natour/helpers/date_parser.rb
192
- - lib/natour/helpers/suppress_output.rb
193
195
  - lib/natour/image.rb
194
196
  - lib/natour/map_geo_admin.rb
195
197
  - lib/natour/public_transport.rb
@@ -197,10 +199,15 @@ files:
197
199
  - lib/natour/species.rb
198
200
  - lib/natour/species_list.rb
199
201
  - lib/natour/station.rb
202
+ - lib/natour/utils/botanical_name_utils.rb
203
+ - lib/natour/utils/date_utils.rb
204
+ - lib/natour/utils/stdout_utils.rb
200
205
  homepage: https://rubygems.org/gems/natour
201
206
  licenses:
202
207
  - MIT
203
208
  metadata:
209
+ bug_tracker_uri: https://github.com/simongysi/natour/issues
210
+ changelog_uri: https://github.com/simongysi/natour/blob/main/CHANGELOG.adoc
204
211
  source_code_uri: https://github.com/simongysi/natour
205
212
  post_install_message:
206
213
  rdoc_options: []
@@ -210,7 +217,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
210
217
  requirements:
211
218
  - - ">="
212
219
  - !ruby/object:Gem::Version
213
- version: '2.4'
220
+ version: '2.5'
214
221
  required_rubygems_version: !ruby/object:Gem::Requirement
215
222
  requirements:
216
223
  - - ">="
@@ -1,14 +0,0 @@
1
- module Natour
2
- module_function
3
-
4
- def suppress_output
5
- orig_stdout = $stdout.clone
6
- orig_stderr = $stderr.clone
7
- $stdout.reopen(File.new(File::NULL, 'w'))
8
- $stderr.reopen(File.new(File::NULL, 'w'))
9
- yield
10
- ensure
11
- $stdout.reopen(orig_stdout)
12
- $stderr.reopen(orig_stderr)
13
- end
14
- end