natour 0.1.0 → 0.5.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 +4 -4
- data/CHANGELOG.adoc +56 -0
- data/README.adoc +1 -1
- data/bin/natour +9 -4
- data/lib/natour.rb +5 -4
- data/lib/natour/asciinurse.rb +39 -29
- data/lib/natour/config.rb +6 -8
- data/lib/natour/{cli/convert.rb → convert.rb} +40 -15
- data/lib/natour/{cli/create.rb → create.rb} +0 -0
- data/lib/natour/data/fonts/dejavuserifcondensed-bold.ttf +0 -0
- data/lib/natour/data/fonts/dejavuserifcondensed-bold_italic.ttf +0 -0
- data/lib/natour/data/fonts/dejavuserifcondensed-italic.ttf +0 -0
- data/lib/natour/data/fonts/dejavuserifcondensed-normal.ttf +0 -0
- data/lib/natour/{js → data/js}/bootstrap.min.js +0 -0
- data/lib/natour/{js → data/js}/jquery-3.5.1.slim.min.js +0 -0
- data/lib/natour/{js → data/js}/loader.js +0 -0
- data/lib/natour/data/themes/natour-theme.yml +22 -0
- data/lib/natour/image.rb +40 -16
- data/lib/natour/map_geo_admin.rb +1 -1
- data/lib/natour/report.rb +4 -3
- data/lib/natour/species_list.rb +31 -15
- data/lib/natour/utils/botanical_name_utils.rb +12 -0
- data/lib/natour/{helpers/date_parser.rb → utils/date_utils.rb} +1 -1
- data/lib/natour/utils/stdout_utils.rb +16 -0
- metadata +20 -12
- data/lib/natour/helpers/suppress_output.rb +0 -14
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b125a5ba293c91fa5efcb56ee32bc6e5ed52c1b8daf82439bcbec6c7b279a29d
|
|
4
|
+
data.tar.gz: bda03749fc2db89b56adadbb8bfb1522b8e116d294be244f918f9a6142005d07
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c3ddac7902534aec8e14fb546287a45d6fd589c3b4c445b1291bef15d209b7eb9c43484f169ee7e3b9dcac44939b57f4d19d6fae07a261edf6d12499af11d16a
|
|
7
|
+
data.tar.gz: e1eebd6fa2c8704e25afe48c2120a146d0513f17a55df883d68aad05bbedd08e04173455119abe06ab8ef15894358b650a5590be74435ffd166f27e698c6aef6
|
data/CHANGELOG.adoc
CHANGED
|
@@ -6,6 +6,62 @@ The format is based on https://keepachangelog.com/en/1.0.0/[Keep a Changelog^],
|
|
|
6
6
|
|
|
7
7
|
== Unreleased
|
|
8
8
|
|
|
9
|
+
== 0.5.0 - 2021-08-16
|
|
10
|
+
|
|
11
|
+
=== Added
|
|
12
|
+
|
|
13
|
+
- Reflect the date of the last update in the revision date
|
|
14
|
+
- Add captions to species lists in the AsciiDoc output
|
|
15
|
+
- Group species lists by taxonomic groups in the AsciiDoc output
|
|
16
|
+
|
|
17
|
+
=== Fixed
|
|
18
|
+
|
|
19
|
+
- Support species lists of Flora Helvetica exported from Favoriten
|
|
20
|
+
- Consider botanical names with the authority name preceding the subspecies
|
|
21
|
+
|
|
22
|
+
== 0.4.0 - 2021-05-02
|
|
23
|
+
|
|
24
|
+
=== Added
|
|
25
|
+
|
|
26
|
+
- Show date/time of images in draft output
|
|
27
|
+
- Support preferred conversion backend for draft output
|
|
28
|
+
|
|
29
|
+
=== Changed
|
|
30
|
+
|
|
31
|
+
- Remove redundant method `Image.portrait?`
|
|
32
|
+
|
|
33
|
+
== 0.3.0 - 2021-03-07
|
|
34
|
+
|
|
35
|
+
=== Changed
|
|
36
|
+
|
|
37
|
+
- Sort the reports according to their GPS track
|
|
38
|
+
- Bump minimum required Ruby version to 2.5
|
|
39
|
+
- Change font in PDF output to support ♀ and ♂ symbols
|
|
40
|
+
|
|
41
|
+
=== Fixed
|
|
42
|
+
|
|
43
|
+
- Make source code compatible with Ruby version 2.5
|
|
44
|
+
|
|
45
|
+
== 0.2.0 - 2021-01-24
|
|
46
|
+
|
|
47
|
+
=== Added
|
|
48
|
+
|
|
49
|
+
- Add this gem's name to the footer of the PDF output
|
|
50
|
+
- Support species lists from https://www.ornitho.ch/[ornitho.ch^] (KML format only)
|
|
51
|
+
- Classify species lists by taxonomic groups (i.e. `SpeciesList.group`)
|
|
52
|
+
|
|
53
|
+
=== Changed
|
|
54
|
+
|
|
55
|
+
- Change `SpeciesList.name` to `SpeciesList.title`
|
|
56
|
+
- Return an empty array from `SpeciesList.load_file` if the format is unknown
|
|
57
|
+
- Change the format of the start time in the AsciiDoc output from _12:30_ to _12:30 Uhr_
|
|
58
|
+
- Change the format of the duration in the AsciiDoc output from _1h30_ to _1:30 h_
|
|
59
|
+
|
|
60
|
+
=== Fixed
|
|
61
|
+
|
|
62
|
+
- Get the date from images even if the orientation tag is missing
|
|
63
|
+
- Fix typo in help message
|
|
64
|
+
|
|
9
65
|
== 0.1.0 - 2020-12-04
|
|
10
66
|
|
|
11
67
|
=== Added
|
data/README.adoc
CHANGED
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
|
)
|
|
@@ -27,9 +28,9 @@ option_parser = OptionParser.new do |opts|
|
|
|
27
28
|
opts.separator(WordWrap.ww(
|
|
28
29
|
'If PATH refers to a directory, one or more reports are created in ' \
|
|
29
30
|
'AsciiDoc format. GPS tracks, images and species lists (Kosmos ' \
|
|
30
|
-
'Vogelführer, Flora Helvetica, Info Flora Online-Feldbuch)
|
|
31
|
-
'included. Images of the map section covered by the GPS tracks are
|
|
32
|
-
'created and included. If PATH refers to an AsciiDoc file, it is ' \
|
|
31
|
+
'Vogelführer, ornitho.ch, Flora Helvetica, Info Flora Online-Feldbuch) ' \
|
|
32
|
+
'are included. Images of the map section covered by the GPS tracks are ' \
|
|
33
|
+
'also created and included. If PATH refers to an AsciiDoc file, it is ' \
|
|
33
34
|
'converted to PDF (or any other supported format).'
|
|
34
35
|
))
|
|
35
36
|
opts.separator('')
|
|
@@ -49,7 +50,7 @@ option_parser = OptionParser.new do |opts|
|
|
|
49
50
|
end
|
|
50
51
|
opts.separator('')
|
|
51
52
|
opts.separator('Creation:')
|
|
52
|
-
opts.on('--track-formats FORMATS', Array, 'GPS track formats (gpx, fit') do |value|
|
|
53
|
+
opts.on('--track-formats FORMATS', Array, 'GPS track formats (gpx, fit)') do |value|
|
|
53
54
|
config['track-formats'] = value.map(&:to_sym)
|
|
54
55
|
end
|
|
55
56
|
opts.on('--[no-]map', 'Create map images') do |value|
|
|
@@ -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
|
data/lib/natour.rb
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
require 'natour/
|
|
2
|
-
require 'natour/
|
|
3
|
-
require 'natour/
|
|
4
|
-
require 'natour/
|
|
1
|
+
require 'natour/utils/botanical_name_utils'
|
|
2
|
+
require 'natour/utils/date_utils'
|
|
3
|
+
require 'natour/utils/stdout_utils'
|
|
4
|
+
require 'natour/convert'
|
|
5
|
+
require 'natour/create'
|
|
5
6
|
require 'natour/asciinurse'
|
|
6
7
|
require 'natour/config'
|
|
7
8
|
require 'natour/gps_track'
|
data/lib/natour/asciinurse.rb
CHANGED
|
@@ -30,9 +30,10 @@ module Natour
|
|
|
30
30
|
doc << "= #{title}"
|
|
31
31
|
if author
|
|
32
32
|
doc << author
|
|
33
|
-
doc <<
|
|
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
|
|
@@ -51,8 +52,8 @@ module Natour
|
|
|
51
52
|
doc << '[cols="h,3"]'
|
|
52
53
|
doc << '|==='
|
|
53
54
|
doc << "|Datum |#{gps_track&.date&.strftime('%d.%m.%Y')}"
|
|
54
|
-
doc << "|Startzeit |#{gps_track&.start_point&.time&.strftime('%H:%M')}"
|
|
55
|
-
doc << "|Dauer |#{gps_track&.duration&.strftime('%
|
|
55
|
+
doc << "|Startzeit |#{gps_track&.start_point&.time&.strftime('%H:%M Uhr')}"
|
|
56
|
+
doc << "|Dauer |#{gps_track&.duration&.strftime('%th:%M h')}"
|
|
56
57
|
doc << "|Strecke |#{distance.call(gps_track)}"
|
|
57
58
|
doc << "|Aufstieg |#{ascent.call(gps_track)}"
|
|
58
59
|
doc << "|Abstieg |#{descent.call(gps_track)}"
|
|
@@ -77,10 +78,10 @@ module Natour
|
|
|
77
78
|
doc << '== Bilder'
|
|
78
79
|
doc << ''
|
|
79
80
|
images.each do |image|
|
|
80
|
-
width = if image.
|
|
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,36 +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
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
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
|
+
|
|
111
115
|
doc << "=== #{info.title}"
|
|
112
116
|
doc << ''
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
doc << "
|
|
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
|
|
118
130
|
end
|
|
119
|
-
doc << '|==='
|
|
120
|
-
doc << ''
|
|
121
131
|
end
|
|
122
132
|
end
|
|
123
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
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
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,17 +3,29 @@ 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,
|
|
15
22
|
safe: :unsafe,
|
|
16
|
-
standalone: true
|
|
23
|
+
standalone: true,
|
|
24
|
+
attributes: {
|
|
25
|
+
'pdf-theme' => 'natour',
|
|
26
|
+
'pdf-themesdir' => "#{__dir__}/data/themes",
|
|
27
|
+
'pdf-fontsdir' => "#{__dir__}/data/fonts"
|
|
28
|
+
}
|
|
17
29
|
)
|
|
18
30
|
|
|
19
31
|
dir = Pathname(filename).dirname
|
|
@@ -24,7 +36,28 @@ module Natour
|
|
|
24
36
|
|
|
25
37
|
if draft
|
|
26
38
|
doc.find_by(context: :image).each do |node|
|
|
27
|
-
|
|
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'))
|
|
28
61
|
end
|
|
29
62
|
end
|
|
30
63
|
|
|
@@ -35,25 +68,17 @@ module Natour
|
|
|
35
68
|
title_logo_image = doc.attr('title-logo-image')
|
|
36
69
|
if title_logo_image
|
|
37
70
|
target = title_logo_image[/^image:{1,2}(.*?)\[(.*?)\]$/, 1]
|
|
38
|
-
|
|
39
|
-
options[:autorotate] = true if target =~ /\.jpe?g$/i
|
|
40
|
-
image = Vips::Image.new_from_file(dir.join(target).to_s, options)
|
|
41
|
-
scale = image_maxdim / image.size.max.to_f
|
|
42
|
-
image = image.resize(scale) if scale < 1.0
|
|
71
|
+
image = Image.load_file(dir.join(target).to_s).autorotate.shrink_to(image_maxdim)
|
|
43
72
|
new_target = tmp_dir.join("title_logo_image_#{Pathname(target).basename}").to_s
|
|
44
|
-
|
|
73
|
+
image.save_as(new_target)
|
|
45
74
|
doc.set_attr('title-logo-image', title_logo_image.gsub(target, new_target))
|
|
46
75
|
end
|
|
47
76
|
|
|
48
77
|
doc.find_by(context: :image).each.with_index do |node, index|
|
|
49
78
|
target = node.attr('target')
|
|
50
|
-
|
|
51
|
-
options[:autorotate] = true if target =~ /\.jpe?g$/i
|
|
52
|
-
image = Vips::Image.new_from_file(dir.join(target).to_s, options)
|
|
53
|
-
scale = image_maxdim / image.size.max.to_f
|
|
54
|
-
image = image.resize(scale) if scale < 1.0
|
|
79
|
+
image = Image.load_file(dir.join(target).to_s).autorotate.shrink_to(image_maxdim)
|
|
55
80
|
new_target = tmp_dir.join("image#{index}_#{Pathname(target).basename}").to_s
|
|
56
|
-
|
|
81
|
+
image.save_as(new_target)
|
|
57
82
|
node.set_attr('target', new_target)
|
|
58
83
|
end
|
|
59
84
|
|
|
File without changes
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
---
|
|
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
|
|
12
|
+
footer:
|
|
13
|
+
recto:
|
|
14
|
+
left:
|
|
15
|
+
content: 'by natour'
|
|
16
|
+
right:
|
|
17
|
+
content: '{page-number}'
|
|
18
|
+
verso:
|
|
19
|
+
left:
|
|
20
|
+
content: $footer_recto_right_content
|
|
21
|
+
right:
|
|
22
|
+
content: $footer_recto_left_content
|
data/lib/natour/image.rb
CHANGED
|
@@ -1,33 +1,57 @@
|
|
|
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 =
|
|
12
|
-
|
|
13
|
-
@
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
)
|
|
21
|
-
rescue Vips::Error => e
|
|
22
|
-
raise unless e.to_s =~ /exif-ifd0-(Orientation|DateTime)/
|
|
13
|
+
@image = image
|
|
14
|
+
orientation = get_field('exif-ifd0-Orientation')
|
|
15
|
+
@landscape = if orientation
|
|
16
|
+
orientation[/^(\d) \(/, 1].to_i.between?(1, 4)
|
|
17
|
+
else
|
|
18
|
+
image.width >= image.height
|
|
19
|
+
end
|
|
20
|
+
date_time = get_field('exif-ifd0-DateTime')
|
|
21
|
+
@date_time = Timeliness.parse(date_time[/^(.*?) \(/, 1], format: 'yyyy:mm:dd hh:nn:ss') if date_time
|
|
23
22
|
end
|
|
24
23
|
|
|
25
|
-
def
|
|
26
|
-
|
|
24
|
+
def self.load_file(filename)
|
|
25
|
+
Image.new(filename, Vips::Image.new_from_file(filename))
|
|
27
26
|
end
|
|
28
27
|
|
|
29
28
|
def landscape?
|
|
30
|
-
|
|
29
|
+
@landscape
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def autorotate
|
|
33
|
+
Image.new(@path, @image.autorot)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def shrink_to(maxdim)
|
|
37
|
+
scale = maxdim / @image.size.max.to_f
|
|
38
|
+
image = if scale < 1.0
|
|
39
|
+
@image.resize(scale)
|
|
40
|
+
else
|
|
41
|
+
@image.copy
|
|
42
|
+
end
|
|
43
|
+
Image.new(@path, image)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def save_as(filename)
|
|
47
|
+
FileUtils.mkdir_p(Pathname(filename).dirname)
|
|
48
|
+
StdoutUtils.suppress_output { @image.write_to_file(filename) }
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
private
|
|
52
|
+
|
|
53
|
+
def get_field(name)
|
|
54
|
+
@image.get(name) if @image.get_fields.include?(name)
|
|
31
55
|
end
|
|
32
56
|
end
|
|
33
57
|
end
|
data/lib/natour/map_geo_admin.rb
CHANGED
|
@@ -9,7 +9,7 @@ module Natour
|
|
|
9
9
|
class MapGeoAdmin
|
|
10
10
|
def initialize(port: 0)
|
|
11
11
|
@doc_root = Dir.mktmpdir
|
|
12
|
-
FileUtils.cp_r("#{__dir__}/js", @doc_root)
|
|
12
|
+
FileUtils.cp_r("#{__dir__}/data/js", @doc_root)
|
|
13
13
|
event = Concurrent::Event.new
|
|
14
14
|
@server = WEBrick::HTTPServer.new(
|
|
15
15
|
StartCallback: -> { event.set },
|
data/lib/natour/report.rb
CHANGED
|
@@ -35,10 +35,10 @@ 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.
|
|
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
|
-
Pathname.glob('**/*.csv', File::FNM_CASEFOLD)
|
|
41
|
+
Pathname.glob('**/*.{csv,kml}', File::FNM_CASEFOLD)
|
|
42
42
|
.map { |filename| SpeciesList.load_file(filename.to_s) }
|
|
43
43
|
.flatten
|
|
44
44
|
.sort_by { |species_list| [species_list.type, species_list.date ? 0 : 1, species_list.date] }
|
|
@@ -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.
|
|
61
|
+
Image.load_file(filename.to_s)
|
|
61
62
|
end
|
|
62
63
|
end
|
|
63
64
|
end
|
data/lib/natour/species_list.rb
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
require 'csv'
|
|
2
|
+
require 'nokogiri'
|
|
2
3
|
require 'pathname'
|
|
3
4
|
|
|
4
5
|
module Natour
|
|
@@ -6,51 +7,64 @@ module Natour
|
|
|
6
7
|
attr_reader :path
|
|
7
8
|
attr_reader :date
|
|
8
9
|
attr_reader :type
|
|
9
|
-
attr_reader :
|
|
10
|
+
attr_reader :group
|
|
11
|
+
attr_reader :title
|
|
10
12
|
attr_reader :description
|
|
11
13
|
|
|
12
|
-
def initialize(path, date, type,
|
|
14
|
+
def initialize(path, date, type, group, title, description, items)
|
|
13
15
|
@path = path
|
|
14
16
|
@date = date
|
|
15
17
|
@type = type
|
|
16
|
-
@
|
|
18
|
+
@group = group
|
|
19
|
+
@title = title
|
|
17
20
|
@description = description
|
|
18
21
|
@items = items
|
|
19
22
|
end
|
|
20
23
|
|
|
21
24
|
def self.load_file(filename)
|
|
22
|
-
block = IO.binread(filename,
|
|
25
|
+
block = IO.binread(filename, 128)
|
|
23
26
|
header = if block.unpack('CC') == [0xff, 0xfe]
|
|
24
27
|
block[2..-1].force_encoding('utf-16le').encode('utf-8')
|
|
25
28
|
elsif block.unpack('CCC') == [0xef, 0xbb, 0xbf]
|
|
26
29
|
block[3..-1].force_encoding('utf-8')
|
|
27
30
|
else
|
|
28
|
-
block
|
|
31
|
+
block
|
|
29
32
|
end
|
|
30
33
|
|
|
31
34
|
case header
|
|
32
35
|
when /^Primary/
|
|
33
36
|
CSV.open(filename, 'r:windows-1252:utf-8', headers: true, liberal_parsing: true) do |csv|
|
|
34
|
-
date =
|
|
37
|
+
date = DateUtils.parse(Pathname(filename).basename).compact.first
|
|
35
38
|
items = csv.map { |row| Species.new(row[1], row[0]) }
|
|
36
39
|
.sort_by(&:name_de).uniq
|
|
37
|
-
[SpeciesList.new(filename, date, :kosmos_vogelfuehrer, nil, nil, items)]
|
|
40
|
+
[SpeciesList.new(filename, date, :kosmos_vogelfuehrer, :birds, nil, nil, items)]
|
|
38
41
|
end
|
|
39
|
-
when
|
|
42
|
+
when /^<\?xml.*?www\.ornitho\.ch/m
|
|
43
|
+
date = DateUtils.parse(Pathname(filename).basename).compact.first
|
|
44
|
+
doc = Nokogiri.XML(File.read(filename, mode: 'r:utf-8'))
|
|
45
|
+
folder = doc.at('/xmlns:kml/xmlns:Document/xmlns:Folder/xmlns:Folder/xmlns:Folder')
|
|
46
|
+
name = folder.at('./xmlns:name').text
|
|
47
|
+
items = folder.xpath('./xmlns:Placemark/xmlns:description')
|
|
48
|
+
.map(&:text)
|
|
49
|
+
.map { |description| Species.new(*description.scan(/>([^&(]+)</).flatten.reverse) }
|
|
50
|
+
.sort_by(&:name_de).uniq
|
|
51
|
+
[SpeciesList.new(filename, date, :ornitho_ch, :birds, name, nil, items)]
|
|
52
|
+
when /^(Favoriten|NUMMER_FLORA)/
|
|
40
53
|
CSV.open(filename, 'r:bom|utf-8', col_sep: ';', skip_blanks: true) do |csv|
|
|
41
|
-
chunks = csv.reject { |row| row.count == 1
|
|
42
|
-
.
|
|
54
|
+
chunks = csv.reject { |row| row.count == 1 }
|
|
55
|
+
.map { |row| row[0] == 'NUMMER_FLORA' ? ['Favoriten'] : row }
|
|
43
56
|
.slice_before { |row| row.count == 1 || row.count == 3 }
|
|
44
57
|
.reject { |rows| rows.count == 1 }
|
|
45
58
|
chunks.map do |rows|
|
|
46
59
|
name, description = rows.shift
|
|
47
|
-
date =
|
|
48
|
-
items = rows.map { |row| Species.new(row[1]
|
|
60
|
+
date = DateUtils.parse(name, Pathname(filename).basename).compact.first
|
|
61
|
+
items = rows.map { |row| Species.new(BotanicalNameUtils.parse(row[1]), row[2]) }
|
|
49
62
|
.sort_by(&:name).uniq
|
|
50
63
|
SpeciesList.new(
|
|
51
64
|
filename,
|
|
52
65
|
date,
|
|
53
66
|
:flora_helvetica,
|
|
67
|
+
:plants,
|
|
54
68
|
name&.gsub(/^(\d{4}-)?\d{2}-\d{2}( |_|-)?/, ''),
|
|
55
69
|
description,
|
|
56
70
|
items
|
|
@@ -59,12 +73,14 @@ module Natour
|
|
|
59
73
|
end
|
|
60
74
|
when /^obs_id/
|
|
61
75
|
CSV.open(filename, 'r:bom|utf-16le:utf-8', col_sep: "\t", headers: true) do |csv|
|
|
62
|
-
date =
|
|
76
|
+
date = DateUtils.parse(Pathname(filename).basename).compact.first
|
|
63
77
|
items = csv.select { |row| row[0] }
|
|
64
|
-
.map { |row| Species.new(row[11]
|
|
78
|
+
.map { |row| Species.new(BotanicalNameUtils.parse(row[11]), nil) }
|
|
65
79
|
.sort_by(&:name).uniq
|
|
66
|
-
[SpeciesList.new(filename, date, :info_flora, nil, nil, items)]
|
|
80
|
+
[SpeciesList.new(filename, date, :info_flora, :plants, nil, nil, items)]
|
|
67
81
|
end
|
|
82
|
+
else
|
|
83
|
+
[]
|
|
68
84
|
end
|
|
69
85
|
end
|
|
70
86
|
|
|
@@ -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
|
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.
|
|
4
|
+
version: 0.5.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:
|
|
11
|
+
date: 2021-08-16 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
|
|
@@ -177,29 +177,37 @@ files:
|
|
|
177
177
|
- bin/natour
|
|
178
178
|
- lib/natour.rb
|
|
179
179
|
- lib/natour/asciinurse.rb
|
|
180
|
-
- lib/natour/cli/convert.rb
|
|
181
|
-
- lib/natour/cli/create.rb
|
|
182
180
|
- lib/natour/config.rb
|
|
181
|
+
- lib/natour/convert.rb
|
|
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
|
|
187
|
+
- lib/natour/data/js/bootstrap.min.js
|
|
188
|
+
- lib/natour/data/js/jquery-3.5.1.slim.min.js
|
|
189
|
+
- lib/natour/data/js/loader.js
|
|
190
|
+
- lib/natour/data/themes/natour-theme.yml
|
|
183
191
|
- lib/natour/fit_file.rb
|
|
184
192
|
- lib/natour/gps_track.rb
|
|
185
193
|
- lib/natour/gps_track_point.rb
|
|
186
194
|
- lib/natour/gpx_file.rb
|
|
187
|
-
- lib/natour/helpers/date_parser.rb
|
|
188
|
-
- lib/natour/helpers/suppress_output.rb
|
|
189
195
|
- lib/natour/image.rb
|
|
190
|
-
- lib/natour/js/bootstrap.min.js
|
|
191
|
-
- lib/natour/js/jquery-3.5.1.slim.min.js
|
|
192
|
-
- lib/natour/js/loader.js
|
|
193
196
|
- lib/natour/map_geo_admin.rb
|
|
194
197
|
- lib/natour/public_transport.rb
|
|
195
198
|
- lib/natour/report.rb
|
|
196
199
|
- lib/natour/species.rb
|
|
197
200
|
- lib/natour/species_list.rb
|
|
198
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
|
|
199
205
|
homepage: https://rubygems.org/gems/natour
|
|
200
206
|
licenses:
|
|
201
207
|
- MIT
|
|
202
208
|
metadata:
|
|
209
|
+
bug_tracker_uri: https://github.com/simongysi/natour/issues
|
|
210
|
+
changelog_uri: https://github.com/simongysi/natour/blob/main/CHANGELOG.adoc
|
|
203
211
|
source_code_uri: https://github.com/simongysi/natour
|
|
204
212
|
post_install_message:
|
|
205
213
|
rdoc_options: []
|
|
@@ -209,7 +217,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
209
217
|
requirements:
|
|
210
218
|
- - ">="
|
|
211
219
|
- !ruby/object:Gem::Version
|
|
212
|
-
version: '2.
|
|
220
|
+
version: '2.5'
|
|
213
221
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
214
222
|
requirements:
|
|
215
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
|