paru 0.2.4.2 → 0.2.4.3

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.
Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/lib/paru.rb +8 -20
  3. data/lib/paru/error.rb +4 -6
  4. data/lib/paru/filter.rb +144 -110
  5. data/lib/paru/filter/ast_manipulation.rb +75 -39
  6. data/lib/paru/filter/attr.rb +72 -36
  7. data/lib/paru/filter/block.rb +14 -8
  8. data/lib/paru/filter/block_quote.rb +12 -9
  9. data/lib/paru/filter/bullet_list.rb +6 -6
  10. data/lib/paru/filter/citation.rb +51 -25
  11. data/lib/paru/filter/cite.rb +29 -20
  12. data/lib/paru/filter/code.rb +41 -24
  13. data/lib/paru/filter/code_block.rb +36 -21
  14. data/lib/paru/filter/definition_list.rb +19 -15
  15. data/lib/paru/filter/definition_list_item.rb +30 -17
  16. data/lib/paru/filter/div.rb +29 -21
  17. data/lib/paru/filter/document.rb +73 -46
  18. data/lib/paru/filter/emph.rb +6 -6
  19. data/lib/paru/filter/empty_block.rb +17 -13
  20. data/lib/paru/filter/empty_inline.rb +24 -17
  21. data/lib/paru/filter/header.rb +38 -23
  22. data/lib/paru/filter/image.rb +13 -11
  23. data/lib/paru/filter/inline.rb +21 -10
  24. data/lib/paru/filter/line_block.rb +6 -6
  25. data/lib/paru/filter/line_break.rb +6 -6
  26. data/lib/paru/filter/link.rb +33 -21
  27. data/lib/paru/filter/list.rb +26 -17
  28. data/lib/paru/filter/list_attributes.rb +53 -32
  29. data/lib/paru/filter/markdown.rb +102 -59
  30. data/lib/paru/filter/math.rb +65 -38
  31. data/lib/paru/filter/meta.rb +26 -16
  32. data/lib/paru/filter/meta_blocks.rb +12 -9
  33. data/lib/paru/filter/meta_bool.rb +6 -6
  34. data/lib/paru/filter/meta_inlines.rb +12 -9
  35. data/lib/paru/filter/meta_list.rb +6 -6
  36. data/lib/paru/filter/meta_map.rb +49 -33
  37. data/lib/paru/filter/meta_string.rb +6 -6
  38. data/lib/paru/filter/meta_value.rb +22 -14
  39. data/lib/paru/filter/node.rb +204 -129
  40. data/lib/paru/filter/note.rb +31 -20
  41. data/lib/paru/filter/null.rb +6 -6
  42. data/lib/paru/filter/ordered_list.rb +34 -18
  43. data/lib/paru/filter/para.rb +20 -13
  44. data/lib/paru/filter/plain.rb +21 -12
  45. data/lib/paru/filter/quoted.rb +27 -18
  46. data/lib/paru/filter/raw_block.rb +32 -19
  47. data/lib/paru/filter/raw_inline.rb +40 -22
  48. data/lib/paru/filter/small_caps.rb +7 -6
  49. data/lib/paru/filter/soft_break.rb +6 -6
  50. data/lib/paru/filter/space.rb +6 -6
  51. data/lib/paru/filter/span.rb +28 -18
  52. data/lib/paru/filter/str.rb +29 -18
  53. data/lib/paru/filter/strikeout.rb +6 -6
  54. data/lib/paru/filter/strong.rb +6 -6
  55. data/lib/paru/filter/subscript.rb +6 -6
  56. data/lib/paru/filter/superscript.rb +6 -6
  57. data/lib/paru/filter/table.rb +51 -29
  58. data/lib/paru/filter/table_row.rb +21 -14
  59. data/lib/paru/filter/target.rb +29 -15
  60. data/lib/paru/filter/version.rb +23 -14
  61. data/lib/paru/pandoc.rb +165 -111
  62. data/lib/paru/pandoc_options.yaml +3 -3
  63. data/lib/paru/selector.rb +176 -153
  64. metadata +2 -3
  65. data/lib/paru/filter/alignment.rb +0 -30
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright 2015, 2016 Huub de Beer <Huub@heerdebeer.org>
2
+ # Copyright 2015, 2016, 2017 Huub de Beer <Huub@heerdebeer.org>
3
3
  #
4
4
  # This file is part of Paru
5
5
  #
@@ -16,7 +16,7 @@
16
16
  # You should have received a copy of the GNU General Public License
17
17
  # along with Paru. If not, see <http://www.gnu.org/licenses/>.
18
18
  # See http://pandoc.org/README.html for an overview of all options
19
- #
19
+ #++
20
20
  # General options
21
21
  from: ""
22
22
  read: ""
@@ -41,7 +41,7 @@ file_scope: true
41
41
  filter: [""]
42
42
  metadata: [""]
43
43
  normalize: true
44
- preserve_tabs: true
44
+ preserve_tabs: true
45
45
  tab_stop: 4
46
46
  track_changes: "accept"
47
47
  extract_media: true
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright 2015, 2016 Huub de Beer <Huub@heerdebeer.org>
2
+ # Copyright 2015, 2016, 2017 Huub de Beer <Huub@heerdebeer.org>
3
3
  #
4
4
  # This file is part of Paru
5
5
  #
@@ -17,157 +17,180 @@
17
17
  # along with Paru. If not, see <http://www.gnu.org/licenses/>.
18
18
  #++
19
19
  module Paru
20
- require_relative "./filter"
21
- require_relative "./error"
22
-
23
- class SelectorParseError < Error
24
- end
25
-
26
- class Selector
27
-
28
- def initialize selector
29
- @type = "Unknown"
30
- @relations = []
31
- parse selector
32
- end
33
-
34
- def matches? node, filtered_nodes
35
- node.type == @type and
36
- @classes.all? {|c| node.has_class? c } and
37
- @relations.all? {|r| r.matches? node, filtered_nodes}
38
- end
39
-
40
- private
41
-
42
- S = /\s*/
43
- TYPE = /(?<type>(?<name>[A-Z][a-zA-Z]*)(?<classes>(\.[a-zA-Z-]+)*))/
44
- OTHER_TYPE = /(?<other_type>(?<other_name>[A-Z][a-zA-Z]*)(?<other_classes>(\.[a-zA-Z-]+)*))/
45
- OPERATOR = /(?<operator>\+|-|>)/
46
- DISTANCE = /(?<distance>[1-9][0-9]*)/
47
- RELATION = /(?<relation>#{S}#{OTHER_TYPE}#{S}#{OPERATOR}#{S}#{DISTANCE}?#{S})/
48
- RELATIONS = /(?<relations>#{RELATION}+)/
49
- SELECTOR = /\A#{S}(?<selector>#{RELATIONS}?#{S}#{TYPE})#{S}\Z/
50
-
51
- def parse selector_string
52
- partial_match = expect_match SELECTOR, selector_string
53
- @type, @classes = expect_pandoc_type partial_match
54
-
55
- while continue_parsing? partial_match
56
- operator = expect partial_match, :operator
57
- distance = expect_integer partial_match, :distance
58
- type, classes = expect_pandoc_other_type partial_match
59
-
60
- @relations.push Relation.new(operator, distance, type, classes)
61
-
62
- partial_match = rest partial_match
63
- end
64
- end
65
-
66
- def is_pandoc_type type
67
- Paru::PANDOC_TYPES.include? type
68
- end
69
-
70
- def expect parts, part
71
- raise SelectorParseError.new "Expected #{part}" if parts[part].nil?
72
- parts[part]
20
+ require_relative './filter'
21
+ require_relative './error'
22
+
23
+ # SelectorParseError is thrown when there is an error parsing a selector
24
+ # used in a filter.
25
+ class SelectorParseError < Error
26
+ end
27
+
28
+
29
+ # A Selector models a relationship between Pandoc AST nodes, such as
30
+ # parent-child or sibling. Selectors in paru are like CSS selectors, but
31
+ # more limited because the Pandoc AST is quite simple.
32
+ #
33
+ # Given a selector expression, Selector determines if a node complies with
34
+ # that selector expression or not.
35
+ class Selector
36
+
37
+ # Create a new Selector based on the selector string
38
+ #
39
+ # @param selector [String] the selector string
40
+ def initialize(selector)
41
+ @type = 'Unknown'
42
+ @relations = []
43
+ parse selector
44
+ end
45
+
46
+ # Does node get selected by this Selector in the context of the already filtered
47
+ # nodes?
48
+ #
49
+ # @param node [Node] the node to check against this Selector
50
+ # @param filtered_nodes [Array<Node>] the context of filtered nodes to take
51
+ # into account as well
52
+ #
53
+ # @return [Boolean] True if the node in the context of the
54
+ # filtered_nodes is selected by this Selector
55
+ def matches? node, filtered_nodes
56
+ node.type == @type and
57
+ @classes.all? {|c| node.has_class? c } and
58
+ @relations.all? {|r| r.matches? node, filtered_nodes}
59
+ end
60
+
61
+ private
62
+
63
+ S = /\s*/
64
+ TYPE = /(?<type>(?<name>[A-Z][a-zA-Z]*)(?<classes>(\.[a-zA-Z-]+)*))/
65
+ OTHER_TYPE = /(?<other_type>(?<other_name>[A-Z][a-zA-Z]*)(?<other_classes>(\.[a-zA-Z-]+)*))/
66
+ OPERATOR = /(?<operator>\+|-|>)/
67
+ DISTANCE = /(?<distance>[1-9][0-9]*)/
68
+ RELATION = /(?<relation>#{S}#{OTHER_TYPE}#{S}#{OPERATOR}#{S}#{DISTANCE}?#{S})/
69
+ RELATIONS = /(?<relations>#{RELATION}+)/
70
+ SELECTOR = /\A#{S}(?<selector>#{RELATIONS}?#{S}#{TYPE})#{S}\Z/
71
+
72
+ # Parse the selector_string to construct this Selector
73
+ def parse(selector_string)
74
+ partial_match = expect_match SELECTOR, selector_string
75
+ @type, @classes = expect_pandoc_type partial_match
76
+
77
+ while continue_parsing? partial_match
78
+ operator = expect partial_match, :operator
79
+ distance = expect_integer partial_match, :distance
80
+ type, classes = expect_pandoc_other_type partial_match
81
+
82
+ @relations.push Relation.new(operator, distance, type, classes)
83
+
84
+ partial_match = rest partial_match
85
+ end
86
+ end
87
+
88
+ # Is type actually a Pandoc AST node type?
89
+ def is_pandoc_type(type)
90
+ Paru::PANDOC_TYPES.include? type
91
+ end
92
+
93
+ def expect(parts, part)
94
+ raise SelectorParseError.new "Expected #{part}" if parts[part].nil?
95
+ parts[part]
96
+ end
97
+
98
+ def expect_match(regexp, string)
99
+ match = regexp.match string
100
+ raise SelectorParseError.new "Unable to parse '#{string}'" if match.nil?
101
+ match
102
+ end
103
+
104
+ def expect_pandoc_type(parts)
105
+ type = expect parts, :name
106
+ classes = parts[:classes].split(".").select {|c| not c.empty?} if not parts[:classes].nil?
107
+ raise SelectorParseError.new "Expected a Pandoc type, got '#{type}' instead" if not is_pandoc_type type
108
+ [type, classes]
109
+ end
110
+
111
+ def expect_pandoc_other_type(parts)
112
+ type = expect parts, :other_name
113
+ classes = parts[:other_classes].split('.').select {|c| not c.empty?} if not parts[:other_classes].nil?
114
+ raise SelectorParseError.new "Expected a Pandoc type, got '#{type}' instead" if not is_pandoc_type type
115
+ [type, classes]
116
+ end
117
+
118
+ def expect_integer(parts, part)
119
+ if parts[part].nil?
120
+ number = 0
121
+ else
122
+ number = parts[part].to_i
123
+ raise SelectorParseError.new "Expected a positive #{part}, got '#{parts[part]}' instead" if number <= 0
124
+ end
125
+ number
126
+ end
127
+
128
+ def continue_parsing?(parts)
129
+ not parts.nil? and not parts[:relations].nil?
130
+ end
131
+
132
+ def rest(parts)
133
+ rest_string = parts[:relations].slice 0, parts[:relations].size - parts[:relation].size
134
+ RELATIONS.match rest_string
135
+ end
136
+ end
137
+
138
+ # @private
139
+ class Relation
140
+ def initialize(selector, distance, type, classes)
141
+ @selector = selector
142
+ @distance = distance
143
+ @type = type
144
+ @classes = classes
145
+ end
146
+
147
+ def matches?(node, filtered_nodes)
148
+ level_nodes = filtered_nodes.keep_if do |n|
149
+ node.is_inline? == n.is_inline? or
150
+ node.can_act_as_both_block_and_inline?
151
+ end
152
+ previous_nodes = previous level_nodes, @distance
153
+ case @selector
154
+ when '+'
155
+ in_sequence? node, previous_nodes
156
+ when '-'
157
+ not_in_sequence? node, previous_nodes
158
+ when '>'
159
+ is_descendant? node
160
+ else
161
+ false
162
+ end
163
+ end
164
+
165
+ def in_sequence?(node, previous_nodes)
166
+ previous_nodes.any? do |other|
167
+ other.type == @type and @classes.all? {|c| other.has_class? c}
168
+ end
169
+ end
170
+
171
+ def not_in_sequence?(node, previous_nodes)
172
+ previous_nodes.all? do |other|
173
+ other.type != @type or not @classes.all? {|c| other.has_class? c}
174
+ end
175
+ end
176
+
177
+ def is_descendant?(node)
178
+ distance = 0
179
+ begin
180
+ distance += 1 if @distance > 0
181
+ parent = node.parent
182
+ ancestry = parent.type == @type and @classes.all? {|c| parent.has_class? c}
183
+ end while not ancestry and not parent.is_root? and distance <= @distance
184
+ ancestry
185
+ end
186
+
187
+ def previous(filtered_nodes, distance)
188
+ distance = [distance, filtered_nodes.size - 1].min
189
+ if distance <= 0
190
+ filtered_nodes.slice(0, filtered_nodes.size - 1)
191
+ else
192
+ filtered_nodes.slice(-1 * distance - 1, distance)
193
+ end
194
+ end
73
195
  end
74
-
75
- def expect_match regexp, string
76
- match = regexp.match string
77
- raise SelectorParseError.new "Unable to parse '#{string}'" if match.nil?
78
- match
79
- end
80
-
81
- def expect_pandoc_type parts
82
- type = expect parts, :name
83
- classes = parts[:classes].split(".").select {|c| not c.empty?} if not parts[:classes].nil?
84
- raise SelectorParseError.new "Expected a Pandoc type, got '#{type}' instead" if not is_pandoc_type type
85
- [type, classes]
86
- end
87
-
88
- def expect_pandoc_other_type parts
89
- type = expect parts, :other_name
90
- classes = parts[:other_classes].split(".").select {|c| not c.empty?} if not parts[:other_classes].nil?
91
- raise SelectorParseError.new "Expected a Pandoc type, got '#{type}' instead" if not is_pandoc_type type
92
- [type, classes]
93
- end
94
-
95
- def expect_integer parts, part
96
- if parts[part].nil?
97
- number = 0
98
- else
99
- number = parts[part].to_i
100
- raise SelectorParseError.new "Expected a positive #{part}, got '#{parts[part]}' instead" if number <= 0
101
- end
102
- number
103
- end
104
-
105
- def continue_parsing? parts
106
- not parts.nil? and not parts[:relations].nil?
107
- end
108
-
109
- def rest parts
110
- rest_string = parts[:relations].slice 0, parts[:relations].size - parts[:relation].size
111
- RELATIONS.match rest_string
112
- end
113
- end
114
-
115
- class Relation
116
- def initialize selector, distance, type, classes
117
- @selector = selector
118
- @distance = distance
119
- @type = type
120
- @classes = classes
121
- end
122
-
123
- def matches? node, filtered_nodes
124
- level_nodes = filtered_nodes.keep_if do |n|
125
- node.is_inline? == n.is_inline? or
126
- node.can_act_as_both_block_and_inline?
127
- end
128
- previous_nodes = previous level_nodes, @distance
129
- case @selector
130
- when "+"
131
- in_sequence? node, previous_nodes
132
- when "-"
133
- not_in_sequence? node, previous_nodes
134
- when ">"
135
- is_descendant? node
136
- else
137
- false
138
- end
139
- end
140
-
141
- def in_sequence? node, previous_nodes
142
- previous_nodes.any? do |other|
143
- other.type == @type and @classes.all? {|c| other.has_class? c}
144
- end
145
- end
146
-
147
- def not_in_sequence? node, previous_nodes
148
- previous_nodes.all? do |other|
149
- other.type != @type or not @classes.all? {|c| other.has_class? c}
150
- end
151
- end
152
-
153
- def is_descendant? node
154
- distance = 0
155
- begin
156
- distance += 1 if @distance > 0
157
- parent = node.parent
158
- ancestry = parent.type == @type and @classes.all? {|c| parent.has_class? c}
159
- end while not ancestry and not parent.is_root? and distance <= @distance
160
- ancestry
161
- end
162
-
163
- def previous filtered_nodes, distance
164
- distance = [distance, filtered_nodes.size - 1].min
165
- if distance <= 0
166
- filtered_nodes.slice(0, filtered_nodes.size - 1)
167
- else
168
- filtered_nodes.slice(-1 * distance - 1, distance)
169
- end
170
- end
171
- end
172
-
173
196
  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.2
4
+ version: 0.2.4.3
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-02-08 00:00:00.000000000 Z
11
+ date: 2017-05-19 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
@@ -23,7 +23,6 @@ files:
23
23
  - lib/paru.rb
24
24
  - lib/paru/error.rb
25
25
  - lib/paru/filter.rb
26
- - lib/paru/filter/alignment.rb
27
26
  - lib/paru/filter/ast_manipulation.rb
28
27
  - lib/paru/filter/attr.rb
29
28
  - lib/paru/filter/block.rb
@@ -1,30 +0,0 @@
1
- #--
2
- # Copyright 2015, 2016 Huub de Beer <Huub@heerdebeer.org>
3
- #
4
- # This file is part of Paru
5
- #
6
- # Paru is free software: you can redistribute it and/or modify
7
- # it under the terms of the GNU General Public License as published by
8
- # the Free Software Foundation, either version 3 of the License, or
9
- # (at your option) any later version.
10
- #
11
- # Paru is distributed in the hope that it will be useful,
12
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
- # GNU General Public License for more details.
15
- #
16
- # You should have received a copy of the GNU General Public License
17
- # along with Paru. If not, see <http://www.gnu.org/licenses/>.
18
- #++
19
- module Paru
20
- module PandocFilter
21
-
22
- class Alignment
23
- ALIGNMENTS = ["AlignLeft", "AlignRight", "AlignCenter", "AlignDefault"]
24
-
25
- def initialize config
26
- @config = config
27
- end
28
- end
29
- end
30
- end