yalphabetize 0.3.0 → 0.6.0

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