paru 0.2.4.4 → 0.2.4.5

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 49f91b95228c398d4ed7e752c9780d4a56bdb128
4
- data.tar.gz: 6096c105a736e686a02e2fc16f1d1985c55dfb05
3
+ metadata.gz: b681740521f95d8baa1e31caa9476e035ef65c72
4
+ data.tar.gz: d9af38ecf31b7116af24fc46ae232c0fa7fdcf4e
5
5
  SHA512:
6
- metadata.gz: 5cf262bca810cbae0f4dffae889de6cc4d53fcc466cc6ea3ad342484aef86a54878933cca5e120fac569b6938d92e5d1c14627f412546349b8bae898a282f77f
7
- data.tar.gz: a79687986c7709c5489efdb59bca496669d3ae1dd7b31397e64a9b5092d1f3b55a673c41463e68e400814066e49483c1db74243775e802affc85a4ffbaea9154
6
+ metadata.gz: 3763a3862f2d2cf6e45adf513dffea00f9888180d1a1d1fb42cd04776aba5fc0c567d73bc8a4a79ac3db5bfaad78bba37178bbb5232a7cd7e95d5f39b49a0548
7
+ data.tar.gz: 4f1a09ecb5fd986cc205f7fbaa8d0e03ddbd493ade3d0bcacb5e52a446db2e4e2eee4d6185c22da19003c8feaa583f1e1d2ce729120756b644aa6c7fcebbef61
data/bin/do-pandoc.rb CHANGED
@@ -2,9 +2,7 @@
2
2
  require "yaml"
3
3
  require 'optparse'
4
4
  require "paru/pandoc"
5
- require_relative "./pandoc2yaml.rb"
6
-
7
- include Pandoc2Yaml
5
+ require "paru/pandoc2yaml"
8
6
 
9
7
  parser = OptionParser.new do |opts|
10
8
  opts.banner = "do-pandoc.rb runs pandoc on an input file using the pandoc configuration specified in that input file."
@@ -44,7 +42,9 @@ if !File.readable? document
44
42
  warn "Cannot read file: #{input_document}"
45
43
  exit
46
44
  end
47
- metadata = YAML.load Pandoc2Yaml.extract_metadata(document)
45
+
46
+ yaml = Paru::Pandoc2Yaml.extract_metadata(document)
47
+ metadata = YAML.load yaml
48
48
 
49
49
  if metadata.has_key? "pandoc" then
50
50
  begin
@@ -65,5 +65,5 @@ if metadata.has_key? "pandoc" then
65
65
  warn "Something went wrong while using pandoc:\n\n#{e.message}"
66
66
  end
67
67
  else
68
- warn "Unsure what to do: no pandoc options in #{input}"
68
+ warn "Unsure what to do: no pandoc options in #{input_document}"
69
69
  end
data/bin/pandoc2yaml.rb CHANGED
@@ -9,86 +9,51 @@
9
9
  # pandoc2yaml.rb input_file
10
10
  #
11
11
  ##
12
- module Pandoc2Yaml
13
- require "json"
14
- require "paru/pandoc"
12
+ require "json"
13
+ require 'optparse'
14
+ require 'paru/pandoc2yaml'
15
15
 
16
- # Paru converters:
17
- # Note. When converting metadata back to the pandoc markdown format, you have
18
- # to use the option "standalone", otherwise the metadata is skipped
19
- PANDOC_2_JSON = Paru::Pandoc.new {from "markdown"; to "json"}
20
- JSON_2_PANDOC = Paru::Pandoc.new {from "json"; to "markdown"; standalone}
21
-
22
- # When converting a pandoc document to JSON, or vice versa, the JSON object
23
- # has the following three properties:
24
- VERSION = "pandoc-api-version"
25
- META = "meta"
26
- BLOCKS = "blocks"
27
-
28
- def extract_metadata input_document
29
- json = JSON.parse(PANDOC_2_JSON << File.read(input_document))
30
- yaml = ""
31
-
32
- version, metadata = json.values_at(VERSION, META)
33
-
34
- if not metadata.empty? then
35
- metadata_document = {
36
- VERSION => version,
37
- META => metadata,
38
- BLOCKS => []
39
- }
40
-
41
- yaml = JSON_2_PANDOC << JSON.generate(metadata_document)
42
- end
43
-
44
- yaml
45
- end
46
- end
47
-
48
- if __FILE__ == $0
49
- include Pandoc2Yaml
50
- require 'optparse'
51
-
52
- parser = OptionParser.new do |opts|
16
+ parser = OptionParser.new do |opts|
53
17
  opts.banner = "pandoc2yaml.rb mines a pandoc markdown file for its YAML metadata"
54
18
  opts.banner << "\n\nUsage: pandoc2yaml.rb some-pandoc-markdownfile.md"
55
19
  opts.separator ""
56
20
  opts.separator "Common options"
57
21
 
58
22
  opts.on_tail("-h", "--help", "Show this message") do
59
- puts opts
60
- exit
23
+ puts opts
24
+ exit
61
25
  end
62
26
 
63
27
  opts.on("-v", "--version", "Show version") do
64
- puts "pandoc2yaml.rb is part of paru version 0.2.3"
65
- exit
28
+ puts "pandoc2yaml.rb is part of paru version 0.2.3"
29
+ exit
66
30
  end
67
- end
31
+ end
68
32
 
69
- parser.parse! ARGV
33
+ parser.parse! ARGV
70
34
 
71
- input_document = ARGV.pop
35
+ input_document = ARGV.pop
72
36
 
73
- if ARGV.size != 0 then
37
+ if ARGV.size != 0 then
74
38
  warn "Expecting exactly one argument: the pandoc file to strip for metadata"
75
39
  puts ""
76
40
  puts parser
77
41
  exit
78
- end
42
+ end
79
43
 
80
- document = File.expand_path input_document
81
- if not File.exist? document
44
+ document = File.expand_path input_document
45
+ if not File.exist? document
82
46
  warn "Cannot find file: #{input_document}"
83
47
  exit
84
- end
48
+ end
85
49
 
86
- if !File.readable? document
50
+ if !File.readable? document
87
51
  warn "Cannot read file: #{input_document}"
88
52
  exit
89
- end
90
-
91
- output_metadata = Pandoc2Yaml.extract_metadata document
92
-
93
- puts output_metadata
94
53
  end
54
+
55
+ yaml = Paru::Pandoc2Yaml.extract_metadata(document)
56
+
57
+ yaml = "---\n..." if yaml.empty?
58
+
59
+ puts yaml
data/lib/paru.rb CHANGED
@@ -20,7 +20,8 @@ module Paru
20
20
  require "paru/pandoc"
21
21
  require "paru/error"
22
22
  require "paru/filter"
23
+ require "paru/pandoc2yaml"
23
24
 
24
25
  # Paru's current version
25
- VERSION = [0, 2, 4, 4]
26
+ VERSION = [0, 2, 4, 5]
26
27
  end
data/lib/paru/filter.rb CHANGED
@@ -198,11 +198,23 @@ module Paru
198
198
  #
199
199
  class Filter
200
200
 
201
- # Run the filter specified by block. In the block you specify
202
- # selectors and actions to be performed on selected nodes. In the
203
- # example below, the selector is "Image", which selects all image
204
- # nodes. The action is to prepend the contents of the image's caption
205
- # by the string "Figure. ".
201
+ # Create a new Filter instance. For convenience, {run} creates a new
202
+ # {Filter} and runs it immediately. Use this constructor if you want
203
+ # to run a filter on different input and output streams that STDIN and
204
+ # STDOUT respectively.
205
+ #
206
+ # @param input [IO = $stdin] the input stream to read, defaults to
207
+ # STDIN
208
+ # @param output [IO = $stdout] the output stream to write, defaults to
209
+ # STDOUT
210
+ def initialize(input = $stdin, output = $stdout)
211
+ @input = input
212
+ @output = output
213
+ end
214
+
215
+ # Run the filter specified by block. This is a convenience method that
216
+ # creates a new {Filter} using input stream STDIN and output stream
217
+ # STDOUT and immediately runs {filter} with the block supplied.
206
218
  #
207
219
  # @param block [Proc] the filter specification
208
220
  #
@@ -213,23 +225,39 @@ module Paru
213
225
  # end
214
226
  # end
215
227
  def self.run(&block)
216
- Filter.new().filter(&block)
228
+ Filter.new($stdin, $stdout).filter(&block)
217
229
  end
218
230
 
219
-
220
231
  # The Document node from JSON formatted pandoc document structure
221
232
  # on STDIN that is being filtered
222
233
  #
223
234
  # @return [Document] create a new Document node from a pandoc AST from
224
235
  # JSON from STDIN
225
236
  def document()
226
- PandocFilter::Document.from_JSON $stdin.read
237
+ PandocFilter::Document.from_JSON @input.read
227
238
  end
228
239
 
229
- # Create a filter using +block+.
240
+ # Create a filter using +block+. In the block you specify
241
+ # selectors and actions to be performed on selected nodes. In the
242
+ # example below, the selector is "Image", which selects all image
243
+ # nodes. The action is to prepend the contents of the image's caption
244
+ # by the string "Figure. ".
245
+ #
246
+ # @param block [Proc] the filter specification
230
247
  #
231
- # @param block [Proc] a block specifying selectors and actions
232
248
  # @return [JSON] a JSON string with the filtered pandoc AST
249
+ #
250
+ # @example Add 'Figure' to each image's caption
251
+ # input = IOString.new(File.read("my_report.md")
252
+ # output = IOString.new
253
+ #
254
+ # Paru::Filter.new(input, output).filter do
255
+ # with "Image" do |image|
256
+ # image.inner_markdown = "Figure. #{image.inner_markdown}"
257
+ # end
258
+ # end
259
+ #
260
+ # # do something with output.string
233
261
  def filter(&block)
234
262
  @selectors = Hash.new
235
263
  @filtered_nodes = []
@@ -240,10 +268,9 @@ module Paru
240
268
  instance_eval(&block)
241
269
  end
242
270
 
243
- puts @doc.to_JSON
271
+ @output.write @doc.to_JSON
244
272
  end
245
273
 
246
-
247
274
  # +current_node+ points to the node that is *now* being processed while
248
275
  # running this filter.
249
276
  #
@@ -24,6 +24,15 @@ module Paru
24
24
  # nodes, and so on.
25
25
  module ASTManipulation
26
26
 
27
+ # Find index of child
28
+ #
29
+ # @param child [Node] the child to find the index for
30
+ #
31
+ # @return [Number] the index of child or nil
32
+ def find_index(child)
33
+ @children.find_index child
34
+ end
35
+
27
36
  # Insert child node among this node's children at position index.
28
37
  #
29
38
  # @param index [Integer] the position to insert the child
@@ -66,7 +75,7 @@ module Paru
66
75
  # @param old_child [Node] the child to replace
67
76
  # @param new_child [Node] the replacement child
68
77
  def replace(old_child, new_child)
69
- old_child_index = @children.find_index old_child
78
+ old_child_index = find_index old_child
70
79
  if old_child_index then
71
80
  replace_at old_child_index, new_child
72
81
  end
@@ -36,10 +36,17 @@ module Paru
36
36
 
37
37
  # Create a new attributes object
38
38
  #
39
- # @param attributes [Array] the attributes as [id, [class names],
39
+ # @param attributes [Array = []] the attributes as [id, [class names],
40
40
  # [key-value pairs]]
41
- def initialize(attributes)
42
- @id, @classes, @data = attributes
41
+ def initialize(attributes = [])
42
+ id, classes, data = attributes
43
+
44
+ @id = id || ""
45
+
46
+ @classes = classes || []
47
+ @classes = [@classes] unless @classes.is_a? Array
48
+
49
+ @data = data || {}
43
50
  end
44
51
 
45
52
  # For each key-value pair of this attributes object
@@ -45,7 +45,9 @@ module Paru
45
45
  end
46
46
 
47
47
  # Set the markdown representation of this Node: replace this Node
48
- # by the Node represented by the markdown string
48
+ # by the Node represented by the markdown string. If an inline
49
+ # node is being replaced and the replacement has more than one
50
+ # paragraph, only the contents of the first paragraph is used
49
51
  #
50
52
  # @param markdown [String] the markdown string to replace this
51
53
  # Node
@@ -67,6 +69,20 @@ module Paru
67
69
  # replace current node by new nodes
68
70
  # There is a difference between inline and block nodes
69
71
  current_index = parent.find_index self
72
+
73
+ # By default, pandoc creates a Block level node when
74
+ # converting a string. However, if the original is a
75
+ # inline level node, so should its replacement node(s) be.
76
+ # Only using first block node (paragraph?)
77
+ if is_inline?
78
+ temp_doc = temp_doc.children.first
79
+
80
+ if not temp_doc.children.all? {|node| node.is_inline?}
81
+ raise Error.new "Cannot replace the inline level node represented by '#{outer_markdown}' with markdown that converts to block level nodes: '#{markdown}'."
82
+ end
83
+
84
+ end
85
+
70
86
  index = current_index
71
87
  temp_doc.each do |child|
72
88
  index += 1
@@ -119,7 +135,7 @@ module Paru
119
135
  temp_doc.children.each {|c| c.parent = @parent}
120
136
 
121
137
  if has_inline?
122
- @children = temp_doc.children[0].children
138
+ @children = temp_doc.children.first.children
123
139
  elsif has_block?
124
140
  @children = temp_doc.children
125
141
  else
@@ -128,6 +144,7 @@ module Paru
128
144
  end
129
145
  end
130
146
  end
147
+
131
148
  end
132
149
  end
133
150
  end
@@ -19,20 +19,12 @@
19
19
  module Paru
20
20
  module PandocFilter
21
21
  require_relative "./meta_map"
22
-
22
+
23
23
  # A Meta node represents the metadata of a document. It is a MetaMap
24
24
  # node.
25
25
  #
26
26
  # @see http://hackage.haskell.org/package/pandoc-types-1.17.0.4/docs/Text-Pandoc-Definition.html#t:Meta
27
27
  class Meta < MetaMap
28
- include Enumerable
29
-
30
- # Create a new Meta node based on the contents
31
- #
32
- # @param value [String]
33
- def initialize(value)
34
- super value
35
- end
36
28
 
37
29
  # The type of a Meta is "meta"
38
30
  #
@@ -46,6 +38,15 @@ module Paru
46
38
  ast_contents
47
39
  end
48
40
 
41
+ # Convert this Meta node to an {MetaMap} node
42
+ #
43
+ # @return [MetaMap] a MetaMap representation of this metadata
44
+ def to_meta_map()
45
+ map = MetaMap.new []
46
+ map.children = @children
47
+ map
48
+ end
49
+
49
50
  end
50
51
  end
51
52
  end
@@ -18,18 +18,10 @@
18
18
  #++
19
19
  module Paru
20
20
  module PandocFilter
21
-
22
21
  require_relative "./node"
23
22
 
24
- # A MetaBlocks Node contains a list of Blocks
23
+ # A MetaBlocks Node contains a list of {Block} nodes
25
24
  class MetaBlocks < Node
26
-
27
- # Create a MetaBlocks node based on the contents
28
- #
29
- # @param value [String] the contents of the MetaBlocks
30
- def initialize(value)
31
- super value
32
- end
33
25
  end
34
26
  end
35
27
  end
@@ -18,18 +18,10 @@
18
18
  #++
19
19
  module Paru
20
20
  module PandocFilter
21
-
22
21
  require_relative "./node"
23
22
 
24
- # A MetaInlines node contains a list of Inline nodes
23
+ # A MetaInlines node contains a list of {Inline} nodes
25
24
  class MetaInlines < Node
26
-
27
- # Create a new MetaInlines Node based on the contents
28
- #
29
- # @param value [String] the contents of this MetaInlines node
30
- def initialize(value)
31
- super value
32
- end
33
25
  end
34
26
  end
35
27
  end
@@ -20,9 +20,11 @@ module Paru
20
20
  module PandocFilter
21
21
 
22
22
  require_relative "./node"
23
+ require_relative "../pandoc.rb"
23
24
 
24
25
  # A MetaMap Node is a map of String keys with MetaValue values
25
26
  class MetaMap < Node
27
+ include Enumerable
26
28
 
27
29
  # Create a new MetaMap based on the contents
28
30
  #
@@ -39,41 +41,118 @@ module Paru
39
41
  end
40
42
  end
41
43
 
42
- # Get the value belonging to key
44
+ # Get the value belonging to key. Prefer to use the {has?}, {get},
45
+ # {replace} and {delete} methods to manipulate metadata.
43
46
  #
44
47
  # @param key [String] the key
45
48
  #
46
49
  # @return [MetaValue] the value belonging to the key
47
50
  def [](key)
48
- if @children.key_exists?
49
- @children[key]
50
- end
51
+ @children[key]
51
52
  end
52
53
 
53
- # Set a value with a key
54
+ # Set a value with a key. It is easier to use the {yaml} method to set
55
+ # metadata properties; the {yaml} method is the preferred method
56
+ # to set the metadata.
54
57
  #
55
58
  # @param key [String] the key to set
56
- # @param value
57
- # [MetaBlocks|MetaBool|MetaInline|MetaList|MetaMap|MetaString|MetaValue]
58
- # the value to set
59
+ # @param value [MetaBlocks|MetaBool|MetaInlines|MetaList|MetaMap|MetaString|MetaValue] the value to set
59
60
  def []=(key, value)
60
61
  @children[key] = value
61
62
  end
62
63
 
63
- # Does this MetaMap node have key?
64
+ # Execute block for each key-value pair
65
+ def each()
66
+ @children.each do |key, value|
67
+ yield(key, value)
68
+ end
69
+ end
70
+
71
+ # Mixin the YAML code into this metadata object
72
+ #
73
+ # @param yaml_string [YAML] A string with YAML data
74
+ # @return [MetaMap] this MetaMap object
75
+ #
76
+ # @example Set some properties in the metadata
77
+ # #!/usr/bin/env ruby
78
+ # require "paru/filter"
79
+ # require "date"
80
+ #
81
+ # Paru::Filter.run do
82
+ # metadata.yaml <<~YAML
83
+ # ---
84
+ # date: #{Date.today.to_s}
85
+ # title: This **is** the title
86
+ # pandoc_options:
87
+ # from: markdown
88
+ # toc: true
89
+ # keywords:
90
+ # - metadata
91
+ # - pandoc
92
+ # - filter
93
+ # ...
94
+ # YAML
95
+ # end
96
+ #
97
+ def yaml(yaml_string)
98
+ meta_from_yaml(yaml_string).each do |key, value|
99
+ self[key] = value
100
+ end
101
+ self
102
+ end
103
+
104
+ # Replace the property in this MetaMap matching the selector with
105
+ # metadata specified by second parameter. If that parameter is a
106
+ # String, it is treated as a YAML string.
107
+ #
108
+ # @param selector [String] a dot-separated sequence of property
109
+ # names denoting a sequence of descendants.
110
+ #
111
+ # @param value [MetaBlocks|MetaBool|MetaInlines|MetaList|MetaMap|MetaString|MetaValue|String]
112
+ # if value is a String, it is treated as a yaml string
113
+ def replace(selector, value)
114
+ parent = select(selector, true)
115
+ if value.is_a? String
116
+ value = meta_from_yaml(value)
117
+ end
118
+ parent.children[last_key(selector)] = value
119
+ end
120
+
121
+ # Get the property in this MetaMap matching the selector
122
+ #
123
+ # @param selector [String] a dot-separated sequence of property
124
+ # names denoting a sequence of descendants.
125
+ #
126
+ # @return [MetaBlocks|MetaBool|MetaInlines|MetaList|MetaMap|MetaString|MetaValue] the value matching the selected property, nil if it cannot be found
127
+ def get(selector)
128
+ select(selector)
129
+ end
130
+
131
+ # Has this MetaMap a descendant matching selector?
64
132
  #
65
- # @param key [String] the key to find
133
+ # @param selector [String] a dot-separated sequence of property
134
+ # names denoting a sequence of descendants
66
135
  #
67
- # @return [Boolean] true if this MetaMap node contains this key
68
- def has_key?(key)
69
- @children.has_key? key
136
+ # @return [Boolean] True if this MetaMap contains a descendant
137
+ # matching selector, false otherwise
138
+ def has?(selector)
139
+ not select(selector).nil?
70
140
  end
71
141
 
72
- # Delete the key-value pair from this MetaMap
142
+ # Delete the property in this MetaMap that matches the selector
143
+ #
144
+ # @param selector [String] a dot-separated sequence of property
145
+ # names denoting a sequence of descendants
146
+ #
147
+ # @return [MetaBlocks|MetaBool|MetaInlines|MetaList|MetaMap|MetaString|MetaValue] the value of the deleted property, nil if it cannot be found
73
148
  #
74
- # @param key [String] the key to delete
75
- def delete(key)
76
- @children.delete key
149
+ def delete(selector)
150
+ if has?(selector)
151
+ parent = select(selector, true)
152
+ parent.children.delete(last_key(selector))
153
+ else
154
+ nil
155
+ end
77
156
  end
78
157
 
79
158
  # The AST contents
@@ -84,6 +163,54 @@ module Paru
84
163
  end
85
164
  ast
86
165
  end
166
+
167
+ private
168
+
169
+ # Select a node given a selector as a dot separated sequence of
170
+ # descendant names.
171
+ #
172
+ # @param selector [String] Dot separated sequence of property
173
+ # names
174
+ #
175
+ # @param get_parent [Boolean = false] Get the parent MetaMap
176
+ # of the selected property instead of its value
177
+ #
178
+ # @return [MetaBlocks|MetaBool|MetaInlines|MetaList|MetaMap|MetaString|MetaValue] the value of the deleted property, nil if it cannot be found
179
+ def select(selector, get_parent = false)
180
+ keys = selector.split(".")
181
+ level = self
182
+
183
+ while not keys.empty?
184
+ key = keys.shift
185
+ if not level.children.has_key? key
186
+ return nil
187
+ else
188
+ if get_parent and keys.empty?
189
+ return level
190
+ else
191
+ level = level[key]
192
+ end
193
+ end
194
+ end
195
+
196
+ level
197
+ end
198
+
199
+ # Get the last key in this selector
200
+ def last_key(selector)
201
+ selector.split(".").last
202
+ end
203
+
204
+ # Convert a yaml string to a MetaMap
205
+ def meta_from_yaml(yaml_string)
206
+ json_string = Pandoc.new do
207
+ from "markdown"
208
+ to "json"
209
+ end << yaml_string
210
+
211
+ meta_doc = PandocFilter::Document.from_JSON json_string
212
+ meta_doc.meta.to_meta_map
213
+ end
87
214
  end
88
215
  end
89
216
  end
@@ -69,6 +69,32 @@ module Paru
69
69
  end
70
70
  end
71
71
  end
72
+
73
+ # Create a new node from a markdown string. This is always a block
74
+ # level node. If more
75
+ # than one new node is created, a {Div} is created as a parent for
76
+ # the newly created block nodes..
77
+ #
78
+ # @param markdown_string [String] the markdown string to convert
79
+ # to a AST node
80
+ #
81
+ # @return [Block|Div] The {Block} node created by converting
82
+ # markdown_string with pandoc; A {Div} node if this conversion
83
+ # holds more than one {Block} node.
84
+ def self.from_markdown(markdown_string)
85
+ node = Node.new []
86
+ node.outer_markdown = markdown_string
87
+
88
+ if node.children.size == 1
89
+ node = node.children.first
90
+ else
91
+ container = from_markdown "<div></div>"
92
+ container.children = node.children
93
+ node = container
94
+ end
95
+
96
+ return node
97
+ end
72
98
 
73
99
  # For each child of this Node, yield the child
74
100
  #
@@ -184,6 +210,21 @@ module Paru
184
210
  false
185
211
  end
186
212
 
213
+ # Convert this Node to a metadata value. If this Node
214
+ # {is_inline?}, it is converted to {MetaInlines} if it is
215
+ # {is_block?}, it is converted to {MetaBlocks}.
216
+ #
217
+ # @return [MetaInlines|MetaBlocks]
218
+ def toMetadata()
219
+ if is_inline? then
220
+ MetaInlines.new to_ast, true
221
+ elsif is_blocks? then
222
+ MetaBlocks.new to_ast, false
223
+ else
224
+ # ?
225
+ end
226
+ end
227
+
187
228
  # If this node has attributes with classes, is name among them?
188
229
  #
189
230
  # @param name [String] the class name to search for
@@ -20,9 +20,9 @@ module Paru
20
20
  module PandocFilter
21
21
  require_relative "./block"
22
22
 
23
- # A Plain node is a basic Block level node with Inline children. Not
24
- # to be confused with Para, which represents a paragraph. A Plain
25
- # is more general.
23
+ # A Plain node is a basic {Block} level node with {Inline} child nodes. Not
24
+ # to be confused with {Para}, which represents a paragraph. A Plain
25
+ # is a more general type of block level node.
26
26
  class Plain < Block
27
27
 
28
28
  # Create a new Plain node based on contents
@@ -0,0 +1,101 @@
1
+ #!/usr/bin/env ruby
2
+ ##
3
+ # pandoc2yaml.rb extracts the metadata from a pandoc markdown file and prints
4
+ # that metadata out again as a pandoc markdown file with nothing in it but that
5
+ # metadata
6
+ #
7
+ # Usage:
8
+ #
9
+ # pandoc2yaml.rb input_file
10
+ #
11
+ ##
12
+ module Paru
13
+ module Pandoc2Yaml
14
+ require "json"
15
+ require_relative "./pandoc.rb"
16
+
17
+ # Paru converters:
18
+ # Note. When converting metadata back to the pandoc markdown format, you have
19
+ # to use the option "standalone", otherwise the metadata is skipped
20
+ PANDOC_2_JSON = Paru::Pandoc.new {from "markdown"; to "json"}
21
+ JSON_2_PANDOC = Paru::Pandoc.new {from "json"; to "markdown"; standalone}
22
+
23
+ # When converting a pandoc document to JSON, or vice versa, the JSON object
24
+ # has the following three properties:
25
+ VERSION = "pandoc-api-version"
26
+ META = "meta"
27
+ BLOCKS = "blocks"
28
+
29
+ # Extract the YAML metadata from input document
30
+ #
31
+ # @param input_document [String] path to input document
32
+ # @return [String] YAML metadata from input document on STDOUT
33
+ def self.extract_metadata input_document
34
+ json = JSON.parse(PANDOC_2_JSON << File.read(input_document))
35
+ yaml = ""
36
+
37
+ version, metadata = json.values_at(VERSION, META)
38
+
39
+ if not metadata.empty? then
40
+ metadata_document = {
41
+ VERSION => version,
42
+ META => metadata,
43
+ BLOCKS => []
44
+ }
45
+
46
+ yaml = JSON_2_PANDOC << JSON.generate(metadata_document)
47
+ end
48
+
49
+ yaml
50
+ end
51
+ end
52
+
53
+ if __FILE__ == $0
54
+ require 'optparse'
55
+
56
+ parser = OptionParser.new do |opts|
57
+ opts.banner = "pandoc2yaml.rb mines a pandoc markdown file for its YAML metadata"
58
+ opts.banner << "\n\nUsage: pandoc2yaml.rb some-pandoc-markdownfile.md"
59
+ opts.separator ""
60
+ opts.separator "Common options"
61
+
62
+ opts.on_tail("-h", "--help", "Show this message") do
63
+ puts opts
64
+ exit
65
+ end
66
+
67
+ opts.on("-v", "--version", "Show version") do
68
+ puts "pandoc2yaml.rb is part of paru version 0.2.3"
69
+ exit
70
+ end
71
+ end
72
+
73
+ parser.parse! ARGV
74
+
75
+ input_document = ARGV.pop
76
+
77
+ if ARGV.size != 0 then
78
+ warn "Expecting exactly one argument: the pandoc file to strip for metadata"
79
+ puts ""
80
+ puts parser
81
+ exit
82
+ end
83
+
84
+ document = File.expand_path input_document
85
+ if not File.exist? document
86
+ warn "Cannot find file: #{input_document}"
87
+ exit
88
+ end
89
+
90
+ if !File.readable? document
91
+ warn "Cannot read file: #{input_document}"
92
+ exit
93
+ end
94
+
95
+ yaml = Pandoc2Yaml.extract_metadata(document)
96
+
97
+ yaml = "---\n..." if yaml.empty?
98
+
99
+ puts yaml
100
+ end
101
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: paru
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.4.4
4
+ version: 0.2.4.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Huub de Beer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-05-19 00:00:00.000000000 Z
11
+ date: 2017-05-29 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Use Pandoc (http://www.pandoc.org) with ruby
14
14
  email: Huub@heerdebeer.org
@@ -81,6 +81,7 @@ files:
81
81
  - lib/paru/filter/target.rb
82
82
  - lib/paru/filter/version.rb
83
83
  - lib/paru/pandoc.rb
84
+ - lib/paru/pandoc2yaml.rb
84
85
  - lib/paru/pandoc_options.yaml
85
86
  - lib/paru/selector.rb
86
87
  homepage: https://heerdebeer.org/Software/markdown/paru/