paru 0.1.0 → 0.2.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.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/lib/paru.rb +2 -2
  3. data/lib/paru/error.rb +2 -2
  4. data/lib/paru/filter.rb +69 -70
  5. data/lib/paru/filter/alignment.rb +7 -7
  6. data/lib/paru/filter/ast_manipulation.rb +39 -39
  7. data/lib/paru/filter/attr.rb +30 -32
  8. data/lib/paru/filter/block.rb +7 -7
  9. data/lib/paru/filter/block_quote.rb +8 -7
  10. data/lib/paru/filter/bullet_list.rb +6 -5
  11. data/lib/paru/filter/citation.rb +23 -23
  12. data/lib/paru/filter/cite.rb +19 -18
  13. data/lib/paru/filter/code.rb +23 -22
  14. data/lib/paru/filter/code_block.rb +20 -19
  15. data/lib/paru/filter/definition_list.rb +14 -13
  16. data/lib/paru/filter/definition_list_item.rb +17 -17
  17. data/lib/paru/filter/div.rb +19 -18
  18. data/lib/paru/filter/document.rb +56 -42
  19. data/lib/paru/filter/emph.rb +5 -4
  20. data/lib/paru/filter/empty_block.rb +17 -0
  21. data/lib/paru/filter/empty_inline.rb +21 -0
  22. data/lib/paru/filter/header.rb +22 -21
  23. data/lib/paru/filter/horizontal_rule.rb +5 -7
  24. data/lib/paru/filter/image.rb +10 -4
  25. data/lib/paru/filter/line_block.rb +9 -0
  26. data/lib/paru/filter/line_break.rb +5 -12
  27. data/lib/paru/filter/link.rb +21 -20
  28. data/lib/paru/filter/list.rb +16 -16
  29. data/lib/paru/filter/list_attributes.rb +31 -18
  30. data/lib/paru/filter/markdown.rb +62 -42
  31. data/lib/paru/filter/math.rb +46 -48
  32. data/lib/paru/filter/meta.rb +15 -16
  33. data/lib/paru/filter/meta_blocks.rb +8 -7
  34. data/lib/paru/filter/meta_bool.rb +5 -4
  35. data/lib/paru/filter/meta_inlines.rb +9 -8
  36. data/lib/paru/filter/meta_list.rb +5 -4
  37. data/lib/paru/filter/meta_map.rb +30 -29
  38. data/lib/paru/filter/meta_string.rb +5 -4
  39. data/lib/paru/filter/meta_value.rb +13 -11
  40. data/lib/paru/filter/node.rb +125 -122
  41. data/lib/paru/filter/note.rb +19 -11
  42. data/lib/paru/filter/null.rb +5 -7
  43. data/lib/paru/filter/ordered_list.rb +18 -17
  44. data/lib/paru/filter/para.rb +12 -11
  45. data/lib/paru/filter/plain.rb +11 -10
  46. data/lib/paru/filter/quoted.rb +17 -16
  47. data/lib/paru/filter/raw_block.rb +18 -18
  48. data/lib/paru/filter/raw_inline.rb +21 -21
  49. data/lib/paru/filter/small_caps.rb +5 -4
  50. data/lib/paru/filter/soft_break.rb +5 -12
  51. data/lib/paru/filter/space.rb +5 -11
  52. data/lib/paru/filter/span.rb +17 -16
  53. data/lib/paru/filter/str.rb +17 -16
  54. data/lib/paru/filter/strikeout.rb +5 -4
  55. data/lib/paru/filter/strong.rb +10 -0
  56. data/lib/paru/filter/subscript.rb +5 -4
  57. data/lib/paru/filter/superscript.rb +5 -4
  58. data/lib/paru/filter/table.rb +28 -27
  59. data/lib/paru/filter/table_row.rb +13 -13
  60. data/lib/paru/filter/target.rb +14 -14
  61. data/lib/paru/filter/version.rb +19 -0
  62. data/lib/paru/pandoc.rb +18 -13
  63. data/lib/paru/pandoc_options.yaml +14 -1
  64. data/lib/paru/selector.rb +152 -148
  65. metadata +9 -5
  66. data/lib/paru/filter/string.rb +0 -9
@@ -0,0 +1,10 @@
1
+ # Strong [Inline]
2
+ module Paru
3
+ module PandocFilter
4
+ require_relative "./inline"
5
+
6
+ class Strong < Inline
7
+ end
8
+ end
9
+ end
10
+
@@ -1,9 +1,10 @@
1
+ # Subscript [Inline]
1
2
  module Paru
2
- module PandocFilter
3
- require_relative "./inline"
3
+ module PandocFilter
4
+ require_relative "./inline"
4
5
 
5
- class Subscript < Inline
6
- end
6
+ class Subscript < Inline
7
7
  end
8
+ end
8
9
  end
9
10
 
@@ -1,9 +1,10 @@
1
+ # Superscript [Inline]
1
2
  module Paru
2
- module PandocFilter
3
- require_relative "./inline"
3
+ module PandocFilter
4
+ require_relative "./inline"
4
5
 
5
- class Superscript < Inline
6
- end
6
+ class Superscript < Inline
7
7
  end
8
+ end
8
9
  end
9
10
 
@@ -1,34 +1,35 @@
1
+ # Table [Inline] [Alignment] [Double] [TableCell] [[TableCell]]
1
2
  module Paru
2
- module PandocFilter
3
- require_relative "./block"
4
- require_relative "./inline"
5
- require_relative "./alignment"
6
-
7
- ALIGNMENTS = ["AlignLeft", "AlignRight", "AlignCenter", "AlignDefault"]
3
+ module PandocFilter
4
+ require_relative "./block"
5
+ require_relative "./inline"
6
+ require_relative "./alignment"
8
7
 
9
- class Table < Block
10
- attr_accessor :caption, :alignment, :column_widths, :headers, :rows
8
+ ALIGNMENTS = ["AlignLeft", "AlignRight", "AlignCenter", "AlignDefault"]
11
9
 
12
- def initialize contents
13
- @caption = Inline.new contents[0]
14
- @alignment = contents[1]
15
- @column_widths = contents[2]
16
- @headers = TableRow.new contents[3]
17
- @rows = []
18
- contents[4].each do |row_data|
19
- @rows.push TableRow.new row_data
20
- end
21
- end
10
+ class Table < Block
11
+ attr_accessor :caption, :alignment, :column_widths, :headers, :rows
22
12
 
23
- def ast_contents
24
- [
25
- @caption.ast_contents,
26
- @alignment,
27
- @column_widths,
28
- @headers.ast_contents,
29
- @rows.map {|row| row.ast_contents}
30
- ]
31
- end
13
+ def initialize contents
14
+ @caption = Inline.new contents[0]
15
+ @alignment = contents[1]
16
+ @column_widths = contents[2]
17
+ @headers = TableRow.new contents[3]
18
+ @rows = []
19
+ contents[4].each do |row_data|
20
+ @rows.push TableRow.new row_data
32
21
  end
22
+ end
23
+
24
+ def ast_contents
25
+ [
26
+ @caption.ast_contents,
27
+ @alignment,
28
+ @column_widths,
29
+ @headers.ast_contents,
30
+ @rows.map {|row| row.ast_contents}
31
+ ]
32
+ end
33
33
  end
34
+ end
34
35
  end
@@ -1,18 +1,18 @@
1
1
  module Paru
2
- module PandocFilter
3
- require_relative "./block"
2
+ module PandocFilter
3
+ require_relative "./block"
4
4
 
5
- class TableRow < Block
6
- def initialize row_data
7
- super []
8
- row_data.each do |cell|
9
- @children.push Block.new cell
10
- end
11
- end
12
-
13
- def ast_contents
14
- @children.map {|child| child.ast_contents}
15
- end
5
+ class TableRow < Block
6
+ def initialize row_data
7
+ super []
8
+ row_data.each do |cell|
9
+ @children.push Block.new cell
16
10
  end
11
+ end
12
+
13
+ def ast_contents
14
+ @children.map {|child| child.ast_contents}
15
+ end
17
16
  end
17
+ end
18
18
  end
@@ -1,19 +1,19 @@
1
1
  module Paru
2
- module PandocFilter
2
+ module PandocFilter
3
3
 
4
- class Target
5
- attr_accessor :url, :title
6
- def initialize contents
7
- @url = contents[0]
8
- @title = contents[1]
9
- end
4
+ class Target
5
+ attr_accessor :url, :title
6
+ def initialize contents
7
+ @url = contents[0]
8
+ @title = contents[1]
9
+ end
10
10
 
11
- def to_ast
12
- [
13
- @url,
14
- @title
15
- ]
16
- end
17
- end
11
+ def to_ast
12
+ [
13
+ @url,
14
+ @title
15
+ ]
16
+ end
18
17
  end
18
+ end
19
19
  end
@@ -0,0 +1,19 @@
1
+ module Paru
2
+ module PandocFilter
3
+ require_relative "./node"
4
+
5
+ class Version < Node
6
+ def initialize contents
7
+ @major, @minor, @revision = contents
8
+ end
9
+
10
+ def ast_type
11
+ "pandoc-api-version"
12
+ end
13
+
14
+ def to_ast
15
+ [@major, @minor, @revision]
16
+ end
17
+ end
18
+ end
19
+ end
data/lib/paru/pandoc.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  module Paru
2
2
 
3
- require 'yaml'
3
+ require "yaml"
4
4
 
5
5
  # Pandoc is a wrapper around the pandoc system. See
6
6
  # <http://pandoc.org/README.html> for details about pandoc. This file is
@@ -22,8 +22,8 @@ module Paru
22
22
  # Converts input string to output string using the pandoc invocation
23
23
  # configures in this Pandoc instance.
24
24
  def convert input
25
- output = ''
26
- IO.popen(to_command, 'r+') do |p|
25
+ output = ""
26
+ IO.popen(to_command, "r+") do |p|
27
27
  p << input
28
28
  p.close_write
29
29
  output << p.read
@@ -39,11 +39,11 @@ module Paru
39
39
  def to_option_string option_sep
40
40
  options_arr = []
41
41
  @options.each do |option, value|
42
- option_string = "--#{option.to_s.gsub '_', '-'}"
42
+ option_string = "--#{option.to_s.gsub "_", "-"}"
43
43
 
44
44
  case value
45
45
  when TrueClass then
46
- # Flags don't have a value, only its name
46
+ # Flags don"t have a value, only its name
47
47
  # For example: --standalone
48
48
  options_arr.push "#{option_string}"
49
49
  when FalseClass then
@@ -53,14 +53,14 @@ module Paru
53
53
  # For example: --css=main.css --css=print.css
54
54
  options_arr.push value.map {|val| "#{option_string}=#{val.to_s}"}.join(option_sep)
55
55
  else
56
- # All options that aren't flags and can occur only once have the
56
+ # All options that aren"t flags and can occur only once have the
57
57
  # same pattern: --option=value
58
58
  options_arr.push "#{option_string}=#{value.to_s}"
59
59
  end
60
60
  end
61
61
  options_arr.join(option_sep)
62
62
  end
63
-
63
+
64
64
  # Pandoc has a number of command line options. Most are simple options,
65
65
  # like flags, that can be set only once. Other options can occur more than
66
66
  # once, such as the css option: to add more than one css file to a
@@ -74,7 +74,7 @@ module Paru
74
74
  # an array with one value, the default value.
75
75
  #
76
76
  # For each of these options a method is defined as follows:
77
- OPTIONS = YAML.load_file File.join(__dir__, 'pandoc_options.yaml')
77
+ OPTIONS = YAML.load_file File.join(__dir__, "pandoc_options.yaml")
78
78
 
79
79
  OPTIONS.keys.each do |option|
80
80
  if OPTIONS[option].is_a? Array then
@@ -85,11 +85,16 @@ module Paru
85
85
  default = OPTIONS[option][0]
86
86
 
87
87
  define_method(option) do |value = default|
88
- if @options[option] then
89
- @options[option].push value
88
+ if @options[option].nil? then
89
+ @options[option] = []
90
+ end
91
+
92
+ if value.is_a? Array then
93
+ @options[option] += value
90
94
  else
91
- @options[option] = [value]
95
+ @options[option].push value
92
96
  end
97
+
93
98
  self
94
99
  end
95
100
 
@@ -99,8 +104,8 @@ module Paru
99
104
 
100
105
  default = OPTIONS[option]
101
106
  define_method(option) do |value = default|
102
- @options[option] = value
103
- self
107
+ @options[option] = value
108
+ self
104
109
  end
105
110
 
106
111
  end
@@ -2,9 +2,17 @@
2
2
  #
3
3
  # General options
4
4
  from: ""
5
+ read: ""
5
6
  to: ""
7
+ write: ""
6
8
  output: ""
7
9
  data_dir: ""
10
+ list_input_formats: true
11
+ list_output_formats: true
12
+ list_extensions: true
13
+ list_highlight_languages: true
14
+ list_highlight_styles: true
15
+ version: true
8
16
  # Reader options
9
17
  parse_raw: true
10
18
  smart: true
@@ -12,10 +20,11 @@ old_dashes: true
12
20
  base_header_level: 1
13
21
  indented_code_classes: ""
14
22
  default_image_extension: ""
23
+ file_scope: true
15
24
  filter: [""]
16
25
  metadata: [""]
17
26
  normalize: true
18
- preserve_tabls: true
27
+ preserve_tabs: true
19
28
  tab_stop: 4
20
29
  track_changes: "accept"
21
30
  extract_media: true
@@ -23,6 +32,8 @@ extract_media: true
23
32
  standalone: true
24
33
  template: ""
25
34
  variable: [""]
35
+ print_default_template: ""
36
+ print_default_data_file: ""
26
37
  dpi: 96
27
38
  wrap: "auto"
28
39
  no_wrap: true
@@ -40,8 +51,10 @@ self_contained: true
40
51
  html_q_tags: true
41
52
  ascii: true
42
53
  reference_links: true
54
+ reference_location: "document"
43
55
  atx_headers: true
44
56
  chapters: true
57
+ top_level_division: "section"
45
58
  number_sections: true
46
59
  number_offset: "0"
47
60
  no_tex_ligatures: true
data/lib/paru/selector.rb CHANGED
@@ -1,151 +1,155 @@
1
1
  module Paru
2
+ require_relative "./filter"
3
+ require_relative "./error"
4
+
5
+ class SelectorParseError < Error
6
+ end
7
+
8
+ class Selector
9
+
10
+ def initialize selector
11
+ @type = "Unknown"
12
+ @relations = []
13
+ parse selector
14
+ end
15
+
16
+ def matches? node, filtered_nodes
17
+ node.type == @type and
18
+ @classes.all? {|c| node.has_class? c } and
19
+ @relations.all? {|r| r.matches? node, filtered_nodes}
20
+ end
21
+
22
+ private
23
+
24
+ S = /\s*/
25
+ TYPE = /(?<type>(?<name>[A-Z][a-zA-Z]*)(?<classes>(\.[a-zA-Z-]+)*))/
26
+ OTHER_TYPE = /(?<other_type>(?<other_name>[A-Z][a-zA-Z]*)(?<other_classes>(\.[a-zA-Z-]+)*))/
27
+ OPERATOR = /(?<operator>\+|-|>)/
28
+ DISTANCE = /(?<distance>[1-9][0-9]*)/
29
+ RELATION = /(?<relation>#{S}#{OTHER_TYPE}#{S}#{OPERATOR}#{S}#{DISTANCE}?#{S})/
30
+ RELATIONS = /(?<relations>#{RELATION}+)/
31
+ SELECTOR = /\A#{S}(?<selector>#{RELATIONS}?#{S}#{TYPE})#{S}\Z/
32
+
33
+ def parse selector_string
34
+ partial_match = expect_match SELECTOR, selector_string
35
+ @type, @classes = expect_pandoc_type partial_match
36
+
37
+ while continue_parsing? partial_match
38
+ operator = expect partial_match, :operator
39
+ distance = expect_integer partial_match, :distance
40
+ type, classes = expect_pandoc_other_type partial_match
41
+
42
+ @relations.push Relation.new(operator, distance, type, classes)
43
+
44
+ partial_match = rest partial_match
45
+ end
46
+ end
47
+
48
+ def is_pandoc_type type
49
+ Paru::PANDOC_TYPES.include? type
50
+ end
51
+
52
+ def expect parts, part
53
+ raise SelectorParseError.new "Expected #{part}" if parts[part].nil?
54
+ parts[part]
55
+ end
56
+
57
+ def expect_match regexp, string
58
+ match = regexp.match string
59
+ raise SelectorParseError.new "Unable to parse '#{string}'" if match.nil?
60
+ match
61
+ end
62
+
63
+ def expect_pandoc_type parts
64
+ type = expect parts, :name
65
+ classes = parts[:classes].split(".").select {|c| not c.empty?} if not parts[:classes].nil?
66
+ raise SelectorParseError.new "Expected a Pandoc type, got '#{type}' instead" if not is_pandoc_type type
67
+ [type, classes]
68
+ end
69
+
70
+ def expect_pandoc_other_type parts
71
+ type = expect parts, :other_name
72
+ classes = parts[:other_classes].split(".").select {|c| not c.empty?} if not parts[:other_classes].nil?
73
+ raise SelectorParseError.new "Expected a Pandoc type, got '#{type}' instead" if not is_pandoc_type type
74
+ [type, classes]
75
+ end
76
+
77
+ def expect_integer parts, part
78
+ if parts[part].nil?
79
+ number = 0
80
+ else
81
+ number = parts[part].to_i
82
+ raise SelectorParseError.new "Expected a positive #{part}, got '#{parts[part]}' instead" if number <= 0
83
+ end
84
+ number
85
+ end
86
+
87
+ def continue_parsing? parts
88
+ not parts.nil? and not parts[:relations].nil?
89
+ end
90
+
91
+ def rest parts
92
+ rest_string = parts[:relations].slice 0, parts[:relations].size - parts[:relation].size
93
+ RELATIONS.match rest_string
94
+ end
95
+ end
96
+
97
+ class Relation
98
+ def initialize selector, distance, type, classes
99
+ @selector = selector
100
+ @distance = distance
101
+ @type = type
102
+ @classes = classes
103
+ end
104
+
105
+ def matches? node, filtered_nodes
106
+ level_nodes = filtered_nodes.keep_if do |n|
107
+ node.is_inline? == n.is_inline? or
108
+ node.can_act_as_both_block_and_inline?
109
+ end
110
+ previous_nodes = previous level_nodes, @distance
111
+ case @selector
112
+ when "+"
113
+ in_sequence? node, previous_nodes
114
+ when "-"
115
+ not_in_sequence? node, previous_nodes
116
+ when ">"
117
+ is_descendant? node
118
+ else
119
+ false
120
+ end
121
+ end
122
+
123
+ def in_sequence? node, previous_nodes
124
+ previous_nodes.any? do |other|
125
+ other.type == @type and @classes.all? {|c| other.has_class? c}
126
+ end
127
+ end
128
+
129
+ def not_in_sequence? node, previous_nodes
130
+ previous_nodes.all? do |other|
131
+ other.type != @type or not @classes.all? {|c| other.has_class? c}
132
+ end
133
+ end
134
+
135
+ def is_descendant? node
136
+ distance = 0
137
+ begin
138
+ distance += 1 if @distance > 0
139
+ parent = node.parent
140
+ ancestry = parent.type == @type and @classes.all? {|c| parent.has_class? c}
141
+ end while not ancestry and not parent.is_root? and distance <= @distance
142
+ ancestry
143
+ end
144
+
145
+ def previous filtered_nodes, distance
146
+ distance = [distance, filtered_nodes.size - 1].min
147
+ if distance <= 0
148
+ filtered_nodes.slice(0, filtered_nodes.size - 1)
149
+ else
150
+ filtered_nodes.slice(-1 * distance - 1, distance)
151
+ end
152
+ end
153
+ end
2
154
 
3
- require_relative "./filter"
4
- require_relative "./error"
5
-
6
- class SelectorParseError < Error
7
- end
8
-
9
- class Selector
10
-
11
- def initialize selector
12
- @type = "Unknown"
13
- @relations = []
14
- parse selector
15
- end
16
-
17
- def matches? node, filtered_nodes
18
- node.type == @type and
19
- @classes.all? {|c| node.has_class? c } and
20
- @relations.all? {|r| r.matches? node, filtered_nodes}
21
- end
22
-
23
- private
24
-
25
- S = /\s*/
26
- TYPE = /(?<type>(?<name>[A-Z][a-zA-Z]*)(?<classes>(\.[a-zA-Z-]+)*))/
27
- OTHER_TYPE = /(?<other_type>(?<other_name>[A-Z][a-zA-Z]*)(?<other_classes>(\.[a-zA-Z-]+)*))/
28
- OPERATOR = /(?<operator>\+|-|>)/
29
- DISTANCE = /(?<distance>[1-9][0-9]*)/
30
- RELATION = /(?<relation>#{S}#{OTHER_TYPE}#{S}#{OPERATOR}#{S}#{DISTANCE}?#{S})/
31
- RELATIONS = /(?<relations>#{RELATION}+)/
32
- SELECTOR = /\A#{S}(?<selector>#{RELATIONS}?#{S}#{TYPE})#{S}\Z/
33
-
34
- def parse selector_string
35
- partial_match = expect_match SELECTOR, selector_string
36
- @type, @classes = expect_pandoc_type partial_match
37
-
38
- while continue_parsing? partial_match
39
- operator = expect partial_match, :operator
40
- distance = expect_integer partial_match, :distance
41
- type, classes = expect_pandoc_other_type partial_match
42
-
43
- @relations.push Relation.new(operator, distance, type, classes)
44
-
45
- partial_match = rest partial_match
46
- end
47
- end
48
-
49
- def is_pandoc_type type
50
- Paru::PANDOC_TYPES.include? type
51
- end
52
-
53
- def expect parts, part
54
- raise SelectorParseError.new "Expected #{part}" if parts[part].nil?
55
- parts[part]
56
- end
57
-
58
- def expect_match regexp, string
59
- match = regexp.match string
60
- raise SelectorParseError.new "Unable to parse '#{string}'" if match.nil?
61
- match
62
- end
63
-
64
- def expect_pandoc_type parts
65
- type = expect parts, :name
66
- classes = parts[:classes].split(".").select {|c| not c.empty?} if not parts[:classes].nil?
67
- raise SelectorParseError.new "Expected a Pandoc type, got '#{type}' instead" if not is_pandoc_type type
68
- [type, classes]
69
- end
70
-
71
- def expect_pandoc_other_type parts
72
- type = expect parts, :other_name
73
- classes = parts[:other_classes].split(".").select {|c| not c.empty?} if not parts[:other_classes].nil?
74
- raise SelectorParseError.new "Expected a Pandoc type, got '#{type}' instead" if not is_pandoc_type type
75
- [type, classes]
76
- end
77
-
78
- def expect_integer parts, part
79
- if parts[part].nil?
80
- number = 0
81
- else
82
- number = parts[part].to_i
83
- raise SelectorParseError.new "Expected a positive #{part}, got '#{parts[part]}' instead" if number <= 0
84
- end
85
- number
86
- end
87
-
88
- def continue_parsing? parts
89
- not parts.nil? and not parts[:relations].nil?
90
- end
91
-
92
- def rest parts
93
- rest_string = parts[:relations].slice 0, parts[:relations].size - parts[:relation].size
94
- RELATIONS.match rest_string
95
- end
96
- end
97
-
98
- class Relation
99
- def initialize selector, distance, type, classes
100
- @selector = selector
101
- @distance = distance
102
- @type = type
103
- @classes = classes
104
- end
105
-
106
- def matches? node, filtered_nodes
107
- previous_nodes = previous filtered_nodes, @distance
108
- case @selector
109
- when "+"
110
- in_sequence? node, previous_nodes
111
- when "-"
112
- not_in_sequence? node, previous_nodes
113
- when ">"
114
- is_descendant? node
115
- else
116
- false
117
- end
118
- end
119
-
120
- def in_sequence? node, previous_nodes
121
- previous_nodes.any? do |other|
122
- other.type == @type and @classes.all? {|c| other.has_class? c}
123
- end
124
- end
125
-
126
- def not_in_sequence? node, previous_nodes
127
- previous_nodes.all? do |other|
128
- other.type != @type or not @classes.all? {|c| other.has_class? c}
129
- end
130
- end
131
-
132
- def is_descendant? node
133
- distance = 0
134
- begin
135
- distance += 1 if @distance > 0
136
- parent = node.parent
137
- ancestry = parent.type == @type and @classes.all? {|c| parent.has_class? c}
138
- end while not ancestry and not parent.is_root? and distance <= @distance
139
- ancestry
140
- end
141
-
142
- def previous filtered_nodes, distance
143
- if distance <= 0
144
- filtered_nodes.slice(0, filtered_nodes.size - 1)
145
- else
146
- filtered_nodes.slice(-1 * distance - 1, distance)
147
- end
148
- end
149
- end
150
-
151
155
  end