natour 0.2.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
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