pandocomatic 0.2.7.8 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/pandocomatic/cli.rb +81 -64
- data/lib/pandocomatic/command/command.rb +37 -35
- data/lib/pandocomatic/command/convert_dir_command.rb +44 -46
- data/lib/pandocomatic/command/convert_file_command.rb +314 -286
- data/lib/pandocomatic/command/convert_file_multiple_command.rb +56 -53
- data/lib/pandocomatic/command/convert_list_command.rb +31 -34
- data/lib/pandocomatic/command/copy_file_command.rb +14 -15
- data/lib/pandocomatic/command/create_link_command.rb +24 -27
- data/lib/pandocomatic/command/skip_command.rb +12 -15
- data/lib/pandocomatic/configuration.rb +682 -867
- data/lib/pandocomatic/default_configuration.yaml +4 -0
- data/lib/pandocomatic/error/cli_error.rb +30 -26
- data/lib/pandocomatic/error/configuration_error.rb +10 -9
- data/lib/pandocomatic/error/io_error.rb +13 -13
- data/lib/pandocomatic/error/pandoc_error.rb +10 -9
- data/lib/pandocomatic/error/pandocomatic_error.rb +15 -14
- data/lib/pandocomatic/error/processor_error.rb +9 -9
- data/lib/pandocomatic/error/template_error.rb +50 -0
- data/lib/pandocomatic/input.rb +53 -54
- data/lib/pandocomatic/multiple_files_input.rb +79 -72
- data/lib/pandocomatic/output.rb +29 -0
- data/lib/pandocomatic/pandoc_metadata.rb +193 -181
- data/lib/pandocomatic/pandocomatic.rb +101 -97
- data/lib/pandocomatic/pandocomatic_yaml.rb +70 -0
- data/lib/pandocomatic/path.rb +171 -0
- data/lib/pandocomatic/printer/command_printer.rb +7 -5
- data/lib/pandocomatic/printer/configuration_errors_printer.rb +7 -6
- data/lib/pandocomatic/printer/error_printer.rb +12 -7
- data/lib/pandocomatic/printer/finish_printer.rb +11 -10
- data/lib/pandocomatic/printer/help_printer.rb +8 -6
- data/lib/pandocomatic/printer/printer.rb +34 -34
- data/lib/pandocomatic/printer/summary_printer.rb +39 -33
- data/lib/pandocomatic/printer/version_printer.rb +8 -8
- data/lib/pandocomatic/printer/views/cli_error.txt +5 -0
- data/lib/pandocomatic/printer/views/configuration_error.txt +2 -1
- data/lib/pandocomatic/printer/views/error.txt +1 -1
- data/lib/pandocomatic/printer/views/finish.txt +1 -1
- data/lib/pandocomatic/printer/views/help.txt +27 -15
- data/lib/pandocomatic/printer/views/summary.txt +7 -1
- data/lib/pandocomatic/printer/views/template_error.txt +1 -0
- data/lib/pandocomatic/printer/views/version.txt +3 -3
- data/lib/pandocomatic/printer/views/warning.txt +1 -1
- data/lib/pandocomatic/printer/warning_printer.rb +21 -19
- data/lib/pandocomatic/processor.rb +28 -28
- data/lib/pandocomatic/processors/fileinfo_preprocessor.rb +35 -30
- data/lib/pandocomatic/processors/metadata_preprocessor.rb +23 -22
- data/lib/pandocomatic/template.rb +244 -0
- data/lib/pandocomatic/warning.rb +24 -25
- metadata +32 -12
@@ -1,123 +1,127 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
#--
|
2
|
-
# Copyright 2014—
|
3
|
-
#
|
4
|
+
# Copyright 2014—2022, Huub de Beer <huub@heerdebeer.org>
|
5
|
+
#
|
4
6
|
# This file is part of pandocomatic.
|
5
|
-
#
|
7
|
+
#
|
6
8
|
# Pandocomatic is free software: you can redistribute it and/or modify
|
7
9
|
# it under the terms of the GNU General Public License as published by the
|
8
10
|
# Free Software Foundation, either version 3 of the License, or (at your
|
9
11
|
# option) any later version.
|
10
|
-
#
|
12
|
+
#
|
11
13
|
# Pandocomatic is distributed in the hope that it will be useful, but
|
12
14
|
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
13
15
|
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
14
16
|
# for more details.
|
15
|
-
#
|
17
|
+
#
|
16
18
|
# You should have received a copy of the GNU General Public License along
|
17
19
|
# with pandocomatic. If not, see <http://www.gnu.org/licenses/>.
|
18
20
|
#++
|
19
21
|
module Pandocomatic
|
20
|
-
|
21
|
-
|
22
|
+
Encoding.default_external = Encoding::UTF_8 # ensure unicode encoding
|
23
|
+
Encoding.default_internal = Encoding::UTF_8
|
24
|
+
|
25
|
+
require 'paru'
|
26
|
+
require 'tempfile'
|
27
|
+
|
28
|
+
require_relative './error/pandocomatic_error'
|
29
|
+
require_relative './error/pandoc_error'
|
22
30
|
|
23
|
-
|
24
|
-
require 'tempfile'
|
31
|
+
require_relative './cli'
|
25
32
|
|
26
|
-
|
27
|
-
|
33
|
+
require_relative './printer/help_printer'
|
34
|
+
require_relative './printer/version_printer'
|
35
|
+
require_relative './printer/error_printer'
|
36
|
+
require_relative './printer/configuration_errors_printer'
|
37
|
+
require_relative './printer/finish_printer'
|
38
|
+
require_relative './printer/summary_printer'
|
28
39
|
|
29
|
-
|
40
|
+
require_relative './command/convert_dir_command'
|
41
|
+
require_relative './command/convert_list_command'
|
42
|
+
require_relative './command/convert_file_command'
|
43
|
+
require_relative './command/convert_file_multiple_command'
|
30
44
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
require_relative './printer/finish_printer.rb'
|
36
|
-
require_relative './printer/summary_printer.rb'
|
45
|
+
# The Pandocomatic class controlls the pandocomatic conversion process
|
46
|
+
class Pandocomatic
|
47
|
+
# Pandocomatic error status codes start from ERROR_STATUS
|
48
|
+
ERROR_STATUS = 1266 # This is the sum of the ASCII values of the characters in 'pandocomatic'
|
37
49
|
|
38
|
-
|
39
|
-
|
40
|
-
require_relative './command/convert_file_command.rb'
|
41
|
-
require_relative './command/convert_file_multiple_command.rb'
|
50
|
+
# Pandocomatic's current version
|
51
|
+
VERSION = [1, 0, 1].freeze
|
42
52
|
|
43
|
-
#
|
44
|
-
class Pandocomatic
|
45
|
-
|
46
|
-
# Pandocomatic error status codes start from ERROR_STATUS
|
47
|
-
ERROR_STATUS = 1266 # This is the sum of the ascii values of the characters in 'pandocomatic'
|
53
|
+
# rubocop:disable Metrics
|
48
54
|
|
49
|
-
|
50
|
-
|
55
|
+
# Run pandocomatic given options
|
56
|
+
#
|
57
|
+
# @param args [String[]] list of options to configure pandocomatic
|
58
|
+
def self.run(args)
|
59
|
+
start_time = Time.now
|
60
|
+
configuration = CLI.parse args
|
51
61
|
|
52
|
-
|
62
|
+
if configuration.show_version?
|
63
|
+
# The version option has precedence over all other options; if
|
64
|
+
# given, the version is printed
|
65
|
+
VersionPrinter.new(VERSION).print
|
66
|
+
elsif configuration.show_help?
|
67
|
+
# The help option has precedence over all other options except the
|
68
|
+
# version option. If given, the help is printed.
|
69
|
+
HelpPrinter.new.print
|
70
|
+
else
|
71
|
+
# When using multiple input files, errors reading these
|
72
|
+
# files are already encountered at this point. If there
|
73
|
+
# are any errors, there is no reason to continue.
|
74
|
+
if configuration.input.errors?
|
75
|
+
ConfigurationErrorsPrinter.new(configuration.input.all_errors).print
|
76
|
+
exit ERROR_STATUS
|
77
|
+
end
|
78
|
+
|
79
|
+
# Run the pandocomatic converter configured according to the options
|
80
|
+
# given.
|
53
81
|
#
|
54
|
-
#
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
# given, the version is printed
|
63
|
-
VersionPrinter.new(VERSION).print
|
64
|
-
elsif configuration.show_help?
|
65
|
-
# The help option has precedence over all other options except the
|
66
|
-
# version option. If given, the help is printed.
|
67
|
-
HelpPrinter.new().print
|
68
|
-
else
|
69
|
-
# When using multiple input files, errors reading these
|
70
|
-
# files are already encountered at this point. If there
|
71
|
-
# are any errors, there is no reason to continue.
|
72
|
-
if configuration.input.has_errors?
|
73
|
-
ConfigurationErrorsPrinter.new(configuration.input.all_errors).print
|
74
|
-
exit ERROR_STATUS
|
75
|
-
end
|
76
|
-
|
77
|
-
# Run the pandocomatic converter configured according to the options
|
78
|
-
# given.
|
79
|
-
#
|
80
|
-
# Pandocomatic has two modes: converting a directory tree or
|
81
|
-
# converting a single file. The mode is selected by the input.
|
82
|
-
if configuration.directory?
|
83
|
-
command = ConvertDirCommand.new(configuration, configuration.input_file, configuration.output)
|
84
|
-
else
|
85
|
-
command = ConvertFileMultipleCommand.new(configuration, configuration.input_file, configuration.output)
|
86
|
-
command.make_quiet unless command.subcommands.size > 1
|
87
|
-
end
|
88
|
-
|
89
|
-
# Notify the user about all configuration errors collected when
|
90
|
-
# determining the commands to run to perform this pandocomatic
|
91
|
-
# conversion.
|
92
|
-
if command.all_errors.size > 0
|
93
|
-
ConfigurationErrorsPrinter.new(command.all_errors).print
|
94
|
-
exit ERROR_STATUS
|
95
|
-
end
|
96
|
-
|
97
|
-
# Pandocomatic is successfully configured: running the
|
98
|
-
# actual conversion now. But first a short summary of the
|
99
|
-
# process to execute is printed.
|
100
|
-
SummaryPrinter.new(command, configuration).print unless configuration.quiet? or not command.directory?
|
101
|
-
|
102
|
-
# Depending on the options dry-run and quiet, the command.execute
|
103
|
-
# method will actually performing the commands (dry-run = false) and
|
104
|
-
# print the command to STDOUT (quiet = false)
|
105
|
-
command.execute()
|
106
|
-
|
107
|
-
FinishPrinter.new(command, configuration, start_time).print unless configuration.quiet?
|
108
|
-
end
|
109
|
-
rescue PandocomaticError => e
|
110
|
-
# Report the error and break off the conversion process.
|
111
|
-
ErrorPrinter.new(e).print
|
112
|
-
exit ERROR_STATUS + 1
|
113
|
-
rescue StandardError => e
|
114
|
-
# An unexpected error has occurred; break off the program drastically
|
115
|
-
# for now. This is likely a bug: ask the user to report it.
|
116
|
-
warn "An unexpected error has occurred. You can report this bug via https://github.com/htdebeer/pandocomatic/issues/new."
|
117
|
-
raise e
|
118
|
-
ensure
|
119
|
-
configuration.clean_up! unless configuration.nil?
|
120
|
-
end
|
82
|
+
# Pandocomatic has two modes: converting a directory tree or
|
83
|
+
# converting a single file. The mode is selected by the input.
|
84
|
+
if configuration.directory?
|
85
|
+
command = ConvertDirCommand.new(configuration, configuration.input_file, configuration.output)
|
86
|
+
else
|
87
|
+
command = ConvertFileMultipleCommand.new(configuration, configuration.input_file,
|
88
|
+
configuration.output)
|
89
|
+
command.make_quiet unless command.subcommands.size > 1
|
121
90
|
end
|
91
|
+
|
92
|
+
# Notify the user about all configuration errors collected when
|
93
|
+
# determining the commands to run to perform this pandocomatic
|
94
|
+
# conversion.
|
95
|
+
if command.all_errors.size.positive?
|
96
|
+
ConfigurationErrorsPrinter.new(command.all_errors).print
|
97
|
+
exit ERROR_STATUS
|
98
|
+
end
|
99
|
+
|
100
|
+
# Pandocomatic is successfully configured: running the
|
101
|
+
# actual conversion now. But first a short summary of the
|
102
|
+
# process to execute is printed.
|
103
|
+
SummaryPrinter.new(command, configuration).print if !configuration.quiet? || command.directory?
|
104
|
+
|
105
|
+
# Depending on the options dry-run and quiet, the command.execute
|
106
|
+
# method will actually performing the commands (dry-run = false) and
|
107
|
+
# print the command to STDOUT (quiet = false)
|
108
|
+
command.execute
|
109
|
+
|
110
|
+
FinishPrinter.new(command, configuration, start_time).print unless configuration.quiet?
|
111
|
+
end
|
112
|
+
rescue PandocomaticError => e
|
113
|
+
# Report the error and break off the conversion process.
|
114
|
+
ErrorPrinter.new(e).print
|
115
|
+
exit ERROR_STATUS + 1
|
116
|
+
rescue StandardError => e
|
117
|
+
# An unexpected error has occurred; break off the program drastically
|
118
|
+
# for now. This is likely a bug: ask the user to report it.
|
119
|
+
warn '[UNEXPECTED ERROR] An unexpected error has occurred. You can report this bug via https://github.com/htdebeer/pandocomatic/issues/new.'
|
120
|
+
raise e
|
121
|
+
ensure
|
122
|
+
configuration&.clean_up!
|
122
123
|
end
|
124
|
+
end
|
125
|
+
|
126
|
+
# rubocop:enable Metrics
|
123
127
|
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#--
|
4
|
+
# Copyright 2022 Huub de Beer <Huub@heerdebeer.org>
|
5
|
+
#
|
6
|
+
# This file is part of pandocomatic.
|
7
|
+
#
|
8
|
+
# Pandocomatic is free software: you can redistribute it and/or modify
|
9
|
+
# it under the terms of the GNU General Public License as published by the
|
10
|
+
# Free Software Foundation, either version 3 of the License, or (at your
|
11
|
+
# option) any later version.
|
12
|
+
#
|
13
|
+
# Pandocomatic is distributed in the hope that it will be useful, but
|
14
|
+
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
15
|
+
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
16
|
+
# for more details.
|
17
|
+
#
|
18
|
+
# You should have received a copy of the GNU General Public License along
|
19
|
+
# with pandocomatic. If not, see <http://www.gnu.org/licenses/>.
|
20
|
+
#++
|
21
|
+
module Pandocomatic
|
22
|
+
require 'date'
|
23
|
+
require 'yaml'
|
24
|
+
|
25
|
+
require_relative './error/template_error'
|
26
|
+
|
27
|
+
# PandocomaticYAML is a wrapper around ruby's YAML library that replaces
|
28
|
+
# occurrences of "$(X)$" in the YAML by the value of the evironment variable
|
29
|
+
# X. If variable X cannot be found, an exception is thrown.
|
30
|
+
module PandocomaticYAML
|
31
|
+
# List of classes that are permitted in YAML
|
32
|
+
PERMITTED_YAML_CLASSES = [Date].freeze
|
33
|
+
|
34
|
+
# Regular expression representing environment variables in templates
|
35
|
+
VAR_PATTERN = /\$\((?<var>[a-zA-Z_][a-zA-Z0-9_]*)\)\$/
|
36
|
+
|
37
|
+
# Load a string, substitute any variables, and parse as YAML.
|
38
|
+
#
|
39
|
+
# @param str [String] String to parse as YAML
|
40
|
+
# @param path [Path|Nil] Path of the source of the string, if any
|
41
|
+
# @return [Hash]
|
42
|
+
# @raise [TemplateError] when environment variable does not exist.
|
43
|
+
def self.load(str, path = nil)
|
44
|
+
YAML.safe_load substitute_variables(str, path), permitted_classes: PERMITTED_YAML_CLASSES
|
45
|
+
end
|
46
|
+
|
47
|
+
# Load a text file, substitute any variables, and parse as YAML.
|
48
|
+
#
|
49
|
+
# @param path [String] Path to text file to parse as YAML
|
50
|
+
# @return [Hash]
|
51
|
+
# @raise [TemplateError] when environment variable does not exist.
|
52
|
+
def self.load_file(path)
|
53
|
+
self.load File.read(path), path
|
54
|
+
end
|
55
|
+
|
56
|
+
# Substitute all environment variables in the str with the values of the
|
57
|
+
# corresponding environment variables.
|
58
|
+
#
|
59
|
+
# @raise [TemplateError] when environment variable does not exist.
|
60
|
+
private_class_method def self.substitute_variables(str, path = nil)
|
61
|
+
str.gsub(VAR_PATTERN) do |_match|
|
62
|
+
key = Regexp.last_match(1)
|
63
|
+
|
64
|
+
raise TemplateError.new :environment_variable_does_not_exist, { key:, path: } unless ENV.key? key
|
65
|
+
|
66
|
+
ENV[key]
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,171 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#--
|
4
|
+
# Copyright 2022 Huub de Beer <Huub@heerdebeer.org>
|
5
|
+
#
|
6
|
+
# This file is part of pandocomatic.
|
7
|
+
#
|
8
|
+
# Pandocomatic is free software: you can redistribute it and/or modify
|
9
|
+
# it under the terms of the GNU General Public License as published by the
|
10
|
+
# Free Software Foundation, either version 3 of the License, or (at your
|
11
|
+
# option) any later version.
|
12
|
+
#
|
13
|
+
# Pandocomatic is distributed in the hope that it will be useful, but
|
14
|
+
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
15
|
+
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
16
|
+
# for more details.
|
17
|
+
#
|
18
|
+
# You should have received a copy of the GNU General Public License along
|
19
|
+
# with pandocomatic. If not, see <http://www.gnu.org/licenses/>.
|
20
|
+
#++
|
21
|
+
module Pandocomatic
|
22
|
+
require 'yaml'
|
23
|
+
|
24
|
+
# Pandocomatic related path functions. Paths in pandocomatic templates have
|
25
|
+
# various forms and behaviors. This behavior is defined by methods in this
|
26
|
+
# module.
|
27
|
+
module Path
|
28
|
+
# Indicator for paths that should be treated as "relative to the root
|
29
|
+
# path". These paths start with this ROOT_PATH_INDICATOR.
|
30
|
+
ROOT_PATH_INDICATOR = '$ROOT$'
|
31
|
+
|
32
|
+
# Update the path to an executable processor or executor given this
|
33
|
+
# Configuration
|
34
|
+
#
|
35
|
+
# @param config [Configuration] the configuration under which to update
|
36
|
+
# the path.
|
37
|
+
# @param path [String] path to the executable
|
38
|
+
# @param dst [String] the destination path
|
39
|
+
# @param check_executable [Boolean = false] Should the executable be
|
40
|
+
# verified to be executable? Defaults to false.
|
41
|
+
#
|
42
|
+
# @return [String] the updated path.
|
43
|
+
def self.update_path(config, path, dst = '', check_executable: false)
|
44
|
+
updated_path = path
|
45
|
+
|
46
|
+
if local_path? path
|
47
|
+
# refers to a local dir; strip the './' before appending it to
|
48
|
+
# the source directory as to prevent /some/path/./to/path
|
49
|
+
updated_path = path[2..]
|
50
|
+
elsif absolute_path? path
|
51
|
+
updated_path = path
|
52
|
+
elsif root_relative_path? path
|
53
|
+
updated_path = make_path_root_relative path, dst, config.root_path
|
54
|
+
else
|
55
|
+
updated_path = which path if check_executable
|
56
|
+
|
57
|
+
if updated_path.nil? || !check_executable
|
58
|
+
# refers to data-dir
|
59
|
+
updated_path = File.join config.data_dir, path
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
updated_path
|
64
|
+
end
|
65
|
+
|
66
|
+
# Cross-platform way of finding an executable in the $PATH.
|
67
|
+
#
|
68
|
+
# which('ruby') #=> /usr/bin/ruby
|
69
|
+
#
|
70
|
+
# Taken from:
|
71
|
+
# http://stackoverflow.com/questions/2108727/which-in-ruby-checking-if-program-exists-in-path-from-ruby#5471032
|
72
|
+
def self.which(cmd)
|
73
|
+
exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
|
74
|
+
ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
|
75
|
+
exts.each do |ext|
|
76
|
+
exe = File.join(path, "#{cmd}#{ext}")
|
77
|
+
return exe if File.executable?(exe) &&
|
78
|
+
!File.directory?(exe)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
nil
|
82
|
+
end
|
83
|
+
|
84
|
+
# Is this path a local path in pandocomatic?
|
85
|
+
#
|
86
|
+
# @param path [String]
|
87
|
+
# @return [Boolean]
|
88
|
+
def self.local_path?(path)
|
89
|
+
if Gem.win_platform?
|
90
|
+
path.match("^\\.\\\\\.*$")
|
91
|
+
else
|
92
|
+
path.start_with? './'
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
# Is this path an absolute path in pandocomatic?
|
97
|
+
#
|
98
|
+
# @param path [String]
|
99
|
+
# @return [Boolean]
|
100
|
+
def self.absolute_path?(path)
|
101
|
+
if Gem.win_platform?
|
102
|
+
path.match("^[a-zA-Z]:\\\\\.*$")
|
103
|
+
else
|
104
|
+
path.start_with? '/'
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
# Is this path a root relative path in pandocomatic?
|
109
|
+
#
|
110
|
+
# @param path [String]
|
111
|
+
# @return [Boolean]
|
112
|
+
def self.root_relative_path?(path)
|
113
|
+
path.start_with? ROOT_PATH_INDICATOR
|
114
|
+
end
|
115
|
+
|
116
|
+
# Determine the root path given a set of command-line options
|
117
|
+
#
|
118
|
+
# @param options [Hash]
|
119
|
+
# @return [String]
|
120
|
+
def self.determine_root_path(options)
|
121
|
+
if options[:root_path_given]
|
122
|
+
options[:root_path]
|
123
|
+
elsif options[:output_given]
|
124
|
+
File.absolute_path(File.dirname(options[:output]))
|
125
|
+
else
|
126
|
+
File.absolute_path '.'
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
# rubocop:disable Metrics
|
131
|
+
|
132
|
+
# Make a path root relative given the destination path and the root path
|
133
|
+
#
|
134
|
+
# @param path [String]
|
135
|
+
# @param dst [String]
|
136
|
+
# @param root [String]
|
137
|
+
# @return [String] The root relative path
|
138
|
+
def self.make_path_root_relative(path, dst, root)
|
139
|
+
# Find how to get to the root directopry from dst directory.
|
140
|
+
# Assumption is that dst is a subdirectory of root.
|
141
|
+
dst_dir = File.dirname(File.absolute_path(dst))
|
142
|
+
|
143
|
+
path.delete_prefix! ROOT_PATH_INDICATOR if root_relative_path? path
|
144
|
+
|
145
|
+
if File.exist?(root) && File.realpath(dst_dir.to_s).start_with?(File.realpath(root))
|
146
|
+
rel_start = ''
|
147
|
+
|
148
|
+
until File.identical?(File.realpath("#{dst_dir}/#{rel_start}"), File.realpath(root))
|
149
|
+
# invariant dst_dir/rel_start <= root
|
150
|
+
rel_start += '../'
|
151
|
+
end
|
152
|
+
|
153
|
+
if rel_start.end_with?('/') && path.start_with?('/')
|
154
|
+
"#{rel_start}#{path.delete_prefix('/')}"
|
155
|
+
else
|
156
|
+
"#{rel_start}#{path}"
|
157
|
+
end
|
158
|
+
else
|
159
|
+
# Because the destination is not in a subdirectory of root, a
|
160
|
+
# relative path to that root cannot be created. Instead,
|
161
|
+
# the path is assumed to be absolute relative to root
|
162
|
+
root = root.delete_suffix '/' if root.end_with? '/'
|
163
|
+
path = path.delete_prefix '/' if path.start_with? '/'
|
164
|
+
|
165
|
+
"#{root}/#{path}"
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
# rubocop:enable Metrics
|
170
|
+
end
|
171
|
+
end
|
@@ -1,23 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
#--
|
2
4
|
# Copyright 2017, Huub de Beer <Huub@heerdebeer.org>
|
3
|
-
#
|
5
|
+
#
|
4
6
|
# This file is part of pandocomatic.
|
5
|
-
#
|
7
|
+
#
|
6
8
|
# Pandocomatic is free software: you can redistribute it and/or modify
|
7
9
|
# it under the terms of the GNU General Public License as published by the
|
8
10
|
# Free Software Foundation, either version 3 of the License, or (at your
|
9
11
|
# option) any later version.
|
10
|
-
#
|
12
|
+
#
|
11
13
|
# Pandocomatic is distributed in the hope that it will be useful, but
|
12
14
|
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
13
15
|
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
14
16
|
# for more details.
|
15
|
-
#
|
17
|
+
#
|
16
18
|
# You should have received a copy of the GNU General Public License along
|
17
19
|
# with pandocomatic. If not, see <http://www.gnu.org/licenses/>.
|
18
20
|
#++
|
19
21
|
module Pandocomatic
|
20
|
-
require_relative './printer
|
22
|
+
require_relative './printer'
|
21
23
|
|
22
24
|
# Printer for Commands in non-quiet mode
|
23
25
|
class CommandPrinter < Printer
|
@@ -1,23 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
#--
|
2
4
|
# Copyright 2017, Huub de Beer <Huub@heerdebeer.org>
|
3
|
-
#
|
5
|
+
#
|
4
6
|
# This file is part of pandocomatic.
|
5
|
-
#
|
7
|
+
#
|
6
8
|
# Pandocomatic is free software: you can redistribute it and/or modify
|
7
9
|
# it under the terms of the GNU General Public License as published by the
|
8
10
|
# Free Software Foundation, either version 3 of the License, or (at your
|
9
11
|
# option) any later version.
|
10
|
-
#
|
12
|
+
#
|
11
13
|
# Pandocomatic is distributed in the hope that it will be useful, but
|
12
14
|
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
13
15
|
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
14
16
|
# for more details.
|
15
|
-
#
|
17
|
+
#
|
16
18
|
# You should have received a copy of the GNU General Public License along
|
17
19
|
# with pandocomatic. If not, see <http://www.gnu.org/licenses/>.
|
18
20
|
#++
|
19
21
|
module Pandocomatic
|
20
|
-
require_relative './printer
|
22
|
+
require_relative './printer'
|
21
23
|
|
22
24
|
# Printer for ConfigurationErrors in non-quiet mode
|
23
25
|
class ConfigurationErrorsPrinter < Printer
|
@@ -26,6 +28,5 @@ module Pandocomatic
|
|
26
28
|
super 'configuration_errors.txt'
|
27
29
|
@errors = errors
|
28
30
|
end
|
29
|
-
|
30
31
|
end
|
31
32
|
end
|
@@ -1,29 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
#--
|
2
4
|
# Copyright 2017, Huub de Beer <Huub@heerdebeer.org>
|
3
|
-
#
|
5
|
+
#
|
4
6
|
# This file is part of pandocomatic.
|
5
|
-
#
|
7
|
+
#
|
6
8
|
# Pandocomatic is free software: you can redistribute it and/or modify
|
7
9
|
# it under the terms of the GNU General Public License as published by the
|
8
10
|
# Free Software Foundation, either version 3 of the License, or (at your
|
9
11
|
# option) any later version.
|
10
|
-
#
|
12
|
+
#
|
11
13
|
# Pandocomatic is distributed in the hope that it will be useful, but
|
12
14
|
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
13
15
|
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
14
16
|
# for more details.
|
15
|
-
#
|
17
|
+
#
|
16
18
|
# You should have received a copy of the GNU General Public License along
|
17
19
|
# with pandocomatic. If not, see <http://www.gnu.org/licenses/>.
|
18
20
|
#++
|
19
21
|
module Pandocomatic
|
20
|
-
require_relative './printer
|
22
|
+
require_relative './printer'
|
21
23
|
|
22
24
|
# Printer for Errors in non-quiet mode
|
23
25
|
class ErrorPrinter < Printer
|
24
26
|
# Create a new ErrorPrinter
|
25
27
|
def initialize(error)
|
26
|
-
template = if error.respond_to? :template
|
28
|
+
template = if error.respond_to? :template
|
29
|
+
error.template
|
30
|
+
else
|
31
|
+
'error.txt'
|
32
|
+
end
|
27
33
|
super template
|
28
34
|
@error = error
|
29
35
|
end
|
@@ -32,6 +38,5 @@ module Pandocomatic
|
|
32
38
|
def print
|
33
39
|
warn to_s
|
34
40
|
end
|
35
|
-
|
36
41
|
end
|
37
42
|
end
|
@@ -1,23 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
#--
|
2
4
|
# Copyright 2017, Huub de Beer <Huub@heerdebeer.org>
|
3
|
-
#
|
5
|
+
#
|
4
6
|
# This file is part of pandocomatic.
|
5
|
-
#
|
7
|
+
#
|
6
8
|
# Pandocomatic is free software: you can redistribute it and/or modify
|
7
9
|
# it under the terms of the GNU General Public License as published by the
|
8
10
|
# Free Software Foundation, either version 3 of the License, or (at your
|
9
11
|
# option) any later version.
|
10
|
-
#
|
12
|
+
#
|
11
13
|
# Pandocomatic is distributed in the hope that it will be useful, but
|
12
14
|
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
13
15
|
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
14
16
|
# for more details.
|
15
|
-
#
|
17
|
+
#
|
16
18
|
# You should have received a copy of the GNU General Public License along
|
17
19
|
# with pandocomatic. If not, see <http://www.gnu.org/licenses/>.
|
18
20
|
#++
|
19
21
|
module Pandocomatic
|
20
|
-
require_relative './summary_printer
|
22
|
+
require_relative './summary_printer'
|
21
23
|
|
22
24
|
# Printer for the end of the conversion process in non-quiet mode
|
23
25
|
class FinishPrinter < SummaryPrinter
|
@@ -25,14 +27,14 @@ module Pandocomatic
|
|
25
27
|
MINUTE = 60
|
26
28
|
|
27
29
|
# Create a new FinishPrinter
|
28
|
-
#
|
30
|
+
#
|
29
31
|
# @param command [Command] the command to finish
|
30
32
|
# @param configuration [Configuration] the configuration of the
|
31
33
|
# pandocomatic invokation
|
32
34
|
# @param start_time [Time] the time the command was started
|
33
35
|
def initialize(command, configuration, start_time)
|
34
36
|
super command, configuration
|
35
|
-
|
37
|
+
template 'finish.txt'
|
36
38
|
|
37
39
|
@start_time = start_time
|
38
40
|
@end_time = Time.now
|
@@ -41,16 +43,15 @@ module Pandocomatic
|
|
41
43
|
# Calculate the duration of the whole conversion process
|
42
44
|
#
|
43
45
|
# @return [Number]
|
44
|
-
def duration
|
46
|
+
def duration
|
45
47
|
seconds = @end_time - @start_time
|
46
48
|
if seconds > MINUTE
|
47
49
|
minutes = (seconds / MINUTE).floor
|
48
|
-
seconds
|
50
|
+
seconds -= (minutes * MINUTE)
|
49
51
|
"#{minutes} minute#{'s' if minutes != 1} and #{seconds.round(1)} second#{'s' if seconds != 1}"
|
50
52
|
else
|
51
53
|
"#{seconds.round(1)} second#{'s' if seconds != 1}"
|
52
54
|
end
|
53
55
|
end
|
54
|
-
|
55
56
|
end
|
56
57
|
end
|