pandocomatic 0.2.8 → 1.0.0
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 -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,103 +1,110 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
#--
|
2
4
|
# Copyright 2019 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
|
22
|
+
require 'tempfile'
|
23
|
+
require_relative './input'
|
20
24
|
|
21
|
-
|
22
|
-
|
25
|
+
# A specific Input class to handle multiple input files
|
26
|
+
class MultipleFilesInput < Input
|
27
|
+
# Create a new MultipleFilesInput. As a side-effect a temporary file
|
28
|
+
# is created as well containing the content of all the files in input.
|
29
|
+
#
|
30
|
+
# @param input [String[]] a list with input files
|
31
|
+
def initialize(input, config)
|
32
|
+
super(input)
|
33
|
+
@config = config
|
34
|
+
create_temp_file
|
35
|
+
end
|
23
36
|
|
24
|
-
#
|
25
|
-
|
37
|
+
# The name of this input
|
38
|
+
#
|
39
|
+
# @return String
|
40
|
+
def name
|
41
|
+
@tmp_file.path
|
42
|
+
end
|
26
43
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
create_temp_file
|
35
|
-
end
|
44
|
+
# Is this input a directory? A MultipleFilesInput cannot be a
|
45
|
+
# directory
|
46
|
+
#
|
47
|
+
# @return Boolean
|
48
|
+
def directory?
|
49
|
+
false
|
50
|
+
end
|
36
51
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
def name()
|
41
|
-
@tmp_file.path
|
42
|
-
end
|
52
|
+
# Destroy the temporary file created for this MultipleFilesInput
|
53
|
+
def destroy!
|
54
|
+
return if @tmp_file.nil?
|
43
55
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
# @return Boolean
|
48
|
-
def directory?()
|
49
|
-
false
|
50
|
-
end
|
56
|
+
@tmp_file.close
|
57
|
+
@tmp_file.unlink
|
58
|
+
end
|
51
59
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
60
|
+
# A string representation of this Input
|
61
|
+
#
|
62
|
+
# @return String
|
63
|
+
def to_s
|
64
|
+
input_string = @input_files.first
|
65
|
+
previous_dir = File.dirname @input_files.first
|
66
|
+
@input_files.slice(1..-1).each do |f|
|
67
|
+
current_dir = File.dirname f
|
68
|
+
if current_dir == previous_dir
|
69
|
+
input_string += " + #{File.basename f}"
|
70
|
+
else
|
71
|
+
previous_dir = current_dir
|
72
|
+
input_string += " + #{f}"
|
58
73
|
end
|
74
|
+
end
|
59
75
|
|
60
|
-
|
61
|
-
|
62
|
-
# @return String
|
63
|
-
def to_s()
|
64
|
-
input_string = @input_files.first
|
65
|
-
previous_dir = File.dirname @input_files.first
|
66
|
-
@input_files.slice(1..-1).each do |f|
|
67
|
-
current_dir = File.dirname f
|
68
|
-
if current_dir == previous_dir
|
69
|
-
input_string += " + #{File.basename f}"
|
70
|
-
else
|
71
|
-
previous_dir = current_dir
|
72
|
-
input_string += " + #{f}"
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
input_string
|
77
|
-
end
|
76
|
+
input_string
|
77
|
+
end
|
78
78
|
|
79
|
-
|
79
|
+
private
|
80
80
|
|
81
|
-
|
82
|
-
# Concatenate all input files into one (temporary) input file
|
83
|
-
# created in the same directory as the first input file
|
84
|
-
@tmp_file = Tempfile.new("pandocomatic_tmp_", File.dirname(self.absolute_path))
|
81
|
+
# rubocop:disable Metrics/AbcSize
|
85
82
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
File.read File.absolute_path(file)
|
91
|
-
}.join("\n\n")
|
83
|
+
def create_temp_file
|
84
|
+
# Concatenate all input files into one (temporary) input file
|
85
|
+
# created in the same directory as the first input file
|
86
|
+
@tmp_file = Tempfile.new('pandocomatic_tmp_', File.dirname(absolute_path))
|
92
87
|
|
93
|
-
|
88
|
+
contents = @input_files.map do |file|
|
89
|
+
@errors.push IOError.new(:file_does_not_exist, nil, file) unless File.exist? file
|
90
|
+
@errors.push IOError.new(:file_is_not_a_file, nil, file) unless File.file? file
|
91
|
+
@errors.push IOError.new(:file_is_not_readable, nil, file) unless File.readable? file
|
92
|
+
File.read File.absolute_path(file)
|
93
|
+
end.join("\n\n")
|
94
94
|
|
95
|
-
|
96
|
-
warn "\nWarning: Encountered the pandocomatic metadata property in more than one YAML metadata block. Only the pandocomatic property from the first YAML metadata block is being used; the other pandocomatic properties have been discarded.\n\n"
|
97
|
-
end
|
95
|
+
metadata = PandocMetadata.load contents
|
98
96
|
|
99
|
-
|
100
|
-
|
101
|
-
|
97
|
+
unless metadata.unique?
|
98
|
+
warn "\nWarning: Encountered the pandocomatic metadata property in"\
|
99
|
+
' more than one YAML metadata block. Only the pandocomatic property'\
|
100
|
+
' from the first YAML metadata block is being used; the other'\
|
101
|
+
" pandocomatic properties have been discarded.\n\n"
|
102
|
+
end
|
103
|
+
|
104
|
+
@tmp_file.write contents
|
105
|
+
@tmp_file.rewind
|
102
106
|
end
|
107
|
+
|
108
|
+
# rubocop:enable Metrics/AbcSize
|
109
|
+
end
|
103
110
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#--
|
4
|
+
# Copyright 2021 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_relative './configuration'
|
23
|
+
|
24
|
+
# Generic class to handle output in a general manner.
|
25
|
+
class Output
|
26
|
+
# Create a new Output
|
27
|
+
def initialize; end
|
28
|
+
end
|
29
|
+
end
|
@@ -1,214 +1,226 @@
|
|
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
|
22
|
+
require 'json'
|
23
|
+
require 'paru'
|
24
|
+
require 'yaml'
|
25
|
+
|
26
|
+
require_relative './error/pandoc_error'
|
27
|
+
require_relative './error/io_error'
|
28
|
+
require_relative './pandocomatic_yaml'
|
29
|
+
|
30
|
+
# Regular expression to find metadata blocks in a string.
|
31
|
+
METADATA_BLOCK = /^---[ \t]*(\r\n|\r|\n)(.+?)^(?:---|\.\.\.)[ \t]*(\r\n|\r|\n)/m
|
32
|
+
|
33
|
+
# PandocMetadata represents the metadata with pandoc options set in
|
34
|
+
# templates and input files.
|
35
|
+
class PandocMetadata < Hash
|
36
|
+
# Extract the YAML metadata from an input string
|
37
|
+
#
|
38
|
+
# @param input [String] the input string
|
39
|
+
# @return [String] the YAML data embedded in the input string
|
40
|
+
def self.pandoc2yaml(input)
|
41
|
+
extract_metadata(input).first
|
42
|
+
end
|
20
43
|
|
21
|
-
|
22
|
-
|
23
|
-
|
44
|
+
# Collect the metadata embedded in the src file and create a new
|
45
|
+
# PandocMetadata instance
|
46
|
+
#
|
47
|
+
# @param src [String] the path to the file to load metadata from
|
48
|
+
# @return [PandocMetadata] the metadata in the source file, or an empty
|
49
|
+
# one if no such metadata is contained in the source file.
|
50
|
+
def self.load_file(src)
|
51
|
+
self.load File.read(src), src
|
52
|
+
end
|
24
53
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
#
|
29
|
-
|
54
|
+
# Collect the metadata embedded in the src file and create a new
|
55
|
+
# PandocMetadata instance
|
56
|
+
#
|
57
|
+
# @param input [String] the string to load the metadata from
|
58
|
+
# @param path [String|Nil] the path to the source of the input, if any
|
59
|
+
# @return [PandocMetadata] the metadata in the source file, or an empty
|
60
|
+
# one if no such metadata is contained in the source file.
|
61
|
+
def self.load(input, path = nil)
|
62
|
+
yaml, pandocomatic_blocks = extract_metadata(input, path)
|
63
|
+
|
64
|
+
if yaml.empty?
|
65
|
+
PandocMetadata.new
|
66
|
+
else
|
67
|
+
PandocMetadata.new PandocomaticYAML.load(yaml, path), unique: pandocomatic_blocks <= 1
|
68
|
+
end
|
69
|
+
end
|
30
70
|
|
31
|
-
#
|
32
|
-
#
|
33
|
-
|
71
|
+
# Creat e new PandocMetadata object based on the properties contained
|
72
|
+
# in a Hash
|
73
|
+
#
|
74
|
+
# @param hash [Hash] initial properties for this new PandocMetadata
|
75
|
+
# object
|
76
|
+
# @param unique [Boolean = true] the pandocomatic property did occur
|
77
|
+
# at most once.
|
78
|
+
# @return [PandocMetadata]
|
79
|
+
def initialize(hash = {}, unique: true)
|
80
|
+
super()
|
81
|
+
merge! hash
|
82
|
+
@unique = unique
|
83
|
+
end
|
34
84
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
85
|
+
# Did the metadata contain multiple pandocomatic blocks?
|
86
|
+
#
|
87
|
+
# @return [Boolean] True if at most one pandocomatic block was present
|
88
|
+
# in the metadata
|
89
|
+
def unique?
|
90
|
+
@unique
|
91
|
+
end
|
42
92
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
load(File.read src)
|
51
|
-
end
|
52
|
-
|
53
|
-
# Collect the metadata embedded in the src file and create a new
|
54
|
-
# PandocMetadata instance
|
55
|
-
#
|
56
|
-
# @param input [String] the string to load the metadata from
|
57
|
-
# @return [PandocMetadata] the metadata in the source file, or an empty
|
58
|
-
# one if no such metadata is contained in the source file.
|
59
|
-
def self.load(input)
|
60
|
-
yaml, pandocomatic_blocks = extract_metadata(input)
|
61
|
-
|
62
|
-
if yaml.empty? then
|
63
|
-
PandocMetadata.new
|
64
|
-
else
|
65
|
-
PandocMetadata.new YAML.load(yaml), 1 >= pandocomatic_blocks
|
66
|
-
end
|
67
|
-
end
|
93
|
+
# Does this PandocMetadata object use a template?
|
94
|
+
#
|
95
|
+
# @return [Boolean] true if it has a key 'use-template' among the
|
96
|
+
# pandocomatic template properties.
|
97
|
+
def template?
|
98
|
+
pandocomatic? and pandocomatic.key? 'use-template' and !pandocomatic['use-template'].empty?
|
99
|
+
end
|
68
100
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
merge! hash
|
80
|
-
@unique = unique
|
101
|
+
# Get all the templates of this PandocMetadata oject
|
102
|
+
#
|
103
|
+
# @return [Array] an array of templates used in this PandocMetadata
|
104
|
+
# object
|
105
|
+
def templates
|
106
|
+
if template?
|
107
|
+
if pandocomatic['use-template'].is_a? Array
|
108
|
+
pandocomatic['use-template']
|
109
|
+
else
|
110
|
+
[pandocomatic['use-template']]
|
81
111
|
end
|
112
|
+
else
|
113
|
+
['']
|
114
|
+
end
|
115
|
+
end
|
82
116
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
117
|
+
# Get the used template's name
|
118
|
+
#
|
119
|
+
# @return [String] the name of the template used, if any, "" otherwise.
|
120
|
+
def template_name
|
121
|
+
if template?
|
122
|
+
pandocomatic['use-template']
|
123
|
+
else
|
124
|
+
''
|
125
|
+
end
|
126
|
+
end
|
90
127
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
128
|
+
# Does this PandocMetadata object have a pandocomatic property?
|
129
|
+
#
|
130
|
+
# @return [Boolean] True if this PandocMetadata object has a Hash
|
131
|
+
# property named "pandocomatic_". False otherwise.
|
132
|
+
#
|
133
|
+
# Note. For backward compatibility with older versions of
|
134
|
+
# pandocomatic, properties named "pandocomatic" (without the trailing
|
135
|
+
# underscore) are also accepted.
|
136
|
+
def pandocomatic?
|
137
|
+
config = nil
|
138
|
+
if key?('pandocomatic') || key?('pandocomatic_')
|
139
|
+
config = self['pandocomatic'] if key? 'pandocomatic'
|
140
|
+
config = self['pandocomatic_'] if key? 'pandocomatic_'
|
141
|
+
end
|
142
|
+
config.is_a? Hash
|
143
|
+
end
|
98
144
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
else
|
111
|
-
[""]
|
112
|
-
end
|
113
|
-
end
|
145
|
+
# Get the pandoc options for this PandocMetadata object
|
146
|
+
#
|
147
|
+
# @return [Hash] the pandoc options if there are any, an empty Hash
|
148
|
+
# otherwise.
|
149
|
+
def pandoc_options
|
150
|
+
if pandoc_options?
|
151
|
+
pandocomatic['pandoc']
|
152
|
+
else
|
153
|
+
{}
|
154
|
+
end
|
155
|
+
end
|
114
156
|
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
end
|
124
|
-
end
|
125
|
-
|
126
|
-
# Does this PandocMetadata object have a pandocomatic property?
|
127
|
-
#
|
128
|
-
# @return [Boolean] True if this PandocMetadata object has a Hash
|
129
|
-
# property named "pandocomatic_". False otherwise.
|
130
|
-
#
|
131
|
-
# Note. For backward compatibility with older versions of
|
132
|
-
# pandocomatic, properties named "pandocomatic" (without the trailing
|
133
|
-
# underscore) are also accepted.
|
134
|
-
def has_pandocomatic?()
|
135
|
-
config = nil
|
136
|
-
if has_key? 'pandocomatic' or has_key? 'pandocomatic_'
|
137
|
-
config = self['pandocomatic'] if has_key? 'pandocomatic'
|
138
|
-
config = self['pandocomatic_'] if has_key? 'pandocomatic_'
|
139
|
-
end
|
140
|
-
config.is_a? Hash
|
141
|
-
end
|
157
|
+
# Get the pandocomatic property of this PandocMetadata object
|
158
|
+
#
|
159
|
+
# @return [Hash] the pandocomatic property as a Hash, if any, an empty
|
160
|
+
# Hash otherwise.
|
161
|
+
def pandocomatic
|
162
|
+
return self['pandocomatic'] if key? 'pandocomatic'
|
163
|
+
return self['pandocomatic_'] if key? 'pandocomatic_'
|
164
|
+
end
|
142
165
|
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
else
|
151
|
-
{}
|
152
|
-
end
|
153
|
-
end
|
166
|
+
# Does this PandocMetadata object has a pandoc options property?
|
167
|
+
#
|
168
|
+
# @return [Boolean] True if there is a pandoc options property in this
|
169
|
+
# PandocMetadata object. False otherwise.
|
170
|
+
def pandoc_options?
|
171
|
+
pandocomatic? and pandocomatic.key? 'pandoc' and !pandocomatic['pandoc'].nil?
|
172
|
+
end
|
154
173
|
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
174
|
+
# Extract the metadata from an input file
|
175
|
+
#
|
176
|
+
# @param input [String] the string to extract metadata from
|
177
|
+
# @return [Array] The return value is an array with the following two
|
178
|
+
# values:
|
179
|
+
#
|
180
|
+
# 1. The extracted metadata as a YAML string
|
181
|
+
# 2. The number of times the pandocomatic properties did occur in the
|
182
|
+
# input.
|
183
|
+
#
|
184
|
+
# If more than one pandocomatic property is contained in the input,
|
185
|
+
# all but the first are discarded and are not present in the
|
186
|
+
# extracted metadata YAML string.
|
187
|
+
private_class_method def self.extract_metadata(input, path)
|
188
|
+
metadata_blocks = MetadataBlockList.new input, path
|
189
|
+
|
190
|
+
["#{YAML.dump(metadata_blocks.full)}...", metadata_blocks.count_pandocomatic_blocks]
|
191
|
+
end
|
163
192
|
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
193
|
+
# List of YAML metadata blocks present in some input source file
|
194
|
+
class MetadataBlockList
|
195
|
+
def initialize(input, path)
|
196
|
+
@metadata_blocks = input
|
197
|
+
.scan(METADATA_BLOCK)
|
198
|
+
.map { |match| PandocomaticYAML.load "---#{match.join}...", path }
|
199
|
+
.select { |block| !block.nil? and !block.empty? }
|
200
|
+
end
|
201
|
+
|
202
|
+
# Count the number of metadata blocks with a "pandocomatic_" property.
|
203
|
+
def count_pandocomatic_blocks
|
204
|
+
@metadata_blocks.count do |block|
|
205
|
+
block.key? 'pandocomatic_' or block.key? 'pandocomatic'
|
170
206
|
end
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
#
|
177
|
-
#
|
178
|
-
#
|
179
|
-
#
|
180
|
-
# 1. The extracted metadata as a YAML string
|
181
|
-
# 2. The number of times the pandocomatic properties did occur in the
|
182
|
-
# input.
|
207
|
+
end
|
208
|
+
|
209
|
+
# Combine all metadata blocks into a single metadata block
|
210
|
+
# @return [Hash]
|
211
|
+
def full
|
212
|
+
# According to the pandoc manual: "A document may contain multiple
|
213
|
+
# metadata blocks. The metadata fields will be combined through a
|
214
|
+
# left-biased union: if two metadata blocks attempt to set the
|
215
|
+
# same field, the value from the first block will be taken."
|
183
216
|
#
|
184
|
-
#
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
.scan(METADATA_BLOCK)
|
190
|
-
.map {|match| YAML.load "---#{match.join()}..."}
|
191
|
-
.select {|block| not block.nil? and not block.empty?}
|
192
|
-
|
193
|
-
pandocomatic_blocks = metadata_blocks.count do |block|
|
194
|
-
block.key? "pandocomatic_" or block.key? "pandocomatic"
|
195
|
-
end
|
196
|
-
|
197
|
-
# According to the pandoc manual: "A document may contain multiple
|
198
|
-
# metadata blocks. The metadata fields will be combined through a
|
199
|
-
# left-biased union: if two metadata blocks attempt to set the
|
200
|
-
# same field, the value from the first block will be taken."
|
201
|
-
#
|
202
|
-
# Here we do the same
|
203
|
-
full_metadata = metadata_blocks
|
204
|
-
.reverse
|
205
|
-
.reduce(Hash.new) {|metadata, block| metadata.merge!(block)}
|
206
|
-
|
207
|
-
yaml_string = YAML.dump(full_metadata) + "..."
|
208
|
-
|
209
|
-
return [yaml_string, pandocomatic_blocks]
|
210
|
-
end
|
211
|
-
|
217
|
+
# Here we do the same
|
218
|
+
@metadata_blocks
|
219
|
+
.reverse
|
220
|
+
.reduce({}) { |metadata, block| metadata.merge!(block) }
|
221
|
+
end
|
212
222
|
end
|
213
223
|
|
224
|
+
private_constant :MetadataBlockList
|
225
|
+
end
|
214
226
|
end
|