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,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
|