paru 0.2.4.2 → 0.2.4.3

Sign up to get free protection for your applications and to get access to all the features.
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