yalphabetize 0.3.0 → 0.6.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 702ef0ac265097aa95ae58399f9bd221336ebba2f29ee51b07ff03beb7c471bd
4
- data.tar.gz: d2da1541ac411f12ba6b3a70534df739cfca69620b07d067dfa75bd18c4d7da7
3
+ metadata.gz: b8a46ac2b83620bfb782115c3619f6db45dc085ac588bf3911a9c5c0380ac27e
4
+ data.tar.gz: 76a8548aee15525a38afa21d1f21958184f8b77346778626a06c0323dd62fee5
5
5
  SHA512:
6
- metadata.gz: 43205417abde2761326cd34006fa49cbd574d1ec98e5d47a01f9a5769fad51883de9bc7822e206cbabf66c56f91ea54ce3c3d986bae3639550d5e3899a9759ff
7
- data.tar.gz: 543936dea7ac58dc5857419cd27330214759109fa3bdb8bdf50524964bb4b1f1d6e30ce9a60fce156c70cb5fdc2694b60fc139f80085678d2841d864dd3e070c
6
+ metadata.gz: 24727bad57547da439e2c63d17be8469c8f605bcfd1dcee96685e274b89933e716a07f3cbd84ff9e8f1c88c37561efe82ec11a477758614e7e75351cd5ffd61d
7
+ data.tar.gz: f841fe74158715af2a2836b8637d9363e9b7371cb77ddd0ac43d109712a9832dd04b5bb81b741218e30f76bbb56b77b6c90b1a6560913ad8d5e5114cfaabb2ea
@@ -2,48 +2,32 @@
2
2
 
3
3
  module Yalphabetize
4
4
  class Alphabetizer
5
- def initialize(stream_node)
5
+ def initialize(stream_node, order_checker_class:)
6
6
  @stream_node = stream_node
7
+ @order_checker_class = order_checker_class
7
8
  end
8
9
 
9
10
  def call
10
- transform(stream_node)
11
- alphabetize(stream_node)
12
- stream_node
13
- end
14
-
15
- private
16
-
17
- attr_reader :stream_node
18
-
19
- def alphabetize(node)
20
- if node.mapping?
21
- alphabetize_children(node)
11
+ stream_node.select(&:mapping?).each do |node|
12
+ order_checker = order_checker_class.new_for(node)
13
+ pair_up_children(node)
14
+ alphabetize_children(node, order_checker)
22
15
  unpair_children(node)
23
16
  end
24
-
25
- node.children&.each { |child_node| alphabetize(child_node) }
26
17
  end
27
18
 
28
- def alphabetize_children(node)
29
- node.children.sort_by! { |key, _value| key.value }
30
- end
19
+ private
31
20
 
32
- def unpair_children(node)
33
- children_clone = node.children.dup
21
+ attr_reader :stream_node, :order_checker_class
34
22
 
35
- children_clone.each do |slice|
36
- node.children.push(*slice)
37
- node.children.shift
23
+ def alphabetize_children(node, order_checker)
24
+ node.children.sort! do |a, b|
25
+ order_checker.compare(a.first.value, b.first.value)
38
26
  end
39
27
  end
40
28
 
41
- def transform(node)
42
- node.children&.each(&method(:transform))
43
-
44
- return unless node.mapping?
45
-
46
- pair_up_children(node)
29
+ def unpair_children(node)
30
+ node.children.flatten!
47
31
  end
48
32
 
49
33
  def pair_up_children(node)
@@ -51,8 +35,7 @@ module Yalphabetize
51
35
 
52
36
  children_clone.each_slice(2) do |slice|
53
37
  node.children.push(slice)
54
- node.children.shift
55
- node.children.shift
38
+ 2.times { node.children.shift }
56
39
  end
57
40
  end
58
41
  end
@@ -10,6 +10,7 @@ module Yalphabetize
10
10
  @autocorrect = options[:autocorrect]
11
11
  @alphabetizer_class = options[:alphabetizer_class]
12
12
  @writer_class = options[:writer_class]
13
+ @order_checker_class = options[:order_checker_class]
13
14
  end
14
15
 
15
16
  def call
@@ -19,14 +20,12 @@ module Yalphabetize
19
20
  else
20
21
  logger.log_no_offence
21
22
  end
22
-
23
- replace_interpolations
24
23
  end
25
24
 
26
25
  private
27
26
 
28
- attr_reader :file_path, :reader_class, :offence_detector_class,
29
- :logger, :autocorrect, :alphabetizer_class, :writer_class
27
+ attr_reader :file_path, :reader_class, :offence_detector_class, :logger, :autocorrect,
28
+ :alphabetizer_class, :writer_class, :order_checker_class
30
29
 
31
30
  def autocorrect_file
32
31
  alphabetize
@@ -36,21 +35,11 @@ module Yalphabetize
36
35
  end
37
36
 
38
37
  def offences?
39
- offence_detector_class.new(stream_node).offences?
40
- end
41
-
42
- def replace_interpolations
43
- interpolations_mapping.each do |uuid, interpolation|
44
- file_content = File.read(file_path)
45
- file_content.sub!(uuid, interpolation)
46
- File.open(file_path, 'w') do |file|
47
- file.write file_content
48
- end
49
- end
38
+ offence_detector_class.new(stream_node, order_checker_class: order_checker_class).offences?
50
39
  end
51
40
 
52
41
  def alphabetize
53
- alphabetizer_class.new(stream_node).call
42
+ alphabetizer_class.new(stream_node, order_checker_class: order_checker_class).call
54
43
  end
55
44
 
56
45
  def handle_aliases
@@ -72,9 +61,5 @@ module Yalphabetize
72
61
  def stream_node
73
62
  @_stream_node ||= reader.to_ast
74
63
  end
75
-
76
- def interpolations_mapping
77
- reader.interpolations_mapping
78
- end
79
64
  end
80
65
  end
@@ -2,8 +2,9 @@
2
2
 
3
3
  module Yalphabetize
4
4
  class OffenceDetector
5
- def initialize(stream_node)
5
+ def initialize(stream_node, order_checker_class:)
6
6
  @stream_node = stream_node
7
+ @order_checker_class = order_checker_class
7
8
  end
8
9
 
9
10
  def offences?
@@ -12,7 +13,7 @@ module Yalphabetize
12
13
 
13
14
  private
14
15
 
15
- attr_reader :stream_node
16
+ attr_reader :stream_node, :order_checker_class
16
17
 
17
18
  def alphabetized?(node)
18
19
  return false if node.mapping? && !alphabetized_children?(node)
@@ -25,7 +26,11 @@ module Yalphabetize
25
26
  end
26
27
 
27
28
  def alphabetized_children?(node)
28
- node.children.each_slice(2).each_cons(2).all? { |a, b| (a.first.value <=> b.first.value) <= 0 }
29
+ order_checker = order_checker_class.new_for(node)
30
+
31
+ node.children.each_slice(2).each_cons(2).all? do |a, b|
32
+ order_checker.ordered?(a.first.value, b.first.value)
33
+ end
29
34
  end
30
35
 
31
36
  def each_child_also_alphabetized?(children)
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ # AaBb
4
+ module Yalphabetize
5
+ module OrderCheckers
6
+ class AlphabeticalThenCapitalizedFirst < Base
7
+ def compare(string, other_string)
8
+ alphabetical_comparison(string, other_string).nonzero? || string <=> other_string
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ # aAbB
4
+ module Yalphabetize
5
+ module OrderCheckers
6
+ class AlphabeticalThenCapitalizedLast < Base
7
+ def compare(string, other_string)
8
+ alphabetical_comparison(string, other_string).nonzero? || string.swapcase <=> other_string.swapcase
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yalphabetize
4
+ module OrderCheckers
5
+ class Base
6
+ def self.new_for(node)
7
+ node_keys = node.children.select.each_with_index do |_, i|
8
+ i.even?
9
+ end.map(&:value)
10
+
11
+ matched_allowed_order = Yalphabetize.config['allowed_orders']&.find do |allowed_order|
12
+ (node_keys - allowed_order).empty?
13
+ end
14
+
15
+ matched_allowed_order ? Custom.new(matched_allowed_order) : new
16
+ end
17
+
18
+ def ordered?(string, other_string)
19
+ !compare(string, other_string).positive?
20
+ end
21
+
22
+ private
23
+
24
+ def alphabetical_comparison(string, other_string)
25
+ string.downcase <=> other_string.downcase
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ # ABab
4
+ module Yalphabetize
5
+ module OrderCheckers
6
+ class CapitalizedFirstThenAlphabetical < Base
7
+ def compare(string, other_string)
8
+ string <=> other_string
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ # abAB
4
+ module Yalphabetize
5
+ module OrderCheckers
6
+ class CapitalizedLastThenAlphabetical < Base
7
+ def compare(string, other_string)
8
+ string.swapcase <=> other_string.swapcase
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yalphabetize
4
+ module OrderCheckers
5
+ class Custom < Base
6
+ def initialize(allowed_order)
7
+ super()
8
+ @allowed_order = allowed_order
9
+ end
10
+
11
+ def compare(string, other_string)
12
+ allowed_order.index(string) <=> allowed_order.index(other_string)
13
+ end
14
+
15
+ private
16
+
17
+ attr_reader :allowed_order
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yalphabetize
4
+ module OrderCheckers
5
+ TOKEN_MAPPING = {
6
+ 'abAB' => CapitalizedLastThenAlphabetical,
7
+ 'aAbB' => AlphabeticalThenCapitalizedLast,
8
+ 'AaBb' => AlphabeticalThenCapitalizedFirst,
9
+ 'ABab' => CapitalizedFirstThenAlphabetical
10
+ }.freeze
11
+ end
12
+ end
@@ -1,37 +1,21 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'psych'
4
- require 'securerandom'
5
4
 
6
5
  module Yalphabetize
7
6
  class Reader
8
7
  def initialize(path)
9
8
  @path = path
10
- @interpolations_mapping = {}
11
9
  end
12
10
 
13
11
  def to_ast
14
- substitute_interpolations
15
12
  stream_node
16
13
  end
17
14
 
18
- attr_reader :interpolations_mapping
19
-
20
15
  private
21
16
 
22
17
  attr_reader :path
23
18
 
24
- def substitute_interpolations
25
- erb_compiler = Yalphabetize::ErbCompiler.new
26
- erb_compiler.compile(file)
27
-
28
- erb_compiler.content.each do |interpolation|
29
- uuid = SecureRandom.uuid
30
- file.sub!(interpolation, uuid)
31
- interpolations_mapping[uuid] = interpolation
32
- end
33
- end
34
-
35
19
  def file
36
20
  @_file ||= File.read(path)
37
21
  end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'psych'
4
+
5
+ module Yalphabetize
6
+ class SequenceIndenter
7
+ def self.call(content)
8
+ new(content).call
9
+ end
10
+
11
+ def initialize(content)
12
+ @content = content
13
+ end
14
+
15
+ def call
16
+ return unless Yalphabetize.config['indent_sequences']
17
+
18
+ find_lines_to_indent
19
+ indent!
20
+ file_lines.join
21
+ end
22
+
23
+ private
24
+
25
+ attr_reader :content
26
+
27
+ def find_lines_to_indent
28
+ @nodes_to_indent = []
29
+
30
+ stream_node.select(&:mapping?).each do |mapping_node|
31
+ block_sequence_nodes(mapping_node)&.each do |sequence_node|
32
+ @nodes_to_indent.push(*sequence_node.children)
33
+ end
34
+ end
35
+ end
36
+
37
+ def block_sequence_nodes(node)
38
+ node.children&.select { |child_node| child_node.sequence? && child_node.style == 1 }
39
+ end
40
+
41
+ def stream_node
42
+ Psych.parse_stream content
43
+ end
44
+
45
+ def indent!
46
+ @nodes_to_indent.each do |node|
47
+ node_end_line = node.start_line == node.end_line ? node.end_line : node.end_line - 1
48
+
49
+ file_lines[node.start_line..node_end_line].each do |line|
50
+ line.gsub!(line, " #{line}")
51
+ end
52
+ end
53
+ end
54
+
55
+ def file_lines
56
+ @_file_lines ||= content.each_line.to_a
57
+ end
58
+ end
59
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Yalphabetize
4
4
  class Version
5
- STRING = '0.3.0'
5
+ STRING = '0.6.0'
6
6
  end
7
7
  end
@@ -10,9 +10,9 @@ module Yalphabetize
10
10
  end
11
11
 
12
12
  def call
13
- File.open(path, 'w') do |file|
14
- file.write new_file_content
15
- end
13
+ indent_sequences
14
+
15
+ File.write(path, new_file_content)
16
16
  end
17
17
 
18
18
  private
@@ -20,7 +20,11 @@ module Yalphabetize
20
20
  attr_reader :stream_node, :path
21
21
 
22
22
  def new_file_content
23
- stream_node.to_yaml nil, line_width: MAX_LINE_WIDTH
23
+ @_new_file_content ||= stream_node.to_yaml(nil, line_width: MAX_LINE_WIDTH)
24
+ end
25
+
26
+ def indent_sequences
27
+ @_new_file_content = SequenceIndenter.call(new_file_content)
24
28
  end
25
29
  end
26
30
  end
@@ -26,7 +26,7 @@ module Yalphabetize
26
26
  end
27
27
 
28
28
  def process_files
29
- file_paths.each(&method(:process_file))
29
+ file_paths.each { |file_path| process_file(file_path) }
30
30
  end
31
31
 
32
32
  def process_file(file_path)
@@ -37,38 +37,23 @@ module Yalphabetize
37
37
  logger: logger,
38
38
  autocorrect: options[:autocorrect],
39
39
  alphabetizer_class: alphabetizer_class,
40
- writer_class: writer_class
40
+ writer_class: writer_class,
41
+ order_checker_class: order_checker_class
41
42
  ).call
42
43
  end
43
44
 
44
45
  def file_paths
45
- @_file_paths ||= finder.paths(only: only_paths, exclude: excluded_paths)
46
+ @_file_paths ||= finder.paths(only: only_paths, exclude: Yalphabetize.config['exclude'])
46
47
  end
47
48
 
48
49
  def only_paths
49
50
  if args.any?
50
51
  args
51
- elsif config
52
- config['only'] || []
53
52
  else
54
- []
53
+ Yalphabetize.config['only']
55
54
  end
56
55
  end
57
56
 
58
- def excluded_paths
59
- if config
60
- config['exclude'] || []
61
- else
62
- []
63
- end
64
- end
65
-
66
- def config
67
- return unless File.exist?('.yalphabetize.yml')
68
-
69
- @_config ||= Psych.load_file('.yalphabetize.yml') || {}
70
- end
71
-
72
57
  def final_log
73
58
  logger.final_summary
74
59
  logger.offences? ? 1 : 0
@@ -101,5 +86,9 @@ module Yalphabetize
101
86
  def file_yalphabetizer_class
102
87
  Yalphabetize::FileYalphabetizer
103
88
  end
89
+
90
+ def order_checker_class
91
+ OrderCheckers::TOKEN_MAPPING[Yalphabetize.config['sort_by']]
92
+ end
104
93
  end
105
94
  end
@@ -25,7 +25,7 @@ module Yalphabetize
25
25
  process_paths(paths)
26
26
  end
27
27
 
28
- files.flatten.select(&method(:valid?)).map { |f| File.expand_path(f) }.uniq
28
+ files.flatten.select { |file| valid?(file) }.map { |f| File.expand_path(f) }.uniq
29
29
  end
30
30
 
31
31
  private
data/lib/yalphabetize.rb CHANGED
@@ -3,14 +3,44 @@
3
3
  require_relative 'yalphabetize/aliaser'
4
4
  require_relative 'yalphabetize/alphabetizer'
5
5
  require_relative 'yalphabetize/cli'
6
- require_relative 'yalphabetize/erb_compiler'
7
6
  require_relative 'yalphabetize/file_yalphabetizer'
8
7
  require_relative 'yalphabetize/logger'
9
8
  require_relative 'yalphabetize/offence_detector'
10
9
  require_relative 'yalphabetize/option_parser'
10
+ require_relative 'yalphabetize/order_checkers/base'
11
+ require_relative 'yalphabetize/order_checkers/alphabetical_then_capitalized_first'
12
+ require_relative 'yalphabetize/order_checkers/alphabetical_then_capitalized_last'
13
+ require_relative 'yalphabetize/order_checkers/capitalized_last_then_alphabetical'
14
+ require_relative 'yalphabetize/order_checkers/capitalized_first_then_alphabetical'
15
+ require_relative 'yalphabetize/order_checkers/custom'
16
+ require_relative 'yalphabetize/order_checkers'
11
17
  require_relative 'yalphabetize/parsing_error'
12
18
  require_relative 'yalphabetize/reader'
19
+ require_relative 'yalphabetize/sequence_indenter'
13
20
  require_relative 'yalphabetize/version'
14
21
  require_relative 'yalphabetize/writer'
15
22
  require_relative 'yalphabetize/yalphabetizer'
16
23
  require_relative 'yalphabetize/yaml_finder'
24
+
25
+ module Yalphabetize
26
+ class << self
27
+ DEFAULT_CONFIG = {
28
+ 'indent_sequences' => true,
29
+ 'exclude' => [],
30
+ 'only' => [],
31
+ 'sort_by' => 'ABab'
32
+ }.freeze
33
+
34
+ def config
35
+ @_config ||= begin
36
+ specified = if File.exist?('.yalphabetize.yml')
37
+ Psych.load_file('.yalphabetize.yml') || {}
38
+ else
39
+ {}
40
+ end
41
+
42
+ DEFAULT_CONFIG.merge(specified)
43
+ end
44
+ end
45
+ end
46
+ end
metadata CHANGED
@@ -1,23 +1,23 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: yalphabetize
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sam Jenkins
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-12-23 00:00:00.000000000 Z
11
+ date: 2022-02-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: psych
14
+ name: factory_bot
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: '0'
20
- type: :runtime
20
+ type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
@@ -25,7 +25,7 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: factory_bot
28
+ name: pry
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ">="
@@ -39,7 +39,7 @@ dependencies:
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
- name: pry
42
+ name: rspec
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - ">="
@@ -53,7 +53,7 @@ dependencies:
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
- name: rspec
56
+ name: rubocop
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - ">="
@@ -67,7 +67,21 @@ dependencies:
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
69
  - !ruby/object:Gem::Dependency
70
- name: rubocop
70
+ name: rubocop-performance
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rubocop-rspec
71
85
  requirement: !ruby/object:Gem::Requirement
72
86
  requirements:
73
87
  - - ">="
@@ -94,8 +108,8 @@ dependencies:
94
108
  - - ">="
95
109
  - !ruby/object:Gem::Version
96
110
  version: '0'
97
- description:
98
- email:
111
+ description:
112
+ email:
99
113
  executables:
100
114
  - yalphabetize
101
115
  extensions: []
@@ -106,22 +120,29 @@ files:
106
120
  - lib/yalphabetize/aliaser.rb
107
121
  - lib/yalphabetize/alphabetizer.rb
108
122
  - lib/yalphabetize/cli.rb
109
- - lib/yalphabetize/erb_compiler.rb
110
123
  - lib/yalphabetize/file_yalphabetizer.rb
111
124
  - lib/yalphabetize/logger.rb
112
125
  - lib/yalphabetize/offence_detector.rb
113
126
  - lib/yalphabetize/option_parser.rb
127
+ - lib/yalphabetize/order_checkers.rb
128
+ - lib/yalphabetize/order_checkers/alphabetical_then_capitalized_first.rb
129
+ - lib/yalphabetize/order_checkers/alphabetical_then_capitalized_last.rb
130
+ - lib/yalphabetize/order_checkers/base.rb
131
+ - lib/yalphabetize/order_checkers/capitalized_first_then_alphabetical.rb
132
+ - lib/yalphabetize/order_checkers/capitalized_last_then_alphabetical.rb
133
+ - lib/yalphabetize/order_checkers/custom.rb
114
134
  - lib/yalphabetize/parsing_error.rb
115
135
  - lib/yalphabetize/reader.rb
136
+ - lib/yalphabetize/sequence_indenter.rb
116
137
  - lib/yalphabetize/version.rb
117
138
  - lib/yalphabetize/writer.rb
118
139
  - lib/yalphabetize/yalphabetizer.rb
119
140
  - lib/yalphabetize/yaml_finder.rb
120
- homepage:
141
+ homepage:
121
142
  licenses: []
122
143
  metadata:
123
144
  rubygems_mfa_required: 'true'
124
- post_install_message:
145
+ post_install_message:
125
146
  rdoc_options: []
126
147
  require_paths:
127
148
  - lib
@@ -137,7 +158,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
137
158
  version: '0'
138
159
  requirements: []
139
160
  rubygems_version: 3.0.3.1
140
- signing_key:
161
+ signing_key:
141
162
  specification_version: 4
142
163
  summary: Alphabetize your YAML files
143
164
  test_files: []
@@ -1,82 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Inspired by ERB::Compiler (https://github.com/ruby/erb/blob/b58b188028fbb403f75d48d62717373fc0908f7a/lib/erb.rb)
4
-
5
- module Yalphabetize
6
- class ErbCompiler
7
- DEFAULT_STAGS = ['<%%', '<%=', '<%#', '<%', '%{', '{{'].freeze
8
- DEFAULT_ETAGS = ['%%>', '%>', '}}', '}'].freeze
9
-
10
- class Scanner
11
- STAG_REG = /(.*?)(#{DEFAULT_STAGS.join('|')}|\z)/m.freeze
12
- ETAG_REG = /(.*?)(#{DEFAULT_ETAGS.join('|')}|\z)/m.freeze
13
-
14
- def initialize(src)
15
- @src = src
16
- @stag = nil
17
- end
18
-
19
- def scan
20
- until scanner.eos?
21
- scanner.scan(stag ? ETAG_REG : STAG_REG)
22
- yield(scanner[1])
23
- yield(scanner[2])
24
- end
25
- end
26
-
27
- attr_accessor :stag
28
-
29
- private
30
-
31
- attr_reader :src
32
-
33
- def scanner
34
- @_scanner ||= StringScanner.new(src)
35
- end
36
- end
37
-
38
- def initialize
39
- @buffer = []
40
- @content = []
41
- end
42
-
43
- def compile(string)
44
- scanner = Scanner.new(string)
45
- scanner.scan do |token|
46
- next if token.nil?
47
- next if token == ''
48
-
49
- if scanner.stag.nil?
50
- compile_stag(token, scanner)
51
- else
52
- compile_etag(token, scanner)
53
- end
54
- end
55
- end
56
-
57
- def compile_stag(stag, scanner)
58
- case stag
59
- when *DEFAULT_STAGS
60
- scanner.stag = stag
61
- buffer << stag
62
- end
63
- end
64
-
65
- def compile_etag(etag, scanner)
66
- buffer << etag
67
-
68
- case etag
69
- when *DEFAULT_ETAGS
70
- content << buffer.join
71
- self.buffer = []
72
- scanner.stag = nil
73
- end
74
- end
75
-
76
- attr_reader :content
77
-
78
- private
79
-
80
- attr_accessor :buffer
81
- end
82
- end