natour 0.7.0 → 0.8.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: 6c649407352883c9e93ab6d6470413127d54803bb35dc72beb83292c9e521626
4
- data.tar.gz: dbeb8f8ae4a412d7832c07ab66d717d40bb5e2ecd096fb076655ef65a6840b53
3
+ metadata.gz: 96d45e360af42e65ff67db55ff6e9814013e0a884ceb5b601ceec10731312181
4
+ data.tar.gz: f495db38dbdef792422945c891ddf830850a812513663e6cffd72fd4757f1b97
5
5
  SHA512:
6
- metadata.gz: b5a810b2ea0220c9eded025e0f00f8e4f782a42b54128f71a2929a84a535e75f45bb3ddff0cf72f7dad08e047c1aaef3b88800e778901405357efd11336b5db0
7
- data.tar.gz: a928d426c1840cb57fb7ab58064850572fc2a7e14aeda6086b2c9560c8b2d7e3e8253c268a9070bef91e4c7fb2c0f26daf2e5664a043f29b595d192a0299137f
6
+ metadata.gz: 2a520888a91305d5cd924d133d1356bc1021b0cf75c2ad7753e577e1a7455afbb610991c080a88ca5dc3e4c0bdc9895e36d518694a9e0b8faa6d27bfe0552ba8
7
+ data.tar.gz: eb6ca2cbc565dfd79e2ea06413a00a9362996cd45aca70b601e06fca58e6acae5d1bd47f2bbf0d8962f6b1a03922f3477446eca019d5648a1b4ad0334a509938
data/CHANGELOG.adoc CHANGED
@@ -6,90 +6,125 @@ The format is based on https://keepachangelog.com/en/1.0.0/[Keep a Changelog^],
6
6
 
7
7
  == Unreleased
8
8
 
9
+ == 0.8.0 - 2022-04-22
10
+
11
+ === Added
12
+
13
+ - Add command to create map images from GPS tracks, waypoints and routes.
14
+ - Add command line option to display the version of this gem.
15
+
16
+ === Changed
17
+
18
+ - Rename arguments of `Natour::MapGeoAdmin.save_image`, i.e. `tracks` to `gps_files`, `layers` to `map_layers` and `size` to `image_size`.
19
+ +
20
+ IMPORTANT: This is a breaking change.
21
+ - Improve the error reporting on the command line interface in case of file errors.
22
+ - Rework the configuration; the structure and naming follows the command line interface and the keys are of type Ruby Symbol. For details, see the README file.
23
+ +
24
+ IMPORTANT: This is a breaking change. Adapt the configuration file accordingly.
25
+ - Rework the command line interface. Use `natour --help` to get more information.
26
+ +
27
+ IMPORTANT: This is a breaking change. Adapt the commands accordingly.
28
+ - Change `backend` and `draft_backend` arguments of `Natour::convert_report` to symbols.
29
+ +
30
+ IMPORTANT: This is a breaking change. Adapt the configuration file accordingly.
31
+ - Rename `Natour::create` to `Natour::create_reports` and `Natour::convert` to `Natour::convert_report`.
32
+ +
33
+ IMPORTANT: This is a breaking change.
34
+
35
+ === Fixed
36
+
37
+ - Do not overwrite map images unless otherwise specified.
38
+ - Do not abort if the configuration file is empty.
39
+
9
40
  == 0.7.0 - 2022-02-14
10
41
 
11
42
  === Added
12
43
 
13
- - Add support for Ruby 3.0 and 3.1
14
- - Support species lists from Vogelführer Birdlife Schweiz
44
+ - Add support for Ruby 3.0 and 3.1.
45
+ - Support species lists from https://www.birdlife.ch/de/content/eine-neue-moderne-vogel-app-fuer-die-schweiz[Vogelführer Birdlife Schweiz^].
15
46
 
16
47
  === Changed
17
48
 
18
- - Return the filenames from `create` and `convert`
49
+ - Return the filenames from `Natour::create` and `Natour::convert`.
19
50
 
20
51
  === Removed
21
52
 
22
- - Drop support for Ruby 2.5
53
+ - Drop support for Ruby 2.5.
23
54
 
24
55
  === Fixed
25
56
 
26
- - Add revision date to the AsciiDoc output regardless of the author
27
- - Prevent conversion from being aborted if a built-in date/time attribute is missing
57
+ - Add revision date to the AsciiDoc output regardless of the author.
58
+ - Prevent conversion from being aborted if a built-in date/time attribute is missing.
28
59
 
29
60
  == 0.6.0 - 2021-11-20
30
61
 
31
62
  === Fixed
32
63
 
33
- - Support GPX files containing only mandatory elements (i.e. no extensions)
34
- - Consider also the image dimensions to determine the orientation, even if the tag is present
64
+ - Support GPX files containing only mandatory elements (i.e. no extensions).
65
+ - Consider also the image dimensions to determine the orientation, even if the tag is present.
35
66
 
36
67
  == 0.5.0 - 2021-08-16
37
68
 
38
69
  === Added
39
70
 
40
- - Reflect the date of the last update in the revision date
41
- - Add captions to species lists in the AsciiDoc output
42
- - Group species lists by taxonomic groups in the AsciiDoc output
71
+ - Reflect the date of the last update in the revision date.
72
+ - Add captions to species lists in the AsciiDoc output.
73
+ - Group species lists by taxonomic groups in the AsciiDoc output.
43
74
 
44
75
  === Fixed
45
76
 
46
- - Support species lists of Flora Helvetica exported from Favoriten
47
- - Consider botanical names with the authority name preceding the subspecies
77
+ - Support species lists of https://www.flora-helvetica.ch/[Flora Helvetica^] exported from _Favoriten_.
78
+ - Consider botanical names with the authority name preceding the subspecies.
48
79
 
49
80
  == 0.4.0 - 2021-05-02
50
81
 
51
82
  === Added
52
83
 
53
- - Show date/time of images in draft output
54
- - Support preferred conversion backend for draft output
84
+ - Show date/time of images in draft output.
85
+ - Support preferred conversion backend for draft output.
55
86
 
56
- === Changed
87
+ === Removed
57
88
 
58
- - Remove redundant method `Image.portrait?`
89
+ - Remove redundant method `Natour::Image.portrait?`.
90
+ +
91
+ IMPORTANT: This is a breaking change. Use `Natour::Image.landscape?` instead.
59
92
 
60
93
  == 0.3.0 - 2021-03-07
61
94
 
62
95
  === Changed
63
96
 
64
- - Sort the reports according to their GPS track
65
- - Bump minimum required Ruby version to 2.5
66
- - Change font in PDF output to support ♀ and ♂ symbols
97
+ - Sort the reports according to their GPS track.
98
+ - Bump minimum required Ruby version to 2.5.
99
+ - Change font in PDF output to support ♀ and ♂ symbols.
67
100
 
68
101
  === Fixed
69
102
 
70
- - Make source code compatible with Ruby version 2.5
103
+ - Make source code compatible with Ruby 2.5.
71
104
 
72
105
  == 0.2.0 - 2021-01-24
73
106
 
74
107
  === Added
75
108
 
76
- - Add this gem's name to the footer of the PDF output
77
- - Support species lists from https://www.ornitho.ch/[ornitho.ch^] (KML format only)
78
- - Classify species lists by taxonomic groups (i.e. `SpeciesList.group`)
109
+ - Add this gem's name to the footer of the PDF output.
110
+ - Support species lists from https://www.ornitho.ch/[ornitho.ch^] (KML format only).
111
+ - Classify species lists by taxonomic groups (i.e. `Natour::SpeciesList.group`).
79
112
 
80
113
  === Changed
81
114
 
82
- - Change `SpeciesList.name` to `SpeciesList.title`
83
- - Return an empty array from `SpeciesList.load_file` if the format is unknown
84
- - Change the format of the start time in the AsciiDoc output from _12:30_ to _12:30 Uhr_
85
- - Change the format of the duration in the AsciiDoc output from _1h30_ to _1:30 h_
115
+ - Rename `Natour::SpeciesList.name` to `Natour::SpeciesList.title`.
116
+ +
117
+ IMPORTANT: This is a breaking change.
118
+ - Return an empty array from `Natour::SpeciesList.load_file` if the format is unknown.
119
+ - Change the format of the start time in the AsciiDoc output from _12:30_ to _12:30 Uhr_.
120
+ - Change the format of the duration in the AsciiDoc output from _1h30_ to _1:30 h_.
86
121
 
87
122
  === Fixed
88
123
 
89
- - Get the date from images even if the orientation tag is missing
90
- - Fix typo in help message
124
+ - Get the date from images even if the orientation tag is missing.
125
+ - Fix typo in help message.
91
126
 
92
127
  == 0.1.0 - 2020-12-04
93
128
 
94
129
  === Added
95
- - First release
130
+ - First release.
data/README.adoc CHANGED
@@ -1,6 +1,6 @@
1
1
  = natour
2
2
 
3
- This https://rubygems.org/gems/natour[RubyGem^] provides an application and a library for reports on nature activities.
3
+ This https://rubygems.org/gems/natour[RubyGem^] provides an application and a library to document nature activities.
4
4
 
5
5
  == Installation
6
6
 
@@ -58,49 +58,101 @@ sudo apt install ./google-chrome-stable_current_amd64.deb
58
58
 
59
59
  == Application
60
60
 
61
- [cols="1,4",options=header]
62
- |===
63
- |Command
64
- |Description
61
+ Create reports in https://asciidoc.org/[AsciiDoc^] format from a directory with GPS tracks, images and species lists. After editing the AsciiDoc files (e.g. selecting the images and describing the adventure), they can be converted to various formats, including PDF and HTML. A typical directory structure and the necessary commands are shown in the following example.
62
+
63
+ ....
64
+ └─ 2022-02-26 Monte Caslano < Root directory
65
+ ├─ Bilder < Directory containing images
66
+ │ ├─ IMG_7687.JPG
67
+ │ ├─ IMG_7688.JPG
68
+ │ ├─ ...
69
+ │ └─ IMG_7870.JPG
70
+ ├─ 2022-02-26 14.45.27.fit < GPS track exported by GPS device
71
+ ├─ 2022-02-26 14.45.27.gpx < GPS track exported by GPS device
72
+ ├─ 2022-02-26 14.45.27.jpg < Image of the map section created
73
+ ├─ 2022-02-26 Monte Caslano.adoc < Report in AsciiDoc format created
74
+ ├─ 2022-02-26 Monte Caslano.pdf < Report converted from AsciiDoc to PDF
75
+ ├─ 2022-02-26MonteCaslano.csv < Species list exported from Kosmos Vogelführer
76
+ └─ flora_helvetica_sammlungen.csv < Species list exported from Flora Helvetica
77
+ ....
65
78
 
66
- |`natour`
67
- |Create reports in https://asciidoc.org/[AsciiDoc^] format from a directory with GPS tracks, images and species lists. After editing the AsciiDoc files, they can be converted to various formats, including PDF and HTML. Use `natour --help` to get more information.
68
- |===
79
+ [source,shell]
80
+ ----
81
+ natour report create "2022-02-26 Monte Caslano"
82
+ ----
83
+
84
+ [source,shell]
85
+ ----
86
+ natour report convert "2022-02-26 Monte Caslano/2022-02-26 Monte Caslano.adoc"
87
+ ----
88
+
89
+ NOTE: Use `natour --help` to get more information.
69
90
 
70
91
  === Configuration
71
92
 
72
- The configuration is built by loading https://yaml.org/[YAML^] files in hierarchical order. The files must be named `natour.yml` and are loaded first from the home directory of the current user and then from the current working directory. The values of the previously loaded files are overwritten by the values of the files loaded later. The key-value pairs are stored internally in a Ruby Hash, where the keys correspond to the command line arguments without leading dashes and without `no-` prefix for boolean switches.
93
+ The configuration is built by loading https://yaml.org/[YAML^] files in hierarchical order. The files must be named `natour.yml` and are loaded first from the home directory of the current user and then from the current working directory. The values of the previously loaded files are overwritten by the values of the files loaded later. The values are stored internally in nested, dictionary-like collections (Ruby `Hash`), where the structure follows to the command line interface. All keys are of type Ruby `Symbol` and correspond to the commands and options, with middle hyphens replaced by underscores, leading hyphens removed, and without the `no-` prefix for boolean switches. The following configuration file shows all entries and their default values.
94
+
95
+ [source,yml]
96
+ ----
97
+ ---
98
+ :report:
99
+ :create:
100
+ :out_dir: null
101
+ :out_file: null
102
+ :overwrite: false
103
+ :track_formats:
104
+ - :gpx
105
+ - :fit
106
+ :map: true
107
+ :map_layers: []
108
+ :adoc_author: null
109
+ :convert:
110
+ :out_dir: null
111
+ :out_file: null
112
+ :overwrite: false
113
+ :backend: :pdf
114
+ :draft: false
115
+ :draft_backend: null
116
+ :image_maxdim: 1800
117
+ :map:
118
+ :create:
119
+ :out_dir: null
120
+ :out_file: null
121
+ :overwrite: false
122
+ :map_layers: []
123
+ :image_size: [1200, 900]
124
+ ----
73
125
 
74
126
  How to restrict GPS tracks to the FIT format (see https://developer.garmin.com/fit/[FIT SDK^]) and add additional map layers (see https://api3.geo.admin.ch/api/faq/index.html#which-layers-are-available[API FAQ - GeoAdmin API 3.0 documentation^]) is shown in the example below.
75
127
 
76
128
  [source,yml]
77
129
  ----
78
130
  ---
79
- track-formats:
80
- - !ruby/sym fit
81
- map-layers:
82
- - ch.swisstopo.swisstlm3d-wanderwege
83
- - ch.bav.haltestellen-oev
131
+ :report:
132
+ :create:
133
+ :track_formats:
134
+ - :fit
135
+ :map_layers:
136
+ - ch.swisstopo.swisstlm3d-wanderwege
137
+ - ch.bav.haltestellen-oev
84
138
  ----
85
139
 
86
140
  == Library
87
141
 
88
- === Basic Use
89
-
90
142
  The basic use is shown in the following example. For details, see the source code and the unit tests.
91
143
 
92
144
  [source,ruby]
93
145
  ----
94
146
  require 'natour'
95
147
 
96
- Natour::create('path/to/dir')
148
+ Natour::create_reports('path/to/dir')
97
149
  ----
98
150
 
99
151
  [source,ruby]
100
152
  ----
101
153
  require 'natour'
102
154
 
103
- Natour::convert('path/to/dir/report.adoc')
155
+ Natour::convert_report('path/to/dir/report.adoc')
104
156
  ----
105
157
 
106
158
  === Testing
data/bin/natour CHANGED
@@ -1,117 +1,165 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require 'word_wrap'
4
- require 'pathname'
5
- require 'optparse'
3
+ require 'clamp'
6
4
  require 'natour'
5
+ require 'pathname'
6
+ require 'word_wrap'
7
7
 
8
- config = Natour::Config.load_file(
9
- Pathname($PROGRAM_NAME).basename.sub_ext('.yml'),
10
- default: {
11
- 'out-dir' => nil,
12
- 'out-file' => nil,
13
- 'overwrite' => false,
14
- 'track-formats' => %i[gpx fit],
15
- 'map' => true,
16
- 'map-layers' => [],
17
- 'adoc-author' => nil,
18
- 'backend' => 'pdf',
19
- 'draft' => false,
20
- 'draft-backend' => nil,
21
- 'image-maxdim' => 1800
22
- }
23
- )
8
+ class NatourCmd < Clamp::Command
9
+ class ReportCmd < Clamp::Command
10
+ class CreateCmd < Clamp::Command
11
+ banner(WordWrap.ww(
12
+ 'Create reports in AsciiDoc format from a directory. GPS tracks, images and species ' \
13
+ 'lists (Kosmos Vogelführer, Vogelführer Birdlife Schweiz, ornitho.ch, Flora Helvetica, ' \
14
+ 'Info Flora Online-Feldbuch) are included. Images of the map section covered by the GPS ' \
15
+ 'tracks are also created and included.'
16
+ ))
17
+ option(%w[-d --out-dir], 'DIR', 'Output directory')
18
+ option(%w[-f --out-file], 'FILE', 'Output filename')
19
+ option(%W[--\[no-\]overwrite], :flag, 'Overwrite existing files')
20
+ option(%w[--track-formats], 'FORMATS', 'GPS track formats (gpx, fit)') { |s| s.split(',').map(&:to_sym) }
21
+ option(%W[--\[no-\]map], :flag, 'Create map images')
22
+ option(%w[--map-layers], 'LAYERS', 'Add additional layers to map images') { |s| s.split(',') }
23
+ option(%w[--adoc-author], 'AUTHOR', 'AsciiDoc author (name <email>[; name2 <email2>...])')
24
+ parameter('PATH', 'Path to directory')
24
25
 
25
- option_parser = OptionParser.new do |opts|
26
- opts.banner = "Usage: #{Pathname($PROGRAM_NAME).basename('.*')} [OPTIONS]... PATH"
27
- opts.separator('')
28
- opts.separator(WordWrap.ww(
29
- 'If PATH refers to a directory, one or more reports are created in ' \
30
- 'AsciiDoc format. GPS tracks, images and species lists (Kosmos ' \
31
- 'Vogelführer, Vogelführer Birdlife Schweiz, ornitho.ch, Flora Helvetica,' \
32
- ' Info Flora Online-Feldbuch) are included. Images of the map section ' \
33
- 'covered by the GPS tracks are also created and included. If PATH refers' \
34
- ' to an AsciiDoc file, it is converted to PDF (or any other supported ' \
35
- 'format).'
36
- ))
37
- opts.separator('')
38
- opts.separator('General:')
39
- opts.on('-h', '--help', 'Display this help screen') do
40
- $stdout.puts(opts)
41
- exit
42
- end
43
- opts.on('-d', '--out-dir DIR', 'Output directory') do |value|
44
- config['out-dir'] = value
45
- end
46
- opts.on('-f', '--out-file FILE', 'Output filename') do |value|
47
- config['out-file'] = value
48
- end
49
- opts.on('--[no-]overwrite', 'Overwrite existing files') do |value|
50
- config['overwrite'] = value
51
- end
52
- opts.separator('')
53
- opts.separator('Creation:')
54
- opts.on('--track-formats FORMATS', Array, 'GPS track formats (gpx, fit)') do |value|
55
- config['track-formats'] = value.map(&:to_sym)
56
- end
57
- opts.on('--[no-]map', 'Create map images') do |value|
58
- config['map'] = value
59
- end
60
- opts.on('--map-layers LAYERS', Array, 'Add additional layers to map images') do |value|
61
- config['map-layers'] = value
62
- end
63
- opts.on('--adoc-author AUTHOR', 'AsciiDoc author (name <email>[; name2 <email2>...])') do |value|
64
- config['adoc-author'] = value
65
- end
66
- opts.separator('')
67
- opts.separator('Conversion:')
68
- opts.on('-b', '--backend BACKEND', 'Conversion backend (pdf, html5 ...)') do |value|
69
- config['backend'] = value
70
- end
71
- opts.on('--[no-]draft', 'Show additional information (e.g. image paths)') do |value|
72
- config['draft'] = value
73
- end
74
- opts.on('--draft-backend BACKEND', 'Preferred conversion backend for draft (pdf, html5 ...)') do |value|
75
- config['draft-backend'] = value
76
- end
77
- opts.on('--image-maxdim DIM', 'Shrink oversized images (PDF only)') do |value|
78
- config['image-maxdim'] = value.to_i
26
+ def execute
27
+ config = context[:config][:report][:create]
28
+ Natour.create_reports(
29
+ path.encode('utf-8').delete_suffix('"').gsub('\\', '/'),
30
+ out_dir: out_dir || config[:out_dir],
31
+ out_file: out_file || config[:out_file],
32
+ overwrite: Natour::BooleanUtils.to_boolean(overwrite?, default_value: config[:overwrite]),
33
+ track_formats: track_formats || config[:track_formats],
34
+ create_map: Natour::BooleanUtils.to_boolean(map?, default_value: config[:map]),
35
+ map_layers: map_layers || config[:map_layers],
36
+ adoc_author: adoc_author || config[:adoc_author]
37
+ )
38
+ rescue Errno::EEXIST, Errno::ENOENT, Errno::EACCES, Errno::EINVAL => e
39
+ message, _, path = Natour::ErrnoUtils.split_message(e)
40
+ abort("ERROR: #{message} '#{path}'")
41
+ end
42
+ end
43
+
44
+ class ConvertCmd < Clamp::Command
45
+ banner(WordWrap.ww(
46
+ 'Convert a report from AsciiDoc to PDF or HTML (or any other supported format).'
47
+ ))
48
+ option(%w[-d --out-dir], 'DIR', 'Output directory')
49
+ option(%w[-f --out-file], 'FILE', 'Output filename')
50
+ option(%W[--\[no-\]overwrite], :flag, 'Overwrite existing files')
51
+ option(%w[-b --backend], 'BACKEND', 'Conversion backend (pdf, html5 ...)', &:to_sym)
52
+ option(%W[--\[no-\]draft], :flag, 'Show additional information (e.g. image paths)')
53
+ option(%w[--draft-backend], 'BACKEND', 'Preferred conversion backend for draft (pdf, html5 ...)', &:to_sym)
54
+ option(%w[--image-maxdim], 'DIM', 'Shrink oversized images (PDF only)') { |s| Integer(s) }
55
+ parameter('PATH', 'Path to AsciiDoc file')
56
+
57
+ def execute
58
+ config = context[:config][:report][:convert]
59
+ Natour.convert_report(
60
+ path.encode('utf-8').delete_suffix('"').gsub('\\', '/'),
61
+ out_dir: out_dir || config[:out_dir],
62
+ out_file: out_file || config[:out_file],
63
+ overwrite: Natour::BooleanUtils.to_boolean(overwrite?, default_value: config[:overwrite]),
64
+ backend: backend || config[:backend],
65
+ draft: Natour::BooleanUtils.to_boolean(draft?, default_value: config[:draft]),
66
+ draft_backend: draft_backend || config[:draft_backend],
67
+ image_maxdim: image_maxdim || config[:image_maxdim]
68
+ )
69
+ rescue Errno::EEXIST, Errno::ENOENT, Errno::EACCES, Errno::EISDIR => e
70
+ message, _, path = Natour::ErrnoUtils.split_message(e)
71
+ abort("ERROR: #{message} '#{path}'")
72
+ end
73
+ end
74
+
75
+ subcommand('create', 'Create AsciiDoc reports from directory', CreateCmd)
76
+ subcommand('convert', 'Convert AsciiDoc report to PDF or HTML', ConvertCmd)
79
77
  end
80
- end
81
78
 
82
- begin
83
- option_parser.parse!
84
- rescue OptionParser::InvalidArgument,
85
- OptionParser::InvalidOption => e
86
- abort("Error: #{e}")
87
- end
79
+ class MapCmd < Clamp::Command
80
+ class CreateCmd < Clamp::Command
81
+ banner(WordWrap.ww(
82
+ 'Create images of the map section covered by the GPS files. The GPS files must be in GPX' \
83
+ ' or KML format and contain tracks, waypoints or routes. The images are saved in JPG or ' \
84
+ 'PNG format.'
85
+ ))
86
+ option(%w[-d --out-dir], 'DIR', 'Output directory')
87
+ option(%w[-f --out-file], 'FILE', 'Output filename')
88
+ option(%W[--\[no-\]overwrite], :flag, 'Overwrite existing files')
89
+ option(%w[--map-layers], 'LAYERS', 'Add additional layers to map images') { |s| s.split(',') }
90
+ option(%w[--image-size], 'WIDTH,HEIGHT', 'Image size') do |s|
91
+ s.split(',', 2).map { |v| Integer(v) }
92
+ end
93
+ parameter('PATH ...', 'Paths to GPS files', attribute_name: :paths)
88
94
 
89
- abort('Error: wrong number of arguments') if ARGV.length != 1
95
+ def execute
96
+ config = context[:config][:map][:create]
97
+ Natour::MapGeoAdmin.open do |map|
98
+ filename = Pathname(out_dir || config[:out_dir] || Pathname(paths.first).dirname)
99
+ .join(out_file || config[:out_file] || Pathname(paths.first).basename.sub_ext('.jpg'))
100
+ map.save_image(
101
+ filename,
102
+ overwrite: Natour::BooleanUtils.to_boolean(overwrite?, default_value: config[:overwrite]),
103
+ gps_files: paths,
104
+ map_layers: map_layers || config[:map_layers],
105
+ image_size: image_size || config[:image_size]
106
+ )
107
+ end
108
+ rescue Errno::EEXIST, Errno::ENOENT, Errno::EACCES => e
109
+ message, _, path = Natour::ErrnoUtils.split_message(e)
110
+ abort("ERROR: #{message} '#{path}'")
111
+ end
112
+ end
90
113
 
91
- path = Pathname(ARGV[0].encode('utf-8')
92
- .delete_suffix('"')
93
- .gsub('\\', '/'))
114
+ subcommand('create', 'Create map images from GPS files', CreateCmd)
115
+ end
94
116
 
95
- if path.directory?
96
- Natour.create(
97
- path,
98
- out_dir: config['out-dir'],
99
- out_file: config['out-file'],
100
- overwrite: config['overwrite'],
101
- track_formats: config['track-formats'],
102
- create_map: config['map'],
103
- map_layers: config['map-layers'],
104
- adoc_author: config['adoc-author']
105
- )
106
- else
107
- Natour.convert(
108
- path,
109
- out_dir: config['out-dir'],
110
- out_file: config['out-file'],
111
- overwrite: config['overwrite'],
112
- backend: config['backend'],
113
- draft: config['draft'],
114
- draft_backend: config['draft-backend'],
115
- image_maxdim: config['image-maxdim']
116
- )
117
+ subcommand('report', 'Create or convert reports', ReportCmd)
118
+ subcommand('map', 'Create map images', MapCmd)
119
+
120
+ option(%w[-v --version], :flag, 'Display the version') do
121
+ $stdout.puts("#{invocation_path} #{Natour::VERSION}")
122
+ exit
123
+ end
117
124
  end
125
+
126
+ config = Natour::Config.load_file(
127
+ Pathname($PROGRAM_NAME).basename.sub_ext('.yml'),
128
+ default: {
129
+ report: {
130
+ create: {
131
+ out_dir: nil,
132
+ out_file: nil,
133
+ overwrite: false,
134
+ track_formats: %i[gpx fit],
135
+ map: true,
136
+ map_layers: [],
137
+ adoc_author: nil
138
+ },
139
+ convert: {
140
+ out_dir: nil,
141
+ out_file: nil,
142
+ overwrite: false,
143
+ backend: :pdf,
144
+ draft: false,
145
+ draft_backend: nil,
146
+ image_maxdim: 1800
147
+ }
148
+ },
149
+ map: {
150
+ create: {
151
+ out_dir: nil,
152
+ out_file: nil,
153
+ overwrite: false,
154
+ map_layers: [],
155
+ image_size: [1200, 900]
156
+ }
157
+ }
158
+ }
159
+ )
160
+
161
+ NatourCmd.run(
162
+ Pathname($PROGRAM_NAME).basename,
163
+ ARGV,
164
+ { config: config }
165
+ )
@@ -1,6 +1,6 @@
1
1
  require 'fileutils'
2
- require 'pathname'
3
2
  require 'ostruct'
3
+ require 'pathname'
4
4
 
5
5
  module Natour
6
6
  module Asciinurse
@@ -120,7 +120,8 @@ module Natour
120
120
  doc << '|==='
121
121
  doc << "|Nr.|#{info.headers.join('|')}"
122
122
  species_list.each do |species|
123
- doc << "|{counter:species_list#{index}}|#{info.columns.map { |method| species.send(method) }.join('|')}"
123
+ doc <<
124
+ "|{counter:species_list#{index}}|#{info.columns.map { |method| species.public_send(method) }.join('|')}"
124
125
  end
125
126
  doc << '|==='
126
127
  doc << ''
data/lib/natour/config.rb CHANGED
@@ -1,17 +1,20 @@
1
+ require 'deep_merge/rails_compat'
1
2
  require 'pathname'
2
3
  require 'yaml'
3
4
 
4
5
  module Natour
5
6
  class Config
6
7
  def self.load_file(filename, default: {}, dirs: [Dir.home, Dir.pwd])
7
- dirs.map do |dir|
8
- YAML.safe_load(
8
+ configs = dirs.map do |dir|
9
+ config = YAML.safe_load(
9
10
  File.read(Pathname(dir).join(filename)),
10
11
  permitted_classes: [Symbol]
11
12
  )
13
+ config || {}
12
14
  rescue Errno::ENOENT
13
15
  {}
14
- end.reduce(default, &:merge)
16
+ end
17
+ configs.reduce(default) { |dst, src| dst.deeper_merge!(src, overwrite_arrays: true) }
15
18
  end
16
19
  end
17
20
  end
@@ -1,15 +1,15 @@
1
- require 'fileutils'
2
- require 'pathname'
3
1
  require 'asciidoctor'
4
2
  require 'asciidoctor-pdf'
5
- require 'vips'
3
+ require 'fileutils'
4
+ require 'pathname'
6
5
  require 'time'
6
+ require 'vips'
7
7
 
8
8
  module Natour
9
9
  module_function
10
10
 
11
- def convert(filename, out_dir: nil, out_file: nil, overwrite: false,
12
- backend: 'pdf', draft: false, draft_backend: nil, image_maxdim: 16000)
11
+ def convert_report(filename, out_dir: nil, out_file: nil, overwrite: false,
12
+ backend: :pdf, draft: false, draft_backend: nil, image_maxdim: 16000)
13
13
  backend = if draft
14
14
  draft_backend || backend
15
15
  else
@@ -65,7 +65,7 @@ module Natour
65
65
  end
66
66
  end
67
67
 
68
- if backend == 'pdf'
68
+ if backend == :pdf
69
69
  Dir.mktmpdir do |tmp_dir|
70
70
  tmp_dir = Pathname(tmp_dir)
71
71
 
@@ -1,12 +1,14 @@
1
+ require 'pathname'
2
+
1
3
  module Natour
2
4
  module_function
3
5
 
4
- def create(dir, out_dir: nil, out_file: nil, overwrite: false,
5
- track_formats: %i[gpx fit], create_map: true, map_layers: [], adoc_author: nil)
6
+ def create_reports(dir, out_dir: nil, out_file: nil, overwrite: false,
7
+ track_formats: %i[gpx fit], create_map: true, map_layers: [], adoc_author: nil)
6
8
  out_dir = Pathname(out_dir || dir)
7
9
  out_file = Pathname(out_file || "#{Pathname(dir).realpath.basename}.adoc")
8
10
  reports = Report.load_directory(
9
- dir, track_formats: track_formats, create_map: create_map, map_layers: map_layers
11
+ dir, track_formats: track_formats, create_map: create_map, overwrite_map: overwrite, map_layers: map_layers
10
12
  )
11
13
  reports.map.with_index(1) do |report, index|
12
14
  filename = if index < 2
@@ -1,7 +1,7 @@
1
+ require 'date'
2
+ require 'duration'
1
3
  require 'fit4ruby'
2
4
  require 'nokogiri'
3
- require 'duration'
4
- require 'date'
5
5
  require 'time'
6
6
 
7
7
  module Natour
@@ -1,6 +1,6 @@
1
+ require 'duration'
1
2
  require 'fileutils'
2
3
  require 'pathname'
3
- require 'duration'
4
4
  require 'time'
5
5
 
6
6
  module Natour
@@ -1,5 +1,5 @@
1
- require 'nokogiri'
2
1
  require 'duration'
2
+ require 'nokogiri'
3
3
  require 'timeliness'
4
4
 
5
5
  module Natour
data/lib/natour/image.rb CHANGED
@@ -1,7 +1,7 @@
1
- require 'vips'
2
- require 'timeliness'
3
1
  require 'fileutils'
4
2
  require 'pathname'
3
+ require 'timeliness'
4
+ require 'vips'
5
5
 
6
6
  module Natour
7
7
  class Image
@@ -1,14 +1,14 @@
1
- require 'fileutils'
2
- require 'pathname'
3
- require 'webrick'
4
1
  require 'concurrent'
5
2
  require 'ferrum'
3
+ require 'fileutils'
4
+ require 'pathname'
6
5
  require 'uri'
6
+ require 'webrick'
7
7
 
8
8
  module Natour
9
9
  class MapGeoAdmin
10
10
  def initialize(port: 0)
11
- @doc_root = Dir.mktmpdir
11
+ @doc_root = Pathname(Dir.mktmpdir)
12
12
  FileUtils.cp_r("#{__dir__}/data/js", @doc_root)
13
13
  event = Concurrent::Event.new
14
14
  @server = WEBrick::HTTPServer.new(
@@ -36,21 +36,27 @@ module Natour
36
36
  FileUtils.remove_entry(@doc_root)
37
37
  end
38
38
 
39
- def save_image(filename, tracks: [], layers: [], size: [1200, 900])
40
- FileUtils.cp(tracks, @doc_root)
41
- FileUtils.mkdir_p(Pathname(filename).dirname)
39
+ def save_image(filename, overwrite: false, gps_files: [], map_layers: [], image_size: [1200, 900])
40
+ FileUtils.cp(gps_files, @doc_root)
42
41
  uri = URI("http://#{@server[:BindAddress]}:#{@server[:Port]}/map")
43
42
  uri.query = URI.encode_www_form(
44
- tracks: tracks.map { |track| Pathname(track).basename }.join(','),
45
- layers: layers.join(','),
46
- size: size.map { |dim| dim.is_a?(String) ? dim : "#{dim}px" }.join(',')
43
+ 'gps-files': gps_files.map { |gps_file| Pathname(gps_file).basename }.join(','),
44
+ 'map-layers': map_layers.join(','),
45
+ 'map-size': image_size.map { |dim| dim.is_a?(String) ? dim : "#{dim}px" }.join(',')
47
46
  )
48
47
  @browser.goto(uri)
48
+ tmp_filename = @doc_root.join(Pathname(filename).basename)
49
49
  @browser.screenshot(
50
- path: filename,
50
+ path: tmp_filename,
51
51
  quality: 100,
52
52
  selector: '.map'
53
53
  )
54
+ FileUtils.mkdir_p(Pathname(filename).dirname)
55
+ mode = File::WRONLY | File::CREAT | File::TRUNC | File::BINARY
56
+ mode |= File::EXCL unless overwrite
57
+ File.open(filename, mode) do |file|
58
+ file.write(File.read(tmp_filename, mode: 'rb'))
59
+ end
54
60
  end
55
61
 
56
62
  def self.open(*args)
@@ -66,11 +72,11 @@ module Natour
66
72
  def do_GET(request, response) # rubocop:disable Naming/MethodName
67
73
  raise WEBrick::HTTPStatus::NotFound unless request.path == '/map'
68
74
 
69
- tracks = request.query.fetch('tracks', '').split(',')
70
- layers = request.query.fetch('layers', '').split(',')
75
+ files = request.query.fetch('gps-files', '').split(',')
76
+ layers = request.query.fetch('map-layers', '').split(',')
71
77
  layers.unshift('ch.swisstopo.pixelkarte-farbe')
72
78
 
73
- width, height = request.query.fetch('size', '').split(',')
79
+ width, height = request.query.fetch('map-size', '').split(',')
74
80
  raise WEBrick::HTTPStatus::BadRequest unless width && height
75
81
 
76
82
  doc = []
@@ -90,27 +96,65 @@ module Natour
90
96
  doc << ' layers.forEach(function(layer) {'
91
97
  doc << ' map.addLayer(ga.layer.create(layer))'
92
98
  doc << ' })'
93
- doc << " var tracks = [#{tracks.map { |track| "\"#{track}\"" }.join(', ')}]"
94
- doc << ' tracks = tracks.map(function(track) {'
95
- doc << ' return new ol.layer.Vector({'
96
- doc << ' source: new ol.source.Vector({'
97
- doc << ' format: new ol.format.GPX(),'
98
- doc << ' url: track'
99
- doc << ' }),'
100
- doc << ' style: new ol.style.Style({'
99
+ doc << ' var styles = {'
100
+ doc << ' "Point": new ol.style.Style({'
101
+ doc << ' image: new ol.style.Circle({'
102
+ doc << ' fill: new ol.style.Fill({'
103
+ doc << ' color: function() {'
104
+ doc << ' var color = "blueviolet"'
105
+ doc << ' var alpha = 0.3'
106
+ doc << ' var [r, g, b] = ol.color.asArray(color)'
107
+ doc << ' return ol.color.asString([r, g, b, alpha])'
108
+ doc << ' }()'
109
+ doc << ' }),'
110
+ doc << ' radius: 6,'
101
111
  doc << ' stroke: new ol.style.Stroke({'
102
112
  doc << ' color: "blueviolet",'
103
- doc << ' width: 3'
113
+ doc << ' width: 1.5'
104
114
  doc << ' })'
105
115
  doc << ' })'
116
+ doc << ' }),'
117
+ doc << ' "LineString": new ol.style.Style({'
118
+ doc << ' stroke: new ol.style.Stroke({'
119
+ doc << ' color: "blueviolet",'
120
+ doc << ' width: 3'
121
+ doc << ' })'
122
+ doc << ' }),'
123
+ doc << ' "MultiLineString": new ol.style.Style({'
124
+ doc << ' stroke: new ol.style.Stroke({'
125
+ doc << ' color: "blueviolet",'
126
+ doc << ' width: 3'
127
+ doc << ' })'
128
+ doc << ' })'
129
+ doc << ' }'
130
+ doc << " var files = [#{files.map { |file| "\"#{file}\"" }.join(', ')}]"
131
+ doc << ' var vectors = files.map(function(file) {'
132
+ doc << ' return new ol.layer.Vector({'
133
+ doc << ' source: new ol.source.Vector({'
134
+ doc << ' format: function() {'
135
+ doc << ' if (file.endsWith(".gpx")) {'
136
+ doc << ' return new ol.format.GPX()'
137
+ doc << ' } else if (file.endsWith(".kml")) {'
138
+ doc << ' return new ol.format.KML({'
139
+ doc << ' extractStyles: false'
140
+ doc << ' })'
141
+ doc << ' } else {'
142
+ doc << ' return null'
143
+ doc << ' }'
144
+ doc << ' }(),'
145
+ doc << ' url: file'
146
+ doc << ' }),'
147
+ doc << ' style: function(feature) {'
148
+ doc << ' return styles[feature.getGeometry().getType()]'
149
+ doc << ' }'
106
150
  doc << ' })'
107
151
  doc << ' })'
108
- doc << ' tracks.forEach(function(track) {'
109
- doc << ' map.addLayer(track)'
110
- doc << ' track.getSource().on("change", function(evt) {'
152
+ doc << ' vectors.forEach(function(vector) {'
153
+ doc << ' map.addLayer(vector)'
154
+ doc << ' vector.getSource().on("change", function(evt) {'
111
155
  doc << ' var extent = ol.extent.createEmpty()'
112
- doc << ' tracks.forEach(function(track) {'
113
- doc << ' ol.extent.extend(extent, track.getSource().getExtent())'
156
+ doc << ' vectors.forEach(function(vector) {'
157
+ doc << ' ol.extent.extend(extent, vector.getSource().getExtent())'
114
158
  doc << ' })'
115
159
  doc << ' map.getView().fit(extent, map.getSize())'
116
160
  doc << ' })'
@@ -1,7 +1,7 @@
1
- require 'uri'
1
+ require 'json'
2
2
  require 'net/http'
3
3
  require 'openssl'
4
- require 'json'
4
+ require 'uri'
5
5
 
6
6
  module Natour
7
7
  class PublicTransport
data/lib/natour/report.rb CHANGED
@@ -29,7 +29,7 @@ module Natour
29
29
  @arrival_point = arrival_point
30
30
  end
31
31
 
32
- def self.load_directory(dir, track_formats: %i[gpx fit], create_map: true, map_layers: [])
32
+ def self.load_directory(dir, track_formats: %i[gpx fit], create_map: true, overwrite_map: false, map_layers: [])
33
33
  Dir.chdir(dir) do
34
34
  path = Pathname(dir)
35
35
  title = Pathname.pwd.basename.to_s.encode('utf-8')
@@ -61,7 +61,7 @@ module Natour
61
61
  track = Pathname(tmp_dir).join(gps_track.path).sub_ext('.gpx')
62
62
  gps_track.save_gpx(track, overwrite: true)
63
63
  filename = Pathname(gps_track.path).sub_ext('.jpg')
64
- map.save_image(filename, tracks: [track], layers: map_layers)
64
+ map.save_image(filename, overwrite: overwrite_map, gps_files: [track], map_layers: map_layers)
65
65
  Image.load_file(filename.to_s)
66
66
  end
67
67
  end
@@ -0,0 +1,11 @@
1
+ module Natour
2
+ module BooleanUtils
3
+ module_function
4
+
5
+ def to_boolean(value, default_value: false)
6
+ return !!value unless value.nil?
7
+
8
+ !!default_value
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,9 @@
1
+ module Natour
2
+ module ErrnoUtils
3
+ module_function
4
+
5
+ def split_message(error)
6
+ error.message.split(/ @ | - /, 3)
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Natour
4
+ VERSION = '0.8.0'
5
+ end
data/lib/natour.rb CHANGED
@@ -1,18 +1,21 @@
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'
6
- require 'natour/asciinurse'
7
- require 'natour/config'
8
- require 'natour/gps_track'
9
- require 'natour/gps_track_point'
10
- require 'natour/gpx_file'
11
- require 'natour/fit_file'
12
- require 'natour/image'
13
- require 'natour/map_geo_admin'
14
- require 'natour/public_transport'
15
- require 'natour/report'
16
- require 'natour/species'
17
- require 'natour/species_list'
18
- require 'natour/station'
1
+ require_relative 'natour/utils/boolean_utils'
2
+ require_relative 'natour/utils/botanical_name_utils'
3
+ require_relative 'natour/utils/date_utils'
4
+ require_relative 'natour/utils/errno_utils'
5
+ require_relative 'natour/utils/stdout_utils'
6
+ require_relative 'natour/asciinurse'
7
+ require_relative 'natour/config'
8
+ require_relative 'natour/convert_report'
9
+ require_relative 'natour/create_reports'
10
+ require_relative 'natour/gps_track'
11
+ require_relative 'natour/gps_track_point'
12
+ require_relative 'natour/gpx_file'
13
+ require_relative 'natour/fit_file'
14
+ require_relative 'natour/image'
15
+ require_relative 'natour/map_geo_admin'
16
+ require_relative 'natour/public_transport'
17
+ require_relative 'natour/report'
18
+ require_relative 'natour/species'
19
+ require_relative 'natour/species_list'
20
+ require_relative 'natour/station'
21
+ require_relative 'natour/version'
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.7.0
4
+ version: 0.8.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: 2022-02-14 00:00:00.000000000 Z
11
+ date: 2022-04-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: asciidoctor
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '1.5'
41
+ - !ruby/object:Gem::Dependency
42
+ name: clamp
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.3'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.3'
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: concurrent-ruby
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -52,6 +66,20 @@ dependencies:
52
66
  - - "~>"
53
67
  - !ruby/object:Gem::Version
54
68
  version: '1.1'
69
+ - !ruby/object:Gem::Dependency
70
+ name: deep_merge
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '1.2'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '1.2'
55
83
  - !ruby/object:Gem::Dependency
56
84
  name: ferrum
57
85
  requirement: !ruby/object:Gem::Requirement
@@ -192,8 +220,8 @@ files:
192
220
  - lib/natour.rb
193
221
  - lib/natour/asciinurse.rb
194
222
  - lib/natour/config.rb
195
- - lib/natour/convert.rb
196
- - lib/natour/create.rb
223
+ - lib/natour/convert_report.rb
224
+ - lib/natour/create_reports.rb
197
225
  - lib/natour/data/fonts/dejavuserifcondensed-bold.ttf
198
226
  - lib/natour/data/fonts/dejavuserifcondensed-bold_italic.ttf
199
227
  - lib/natour/data/fonts/dejavuserifcondensed-italic.ttf
@@ -213,9 +241,12 @@ files:
213
241
  - lib/natour/species.rb
214
242
  - lib/natour/species_list.rb
215
243
  - lib/natour/station.rb
244
+ - lib/natour/utils/boolean_utils.rb
216
245
  - lib/natour/utils/botanical_name_utils.rb
217
246
  - lib/natour/utils/date_utils.rb
247
+ - lib/natour/utils/errno_utils.rb
218
248
  - lib/natour/utils/stdout_utils.rb
249
+ - lib/natour/version.rb
219
250
  homepage: https://github.com/simongysi/natour
220
251
  licenses:
221
252
  - MIT
@@ -238,8 +269,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
238
269
  - !ruby/object:Gem::Version
239
270
  version: '0'
240
271
  requirements: []
241
- rubygems_version: 3.0.3
272
+ rubygems_version: 3.3.7
242
273
  signing_key:
243
274
  specification_version: 4
244
- summary: natour provides an application and a library for reports on nature activities
275
+ summary: natour provides an application and a library to document nature activities.
245
276
  test_files: []