xhtml_report_generator 2.1.1 → 2.2.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
  SHA1:
3
- metadata.gz: d3bb7dd2a10d07719f2cac295e6710218fab5f2d
4
- data.tar.gz: 0acaa09996b500ec388e63fd06dc9e9a5b1c7c74
3
+ metadata.gz: 3aa1ee1460f949608080993ab68e93eab9298561
4
+ data.tar.gz: 3ac67dd1dcde669790405a065295abdcc223d36d
5
5
  SHA512:
6
- metadata.gz: bdfcc8d627bec2b696efaac8ca4449a39a0c234d9a7ee44d16b02ca46267b05d15dffc653ef7d46ccdd97762d631a67eb0a3919db45bee83d4f5610a4ae038b5
7
- data.tar.gz: e7c5cbcd6902fd9640eafc63fb41f7f216bd6f3ae3684039428cb9e96985b1f92f79dae02f659dff4ddb558774b8a465cec3983f759319c9c3277d731fb4cc68
6
+ metadata.gz: d5499730f068d0597fe8ae3f7fba1e1af58257a7b2ae52c11993e1f3ca0062fc095d8f0e6c48919ccb1141602ed3a6d7b5019d2059747f04c14466c2ee0e1553
7
+ data.tar.gz: f92130285b5d241af4c17a10068c2c18a155a29cfca58ca6024c20da4b0e1c8dc1f80ba87e3d8dba21dacddb077310080b835ad6922e547a5f73e28544190092
data/README.md CHANGED
@@ -1,15 +1,20 @@
1
- xhtml-report-generator
1
+ xhtml_report_generator
2
2
  ======================
3
3
 
4
- This project was written to provide an easy way to create valid xhtml documents.
4
+ This project was written to provide an easy way to create valid xhtml or html documents.
5
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.
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 if you didn't write before.
8
+
9
+ Ruby version
10
+ -----
11
+ This gem was mainly tested with ruby version 2.2.3. Except of the test_encoding_issues unit tests, all other tests are
12
+ also passing with 1.9.3. Probably there were issues in ruby itself for earlier versions.
8
13
 
9
14
 
10
15
  Example usage
11
16
  -------------
12
- In the following you can find a quick start on how to use xhtml-report-generator.
17
+ In the following you can find a quick start on how to use xhtml_report_generator.
13
18
  Basically the project is built in a way that lets you supply your own methods for everything.
14
19
  By default "custom.rb" is loaded through instance eval, so you can check the corresponding documentation for available methods.
15
20
 
@@ -21,9 +26,11 @@ Basically starting from version 2 the syntax for each method of custom.rb is uni
21
26
  def method({"attribute" => "value", "attribute2" => "value2"}) {contents}
22
27
 
23
28
  in addition the method naming convention was changed from camelCase to underscore to comply more with ruby conventions.
29
+
30
+ See <a href=http://www.rubydoc.info/gems/xhtml_report_generator/Custom>http://www.rubydoc.info/gems/xhtml_report_generator/Custom</> for the documentation of available methods.
24
31
 
25
32
  <pre>
26
- require 'xhtml-report-generator'
33
+ require 'xhtml_report_generator'
27
34
 
28
35
  gen1 = XhtmlReportGenerator::Generator.new
29
36
  gen1.create_layout("Title")
@@ -33,9 +40,62 @@ gen1.heading("h3") {"section"}
33
40
  gen1.content({"class"=>"bold"}) {"content function: Hallo welt &lt;br /> html test &lt;span class=\"r\" >red span test&lt;/span>"}
34
41
  gen1.html("&lt;p class=\"italic\">html function: Hallo welt &lt;br /> html test &lt;span class=\"r\" >red span test&lt;/span>&lt;/p>")
35
42
  gen1.highlight(/Ha.*lt/)
43
+ gen1.link("https://rubygems.org/gems/xhtml_report_generator/") {"download the gem"}
44
+ # browser will parse this as html (based on file extension)
45
+ gen1.write("myreport.html")
46
+ # browser will parse this as xhtml (based on file extension)
47
+ gen1.write("myreport.xhtml")
48
+ </pre>
49
+
50
+ Adding some graphs to your reports
51
+ ----------------------------------
52
+ Due to the xml nature it is also easy to insert SVG graphs / pictures. Check out the svg-graph gem
53
+
54
+ <pre>
55
+ require 'xhtml_report_generator'
56
+ require 'SVG/Graph/Line'
57
+ require 'REXML/document'
58
+
59
+ gen1 = XhtmlReportGenerator::Generator.new
60
+ gen1.create_layout("Graph example")
61
+ gen1.heading("h1") {"my graph"}
62
+
63
+ x_axis = %w(Jan Feb Mar);
64
+ data_sales_02 = [12, 45, 21]
65
+ data_sales_03 = [15, 30, 40]
66
+
67
+ graph = SVG::Graph::Line.new({
68
+ :height => 300,
69
+ :width => 500,
70
+ :show_graph_title => true,
71
+ :graph_title => 'Graph Title',
72
+ :show_x_title => true,
73
+ :x_title => 'Month',
74
+ :show_y_title => true,
75
+ #:y_title_text_direction => :bt,
76
+ :y_title => 'cash',
77
+ :fields => x_axis})
78
+
79
+ graph.add_data({:data => data_sales_02, :title => 'Sales2002'})
80
+ graph.add_data({:data => data_sales_03, :title => 'Sales2003'})
81
+
82
+ # we can't add the entire xml document since multiple xml declarations are invalid
83
+ # so we add only
84
+ doc = REXML::Document.new(graph.burn())
85
+ svg = doc.elements["//svg"]
86
+ out = ''
87
+ f = REXML::Formatters::Pretty.new(0)
88
+ f.compact = true
89
+ f.write(svg, out)
90
+
91
+ gen1.html(out)
92
+ gen1.write("graph.xhtml")
36
93
 
37
94
  </pre>
38
95
 
96
+
97
+
98
+
39
99
  Changes from version 1.x to 2.x
40
100
  -------------------------------
41
101
  To ease with migration here is a list with the changed function names, please also check the new synopsis
@@ -1,8 +1,6 @@
1
- # logfile.title("mein title")
2
- # logfile.section
3
- # logfil.content("mein resultat")
4
- # logfile.markup(regexstart, regex end, :yellow)
1
+ # encoding: utf-8
5
2
  require 'rexml/document'
3
+ require 'rexml/formatters/transitive'
6
4
 
7
5
  module XhtmlReportGenerator
8
6
 
@@ -29,36 +27,73 @@ module XhtmlReportGenerator
29
27
  }
30
28
  # either use the default files provided with the gem, or those provided by the caller
31
29
  symbols = symbols.merge(opts)
30
+ custom_rb_path = symbols[:custom_rb]
32
31
  for key in symbols.keys do
33
32
  # read the contents into the symbols hash
34
33
  symbols[key] = File.read(symbols[key])
35
34
  end
36
35
  # load the custom module and extend it, use instance_eval otherwise the module will affect
37
36
  # all existing Generator classes
38
- instance_eval symbols[:custom_rb]
37
+ instance_eval(symbols[:custom_rb], custom_rb_path)
39
38
 
40
39
  @document = Generator.create_xhtml_document("Title")
41
40
  head = @document.elements["//head"]
41
+
42
+ head.add_element("meta", {"charset" => "utf-8"})
43
+
42
44
  # insert the custom css, and javascript files
43
45
  style = head.add_element("style", {"type" => "text/css"})
44
- # remove all newlines
45
- style.add_text(REXML::CData.new("\n"+symbols[:css].gsub(/\n/, "")+"\n"))
46
+ cdata(symbols[:css], style)
46
47
 
47
48
  style = head.add_element("style", {"type" => "text/css", "media"=>"print"})
48
- style.add_text(REXML::CData.new("\n"+symbols[:css_print].gsub(/\n/, "")+"\n"))
49
+ cdata(symbols[:css_print], style)
49
50
 
50
51
  script = head.add_element("script", {"type" => "text/javascript"})
51
- script.add_text(REXML::CData.new("\n"+symbols[:jquery]+"\n"))
52
+ cdata(symbols[:jquery], script)
52
53
 
53
54
  script = head.add_element("script", {"type" => "text/javascript"})
54
- script.add_text(REXML::CData.new("\n"+symbols[:toc]+"\n"))
55
+ cdata(symbols[:toc], script)
56
+ end
57
+
58
+ # Surrounds CData tag with c-style comments to remain compatible with normal html.
59
+ # For plain xhtml documents this is not needed.
60
+ # Example /*<![CDATA[*/\n ...content ... \n/*]]>*/
61
+ # @param str [String] the string to be enclosed in cdata
62
+ # @param parent_element [REXML::Element] the element to which cdata should be added
63
+ # @return [String] CDATA enclosed in c-style comments /**/
64
+ def cdata(str, parent_element)
65
+ f = REXML::Formatters::Transitive.new(0) # use Transitive to preserve source formatting
66
+ # somehow there is a problem with CDATA, any text added after will automatically go into the CDATA
67
+ # so we have do add a dummy node after the CDATA and then add the text.
68
+ parent_element.add_text("/*")
69
+ parent_element.add(REXML::CData.new("*/\n"+str+"\n/*"))
70
+ parent_element.add(REXML::Comment.new("dummy comment to make c-style comments for cdata work"))
71
+ parent_element.add_text("*/")
72
+ end
73
+
74
+ # Check if the give string is a valid UTF-8 byte sequence. If it is not valid UTF-8, then
75
+ # all invalid bytes are replaced by "\u2e2e" (\xe2\xb8\xae) ('REVERSED QUESTION MARK') because the default
76
+ # replacement character "\uFFFD" ('QUESTION MARK IN DIAMOND BOX') is two slots wide and might
77
+ # destroy mono spaced formatting
78
+ # @param str [String] of any encoding
79
+ # @return [String] UTF-8 encoded valid string
80
+ def encoding_fixer(str)
81
+ #if !str.force_encoding('UTF-8').valid_encoding?
82
+ # str.encode!('UTF-8', 'ISO-8859-1', {:invalid => :replace, :undef => :replace, :xml => :text})
83
+ #end
84
+ tmp = str.force_encoding('UTF-8').encode('UTF-8',{:invalid => :replace, :undef => :replace, :replace => "\u2e2e"})
85
+ # replace all special control chars as well but keep newline and whitespace "\u2e2e"
86
+ tmp.force_encoding('binary').gsub!(/[\x00-\x07\x0C-\x1F]|\xef\xbf\xbe|\xef\xbf\xbf/n, "\xe2\xb8\xae".force_encoding('binary'))
87
+ return tmp.force_encoding('UTF-8')
55
88
  end
56
89
 
57
90
  # Creates a minimal valid xhtml document including header title and body elements
58
91
  # @param title [String] Title in the header section
59
92
  def self.create_xhtml_document(title)
60
- header = '<?xml version="1.0" encoding="UTF-8" standalone="no"?>'
61
- header += '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">'
93
+ # don't use version 1.1 - firefox has not yet a parser vor xml 1.1
94
+ # https://bugzilla.mozilla.org/show_bug.cgi?id=233154
95
+ header = '<?xml version="1.0" encoding="UTF-8"?>'
96
+ header << '<!DOCTYPE html>'
62
97
 
63
98
  doc = REXML::Document.new(header)
64
99
  html = doc.add_element("html", {"xmlns" => "http://www.w3.org/1999/xhtml"})
@@ -71,14 +106,18 @@ module XhtmlReportGenerator
71
106
  end
72
107
 
73
108
  # returns the string representation of the xml document
74
- # @param indent [Number] indent for child elements. defaults to 0.
109
+ # @param indent [Number] indent for child elements. defaults to 0.
110
+ # Note: if you change the indet this might destroy formatting of <pre> sections
111
+ # @return [String] formatted xml document
75
112
  def to_s(indent = 0)
76
113
  output = ""
77
114
  # note : transitive is needed to preserve newlines in <pre> tags
78
115
  # note2: the hash options syntax is supported only from ruby version >= 2.0.0 we need the old style
79
116
  # for compatibility with 1.9.3
80
- #@document.write({:output=>output, :indent=>indent, :transitive=>true})
81
- @document.write(output, indent, true)
117
+ # @document.write({:output=>output, :indent=>indent, :transitive=>true})
118
+ # change to Formatters since document.write is deprecated
119
+ f = REXML::Formatters::Transitive.new(indent)
120
+ f.write(@document, output)
82
121
  return output
83
122
  end
84
123
 
@@ -1,3 +1,4 @@
1
+ # encoding: utf-8
1
2
  require 'base64'
2
3
  # The module name doesn't matter, just make sure at the end to 'extend' it
3
4
  # because it will be 'eval'ed by the initialize method of the XhtmlReportGenerator::Generator class.
@@ -28,7 +29,7 @@ module Custom
28
29
  div.add_text("Quick Links")
29
30
  div.add_element("br");div.add_element("br")
30
31
  end
31
-
32
+
32
33
  @div_middle = @body.add_element("div", {"class" => "middle"})
33
34
  @layout = true
34
35
  end
@@ -85,7 +86,7 @@ module Custom
85
86
  @div_middle.insert_after(@current, temp)
86
87
  @current = temp
87
88
  raise "Block argument is mandatory" unless block_given?
88
- text = block.call()
89
+ text = encoding_fixer(block.call())
89
90
  @current.add_text(text)
90
91
  return @current
91
92
  end
@@ -100,7 +101,7 @@ module Custom
100
101
  @div_middle.insert_after(@current, temp)
101
102
  @current = temp
102
103
  raise "Block argument is mandatory" unless block_given?
103
- text = block.call()
104
+ text = encoding_fixer(block.call())
104
105
  @current.add_text(text)
105
106
  return @current
106
107
  end
@@ -109,7 +110,8 @@ module Custom
109
110
  # @param text [String] valid xhtml code which is included into the document
110
111
  # @return [REXML::Element] the Element which was just added
111
112
  def html(text)
112
- # we need to create a new document with a pseudo root
113
+ # we need to create a new document with a pseudo root becaus having multiple nodes at top
114
+ # level is not valid xml
113
115
  doc = REXML::Document.new("<root>"+text+"</root>")
114
116
  # then we move all children of root to the actual div middle element and insert after current
115
117
  for i in doc.root.to_a do
@@ -119,6 +121,23 @@ module Custom
119
121
  return @current
120
122
  end
121
123
 
124
+ # Appends a <a href = > node after the @current nodes
125
+ # @param href [String] this is the
126
+ # @param attrs [Hash] attributes for the <a> element
127
+ # @yieldreturn [String] the text to be added to the <a> element
128
+ # @return [REXML::Element] the Element which was just added
129
+ def link(href, attrs={}, &block)
130
+ temp = REXML::Element.new("a")
131
+ attrs.merge!({"href" => href})
132
+ temp.add_attributes(attrs)
133
+ @div_middle.insert_after(@current, temp)
134
+ @current = temp
135
+ raise "Block argument is mandatory" unless block_given?
136
+ text = encoding_fixer(block.call())
137
+ @current.add_text(text)
138
+ return @current
139
+ end
140
+
122
141
  # @param path [String] absolute or relative path to the image that should be inserted into the report
123
142
  # @param attrs [Hash] attributes for the <img> element, any valid html attributes can be specified
124
143
  # you may specify attributes such "alt", "height", "width"
@@ -270,7 +289,7 @@ module Custom
270
289
  @div_middle.insert_after(@current, temp)
271
290
  @current = temp
272
291
  raise "Block argument is mandatory" unless block_given?
273
- text = block.call()
292
+ text = encoding_fixer(block.call())
274
293
  @current.text = text
275
294
  return @current
276
295
  end
@@ -297,7 +316,7 @@ module Custom
297
316
 
298
317
  @current = temp
299
318
  raise "Block argument is mandatory" unless block_given?
300
- text = block.call()
319
+ text = encoding_fixer(block.call())
301
320
  @current.text = text
302
321
  return @current
303
322
  end
@@ -1,5 +1,5 @@
1
- $(document).ready(function(){$("td").each(function(b){b=$(this);null!==b.html().match(/^passed$/)?b.attr("style","background-color:#19D119;"):null!==b.html().match(/^failed$/)?b.attr("style","background-color:#FF4719;"):null!==b.html().match(/^check$/)&&b.attr("style","background-color:#FFFF00;")});$("[class=rtoconly],[class=bothtoc]").each(function(b){var a=$(this),c=a.attr("class");a.attr("id",c+b);$("#rtoc").append("<a href='#"+c+b+"'>"+a.html()+"</a> <br />\n")});h3index=h2index=h1index=0;$("h1, h2, h3, a.h2, a.h1").each(function(b){var a=
2
- $(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),
3
- 0;if("h2"==a.attr("class"))return a.attr("href",lasth2),a.html(lasth2cont),0}if("rtoconly"==a.attr("class"))return 0;$("#ltoc").append("<div id='div_fold_"+h1index+"_"+h2index+"_"+h3index+"'><a id='a_fold_"+h1index+"_"+h2index+"_"+h3index+"' style='cursor:pointer'>&#160;-&#160;</a> <a id='link"+b+"' href='#"+a.attr("id")+"' >"+a.html()+"</a> <br /> </div>\n");return 0});$('a[id^="a_fold"]').click(function(){var b=$(this),a=b.attr("id").match(/(\d+)_(\d+)_(\d+)/);if(b.html().match(/-/))var c="&#160;+&#160;",
4
- e=!1;else c="&#160;-&#160;",e=!0;b.html(c);if("0"==a[2]){var d=new RegExp("div_fold_"+a[1]+"_[1-9]\\d*_0");$("div").filter(function(){return this.id.match(d)}).each(function(){$(this).children('a[id^="a_fold"]').html(c);$(this).toggle(e)});d=new RegExp("div_fold_"+a[1]+"_\\d+_[1-9]\\d*");$("div").filter(function(){return this.id.match(d)}).each(function(){$(this).children('a[id^="a_fold"]').html(c);$(this).toggle(e)})}else"0"==a[3]&&(d=new RegExp("div_fold_"+a[1]+"_"+a[2]+"_[1-9]\\d*"),$("div").filter(function(){return this.id.match(d)}).each(function(){$(this).children('a[id^="a_fold"]').html(c);
5
- $(this).toggle(e)}))})});
1
+ $(document).ready(function(){$("td").each(function(b){b=$(this);null!==b.html().match(/^passed$/i)?b.attr("style","background-color:#19D119;"):null!==b.html().match(/^failed$/i)?b.attr("style","background-color:#FF4719;"):null!==b.html().match(/^check$/i)&&b.attr("style","background-color:#FFFF00;")});$("[class=rtoconly],[class=bothtoc]").each(function(b){var a=$(this),c=a.attr("class");a.attr("id",c+b);$("#rtoc").append("<a href='#"+c+b+"'>"+a.html()+"</a> <br />\n")});h3index=h2index=h1index=0;
2
+ $("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").toUpperCase())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").toUpperCase())h2index+=1,h3index=0,a.prepend(h1index+"."+h2index+" "),lasth2="#"+a.attr("id"),lasth2cont=a.html();else if("H3"==a.prop("tagName").toUpperCase())h3index+=1,a.prepend(h1index+"."+h2index+
3
+ "."+h3index+" ");else{if("H1"==a.attr("class").toUpperCase())return a.attr("href",lasth1),a.html(lasth1cont),0;if("H2"==a.attr("class").toUpperCase())return a.attr("href",lasth2),a.html(lasth2cont),0}if("undefined"!=typeof a.attr("class")&&"RTOCONLY"==a.attr("class").toUpperCase())return 0;$("#ltoc").append("<div id='div_fold_"+h1index+"_"+h2index+"_"+h3index+"'><a id='a_fold_"+h1index+"_"+h2index+"_"+h3index+"' style='cursor:pointer'>&#160;-&#160;</a> <a id='link"+b+"' href='#"+a.attr("id")+"' >"+
4
+ a.html()+"</a> <br /> </div>\n");return 0});$('a[id^="a_fold"]').click(function(){var b=$(this),a=b.attr("id").match(/(\d+)_(\d+)_(\d+)/);if(b.html().match(/-/))var c="&#160;+&#160;",e=!1;else c="&#160;-&#160;",e=!0;b.html(c);if("0"==a[2]){var d=new RegExp("div_fold_"+a[1]+"_[1-9]\\d*_0");$("div").filter(function(){return this.id.match(d)}).each(function(){$(this).children('a[id^="a_fold"]').html(c);$(this).toggle(e)});d=new RegExp("div_fold_"+a[1]+"_\\d+_[1-9]\\d*");$("div").filter(function(){return this.id.match(d)}).each(function(){$(this).children('a[id^="a_fold"]').html(c);
5
+ $(this).toggle(e)})}else"0"==a[3]&&(d=new RegExp("div_fold_"+a[1]+"_"+a[2]+"_[1-9]\\d*"),$("div").filter(function(){return this.id.match(d)}).each(function(){$(this).children('a[id^="a_fold"]').html(c);$(this).toggle(e)}))})});
@@ -1,5 +1,5 @@
1
1
  module XhtmlReportGenerator
2
- VERSION = '2.1.1'
2
+ VERSION = '2.2.0'
3
3
  end
4
4
 
5
5
  # puts XhtmlReportGenerator::VERSION
metadata CHANGED
@@ -1,25 +1,27 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: xhtml_report_generator
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.1
4
+ version: 2.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Manuel Widmer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-12-24 00:00:00.000000000 Z
11
+ date: 2016-01-29 00:00:00.000000000 Z
12
12
  dependencies: []
13
- description: "The generator can be used to create xhtml files. It comes with some
14
- default utility functions.\n== Here is an example usage\n gen1 = XhtmlReportGenerator::Generator.new\n
13
+ description: "The generator can be used to create html or xhtml files. It comes with
14
+ many utility functions.\n== Example usage\n gen1 = XhtmlReportGenerator::Generator.new\n
15
15
  \ gen1.create_layout(\"Title\")\n gen1.heading(\"h1\", {\"class\" => \"bothtoc\"})
16
16
  {\"titel\"}\n gen1.heading(\"h2\") {\"subtitel\"}\n gen1.heading(\"h3\") {\"section\"}\n
17
- \ gen1.content({\"class\"=>\"bold\"}) {\"content function: Hallo welt &lt;br />
18
- html test &lt;span class=\"r\" >red span test&lt;/span>\"}\n gen1.html(\"&lt;p
19
- class=\"italic\">html function: Hallo welt &lt;br /> html test &lt;span class=\"r\"
20
- >red span test&lt;/span>&lt;/p>\")\n gen1.highlight(/Ha.*lt/)\n \nThe javascript
21
- to render the table of contents, the custom generator functions and style sheet
22
- all can be\nsupplied by your own, if necessary. \n"
17
+ \ gen1.content({\"class\"=>\"bold\"}) {\"content function: Hallo welt <br /> html
18
+ test <span class=\"r\" >red span test</span>\"}\n gen1.html(\"<p class=\"italic\">html
19
+ function: Hallo welt <br /> html test <span class=\"r\" >red span test<span></p>\")\n
20
+ \ gen1.highlight(/Ha.*lt/)\n \nThe javascript to render the table of contents,
21
+ the custom generator functions and style sheet all can be\nsupplied by your own,
22
+ if necessary. By default there are methods to insert tables, links, paragraphs,
23
+ preformatted text\nand arbitrary xhtml code. Due to the xml nature it is also easy
24
+ to insert SVG graphs / pictures.\n\n"
23
25
  email: m-widmer@gmx.ch
24
26
  executables: []
25
27
  extensions: []
@@ -57,5 +59,5 @@ rubyforge_project:
57
59
  rubygems_version: 2.4.5.1
58
60
  signing_key:
59
61
  specification_version: 4
60
- summary: A simple and quick xhtml report generator
62
+ summary: A simple html or xhtml generator to create human readable support
61
63
  test_files: []