ad_hoc_template 0.2.0 → 0.3.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 +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
|