xhtml_report_generator 1.1.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +73 -0
- data/lib/xhtml_report_generator.rb +17 -10
- data/lib/xhtml_report_generator/custom.rb +120 -69
- data/lib/xhtml_report_generator/toc.js +1 -2
- data/lib/xhtml_report_generator/version.rb +1 -1
- metadata +21 -18
- checksums.yaml +0 -7
data/README.md
CHANGED
@@ -1,2 +1,75 @@
|
|
1
1
|
xhtml-report-generator
|
2
2
|
======================
|
3
|
+
|
4
|
+
This project was written to provide an easy way to create valid xhtml documents.
|
5
|
+
Usecases are the automatic creation of reports (e.g. program logs) with automatically created table of contents.
|
6
|
+
xhtml-report-generator is not a Logger replacement, since the complete document is always kept in memory and
|
7
|
+
only written to disk on demand. Hence in case of crashes the data might be lost.
|
8
|
+
|
9
|
+
|
10
|
+
Example usage
|
11
|
+
-------------
|
12
|
+
In the following you can find a quick start on how to use xhtml-report-generator.
|
13
|
+
Basically the project is built in a way that lets you supply your own methods for everything.
|
14
|
+
By default "custom.rb" is loaded through instance eval, so you can check the corresponding documentation for available methods.
|
15
|
+
|
16
|
+
Note that there is a major syntax change for "custom.rb" between version 1.x and 2.x of the gem.
|
17
|
+
Here an example for version >= 2 of this gem is provided.
|
18
|
+
|
19
|
+
Basically starting from version 2 the syntax for each method of custom.rb is unified. It accepts an hash of html attributes as argument, and the actual contents as block argument.
|
20
|
+
|
21
|
+
def method({"attribute" => "value", "attribute" => "value"}) {contents}
|
22
|
+
|
23
|
+
in addition the method naming convention was changed from camelCase to underscore to comply more with ruby conventions.
|
24
|
+
|
25
|
+
<pre>
|
26
|
+
require 'xhtml-report-generator'
|
27
|
+
|
28
|
+
gen1 = XhtmlReportGenerator::Generator.new
|
29
|
+
gen1.create_layout("Title")
|
30
|
+
gen1.heading("h1", {"class" => "bothtoc"}) {"titel"}
|
31
|
+
gen1.heading("h2") {"subtitel"}
|
32
|
+
gen1.heading("h3") {"section"}
|
33
|
+
gen1.content() {"content function: Hallo welt <br /> html test <span class=\"r\" >red span test</span>", {"class"=>"bold"}}
|
34
|
+
gen1.html("<p class="italic">html function: Hallo welt <br /> html test <span class=\"r\" >red span test</span></p>")
|
35
|
+
gen1.highlight(/Ha.*lt/)
|
36
|
+
|
37
|
+
</pre>
|
38
|
+
|
39
|
+
Changes from version 1.x to 2.x
|
40
|
+
-------------------------------
|
41
|
+
To ease with migration here is a list with the changed function names, please also check the new synopsis
|
42
|
+
|
43
|
+
XhtmlReportGenerator::Generator :
|
44
|
+
|
45
|
+
<pre>
|
46
|
+
createXhtmlDoc -> create_xhtml_document
|
47
|
+
|
48
|
+
writeToFile -> write(file=@file, mode='w')
|
49
|
+
</pre>
|
50
|
+
|
51
|
+
Custom :
|
52
|
+
|
53
|
+
<pre>
|
54
|
+
createLayout -> create_layout(title, layout=3)
|
55
|
+
|
56
|
+
setTitle -> set_title(title)
|
57
|
+
|
58
|
+
getTitle -> get_title
|
59
|
+
|
60
|
+
setCurrent! -> set_current!(xpath)
|
61
|
+
|
62
|
+
getCurrent -> get_current
|
63
|
+
|
64
|
+
highlightCaptures -> highlight_captures(regex, color="y", el = @current)
|
65
|
+
|
66
|
+
code -> code(attrs={}, &block)
|
67
|
+
|
68
|
+
content -> content(attrs={}, &block)
|
69
|
+
|
70
|
+
heading -> heading(tag_type="h1", attrs={}, &block)
|
71
|
+
|
72
|
+
headingTop -> heading_top(tag_type="h1", attrs={}, &block)
|
73
|
+
|
74
|
+
</pre>
|
75
|
+
|
@@ -9,7 +9,7 @@ module XhtmlReportGenerator
|
|
9
9
|
# This is the main generator class. It can be instanced with custom javascript, css, and ruby files to allow
|
10
10
|
# generation of arbitrary reports.
|
11
11
|
class Generator
|
12
|
-
attr_accessor :document
|
12
|
+
attr_accessor :document, :file
|
13
13
|
# @param opts [Hash] See the example for an explanation of the valid symbols
|
14
14
|
# @example Valid symbols for the opts Hash
|
15
15
|
# :jquery if specified, path to a version of jquery, that will be inlined into the html header section
|
@@ -21,9 +21,9 @@ module XhtmlReportGenerator
|
|
21
21
|
# define the default values
|
22
22
|
path = File.expand_path("../xhtml_report_generator", __FILE__)
|
23
23
|
symbols = {
|
24
|
-
:jquery
|
25
|
-
:toc
|
26
|
-
:css
|
24
|
+
:jquery => File.expand_path("jquery.js",path),
|
25
|
+
:toc => File.expand_path("toc.js",path),
|
26
|
+
:css => File.expand_path("style_template.css",path),
|
27
27
|
:css_print => File.expand_path("print_template.css",path),
|
28
28
|
:custom_rb => File.expand_path("custom.rb",path)
|
29
29
|
}
|
@@ -37,7 +37,7 @@ module XhtmlReportGenerator
|
|
37
37
|
# all existing Generator classes
|
38
38
|
instance_eval symbols[:custom_rb]
|
39
39
|
|
40
|
-
@document = Generator.
|
40
|
+
@document = Generator.create_xhtml_document("Title")
|
41
41
|
head = @document.elements["//head"]
|
42
42
|
# insert the custom css, and javascript files
|
43
43
|
style = head.add_element("style", {"type" => "text/css"})
|
@@ -56,7 +56,7 @@ module XhtmlReportGenerator
|
|
56
56
|
|
57
57
|
# Creates a minimal valid xhtml document including header title and body elements
|
58
58
|
# @param title [String] Title in the header section
|
59
|
-
def self.
|
59
|
+
def self.create_xhtml_document(title)
|
60
60
|
header = '<?xml version="1.0" encoding="UTF-8" standalone="no"?>'
|
61
61
|
header += '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">'
|
62
62
|
|
@@ -74,7 +74,7 @@ module XhtmlReportGenerator
|
|
74
74
|
# @param indent [Number] indent for child elements. defaults to 0.
|
75
75
|
def to_s(indent = 0)
|
76
76
|
output = ""
|
77
|
-
# note transitive is needed to preserve newlines in <pre> tags
|
77
|
+
# note : transitive is needed to preserve newlines in <pre> tags
|
78
78
|
# note2: the hash options syntax is supported only from ruby version >= 2.0.0 we need the old style
|
79
79
|
# for compatibility with 1.9.3
|
80
80
|
#@document.write({:output=>output, :indent=>indent, :transitive=>true})
|
@@ -82,12 +82,19 @@ module XhtmlReportGenerator
|
|
82
82
|
return output
|
83
83
|
end
|
84
84
|
|
85
|
-
#
|
86
|
-
#
|
85
|
+
# Saves the xml document to a file. If no file is given, the file which was used most recently for this Generator
|
86
|
+
# object will be overwritten.
|
87
|
+
# @param file [String] absolute or relative path to the file to which will be written. Default: last file used.
|
87
88
|
# @param mode [String] defaults to 'w', one of the file open modes that allows writing ['r+','w','w+','a','a+']
|
88
|
-
def
|
89
|
+
def write(file=@file, mode='w')
|
90
|
+
# instance variables are nil if they were never initialized
|
91
|
+
if file == nil
|
92
|
+
raise "no valid file given"
|
93
|
+
end
|
94
|
+
@file = file
|
89
95
|
File.open(file, "#{mode}:UTF-8") {|f| f.write(self.to_s)}
|
90
96
|
end
|
97
|
+
|
91
98
|
end
|
92
99
|
end
|
93
100
|
|
@@ -5,28 +5,42 @@ module Custom
|
|
5
5
|
# creates the basic page layout and sets the current Element to the main content area (middle div)
|
6
6
|
# @example The middle div is matched by the following xPath
|
7
7
|
# //body/div[@class='middle']
|
8
|
-
|
8
|
+
# @param title [String] the title of the document
|
9
|
+
# @param layout [Fixnum] one of 0,1,2,3 where 0 means minimal layout without left and right table of contents,
|
10
|
+
# 1 means only left toc, 2 means only right toc, and 3 means full layout with left and right toc.
|
11
|
+
def create_layout(title, layout=3)
|
12
|
+
raise "invalid layout selector, choose from 0..3" if (layout < 0) || (layout > 3)
|
13
|
+
|
9
14
|
@body = @document.elements["//body"]
|
10
15
|
# only add the layout if it is not already there
|
11
16
|
if !@layout
|
12
17
|
@body.add_element("div", {"class" => "head"})
|
18
|
+
|
19
|
+
if (layout & 0x1) != 0
|
13
20
|
div = @body.add_element("div", {"class" => "lefttoc", "id" => "ltoc"})
|
14
21
|
div.add_text("Table of Contents")
|
15
22
|
div.add_element("br")
|
23
|
+
end
|
24
|
+
|
25
|
+
if (layout & 0x2) != 0
|
16
26
|
div = @body.add_element("div", {"class" => "righttoc", "id" => "rtoc"})
|
17
27
|
div.add_text("Quick Links")
|
18
28
|
div.add_element("br");div.add_element("br")
|
29
|
+
end
|
30
|
+
|
19
31
|
@div_middle = @body.add_element("div", {"class" => "middle"})
|
20
32
|
@layout = true
|
21
33
|
end
|
22
34
|
@current = @document.elements["//body/div[@class='middle']"]
|
35
|
+
set_title(title)
|
23
36
|
end
|
24
37
|
|
25
|
-
# sets the title of the document in the
|
26
|
-
#
|
27
|
-
|
28
|
-
|
29
|
-
|
38
|
+
# sets the title of the document in the <head> section as well as in the layout header div
|
39
|
+
# create_layout must be called before!
|
40
|
+
# @param title [String] the text which will be insertead
|
41
|
+
def set_title(title)
|
42
|
+
if !@layout
|
43
|
+
raise "call create_layout first"
|
30
44
|
end
|
31
45
|
pagetitle = @document.elements["//head/title"]
|
32
46
|
pagetitle.text = title
|
@@ -35,48 +49,64 @@ module Custom
|
|
35
49
|
end
|
36
50
|
|
37
51
|
# returns the title text of the report
|
38
|
-
|
52
|
+
# @return [String] The title of the report
|
53
|
+
def get_title()
|
39
54
|
pagetitle = @document.elements["//head/title"]
|
40
55
|
return pagetitle.text
|
41
56
|
end
|
42
57
|
|
43
58
|
# set the current element to the element or first element matched by the xpath expression.
|
44
59
|
# The current element is the one which can be modified through highlighting.
|
45
|
-
# @param xpath [REXML::Element|String] the element or
|
46
|
-
def
|
60
|
+
# @param xpath [REXML::Element|String] the element or an xpath string
|
61
|
+
def set_current!(xpath)
|
47
62
|
if xpath.is_a?(REXML::Element)
|
48
63
|
@current = xpath
|
49
|
-
|
64
|
+
elsif xpath.is_a?(String)
|
50
65
|
@current = @document.elements[xpath]
|
66
|
+
else
|
67
|
+
raise "xpath is neither a String nor a REXML::Element"
|
51
68
|
end
|
52
69
|
end
|
53
70
|
|
54
71
|
# returns the current xml element
|
55
|
-
|
72
|
+
# @return [REXML::Element] the xml element after which the following elements will be added
|
73
|
+
def get_current()
|
56
74
|
return @current
|
57
75
|
end
|
58
76
|
|
59
77
|
# Appends a <pre> node after the @current node
|
60
|
-
|
78
|
+
# @param attrs [Hash] attributes for the <pre> element
|
79
|
+
# @yieldreturn [String] the text to be added to the <pre> element
|
80
|
+
# @return [REXML::Element] the Element which was just added
|
81
|
+
def code(attrs={}, &block)
|
61
82
|
temp = REXML::Element.new("pre")
|
62
83
|
temp.add_attributes(attrs)
|
63
84
|
@div_middle.insert_after(@current, temp)
|
64
85
|
@current = temp
|
86
|
+
raise "Block argument is mandatory" unless block_given?
|
87
|
+
text = block.call()
|
65
88
|
@current.add_text(text)
|
66
89
|
return @current
|
67
90
|
end
|
68
91
|
|
69
92
|
# Appends a <p> node after the @current node
|
70
|
-
|
93
|
+
# @param attrs [Hash] attributes for the <p> element
|
94
|
+
# @yieldreturn [String] the text to be added to the <p> element
|
95
|
+
# @return [REXML::Element] the Element which was just added
|
96
|
+
def content(attrs={}, &block)
|
71
97
|
temp = REXML::Element.new("p")
|
72
98
|
temp.add_attributes(attrs)
|
73
99
|
@div_middle.insert_after(@current, temp)
|
74
100
|
@current = temp
|
101
|
+
raise "Block argument is mandatory" unless block_given?
|
102
|
+
text = block.call()
|
75
103
|
@current.add_text(text)
|
76
104
|
return @current
|
77
105
|
end
|
78
106
|
|
79
107
|
# insert arbitrary xml code after the @current element in the content pane (div middle)
|
108
|
+
# @param text [String] valid xhtml code which is included into the document
|
109
|
+
# @return [REXML::Element] the Element which was just added
|
80
110
|
def html(text)
|
81
111
|
# we need to create a new document with a pseudo root
|
82
112
|
doc = REXML::Document.new("<root>"+text+"</root>")
|
@@ -87,15 +117,22 @@ module Custom
|
|
87
117
|
end
|
88
118
|
return @current
|
89
119
|
end
|
90
|
-
|
91
|
-
#
|
120
|
+
|
121
|
+
# Scans all REXML::Text children of an REXML::Element for any occurrences of regex.
|
122
|
+
# The text will be matched as one, not line by line as you might think.
|
123
|
+
# If you want to write a regexp matching multiple lines keep in mind that the dot "." by default doesn't
|
124
|
+
# match newline characters. Consider using the "m" option (e.g. /regex/m ) which makes dot match newlines
|
125
|
+
# or match newlines explicitly.
|
126
|
+
# highlight_captures then puts a <span> </span> tag around all captures of the regex
|
92
127
|
# NOTE: nested captures are not supported and don't make sense in this context!!
|
93
128
|
# @param regex [Regexp] a regular expression that will be matched
|
94
129
|
# @param color [String] at this point one of "y", "r", "g", "b" (yellow, red, green, blue) is supported
|
95
|
-
# @param el [REXML::Element] the Element (scope) which will be searched for pattern matches
|
96
|
-
|
130
|
+
# @param el [REXML::Element] the Element (scope) which will be searched for pattern matches, by default the last inserted element will be scanned
|
131
|
+
# @return [Fixnum] the number of highlighted captures
|
132
|
+
def highlight_captures(regex, color="y", el = @current)
|
97
133
|
# get all children of the current node
|
98
134
|
arr = el.to_a()
|
135
|
+
num_matches = 0
|
99
136
|
# depth first recursion into grand-children
|
100
137
|
for i in arr do
|
101
138
|
# detach from current
|
@@ -106,32 +143,40 @@ module Custom
|
|
106
143
|
|
107
144
|
# We get an array of [[start,length], [start,length], ...] for all our regex SUB-matches
|
108
145
|
positions = i.value().enum_for(:scan, regex).flat_map {
|
109
|
-
# Regexp.last_match is a MatchData object, the index 0 is the entire match
|
110
|
-
# indices 1..n are the captures (sub expressions)
|
146
|
+
# Regexp.last_match is a MatchData object, the index 0 is the entire match, 1 to n are captures
|
111
147
|
array = Array.new
|
112
148
|
for k in 1..Regexp.last_match.length - 1 do
|
113
149
|
array.push([Regexp.last_match.begin(k),
|
114
150
|
Regexp.last_match.end(k)-Regexp.last_match.begin(k)])
|
115
151
|
end
|
152
|
+
# return the array for the flat_map
|
116
153
|
array
|
117
154
|
}
|
118
|
-
|
155
|
+
num_matches += positions.length
|
156
|
+
replace_text_with_elements(el, i, "span", {"class" => color}, positions)
|
119
157
|
else
|
120
158
|
# for non-text nodes we recurse into it and finally reattach to our parent to preserve ordering
|
121
|
-
|
159
|
+
num_matches += highlight_captures(regex, color, i)
|
122
160
|
el.add(i)
|
123
161
|
end # if i.class.to_s() == "REXML::Text"
|
124
162
|
end # for i in arr do
|
125
|
-
|
163
|
+
return num_matches
|
126
164
|
end
|
127
165
|
|
128
|
-
#
|
166
|
+
# Scans all REXML::Text children of an REXML::Element for any occurrences of regex.
|
167
|
+
# The text will be matched as one, not line by line as you might think.
|
168
|
+
# If you want to write a regexp matching multiple lines keep in mind that the dot "." by default doesn't
|
169
|
+
# match newline characters. Consider using the "m" option (e.g. /regex/m ) which makes dot match newlines
|
170
|
+
# or match newlines explicitly.
|
171
|
+
# highlight then puts a <span> </span> tag around all matches of regex
|
129
172
|
# @param regex [Regexp] a regular expression that will be matched
|
130
173
|
# @param color [String] at this point one of "y", "r", "g", "b" (yellow, red, green, blue) is supported
|
131
174
|
# @param el [REXML::Element] the Element (scope) which will be searched for pattern matches
|
175
|
+
# @return [Fixnum] the number of highlighted captures
|
132
176
|
def highlight(regex, color="y", el = @current)
|
133
177
|
# get all children of the current node
|
134
178
|
arr = el.to_a()
|
179
|
+
num_matches = 0
|
135
180
|
#puts arr.inspect
|
136
181
|
# depth first recursion into grand-children
|
137
182
|
for i in arr do
|
@@ -147,23 +192,26 @@ module Custom
|
|
147
192
|
[Regexp.last_match.begin(0),
|
148
193
|
Regexp.last_match.end(0)-Regexp.last_match.begin(0)]
|
149
194
|
}
|
150
|
-
|
195
|
+
num_matches += positions.length
|
196
|
+
replace_text_with_elements(el, i, "span", {"class" => color}, positions)
|
151
197
|
else
|
152
198
|
# for non-text nodes we recurse into it and finally reattach to our parent to preserve ordering
|
153
199
|
# puts "recurse"
|
154
|
-
highlight(regex, color, i)
|
200
|
+
num_matches += highlight(regex, color, i)
|
155
201
|
el.add(i)
|
156
202
|
end # if i.class.to_s() == "REXML::Text"
|
157
203
|
end # for i in arr do
|
204
|
+
return num_matches
|
158
205
|
end
|
159
206
|
|
160
207
|
# creates a html table from two dimensional array of the form Array[row][col]
|
161
|
-
# @param table_data [Array] containing all data, the '.to_s' method will be called on each element
|
208
|
+
# @param table_data [Array<Array>] of the form Array[row][column] containing all data, the '.to_s' method will be called on each element,
|
162
209
|
# @param headers [Number] either of 0, 1, 2, 3. Where 0 is no headers (<th>) at all, 1 is only the first row,
|
163
210
|
# 2 is only the first column and 3 is both, first row and first column as <th> elements. Every other number
|
164
211
|
# is equivalent to the bitwise AND of the two least significant bits with 1, 2 or 3
|
165
|
-
|
166
|
-
|
212
|
+
# @return [REXML::Element] the Element which was just added
|
213
|
+
def table(table_data, headers=0, table_attrs={}, tr_attrs={}, th_attrs={}, td_attrs={})
|
214
|
+
|
167
215
|
temp = REXML::Element.new("table")
|
168
216
|
temp.add_attributes(table_attrs)
|
169
217
|
|
@@ -189,60 +237,63 @@ module Custom
|
|
189
237
|
end
|
190
238
|
|
191
239
|
# Appends a new heading element to body, and sets current to this new heading
|
192
|
-
# @param
|
193
|
-
# @param
|
194
|
-
# @
|
195
|
-
#
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
opts = {"class" => "bothtoc"}
|
202
|
-
else
|
203
|
-
opts = {}
|
204
|
-
end
|
205
|
-
|
206
|
-
temp = REXML::Element.new(type)
|
207
|
-
temp.add_attributes(opts)
|
240
|
+
# @param tag_type [String] specifiy "h1", "h2", "h3" for the heading, defaults to "h1"
|
241
|
+
# @param attrs [Hash] attributes for the <h#> element, any valid html attributes can be specified
|
242
|
+
# @option attrs [String] "class" by default every heading is added to the left table of contents (toc)
|
243
|
+
# use the class "onlyrtoc" or "bothtoc" to add a heading only to the right toc or to both tocs respectively
|
244
|
+
# @yieldreturn [String] the text to be added to the <h#> element
|
245
|
+
# @return [REXML::Element] the Element which was just added
|
246
|
+
def heading(tag_type="h1", attrs={}, &block)
|
247
|
+
temp = REXML::Element.new(tag_type)
|
248
|
+
temp.add_attributes(attrs)
|
208
249
|
|
209
250
|
@div_middle.insert_after(@current, temp)
|
210
251
|
@current = temp
|
252
|
+
raise "Block argument is mandatory" unless block_given?
|
253
|
+
text = block.call()
|
211
254
|
@current.text = text
|
212
255
|
return @current
|
213
256
|
end
|
214
|
-
|
215
|
-
# Inserts a new heading element at the very beginning of the middle div section, and points @current to this heading
|
216
|
-
# @param text [String] the heading text
|
217
|
-
# @param type [String] specifiy "h1", "h2", "h3" for the heading
|
218
|
-
# @param toc [symbol] one of :ltoc, :rtoc, :btoc depending on in which toc you want to display the heading
|
219
|
-
# @return the added element
|
220
|
-
def headingTop(text, type="h1", toc=:ltoc)
|
221
|
-
case toc
|
222
|
-
when :rtoc
|
223
|
-
opts = {"class" => "onlyrtoc"}
|
224
|
-
when :btoc
|
225
|
-
opts = {"class" => "bothtoc"}
|
226
|
-
else
|
227
|
-
opts = {}
|
228
|
-
end
|
229
257
|
|
230
|
-
|
231
|
-
|
232
|
-
#
|
233
|
-
@
|
234
|
-
|
235
|
-
@
|
236
|
-
return
|
237
|
-
|
258
|
+
# Inserts a new heading element at the very beginning of the middle div section, and points @current to this heading
|
259
|
+
# @param tag_type [String] specifiy "h1", "h2", "h3" for the heading, defaults to "h1"
|
260
|
+
# @param attrs [Hash] attributes for the <h#> element, any valid html attributes can be specified
|
261
|
+
# @option attrs [String] "class" by default every heading is added to the left table of contents (toc)
|
262
|
+
# use the class "onlyrtoc" or "bothtoc" to add a heading only to the right toc or to both tocs respectively
|
263
|
+
# @yieldreturn [String] the text to be added to the <h#> element
|
264
|
+
# @return [REXML::Element] the Element which was just added
|
265
|
+
def heading_top(tag_type="h1", attrs={}, &block)
|
266
|
+
temp = REXML::Element.new(tag_type)
|
267
|
+
temp.add_attributes(attrs)
|
268
|
+
# insert before the first child of div middle
|
269
|
+
@div_middle.insert_before("//div[@class='middle']/*[1]", temp)
|
270
|
+
@current = temp
|
271
|
+
raise "Block argument is mandatory" unless block_given?
|
272
|
+
text = block.call()
|
273
|
+
@current.text = text
|
274
|
+
return @current
|
275
|
+
end
|
238
276
|
|
277
|
+
# Helper Method for the highlight methods. it will introduce specific xhtml tags around parts of a text child of an xml element.
|
278
|
+
# @example
|
279
|
+
# we have the following xml part
|
280
|
+
# <test>
|
281
|
+
# some arbitrary
|
282
|
+
# text child content
|
283
|
+
# </test>
|
284
|
+
# now we call replace_text_with_elements to place <span> around the word "arbitrary"
|
285
|
+
# =>
|
286
|
+
# <test>
|
287
|
+
# some <span>arbitrary</span>
|
288
|
+
# text child content
|
289
|
+
# </test>
|
239
290
|
# @param element [REXML::Element] the element in whose text tags will be added at the specified indices of @index_length_array
|
240
291
|
# @param parent [REXML::Element] the parent to which @element should be attached after parsing
|
241
292
|
# @param tagname [String] the tag that will be introduced as <tagname> at the indices specified
|
242
293
|
# @param attribs [Hash] Attributes that will be added to the inserted tag e.g. <tagname attrib="test">
|
243
294
|
# @param index_length_array [Array] Array of the form [[index, lenght], [index, lenght], ...] that specifies
|
244
295
|
# the start position and length of the substring around which the tags will be introduced
|
245
|
-
def
|
296
|
+
def replace_text_with_elements(parent, element, tagname, attribs, index_length_array)
|
246
297
|
last_end = 0
|
247
298
|
index = 0
|
248
299
|
#puts index_length_array.inspect
|
@@ -275,7 +326,7 @@ end
|
|
275
326
|
|
276
327
|
end
|
277
328
|
|
278
|
-
#private_instance_methods(:
|
329
|
+
#private_instance_methods(:replace_text_with_elements)
|
279
330
|
|
280
331
|
end
|
281
332
|
|
@@ -1,2 +1 @@
|
|
1
|
-
|
2
|
-
$(document).ready(function(){$("td").each(function(b){b=$(this);null!==b.html().match(/passed/)&&b.attr("style","background-color:#00FF00;");null!==b.html().match(/failed/)&&b.attr("style","background-color:#FF0000;")});$("[class=rtoconly],[class=bothtoc]").each(function(b){var a=$(this);type=a.attr("class");a.attr("id",type+b);$("#rtoc").append("<a href='#"+type+b+"'>"+a.html()+"</a> <br />\n")});h3index=h2index=h1index=0;$("h1, h2, h3, a.h2, a.h1").each(function(b){var a=$(this);void 0==a.attr("id")&& a.attr("id","title"+b);if("h1"==a.prop("tagName"))h1index+=1,h3index=h2index=0,a.prepend(h1index+" "),$("#ltoc").append("<br />\n"),lasth1="#"+a.attr("id"),lasth1cont=a.html();else if("h2"==a.prop("tagName"))h2index+=1,h3index=0,a.prepend(h1index+"."+h2index+" "),lasth2="#"+a.attr("id"),lasth2cont=a.html();else if("h3"==a.prop("tagName"))h3index+=1,a.prepend(h1index+"."+h2index+"."+h3index+" ");else{if("h1"==a.attr("class"))return a.attr("href",lasth1),a.html(lasth1cont),0;if("h2"==a.attr("class"))return a.attr("href", lasth2),a.html(lasth2cont),0}if("rtoconly"==a.attr("class"))return 0;$("#ltoc").append("<a id='link"+b+"' href='#"+a.attr("id")+"' >"+a.html()+"</a> <br />\n");return 0})});
|
1
|
+
$(document).ready(function(){$("td").each(function(b){b=$(this);null!==b.html().match(/passed/)&&b.attr("style","background-color:#00FF00;");null!==b.html().match(/failed/)&&b.attr("style","background-color:#FF0000;")});$("[class=rtoconly],[class=bothtoc]").each(function(b){var a=$(this);type=a.attr("class");a.attr("id",type+b);$("#rtoc").append("<a href='#"+type+b+"'>"+a.html()+"</a> <br />\n")});h3index=h2index=h1index=0;$("h1, h2, h3, a.h2, a.h1").each(function(b){var a=$(this);void 0==a.attr("id")&&a.attr("id","title"+b);if("h1"==a.prop("tagName"))h1index+=1,h3index=h2index=0,a.prepend(h1index+" "),$("#ltoc").append("<br />\n"),lasth1="#"+a.attr("id"),lasth1cont=a.html();else if("h2"==a.prop("tagName"))h2index+=1,h3index=0,a.prepend(h1index+"."+h2index+" "),lasth2="#"+a.attr("id"),lasth2cont=a.html();else if("h3"==a.prop("tagName"))h3index+=1,a.prepend(h1index+"."+h2index+"."+h3index+" ");else{if("h1"==a.attr("class"))return a.attr("href",lasth1),a.html(lasth1cont),0;if("h2"==a.attr("class"))return a.attr("href",lasth2),a.html(lasth2cont),0}if("rtoconly"==a.attr("class"))return 0;$("#ltoc").append("<a id='link"+b+"' href='#"+a.attr("id")+"' >"+a.html()+"</a> <br />\n");return 0})});
|
metadata
CHANGED
@@ -1,61 +1,64 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: xhtml_report_generator
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
|
+
prerelease:
|
5
6
|
platform: ruby
|
6
7
|
authors:
|
7
8
|
- Manuel Widmer
|
8
9
|
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
11
|
-
date: 2015-
|
12
|
+
date: 2015-08-19 00:00:00.000000000 Z
|
12
13
|
dependencies: []
|
13
|
-
description: "The generator can be used to create xhtml files. It comes with some
|
14
|
+
description: ! "The generator can be used to create xhtml files. It comes with some
|
14
15
|
default utility functions.\n== Here is an example usage\n gen1 = XhtmlReportGenerator::Generator.new\n
|
15
|
-
\ gen1.
|
16
|
-
\"
|
17
|
-
\
|
18
|
-
>red span test</span>\", {\"class\"=>\"bold\"}
|
19
|
-
function: Hallo welt <br /> html test <span class=\"r\" >red span test</span></p>\")\n
|
20
|
-
javascript to render the table of contents,
|
21
|
-
sheet all can be\nsupplied by your own,
|
16
|
+
\ gen1.create_layout(\"Title\")\n gen1.heading(\"h1\", {\"class\" => \"bothtoc\"})
|
17
|
+
{\"titel\"}\n gen1.heading(\"h2\") {\"subtitel\"}\n gen1.heading(\"h3\") {\"section\"}\n
|
18
|
+
\ gen1.content() {\"content function: Hallo welt <br /> html test <span class=\"r\"
|
19
|
+
>red span test</span>\", {\"class\"=>\"bold\"}}\n gen1.html(\"<p class=\"italic\">html
|
20
|
+
function: Hallo welt <br /> html test <span class=\"r\" >red span test</span></p>\")\n
|
21
|
+
\ gen1.highlight(/Ha.*lt/)\n \nThe javascript to render the table of contents,
|
22
|
+
the custom generator functions and style sheet all can be\nsupplied by your own,
|
23
|
+
if necessary. \n"
|
22
24
|
email: m-widmer@gmx.ch
|
23
25
|
executables: []
|
24
26
|
extensions: []
|
25
27
|
extra_rdoc_files: []
|
26
28
|
files:
|
27
|
-
- LICENSE
|
28
|
-
- README.md
|
29
|
-
- lib/xhtml_report_generator.rb
|
30
29
|
- lib/xhtml_report_generator/custom.rb
|
31
30
|
- lib/xhtml_report_generator/jquery.js
|
32
31
|
- lib/xhtml_report_generator/print_template.css
|
33
32
|
- lib/xhtml_report_generator/style_template.css
|
34
33
|
- lib/xhtml_report_generator/toc.js
|
35
34
|
- lib/xhtml_report_generator/version.rb
|
35
|
+
- lib/xhtml_report_generator.rb
|
36
|
+
- LICENSE
|
37
|
+
- README.md
|
36
38
|
homepage: https://rubygems.org/gems/xhtml_report_generator
|
37
39
|
licenses:
|
38
40
|
- MIT
|
39
|
-
metadata: {}
|
40
41
|
post_install_message:
|
41
42
|
rdoc_options: []
|
42
43
|
require_paths:
|
43
44
|
- lib
|
44
45
|
required_ruby_version: !ruby/object:Gem::Requirement
|
46
|
+
none: false
|
45
47
|
requirements:
|
46
|
-
- - '>='
|
48
|
+
- - ! '>='
|
47
49
|
- !ruby/object:Gem::Version
|
48
50
|
version: 1.8.7
|
49
51
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
52
|
+
none: false
|
50
53
|
requirements:
|
51
|
-
- - '>='
|
54
|
+
- - ! '>='
|
52
55
|
- !ruby/object:Gem::Version
|
53
56
|
version: '0'
|
54
57
|
requirements: []
|
55
58
|
rubyforge_project:
|
56
|
-
rubygems_version:
|
59
|
+
rubygems_version: 1.8.30
|
57
60
|
signing_key:
|
58
|
-
specification_version:
|
61
|
+
specification_version: 3
|
59
62
|
summary: A simple and quick xhtml report generator
|
60
63
|
test_files: []
|
61
64
|
has_rdoc:
|
checksums.yaml
DELETED
@@ -1,7 +0,0 @@
|
|
1
|
-
---
|
2
|
-
SHA1:
|
3
|
-
metadata.gz: 8245325d398df596821aad2471b7fe703e541f1c
|
4
|
-
data.tar.gz: 8090a12abf591da6ee1f7af51483f142228dd029
|
5
|
-
SHA512:
|
6
|
-
metadata.gz: f1195b1d581cfc0c25c47d077603e8f53a77e85d79e0ad28f5805a62464bd7427f040fafd6405fd112f390f69f6428b721c109e2dfdb9d9481796ddb1f8095ef
|
7
|
-
data.tar.gz: 39a0c261ac28951b05c1ed55bea11111f0cb00f66e0696cde7b800ee07ba1b9a0e6b1b55b3f9af1c27809d0c1b00e0569a44643edc826bb87ac18b24f5640316
|