pandocomatic 0.2.8 → 1.0.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/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 -290
- 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 +69 -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, 0].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,69 @@
|
|
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
|
+
require_relative './error/template_error'
|
25
|
+
|
26
|
+
# PandocomaticYAML is a wrapper around ruby's YAML library that replaces
|
27
|
+
# occurrences of "$(X)$" in the YAML by the value of the evironment variable
|
28
|
+
# X. If variable X cannot be found, an exception is thrown.
|
29
|
+
module PandocomaticYAML
|
30
|
+
# List of classes that are permitted in YAML
|
31
|
+
PERMITTED_YAML_CLASSES = [Date].freeze
|
32
|
+
|
33
|
+
# Regular expression representing environment variables in templates
|
34
|
+
VAR_PATTERN = /\$\((?<var>[a-zA-Z_][a-zA-Z0-9_]*)\)\$/
|
35
|
+
|
36
|
+
# Load a string, substitute any variables, and parse as YAML.
|
37
|
+
#
|
38
|
+
# @param str [String] String to parse as YAML
|
39
|
+
# @param path [Path|Nil] Path of the source of the string, if any
|
40
|
+
# @return [Hash]
|
41
|
+
# @raise [TemplateError] when environment variable does not exist.
|
42
|
+
def self.load(str, path = nil)
|
43
|
+
YAML.safe_load substitute_variables(str, path), permitted_classes: PERMITTED_YAML_CLASSES
|
44
|
+
end
|
45
|
+
|
46
|
+
# Load a text file, substitute any variables, and parse as YAML.
|
47
|
+
#
|
48
|
+
# @param path [String] Path to text file to parse as YAML
|
49
|
+
# @return [Hash]
|
50
|
+
# @raise [TemplateError] when environment variable does not exist.
|
51
|
+
def self.load_file(path)
|
52
|
+
self.load File.read(path), path
|
53
|
+
end
|
54
|
+
|
55
|
+
# Substitute all environment variables in the str with the values of the
|
56
|
+
# corresponding environment variables.
|
57
|
+
#
|
58
|
+
# @raise [TemplateError] when environment variable does not exist.
|
59
|
+
private_class_method def self.substitute_variables(str, path = nil)
|
60
|
+
str.gsub(VAR_PATTERN) do |_match|
|
61
|
+
key = Regexp.last_match(1)
|
62
|
+
|
63
|
+
raise TemplateError.new :environment_variable_does_not_exist, { key:, path: } unless ENV.key? key
|
64
|
+
|
65
|
+
ENV[key]
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
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
|