ad_hoc_template 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/lib/ad_hoc_template.rb +24 -3
- data/lib/ad_hoc_template/command_line_interface.rb +27 -11
- data/lib/ad_hoc_template/entry_format_generator.rb +49 -0
- data/lib/ad_hoc_template/parser.rb +127 -58
- data/lib/ad_hoc_template/pseudohiki_formatter.rb +1 -1
- data/lib/ad_hoc_template/record_reader.rb +294 -160
- data/lib/ad_hoc_template/version.rb +1 -1
- data/spec/ad_hoc_template_spec.rb +151 -5
- data/spec/command_line_interface_spec.rb +107 -7
- data/spec/entry_format_generator_spec.rb +163 -0
- data/spec/parser_spec.rb +114 -18
- data/spec/pseudohiki_formatter_spec.rb +2 -2
- data/spec/record_reader_spec.rb +253 -9
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a41e80d33bd430c264ac2704bf7850baf3bcebc7
|
4
|
+
data.tar.gz: f10b0463f915e33987e5ac04e4928737eba11fc2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0b423fd73c6d59c11975fadddccdf56697a15f9784510277b23c4011c66b0d235b111285201ca24659c72b1456294990939a172bfd8998e86a441c57e16ac426
|
7
|
+
data.tar.gz: bfb7de0f42fd16cba6e2c75ee0e2d7764c86cd2e4d135e38f1cc05cc271b9dc45681a351ddc84d68175d85c6019df23c99b94202efc650f981ce2b1063a56f10
|
data/README.md
CHANGED
data/lib/ad_hoc_template.rb
CHANGED
@@ -3,6 +3,7 @@ require "ad_hoc_template/parser"
|
|
3
3
|
require "ad_hoc_template/record_reader"
|
4
4
|
require "ad_hoc_template/default_tag_formatter"
|
5
5
|
require "ad_hoc_template/pseudohiki_formatter"
|
6
|
+
require "ad_hoc_template/entry_format_generator"
|
6
7
|
|
7
8
|
module AdHocTemplate
|
8
9
|
class DataLoader
|
@@ -29,6 +30,8 @@ module AdHocTemplate
|
|
29
30
|
case tree
|
30
31
|
when Parser::IterationTagNode
|
31
32
|
format_iteration_tag(tree)
|
33
|
+
when Parser::FallbackTagNode
|
34
|
+
''.freeze
|
32
35
|
when Parser::TagNode
|
33
36
|
format_tag(tree)
|
34
37
|
when Parser::Leaf
|
@@ -40,12 +43,15 @@ module AdHocTemplate
|
|
40
43
|
|
41
44
|
def format_iteration_tag(tag_node)
|
42
45
|
sub_records = @record[tag_node.type]||[@record]
|
43
|
-
tag_node =
|
46
|
+
tag_node = cast(tag_node)
|
47
|
+
fallback_nodes = tag_node.select {|sub_node| sub_node.kind_of? Parser::FallbackTagNode }
|
44
48
|
|
45
49
|
sub_records.map do |record|
|
46
50
|
if tag_node.contains_any_value_assigned_tag_node?(record)
|
47
51
|
data_loader = AdHocTemplate::DataLoader.new(record, @tag_formatter)
|
48
52
|
tag_node.map {|leaf| leaf.accept(data_loader) }.join
|
53
|
+
elsif not fallback_nodes.empty?
|
54
|
+
format_fallback_tags(fallback_nodes, record)
|
49
55
|
else
|
50
56
|
"".freeze
|
51
57
|
end
|
@@ -60,10 +66,25 @@ module AdHocTemplate
|
|
60
66
|
def format(tree)
|
61
67
|
tree.accept(self).join
|
62
68
|
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
def cast(node, node_type=Parser::TagNode)
|
73
|
+
node_type.new.concat(node.clone)
|
74
|
+
end
|
75
|
+
|
76
|
+
def format_fallback_tags(fallback_nodes, record)
|
77
|
+
data_loader = AdHocTemplate::DataLoader.new(record, @tag_formatter)
|
78
|
+
fallback_nodes = fallback_nodes.map {|node| cast(node, Parser::IterationTagNode) }
|
79
|
+
fallback_nodes = cast(fallback_nodes)
|
80
|
+
fallback_nodes.map do |node|
|
81
|
+
node.contains_any_value_tag? ? node.accept(data_loader) : node.join
|
82
|
+
end
|
83
|
+
end
|
63
84
|
end
|
64
85
|
|
65
|
-
def self.
|
66
|
-
|
86
|
+
def self.render(record_data, template, tag_type=:default, data_format=:default,
|
87
|
+
tag_formatter=DefaultTagFormatter.new)
|
67
88
|
tree = Parser.parse(template, tag_type)
|
68
89
|
record = RecordReader.read_record(record_data, data_format)
|
69
90
|
DataLoader.format(tree, record, tag_formatter)
|
@@ -6,6 +6,7 @@ require 'optparse_plus'
|
|
6
6
|
module AdHocTemplate
|
7
7
|
class CommandLineInterface
|
8
8
|
attr_accessor :output_filename, :template_data, :record_data, :tag_type, :data_format
|
9
|
+
attr_writer :output_empty_entry
|
9
10
|
|
10
11
|
TAG_RE_TO_TYPE = {
|
11
12
|
/\Ad(efault)?/i => :default,
|
@@ -13,6 +14,7 @@ module AdHocTemplate
|
|
13
14
|
/\As(quare_brackets)?/i => :square_brackets,
|
14
15
|
/\Axml_like1/i => :xml_like1,
|
15
16
|
/\Axml_like2/i => :xml_like2,
|
17
|
+
/\Axml_comment_like/i => :xml_comment_like,
|
16
18
|
}
|
17
19
|
|
18
20
|
FORMAT_RE_TO_FORMAT = {
|
@@ -47,6 +49,7 @@ module AdHocTemplate
|
|
47
49
|
opt.on(:tag_type) {|given_type| choose_tag_type(given_type) }
|
48
50
|
opt.on(:data_format) {|data_format| choose_data_format(data_format) }
|
49
51
|
opt.on(:tag_config) {|tag_config_yaml| register_user_defined_tag_type(tag_config_yaml) }
|
52
|
+
opt.on(:entry_format) {|entry_format| @output_empty_entry = true }
|
50
53
|
|
51
54
|
opt.parse!
|
52
55
|
end
|
@@ -68,11 +71,16 @@ module AdHocTemplate
|
|
68
71
|
@record_data = record ? File.read(record) : ARGF.read
|
69
72
|
end
|
70
73
|
|
71
|
-
def
|
72
|
-
AdHocTemplate.
|
74
|
+
def render
|
75
|
+
AdHocTemplate.render(@record_data, @template_data, @tag_type,
|
73
76
|
@data_format, @tag_formatter)
|
74
77
|
end
|
75
78
|
|
79
|
+
def generate_entry_format
|
80
|
+
tree = Parser.parse(@template_data, @tag_type)
|
81
|
+
EntryFormatGenerator.extract_labels(tree, @data_format)
|
82
|
+
end
|
83
|
+
|
76
84
|
def open_output
|
77
85
|
if @output_filename
|
78
86
|
open(@output_filename, "wb") do |out|
|
@@ -86,22 +94,26 @@ module AdHocTemplate
|
|
86
94
|
def execute
|
87
95
|
parse_command_line_options
|
88
96
|
read_input_files
|
89
|
-
|
97
|
+
output = @output_empty_entry ? generate_entry_format : render
|
98
|
+
open_output {|out| out.print output }
|
90
99
|
end
|
91
100
|
|
92
101
|
private
|
93
102
|
|
94
103
|
def choose_tag_type(given_type)
|
95
|
-
|
96
|
-
|
104
|
+
err_msg = "The given type is not found. The default tag is chosen."
|
105
|
+
|
106
|
+
if_any_regex_match(TAG_RE_TO_TYPE, given_type, err_msg) do |re, tag_type|
|
97
107
|
@tag_type = tag_type
|
98
108
|
end
|
99
109
|
end
|
100
110
|
|
101
111
|
def choose_data_format(data_format)
|
102
|
-
|
103
|
-
|
104
|
-
|
112
|
+
err_msg = "The given format is not found. The default format is chosen."
|
113
|
+
format_part, label_part = data_format.split(/:/, 2)
|
114
|
+
|
115
|
+
if_any_regex_match(FORMAT_RE_TO_FORMAT, format_part, err_msg) do |re, format|
|
116
|
+
@data_format = [:csv, :tsv].include?(format) ? make_csv_option(label_part, format) : format
|
105
117
|
end
|
106
118
|
end
|
107
119
|
|
@@ -110,9 +122,9 @@ module AdHocTemplate
|
|
110
122
|
@tag_type = Parser.register_user_defined_tag_type(config)
|
111
123
|
end
|
112
124
|
|
113
|
-
def make_csv_option(
|
114
|
-
iteration_label
|
115
|
-
|
125
|
+
def make_csv_option(iteration_label, format)
|
126
|
+
return format if iteration_label.nil? or iteration_label.empty?
|
127
|
+
{ format => iteration_label }
|
116
128
|
end
|
117
129
|
|
118
130
|
def guess_file_format(filename)
|
@@ -151,3 +163,7 @@ tag_config:
|
|
151
163
|
short: "-u [tag_config.yaml]"
|
152
164
|
long: "--user-defined-tag [=tag_config.yaml]"
|
153
165
|
description: "Configure a user-defined tag. The configuration file is in YAML format."
|
166
|
+
entry_format:
|
167
|
+
short: "-e"
|
168
|
+
long: "--entry-format"
|
169
|
+
description: "Extract tag labels from a template and generate an empty data entry format"
|
@@ -0,0 +1,49 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
module AdHocTemplate
|
4
|
+
module EntryFormatGenerator
|
5
|
+
class LabelChecker
|
6
|
+
attr_reader :labels
|
7
|
+
def initialize
|
8
|
+
@labels = {}
|
9
|
+
end
|
10
|
+
|
11
|
+
def visit(tree)
|
12
|
+
case tree
|
13
|
+
when Parser::IterationTagNode, Parser::FallbackTagNode
|
14
|
+
visit_iteration_tag_node(tree)
|
15
|
+
when Parser::TagNode
|
16
|
+
@labels[tree.join.strip] = nil
|
17
|
+
when Parser::Node
|
18
|
+
tree.each {|node| node.accept(self) }
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def visit_iteration_tag_node(tree)
|
25
|
+
if iteration_label = tree.type
|
26
|
+
sub_checker = self.class.new
|
27
|
+
@labels[iteration_label] = [sub_checker.labels]
|
28
|
+
tree.each { |node| node.accept(sub_checker) }
|
29
|
+
else
|
30
|
+
tree.each {|node| node.accept(self) }
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.extract_labels(parsed_template, target_format=nil)
|
36
|
+
labels = extract_labels_as_ruby_objects(parsed_template)
|
37
|
+
|
38
|
+
RecordReader.dump(labels, target_format)
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.extract_labels_as_ruby_objects(parsed_template)
|
42
|
+
label_checker = LabelChecker.new
|
43
|
+
parsed_template.accept(label_checker)
|
44
|
+
label_checker.labels
|
45
|
+
end
|
46
|
+
|
47
|
+
private_class_method :extract_labels_as_ruby_objects
|
48
|
+
end
|
49
|
+
end
|
@@ -4,30 +4,19 @@ require "pseudohiki/inlineparser"
|
|
4
4
|
require "htmlelement"
|
5
5
|
|
6
6
|
module AdHocTemplate
|
7
|
+
LINE_END_RE = /(?:\r?\n|\r)/
|
8
|
+
LINE_END_STR = '(?:\r?\n|\r)'
|
9
|
+
|
7
10
|
class Parser < TreeStack
|
8
11
|
class TagNode < Parser::Node
|
9
12
|
attr_reader :type
|
10
13
|
|
11
14
|
def push(node=TreeStack::Node.new)
|
12
|
-
|
15
|
+
first_leaf = node[0]
|
16
|
+
node[0] = assign_value_to_type(first_leaf) if empty? and first_leaf
|
13
17
|
super
|
14
18
|
end
|
15
19
|
|
16
|
-
def assign_type(first_leaf)
|
17
|
-
if not first_leaf.kind_of? String or /\A\s/ =~ first_leaf
|
18
|
-
return first_leaf.sub(/\A(?:\r?\n|\r)/, "")
|
19
|
-
end
|
20
|
-
@type, first_leaf_content = split_by_newline_or_spaces(first_leaf)
|
21
|
-
@type = '#'.freeze + @type if kind_of? IterationTagNode
|
22
|
-
first_leaf_content||""
|
23
|
-
end
|
24
|
-
|
25
|
-
def split_by_newline_or_spaces(first_leaf)
|
26
|
-
sep = /\A\S*(?:\r?\n|\r)/ =~ first_leaf ? /(?:\r?\n|\r)/ : /\s+/
|
27
|
-
first_leaf.split(sep, 2)
|
28
|
-
end
|
29
|
-
private :assign_type, :split_by_newline_or_spaces
|
30
|
-
|
31
20
|
def contains_any_value_assigned_tag_node?(record)
|
32
21
|
self.select {|n| n.kind_of?(TagNode) }.each do |node|
|
33
22
|
if node.kind_of? IterationTagNode
|
@@ -40,8 +29,33 @@ module AdHocTemplate
|
|
40
29
|
false
|
41
30
|
end
|
42
31
|
|
32
|
+
def contains_any_value_tag?
|
33
|
+
select {|n| n.kind_of?(TagNode) }.each do |node|
|
34
|
+
case node
|
35
|
+
when IterationTagNode, FallbackTagNode
|
36
|
+
return node.contains_any_value_tag?
|
37
|
+
when TagNode
|
38
|
+
return true
|
39
|
+
end
|
40
|
+
end
|
41
|
+
false
|
42
|
+
end
|
43
|
+
|
43
44
|
private
|
44
45
|
|
46
|
+
def assign_value_to_type(first_leaf)
|
47
|
+
if first_leaf.kind_of? String and /\A\s/ =~ first_leaf
|
48
|
+
return first_leaf.sub(/\A#{LINE_END_STR}/, "")
|
49
|
+
end
|
50
|
+
@type, first_leaf_content = split_by_newline_or_spaces(first_leaf)
|
51
|
+
first_leaf_content||""
|
52
|
+
end
|
53
|
+
|
54
|
+
def split_by_newline_or_spaces(first_leaf)
|
55
|
+
sep = /\A\S*#{LINE_END_STR}/ =~ first_leaf ? LINE_END_RE : /\s+/
|
56
|
+
first_leaf.split(sep, 2)
|
57
|
+
end
|
58
|
+
|
45
59
|
def empty_sub_records?(record, node)
|
46
60
|
sub_records = record[node.type]
|
47
61
|
return true if sub_records.nil? or sub_records.empty?
|
@@ -53,18 +67,40 @@ module AdHocTemplate
|
|
53
67
|
def any_value_assigned_to_iteration_tag?(tag_node, record)
|
54
68
|
if tag_node.type
|
55
69
|
not empty_sub_records?(record, tag_node)
|
70
|
+
elsif tag_node.kind_of? FallbackTagNode
|
71
|
+
false
|
56
72
|
else
|
57
73
|
tag_node.contains_any_value_assigned_tag_node?(record)
|
58
74
|
end
|
59
75
|
end
|
60
76
|
end
|
61
77
|
|
62
|
-
class IterationTagNode < TagNode
|
78
|
+
class IterationTagNode < TagNode
|
79
|
+
def assign_value_to_type(first_leaf)
|
80
|
+
return first_leaf unless first_leaf.kind_of? String
|
81
|
+
|
82
|
+
if /\A[^\s:]*:\s/ =~ first_leaf
|
83
|
+
@type, remaining_part = first_leaf.split(/:\s/, 2)
|
84
|
+
@type = @type.empty? ? nil : '#'.freeze + @type
|
85
|
+
return remaining_part
|
86
|
+
end
|
87
|
+
|
88
|
+
first_leaf.sub(/\A#{LINE_END_STR}/, '')
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
class FallbackTagNode < TagNode
|
93
|
+
def assign_value_to_type(first_leaf)
|
94
|
+
return first_leaf unless first_leaf.kind_of? String
|
95
|
+
first_leaf.sub(/\A#{LINE_END_STR}/, '')
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
63
99
|
class Leaf < Parser::Leaf; end
|
64
100
|
|
65
101
|
class TagType
|
66
102
|
attr_reader :head, :tail, :token_pat, :remove_iteration_indent
|
67
|
-
attr_reader :
|
103
|
+
attr_reader :head_of, :tail_of
|
68
104
|
@types = {}
|
69
105
|
|
70
106
|
def self.[](tag_name)
|
@@ -72,72 +108,111 @@ module AdHocTemplate
|
|
72
108
|
end
|
73
109
|
|
74
110
|
def self.register(tag_name=:default, tag=["<%", "%>"], iteration_tag=["<%#", "#%>"],
|
75
|
-
remove_iteration_indent=false)
|
76
|
-
@types[tag_name] = new(tag, iteration_tag, remove_iteration_indent)
|
111
|
+
fallback_tag=["<%*", "*%>"], remove_iteration_indent=false)
|
112
|
+
@types[tag_name] = new(tag, iteration_tag, fallback_tag, remove_iteration_indent)
|
77
113
|
end
|
78
114
|
|
79
|
-
def initialize(tag, iteration_tag, remove_iteration_indent)
|
80
|
-
assign_type(tag, iteration_tag)
|
115
|
+
def initialize(tag, iteration_tag, fallback_tag, remove_iteration_indent)
|
116
|
+
assign_type(tag, iteration_tag, fallback_tag)
|
81
117
|
@token_pat = PseudoHiki.compile_token_pat(@head.keys, @tail.keys)
|
82
118
|
@remove_iteration_indent = remove_iteration_indent
|
83
119
|
end
|
84
120
|
|
85
|
-
def assign_type(tag, iteration_tag)
|
86
|
-
|
87
|
-
@head, @tail = {}, {}
|
88
|
-
[
|
121
|
+
def assign_type(tag, iteration_tag, fallback_tag)
|
122
|
+
node_tag_pairs = [
|
89
123
|
[TagNode, tag],
|
90
|
-
[IterationTagNode, iteration_tag]
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
124
|
+
[IterationTagNode, iteration_tag],
|
125
|
+
[FallbackTagNode, fallback_tag]
|
126
|
+
]
|
127
|
+
|
128
|
+
setup_attributes(node_tag_pairs)
|
129
|
+
end
|
130
|
+
|
131
|
+
private
|
132
|
+
|
133
|
+
def setup_attributes(node_tag_pairs)
|
134
|
+
@head, @tail, @head_of, @tail_of = {}, {}, {}, {}
|
135
|
+
|
136
|
+
node_tag_pairs.each do |node, tag|
|
137
|
+
head, tail = tag
|
138
|
+
@head[head] = node
|
139
|
+
@tail[tail] = node
|
140
|
+
@head_of[node] = head
|
141
|
+
@tail_of[node] = tail
|
95
142
|
end
|
96
143
|
end
|
97
144
|
|
98
145
|
register
|
99
|
-
register(:square_brackets, ["[[", "]]"], ["[[#", "#]]"])
|
100
|
-
register(:curly_brackets, ["{{", "}}"], ["{{#", "#}}"])
|
101
|
-
register(:xml_like1, ["<!--%", "%-->"], ["<iterate>", "</iterate>"], true)
|
102
|
-
register(:xml_like2, ["<fill>", "</fill>"], ["<iterate>", "</iterate>"], true)
|
103
|
-
register(:xml_comment_like, ["<!--%", "%-->"], ["<!--%iterate%-->", "<!--%/iterate%-->"], true)
|
146
|
+
register(:square_brackets, ["[[", "]]"], ["[[#", "#]]"], ["[[*", "*]]"])
|
147
|
+
register(:curly_brackets, ["{{", "}}"], ["{{#", "#}}"], ["{{*", "*}}"])
|
148
|
+
register(:xml_like1, ["<!--%", "%-->"], ["<iterate>", "</iterate>"], ["<fallback>", "</fallback>"], true)
|
149
|
+
register(:xml_like2, ["<fill>", "</fill>"], ["<iterate>", "</iterate>"], ["<fallback>", "</fallback>"], true)
|
150
|
+
register(:xml_comment_like, ["<!--%", "%-->"], ["<!--%iterate%-->", "<!--%/iterate%-->"], ["<!--%fallback%-->", "<!--%/fallback%-->"], true)
|
104
151
|
end
|
105
152
|
|
106
153
|
class UserDefinedTagTypeConfigError < StandardError; end
|
107
154
|
|
108
155
|
def self.parse(str, tag_name=:default)
|
109
|
-
|
110
|
-
str = remove_indent_before_iteration_tags(str, TagType[tag_name])
|
111
|
-
end
|
156
|
+
str = remove_indents_and_newlines_if_necessary(str, tag_name)
|
112
157
|
new(str, TagType[tag_name]).parse.tree
|
113
158
|
end
|
114
159
|
|
115
|
-
def self.remove_indent_before_iteration_tags(template_source, tag_type)
|
116
|
-
start_tag, end_tag = [
|
117
|
-
tag_type.iteration_start,
|
118
|
-
tag_type.iteration_end
|
119
|
-
].map {|tag| Regexp.escape(tag) }
|
120
|
-
template_source.gsub(/^([ \t]+#{start_tag}\S*(?:\r?\n|\r))/) {|s| s.lstrip }
|
121
|
-
.gsub(/^([ \t]+#{end_tag}(?:\r?\n|\r))/) {|s| s.lstrip }
|
122
|
-
end
|
123
|
-
|
124
160
|
def self.register_user_defined_tag_type(config_source)
|
125
161
|
config = YAML.load(config_source)
|
126
|
-
%w(tag_name tag iteration_tag).each do |item|
|
162
|
+
%w(tag_name tag iteration_tag fallback_tag).each do |item|
|
127
163
|
config[item] || raise(UserDefinedTagTypeConfigError,
|
128
164
|
"\"#{item}\" should be defined.")
|
129
165
|
end
|
130
166
|
TagType.register(registered_tag_name = config["tag_name"].to_sym,
|
131
167
|
config["tag"],
|
132
168
|
config["iteration_tag"],
|
169
|
+
config["fallback_tag"],
|
133
170
|
config["remove_indent"] || false)
|
134
171
|
registered_tag_name
|
135
172
|
end
|
136
173
|
|
137
|
-
def
|
174
|
+
def self.remove_indents_and_newlines_if_necessary(str, tag_name)
|
175
|
+
node_types = [IterationTagNode, FallbackTagNode]
|
176
|
+
tag_type = TagType[tag_name]
|
177
|
+
if TagType[tag_name].remove_iteration_indent
|
178
|
+
str = remove_indent_before_iteration_tags(str, tag_type)
|
179
|
+
str = remove_indent_before_fallback_tags(str, tag_type)
|
180
|
+
end
|
181
|
+
remove_trailing_newline_of_end_tags(node_types, str, tag_type)
|
182
|
+
end
|
183
|
+
|
184
|
+
def self.remove_indent_before_iteration_tags(template_source, tag_type)
|
185
|
+
start_tag, end_tag = [
|
186
|
+
tag_type.head_of[IterationTagNode],
|
187
|
+
tag_type.tail_of[IterationTagNode],
|
188
|
+
].map {|tag| Regexp.escape(tag) }
|
189
|
+
template_source.gsub(/^([ \t]+#{start_tag}\S*#{LINE_END_STR})/) {|s| s.lstrip }
|
190
|
+
.gsub(/^([ \t]+#{end_tag}#{LINE_END_STR})/) {|s| s.lstrip }
|
191
|
+
end
|
192
|
+
|
193
|
+
def self.remove_indent_before_fallback_tags(template_source, tag_type)
|
194
|
+
tag_re_str = [
|
195
|
+
tag_type.head_of[FallbackTagNode],
|
196
|
+
tag_type.tail_of[FallbackTagNode],
|
197
|
+
].map {|tag| Regexp.escape(tag) }.join('|')
|
198
|
+
template_source.gsub(/^([ \t]+(?:#{tag_re_str})#{LINE_END_STR})/) {|s| s.lstrip }
|
199
|
+
end
|
200
|
+
|
201
|
+
def self.remove_trailing_newline_of_end_tags(node_types, source, tag_type)
|
202
|
+
node_types.inject(source) do |s, node_type|
|
203
|
+
end_tag = tag_type.tail_of[node_type]
|
204
|
+
s.gsub(/#{Regexp.escape(end_tag)}#{LINE_END_STR}/, end_tag)
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
private_class_method(:remove_indents_and_newlines_if_necessary,
|
209
|
+
:remove_indent_before_iteration_tags,
|
210
|
+
:remove_indent_before_fallback_tags,
|
211
|
+
:remove_trailing_newline_of_end_tags)
|
212
|
+
|
213
|
+
def initialize(source, tag)
|
138
214
|
@tag = tag
|
139
|
-
|
140
|
-
@tokens = PseudoHiki.split_into_tokens(str, @tag.token_pat)
|
215
|
+
@tokens = PseudoHiki.split_into_tokens(source, @tag.token_pat)
|
141
216
|
super()
|
142
217
|
end
|
143
218
|
|
@@ -150,11 +225,5 @@ module AdHocTemplate
|
|
150
225
|
|
151
226
|
self
|
152
227
|
end
|
153
|
-
|
154
|
-
private
|
155
|
-
|
156
|
-
def remove_trailing_newline_of_iteration_end_tag(str, iteration_end_tag)
|
157
|
-
str.gsub(/#{Regexp.escape(iteration_end_tag)}(?:\r?\n|\r)/, iteration_end_tag)
|
158
|
-
end
|
159
228
|
end
|
160
229
|
end
|