redmine_api_helper 0.3.24
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.
Potentially problematic release.
This version of redmine_api_helper might be problematic. Click here for more details.
- checksums.yaml +7 -0
- data/.gitattributes +2 -0
- data/.gitignore +11 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +6 -0
- data/LICENSE +339 -0
- data/README.md +30 -0
- data/Rakefile +2 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/date_helper/date.rb +311 -0
- data/lib/odf_writer/bookmark.rb +110 -0
- data/lib/odf_writer/bookmark_reader.rb +77 -0
- data/lib/odf_writer/document.rb +372 -0
- data/lib/odf_writer/field.rb +174 -0
- data/lib/odf_writer/field_reader.rb +78 -0
- data/lib/odf_writer/image.rb +158 -0
- data/lib/odf_writer/image_reader.rb +76 -0
- data/lib/odf_writer/images.rb +89 -0
- data/lib/odf_writer/list_style.rb +331 -0
- data/lib/odf_writer/nested.rb +156 -0
- data/lib/odf_writer/odf_helper.rb +56 -0
- data/lib/odf_writer/parser/default.rb +685 -0
- data/lib/odf_writer/path_finder.rb +114 -0
- data/lib/odf_writer/section.rb +120 -0
- data/lib/odf_writer/section_reader.rb +61 -0
- data/lib/odf_writer/style.rb +417 -0
- data/lib/odf_writer/table.rb +135 -0
- data/lib/odf_writer/table_reader.rb +61 -0
- data/lib/odf_writer/template.rb +222 -0
- data/lib/odf_writer/text.rb +97 -0
- data/lib/odf_writer/text_reader.rb +77 -0
- data/lib/odf_writer/version.rb +29 -0
- data/lib/redmine_api_helper/api_helper.rb +333 -0
- data/lib/redmine_api_helper/args_helper.rb +106 -0
- data/lib/redmine_api_helper/attachments_api_helper.rb +52 -0
- data/lib/redmine_api_helper/define_api_helpers.rb +78 -0
- data/lib/redmine_api_helper/document_categories_api_helper.rb +38 -0
- data/lib/redmine_api_helper/groups_api_helper.rb +80 -0
- data/lib/redmine_api_helper/helpers.rb +50 -0
- data/lib/redmine_api_helper/issue_priorities_api_helper.rb +38 -0
- data/lib/redmine_api_helper/issue_relations_api_helper.rb +66 -0
- data/lib/redmine_api_helper/issue_statuses_api_helper.rb +36 -0
- data/lib/redmine_api_helper/issues_api_helper.rb +124 -0
- data/lib/redmine_api_helper/my_account_api_helper.rb +45 -0
- data/lib/redmine_api_helper/news_api_helper.rb +73 -0
- data/lib/redmine_api_helper/project_memberships_api_helper.rb +77 -0
- data/lib/redmine_api_helper/projects_api_helper.rb +73 -0
- data/lib/redmine_api_helper/roles_api_helper.rb +52 -0
- data/lib/redmine_api_helper/scripts_api_helper.rb +87 -0
- data/lib/redmine_api_helper/search_api_helper.rb +38 -0
- data/lib/redmine_api_helper/time_entries_api_helper.rb +73 -0
- data/lib/redmine_api_helper/time_entry_activities_api_helper.rb +38 -0
- data/lib/redmine_api_helper/trackers_api_helper.rb +38 -0
- data/lib/redmine_api_helper/users_api_helper.rb +73 -0
- data/lib/redmine_api_helper/version.rb +24 -0
- data/lib/redmine_api_helper/wiki_pages_api_helper.rb +66 -0
- data/lib/redmine_api_helper.rb +88 -0
- data/redmine_api_helper.gemspec +35 -0
- metadata +148 -0
@@ -0,0 +1,135 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
# Ruby Gem to create a self populating Open Document Format (.odf) text file.
|
4
|
+
#
|
5
|
+
# Copyright 2021 Stephan Wenzel <stephan.wenzel@drwpatent.de>
|
6
|
+
#
|
7
|
+
# This program is free software; you can redistribute it and/or
|
8
|
+
# modify it under the terms of the GNU General Public License
|
9
|
+
# as published by the Free Software Foundation; either version 2
|
10
|
+
# of the License, or (at your option) any later version.
|
11
|
+
#
|
12
|
+
# This program is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
# GNU General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU General Public License
|
18
|
+
# along with this program; if not, write to the Free Software
|
19
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
20
|
+
#
|
21
|
+
|
22
|
+
module ODFWriter
|
23
|
+
|
24
|
+
########################################################################################
|
25
|
+
#
|
26
|
+
# Table: poulate and grow tables
|
27
|
+
#
|
28
|
+
########################################################################################
|
29
|
+
class Table
|
30
|
+
|
31
|
+
include Nested
|
32
|
+
|
33
|
+
attr_accessor :name, :collection, :proc
|
34
|
+
|
35
|
+
######################################################################################
|
36
|
+
#
|
37
|
+
# initialize
|
38
|
+
#
|
39
|
+
######################################################################################
|
40
|
+
def initialize(options)
|
41
|
+
@name = options[:name]
|
42
|
+
@field = options[:field]
|
43
|
+
@collection = options[:collection]
|
44
|
+
@proc = options[:proc]
|
45
|
+
@key = @field || @name
|
46
|
+
|
47
|
+
@fields = []
|
48
|
+
@texts = []
|
49
|
+
@tables = []
|
50
|
+
@images = []
|
51
|
+
@bookmarks = []
|
52
|
+
|
53
|
+
@template_rows = []
|
54
|
+
@header = options[:header] || false
|
55
|
+
@skip_if_empty = options[:skip_if_empty] || false
|
56
|
+
|
57
|
+
end #def
|
58
|
+
|
59
|
+
######################################################################################
|
60
|
+
#
|
61
|
+
# replace!
|
62
|
+
#
|
63
|
+
######################################################################################
|
64
|
+
def replace!(doc, manifest, file, row = nil)
|
65
|
+
|
66
|
+
return unless table = find_table_node(doc)
|
67
|
+
|
68
|
+
@template_rows = table.xpath("table:table-row")
|
69
|
+
|
70
|
+
@header = table.xpath("table:table-header-rows").empty? ? @header : false
|
71
|
+
|
72
|
+
@collection = items(row, @key, @proc) if row
|
73
|
+
|
74
|
+
if @skip_if_empty && @collection.empty?
|
75
|
+
table.remove
|
76
|
+
return
|
77
|
+
end
|
78
|
+
|
79
|
+
@collection.each do |item|
|
80
|
+
|
81
|
+
new_node = get_next_row
|
82
|
+
#
|
83
|
+
# experimental: new node must be added to doc prior to replace!
|
84
|
+
# else new_section does not have a name space
|
85
|
+
#
|
86
|
+
table.add_child(new_node)
|
87
|
+
|
88
|
+
@tables.each { |t| t.replace!(new_node, manifest, file, item) }
|
89
|
+
@texts.each { |t| t.replace!(new_node, item) }
|
90
|
+
@fields.each { |f| f.replace!(new_node, item) }
|
91
|
+
@images.each { |f| f.replace!(new_node, manifest, file, item) }
|
92
|
+
|
93
|
+
end
|
94
|
+
Image.unique_image_names( doc) if @images.present?
|
95
|
+
|
96
|
+
@template_rows.each_with_index do |r, i|
|
97
|
+
r.remove if (get_start_node..template_length) === i
|
98
|
+
end
|
99
|
+
|
100
|
+
end #def
|
101
|
+
|
102
|
+
######################################################################################
|
103
|
+
#
|
104
|
+
# private
|
105
|
+
#
|
106
|
+
######################################################################################
|
107
|
+
private
|
108
|
+
|
109
|
+
def get_next_row
|
110
|
+
@row_cursor = get_start_node unless defined?(@row_cursor)
|
111
|
+
|
112
|
+
ret = @template_rows[@row_cursor]
|
113
|
+
if @template_rows.size == @row_cursor + 1
|
114
|
+
@row_cursor = get_start_node
|
115
|
+
else
|
116
|
+
@row_cursor += 1
|
117
|
+
end
|
118
|
+
return ret.dup
|
119
|
+
end #def
|
120
|
+
|
121
|
+
def get_start_node
|
122
|
+
@header ? 1 : 0
|
123
|
+
end #def
|
124
|
+
|
125
|
+
def template_length
|
126
|
+
@tl ||= @template_rows.size
|
127
|
+
end #def
|
128
|
+
|
129
|
+
def find_table_node(doc)
|
130
|
+
tables = doc.xpath(".//table:table[@table:name='#{@name}']")
|
131
|
+
tables.empty? ? nil : tables.first
|
132
|
+
end #def
|
133
|
+
|
134
|
+
end #class
|
135
|
+
end #module
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
# Ruby Gem to create a self populating Open Document Format (.odf) text file.
|
4
|
+
#
|
5
|
+
# Copyright 2021 Stephan Wenzel <stephan.wenzel@drwpatent.de>
|
6
|
+
#
|
7
|
+
# This program is free software; you can redistribute it and/or
|
8
|
+
# modify it under the terms of the GNU General Public License
|
9
|
+
# as published by the Free Software Foundation; either version 2
|
10
|
+
# of the License, or (at your option) any later version.
|
11
|
+
#
|
12
|
+
# This program is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
# GNU General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU General Public License
|
18
|
+
# along with this program; if not, write to the Free Software
|
19
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
20
|
+
#
|
21
|
+
|
22
|
+
module ODFWriter
|
23
|
+
|
24
|
+
########################################################################################
|
25
|
+
#
|
26
|
+
# TableReader: find all tables and set name
|
27
|
+
#
|
28
|
+
########################################################################################
|
29
|
+
class TableReader
|
30
|
+
|
31
|
+
attr_accessor :name
|
32
|
+
|
33
|
+
######################################################################################
|
34
|
+
#
|
35
|
+
# initialize
|
36
|
+
#
|
37
|
+
######################################################################################
|
38
|
+
def initialize(opts)
|
39
|
+
@name = opts[:name]
|
40
|
+
end #def
|
41
|
+
|
42
|
+
######################################################################################
|
43
|
+
#
|
44
|
+
# tables
|
45
|
+
#
|
46
|
+
######################################################################################
|
47
|
+
def tables( doc )
|
48
|
+
nodes( doc ).keys
|
49
|
+
end #def
|
50
|
+
|
51
|
+
######################################################################################
|
52
|
+
#
|
53
|
+
# nodes
|
54
|
+
#
|
55
|
+
######################################################################################
|
56
|
+
def nodes( doc )
|
57
|
+
doc.xpath(".//table:table").map{|node| [node.attr("table:name"), node] }.to_h
|
58
|
+
end #def
|
59
|
+
end #class
|
60
|
+
|
61
|
+
end #module
|
@@ -0,0 +1,222 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
# Ruby Gem to create a self populating Open Document Format (.odf) text file.
|
4
|
+
#
|
5
|
+
# Copyright 2021 Stephan Wenzel <stephan.wenzel@drwpatent.de>
|
6
|
+
#
|
7
|
+
# This program is free software; you can redistribute it and/or
|
8
|
+
# modify it under the terms of the GNU General Public License
|
9
|
+
# as published by the Free Software Foundation; either version 2
|
10
|
+
# of the License, or (at your option) any later version.
|
11
|
+
#
|
12
|
+
# This program is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
# GNU General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU General Public License
|
18
|
+
# along with this program; if not, write to the Free Software
|
19
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
20
|
+
#
|
21
|
+
|
22
|
+
module ODFWriter
|
23
|
+
|
24
|
+
########################################################################################
|
25
|
+
#
|
26
|
+
# Template: handles files in .odt-package
|
27
|
+
#
|
28
|
+
########################################################################################
|
29
|
+
class Template
|
30
|
+
|
31
|
+
######################################################################################
|
32
|
+
#
|
33
|
+
# constants - we only work and content and styles (contains headers and footers) parts of odf
|
34
|
+
#
|
35
|
+
######################################################################################
|
36
|
+
CONTENT_ENTRIES = {
|
37
|
+
"content.xml" => {:symbol => :content, :path => "content.xml"},
|
38
|
+
"styles.xml" => {:symbol => :styles, :path => "styles.xml" }
|
39
|
+
}.freeze
|
40
|
+
|
41
|
+
CONTENT_FILES = {
|
42
|
+
:content => {:file => "content.xml", :path => "content.xml"},
|
43
|
+
:styles => {:file => "styles.xml", :path => "styles.xml" }
|
44
|
+
}.freeze
|
45
|
+
|
46
|
+
MANIFEST = 'META-INF/manifest.xml'.freeze
|
47
|
+
|
48
|
+
######################################################################################
|
49
|
+
#
|
50
|
+
# accessors
|
51
|
+
#
|
52
|
+
######################################################################################
|
53
|
+
attr_accessor :output_stream
|
54
|
+
|
55
|
+
######################################################################################
|
56
|
+
#
|
57
|
+
# initialize
|
58
|
+
#
|
59
|
+
######################################################################################
|
60
|
+
def initialize(path = nil, zip_stream: nil)
|
61
|
+
|
62
|
+
raise "You must provide either a filename or a zip_stream: string" unless path || zip_stream
|
63
|
+
raise "Template [#{template}] not found." if path && !::File.exist?(path)
|
64
|
+
|
65
|
+
@path = path
|
66
|
+
@zip_stream = zip_stream
|
67
|
+
end #def
|
68
|
+
|
69
|
+
######################################################################################
|
70
|
+
#
|
71
|
+
# content
|
72
|
+
#
|
73
|
+
######################################################################################
|
74
|
+
def content(&block)
|
75
|
+
|
76
|
+
entries.each do |entry|
|
77
|
+
|
78
|
+
if entry.directory?
|
79
|
+
next
|
80
|
+
|
81
|
+
elsif CONTENT_ENTRIES.keys.include?(entry.name)
|
82
|
+
# relevant file with valid file name
|
83
|
+
entry.get_input_stream do |input_stream|
|
84
|
+
file_content = input_stream.sysread
|
85
|
+
yield CONTENT_ENTRIES[entry.name][:symbol], to_xml(file_content)
|
86
|
+
end
|
87
|
+
|
88
|
+
end #if
|
89
|
+
end #each
|
90
|
+
end #def
|
91
|
+
|
92
|
+
######################################################################################
|
93
|
+
#
|
94
|
+
# update_content: create write buffer for zip
|
95
|
+
#
|
96
|
+
######################################################################################
|
97
|
+
def update_content
|
98
|
+
@buffer = Zip::OutputStream.write_buffer do |out|
|
99
|
+
@output_stream = out
|
100
|
+
yield self
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
######################################################################################
|
105
|
+
#
|
106
|
+
# update_files: open and traverse zip directory, pick content.xml
|
107
|
+
# and styles.xml process and eventually write contents
|
108
|
+
# to buffer
|
109
|
+
# a pointer to manifest.xml is provided
|
110
|
+
#
|
111
|
+
######################################################################################
|
112
|
+
def update_files(&block)
|
113
|
+
|
114
|
+
# get manifest, in case a file is added
|
115
|
+
@manifest = manifest; digest = Digest::MD5.hexdigest(@manifest)
|
116
|
+
|
117
|
+
entries.each do |entry|
|
118
|
+
|
119
|
+
# search content files
|
120
|
+
if entry.directory?
|
121
|
+
next
|
122
|
+
|
123
|
+
# process content files
|
124
|
+
elsif CONTENT_ENTRIES.keys.include?(entry.name)
|
125
|
+
|
126
|
+
entry.get_input_stream do |input_stream|
|
127
|
+
file_content = input_stream.sysread
|
128
|
+
file_symbol = CONTENT_ENTRIES[entry.name][:symbol]
|
129
|
+
process_entry(file_symbol, file_content, @manifest, &block)
|
130
|
+
@output_stream.put_next_entry(entry.name)
|
131
|
+
@output_stream.write file_content
|
132
|
+
end #do
|
133
|
+
|
134
|
+
else
|
135
|
+
entry.get_input_stream do |input_stream|
|
136
|
+
@output_stream.put_next_entry(entry.name)
|
137
|
+
@output_stream.write input_stream.sysread
|
138
|
+
end
|
139
|
+
end #if
|
140
|
+
end #each
|
141
|
+
|
142
|
+
# eventually write back content file
|
143
|
+
if @manifest && digest != Digest::MD5.hexdigest(@manifest)
|
144
|
+
@output_stream.put_next_entry(MANIFEST)
|
145
|
+
@output_stream.write @manifest
|
146
|
+
end #if
|
147
|
+
|
148
|
+
end #def
|
149
|
+
|
150
|
+
|
151
|
+
######################################################################################
|
152
|
+
#
|
153
|
+
# data: just a handle to data in buffer
|
154
|
+
#
|
155
|
+
######################################################################################
|
156
|
+
def data
|
157
|
+
@buffer.string
|
158
|
+
end
|
159
|
+
|
160
|
+
######################################################################################
|
161
|
+
#
|
162
|
+
# private
|
163
|
+
#
|
164
|
+
######################################################################################
|
165
|
+
private
|
166
|
+
|
167
|
+
######################################################################################
|
168
|
+
# entries: just open zip file or buffer
|
169
|
+
######################################################################################
|
170
|
+
def entries
|
171
|
+
if @path
|
172
|
+
Zip::File.open(@path)
|
173
|
+
elsif @zip_stream
|
174
|
+
Zip::File.open_buffer(@zip_stream.force_encoding("ASCII-8BIT"))
|
175
|
+
end
|
176
|
+
end #def
|
177
|
+
|
178
|
+
######################################################################################
|
179
|
+
# manifest: read manifest
|
180
|
+
######################################################################################
|
181
|
+
def manifest
|
182
|
+
manifest = nil
|
183
|
+
entries.each do |entry|
|
184
|
+
next if entry.directory?
|
185
|
+
entry.get_input_stream do |input_stream|
|
186
|
+
if MANIFEST == entry.name
|
187
|
+
manifest = input_stream.sysread.dup
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
manifest
|
192
|
+
end #def
|
193
|
+
|
194
|
+
######################################################################################
|
195
|
+
# to_xml
|
196
|
+
######################################################################################
|
197
|
+
def to_xml(raw_xml)
|
198
|
+
Nokogiri::XML(raw_xml)
|
199
|
+
end #def
|
200
|
+
|
201
|
+
######################################################################################
|
202
|
+
# process_entry: provide Nokogiri Object to caller, after having provided a file
|
203
|
+
######################################################################################
|
204
|
+
def process_entry(file_symbol, file_content, manifest)
|
205
|
+
|
206
|
+
# create xml from file content
|
207
|
+
doc = to_xml(file_content ) # { |x| x.noblanks }
|
208
|
+
man = to_xml(manifest ) # { |x| x.noblanks }
|
209
|
+
|
210
|
+
# yield xml
|
211
|
+
yield file_symbol, doc, man
|
212
|
+
|
213
|
+
# replace file_content and manifest in place
|
214
|
+
# remove spurious whitespaces between tags "> <" becomes "><"
|
215
|
+
file_content.replace(doc.to_xml(save_with: Nokogiri::XML::Node::SaveOptions::AS_XML).squish.gsub(/(?<=>)\s+(?=<)/, ""))
|
216
|
+
# Microsoft Words complains if no trailing newline is present
|
217
|
+
manifest.replace(man.to_xml(save_with: Nokogiri::XML::Node::SaveOptions::AS_XML))
|
218
|
+
|
219
|
+
end #def
|
220
|
+
|
221
|
+
end #class
|
222
|
+
end #module
|
@@ -0,0 +1,97 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
# Ruby Gem to create a self populating Open Document Format (.odf) text file.
|
4
|
+
#
|
5
|
+
# Copyright 2021 Stephan Wenzel <stephan.wenzel@drwpatent.de>
|
6
|
+
#
|
7
|
+
# This program is free software; you can redistribute it and/or
|
8
|
+
# modify it under the terms of the GNU General Public License
|
9
|
+
# as published by the Free Software Foundation; either version 2
|
10
|
+
# of the License, or (at your option) any later version.
|
11
|
+
#
|
12
|
+
# This program is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
# GNU General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU General Public License
|
18
|
+
# along with this program; if not, write to the Free Software
|
19
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
20
|
+
#
|
21
|
+
|
22
|
+
module ODFWriter
|
23
|
+
|
24
|
+
########################################################################################
|
25
|
+
#
|
26
|
+
# Text: replace text items
|
27
|
+
#
|
28
|
+
########################################################################################
|
29
|
+
class Text < Field
|
30
|
+
|
31
|
+
######################################################################################
|
32
|
+
#
|
33
|
+
# constants
|
34
|
+
#
|
35
|
+
######################################################################################
|
36
|
+
DELIMITERS = %w({ })
|
37
|
+
|
38
|
+
######################################################################################
|
39
|
+
#
|
40
|
+
# replace!
|
41
|
+
#
|
42
|
+
######################################################################################
|
43
|
+
def replace!(content, item = nil)
|
44
|
+
|
45
|
+
return unless node = find_text_node(content)
|
46
|
+
|
47
|
+
text = value(item)
|
48
|
+
|
49
|
+
@parser = Parser::Default.new(text, node,
|
50
|
+
:doc => content,
|
51
|
+
:remove_classes => @remove_classes,
|
52
|
+
:remove_class_prefix => @remove_class_prefix,
|
53
|
+
:remove_class_suffix => @remove_class_suffix
|
54
|
+
)
|
55
|
+
|
56
|
+
@parser.paragraphs.each do |p|
|
57
|
+
node.before(p)
|
58
|
+
end
|
59
|
+
|
60
|
+
node.remove
|
61
|
+
|
62
|
+
end #def
|
63
|
+
|
64
|
+
######################################################################################
|
65
|
+
#
|
66
|
+
# private
|
67
|
+
#
|
68
|
+
######################################################################################
|
69
|
+
private
|
70
|
+
|
71
|
+
######################################################################################
|
72
|
+
# find_text_node
|
73
|
+
######################################################################################
|
74
|
+
def find_text_node(doc)
|
75
|
+
texts = doc.xpath(".//text:p[text()='#{placeholder}']")
|
76
|
+
if texts.empty?
|
77
|
+
texts = doc.xpath(".//text:p/text:span[text()='#{placeholder}']")
|
78
|
+
if texts.empty?
|
79
|
+
texts = nil
|
80
|
+
else
|
81
|
+
texts = texts.first.parent
|
82
|
+
end
|
83
|
+
else
|
84
|
+
texts = texts.first
|
85
|
+
end
|
86
|
+
|
87
|
+
texts
|
88
|
+
end #def
|
89
|
+
|
90
|
+
######################################################################################
|
91
|
+
# placeholder
|
92
|
+
######################################################################################
|
93
|
+
def placeholder
|
94
|
+
"#{DELIMITERS[0]}#{@name.to_s.upcase}#{DELIMITERS[1]}"
|
95
|
+
end #def
|
96
|
+
end #class
|
97
|
+
end #module
|