docgenerator 0.1.1

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.
data/docgenerator.rb ADDED
@@ -0,0 +1,137 @@
1
+ #Generic methods to create documents.
2
+ #The target format ia generic, supported are LaTeX and HTML.
3
+ #
4
+ #==Elements
5
+ #A document is structured by elements.
6
+ #Each element contains attributes/parameters and content.
7
+ #(Think of HTML-attributes and TeX-Parameters and the content of HTML-Tags and TeX-Environments.).
8
+ #
9
+ #Each element corresponds to a HTML-Tag or a LaTeX-Makro/Environment.
10
+ #There is a "translation" between HTML and LaTeX elements.
11
+ #
12
+ #Elements are defined by Element.get (or the method element() ),
13
+ #new element types can be defined with Element.create() ).
14
+ #
15
+ #Some elements (in fact, most of them) are generated dynamic,
16
+ #so they qill not occur in this generated documentation).
17
+ #== Examples
18
+ #See the file Example_DocGenerator.rb
19
+ #
20
+ #
21
+ #== Open topics
22
+ #- control content
23
+ # (Tag br in HTML klappt).
24
+ #- Wiki-Output
25
+ #- ASCII-Output
26
+
27
+
28
+ #How to handle the End-Tag for br/hr...
29
+ #-false: set <br /> (XHTML)
30
+ #-nil: set <br> (HTML)
31
+ #~ Problem:
32
+ #~ HTML darf keine Endtags haben, XHTML verlangt es.
33
+ #~ Die Konstante ENDTAG macht es einstellbar.
34
+ #~ Zu machen: Flag im Dokument ob HTML oder XHTML.
35
+ #~ Aber woher weiss element in welches Dokument es geh�rt?
36
+ #~ Gleiche Problem bei to_s, bzw. Document.target
37
+ ENDTAG = false if ! defined?( ENDTAG )
38
+ #filled in DocGeneratorTemplate.rb (or elsewhere)
39
+ SUPPORTED_LaTeX_TEMPLATES = [] if ! defined?( SUPPORTED_LaTeX_TEMPLATES )
40
+ SUPPORTED_HTML_TEMPLATES = [] if ! defined?( SUPPORTED_HTML_TEMPLATES )
41
+
42
+ #
43
+ #@target @@target hat noch bugs.
44
+ #mit UNDER_CONSTRUCTION = true kann der Testmodus
45
+ UNDER_CONSTRUCTION = false if ! defined?( UNDER_CONSTRUCTION )
46
+
47
+ module Backlinks
48
+ def set_backlink( content)
49
+ #Prepare backword link
50
+ cl = [ content ].flatten #content list
51
+ cl.each{|c|
52
+ if c.respond_to?( :part_of )
53
+ c.part_of << self
54
+ end
55
+ if c.respond_to?( :part_of_doc )
56
+ c.part_of_doc << self.part_of_doc
57
+ c.part_of_doc.flatten!
58
+ #fixme Hier auch attribute backlink setzen?
59
+ if c.part_of_doc.include?( nil )
60
+ raise "Add nil as document in #{self.inspect}"
61
+ end
62
+ end
63
+ #Log in case of error.
64
+ if UNDER_CONSTRUCTION and
65
+ ! ( c.respond_to?( :part_of ) or c.respond_to?( :part_of_doc ) ) and
66
+ ! (c.is_a?(String) or c.is_a?(Fixnum) )
67
+ puts "set_backlink: Not supported by #{c.inspect} in #{self.inspect} (#{c.respond_to?( :part_of )}/#{c.respond_to?( :part_of_doc )})"
68
+ end
69
+
70
+ }
71
+ return self
72
+ end
73
+ #List of elements, where this element is part of.
74
+ #Filled by << in the superior element.
75
+ #Normaly only one element
76
+ attr_reader :part_of
77
+ #List of documents, where this element is part of.
78
+ #Filled by << in the superior element.
79
+ #Normaly only one element
80
+ attr_reader :part_of_doc
81
+ #Return an array with all ancestors.
82
+ #contains pairs of: [ ancestor, [array of ancestors ancestors]]
83
+ def ancestors
84
+ anc = []
85
+ @part_of.each{|a|
86
+ anc << a
87
+ anc << a.ancestors if a.respond_to?(:ancestors)
88
+ }
89
+ return anc
90
+ end
91
+ end
92
+ require 'docgenerator_element'
93
+
94
+ #Returns an element of a type "name".
95
+ #Attributes and content are optional parameter.
96
+ #
97
+ def element( name, attr = {}, content = nil )
98
+ element = Element.get( name )
99
+ if element
100
+ element = element.new(attr, content ) if element
101
+ else
102
+ element = Element.create( name, {}, true ).new(attr, content )
103
+ puts "Usage of undefined element #{name}"
104
+ end
105
+ return element
106
+ end
107
+
108
+ require 'docgenerator_template'
109
+ require 'docgenerator_css'
110
+ require 'docgenerator_attribute'
111
+ require 'docgenerator_document'
112
+
113
+ #~ require 'DocGenerator_HTML' if __FILE__ != 'DocGenerator_HTML' #and __FILE__ != $0
114
+ #~ require 'DocGenerator_LaTeX' if __FILE__ != 'DocGenerator_LaTeX' #and __FILE__ != $0
115
+ require 'docgenerator_elements'
116
+ require 'docgenerator_environments'
117
+ require 'docgenerator_lists' #define environment
118
+ require 'docgenerator_sections'
119
+ require 'docgenerator_tabular'
120
+ require 'docgenerator_footnote'
121
+ require 'docgenerator_characters' #special characters (spaces, euro-sign...)
122
+
123
+ __END__
124
+ class Test
125
+ def required?(); true; end
126
+ end
127
+ test = Test.new()
128
+ puts test.required?
129
+ Test.class_eval('def required?(); false; end')
130
+ puts test.required?
131
+
132
+ testclass2 = Class.new( Test )
133
+ test2 = testclass2.new()
134
+ puts test2.required?
135
+ testclass2.class_eval('def required?(); true; end')
136
+ puts test2.required?
137
+ puts test.required?
@@ -0,0 +1,142 @@
1
+ #Administrate attributes for elements.
2
+ class Attribute
3
+ include Backlinks
4
+ @@settings = {}
5
+ @@values = {}
6
+ @@sortkey = 99 #Just a counter to get identic positions between different program runs.
7
+ #Generic creation of a new class to define a new Atttribute.
8
+ #Settings is a hash with generell settings.
9
+ #Supported parameters:
10
+ #- :required
11
+ #- :content adding values to this attribute add it to the content.
12
+ #- :values allowed values
13
+ #- :html used for html-output
14
+ #- :latex used for latex-output
15
+ #The sortkey is used for a sort-sequence of attributes.
16
+ def Attribute.create( settings = [], values = nil, sortkey = (@@sortkey += 1 ) )
17
+ #First some checks
18
+ if ! settings.kind_of?( Array )
19
+ raise "Type error Attribute.create: Expected Array, get #{attr.class}"
20
+ end
21
+ #Generic class creation
22
+ attributeclass = Class.new( Attribute )
23
+ #Set the flags.
24
+ settings.each{|setting|
25
+ case setting
26
+ when :required
27
+ attributeclass.class_eval('def required?(); true; end')
28
+ when :content
29
+ attributeclass.class_eval('def content?(); true; end')
30
+ when :unique
31
+ attributeclass.class_eval('def unique?(); true; end')
32
+ when :html
33
+ attributeclass.class_eval('def html?(); true; end')
34
+ when :latex
35
+ attributeclass.class_eval('def latex?(); true; end')
36
+ when :texkeyval
37
+ attributeclass.class_eval('def texkeyval?(); true; end')
38
+ when :text
39
+ attributeclass.class_eval('def text?(); true; end')
40
+ when :wiki
41
+ attributeclass.class_eval('def wiki?(); true; end')
42
+ else
43
+ puts "Attribute: Unknown setting <#{setting.inspect}>"
44
+ end
45
+ }
46
+ if values
47
+ attributeclass.class_eval("def allowed_values(); return #{values.inspect}; end")
48
+ end
49
+ attributeclass.class_eval("def sortkey(); return #{sortkey}; end")
50
+ return attributeclass
51
+ end
52
+
53
+ #Each attribute is assigned to an element.
54
+ def initialize( name, element )
55
+ @name = name
56
+ @element = element
57
+ @attr_content = []
58
+ @part_of = [element] #list of elements, where this element is part of (normaly only one element)
59
+ @part_of_doc = [] #list of documents, where this element is part of (normaly only one document)
60
+ #@part_of_doc = element.part_of_doc May not work - is empty to generation time
61
+
62
+ end
63
+ #Return class settings. Can be used for some checks.
64
+ def settings()
65
+ @@settings
66
+ end
67
+ #Check if the attribute is required.
68
+ #Redefined by Attribute.create and used in Element.to_s.
69
+ def required?(); false; end
70
+ #Check if the attribute can contain a "content".
71
+ #Redefined by Attribute.create.
72
+ def content?(); false; end
73
+ #Values may be added only once.
74
+ def unique?(); false; end
75
+ #Sometimes the content of an attribute is needed directly.
76
+ def content(); @attr_content; end
77
+ #Check if content was added
78
+ def filled?(); return @attr_content.size > 0; end
79
+ #Attribut is used for HTML.
80
+ def html?(); false; end
81
+ #Attribut is used for Text.
82
+ def text?(); false; end
83
+ #Attribut is used for Wiki.
84
+ def wiki?(); false; end
85
+ #Attribute is used for latex.
86
+ #Only for informational reasons.
87
+ def latex?(); false; end
88
+ #Attribute is used as a keyval-option
89
+ def texkeyval?(); false; end
90
+ #Return all allowed values.
91
+ #Redefined by Attribute.create and used in Attributes.<<
92
+ #By default everything is allowed.
93
+ #
94
+ #This method must return an Array with the allowed values or classes.
95
+ def allowed_values()
96
+ return nil
97
+ end
98
+ #Check if the given value is allowed.
99
+ def allowed?( value )
100
+ return true if allowed_values() == nil
101
+ allowed_values().each{|v|
102
+ if value == v
103
+ return true
104
+ elsif v.class == Class and value.is_a?( v )
105
+ return true
106
+ end
107
+ #Check next allowed value.
108
+ }
109
+ #No allowed value is set.
110
+ return false
111
+ #~ return allowed_values().include?( value )
112
+ end
113
+ #Add a value to the attribute content.
114
+ def <<( value )
115
+ if ! self.allowed?( value )
116
+ puts "Attribute #{@name}: Illegal value #{value.inspect} in #{@element.inspect}"
117
+ end
118
+ set_backlink( value )
119
+ if unique? and @attr_content.size > 0
120
+ puts "Attribute #{@name}: More then one value added (#{value}) in #{@element.inspect}"
121
+ return self
122
+ end
123
+ if content?
124
+ @element << value
125
+ else
126
+ @attr_content << value
127
+ end
128
+ end
129
+ #Return the content.
130
+ def to_s()
131
+ #~ def to_s( target = Document.target( self ) )
132
+ #list of documents, where this element is part of (normaly only one element)
133
+ if @part_of_doc.size == 0
134
+ @part_of_doc = @element.part_of_doc
135
+ set_backlink( @attr_content )
136
+ end
137
+ @attr_content.to_s()
138
+ end
139
+ def inspect()
140
+ return "<#Attribute #{@name} #{@attr_content.inspect} (in #{@element.ids}) >"
141
+ end
142
+ end
@@ -0,0 +1,171 @@
1
+ #
2
+ # Special Characters
3
+ #
4
+ Element.create( [:space, :ensp], {},false,
5
+ { :html => '&ensp;',
6
+ :latex => '~'
7
+ } )
8
+ Element.create( [:bigspace, :emsp], {},false,
9
+ { :html => '&emsp;',
10
+ :latex => '~~'
11
+ } )
12
+ Element.create( [:nbsp], {},false,
13
+ { :html => '&nbsp;',
14
+ :latex => '~'
15
+ } )
16
+ #
17
+ #Requires \usepackage[right,eurosym]{eurofont}
18
+ # @head << element(:usepackage, {:option=>'right,eurosym' }, 'eurofont' )
19
+ Element.create( [:euro], {},false,
20
+ { :html => '&euro;',
21
+ :latex => '\euro'
22
+ } )
23
+
24
+ Element.create( [:percent, :'%'], {},false,
25
+ { :html => '%',
26
+ :latex => '\%'
27
+ } )
28
+
29
+ Element.create( [:'^'], {},false,
30
+ { :html => '^',
31
+ :latex => '\hat{}'
32
+ } )
33
+
34
+ Element.create( [:iquest ], {},false, #� umgekehrtes Fragezeichen
35
+ { :html => '&iquest;',
36
+ :latex => '�' #?`
37
+ } )
38
+
39
+
40
+ Element.create( [:ampersand, :'&'], {},false,
41
+ { :html => '&amp;',
42
+ :latex => '\&'
43
+ } )
44
+
45
+ Element.create( [:rbrace, :'}'], {},false,
46
+ { :html => '}',
47
+ :latex => '\}'
48
+ } )
49
+ Element.create( [:lbrace, :'{'], {},false,
50
+ { :html => '{',
51
+ :latex => '\{'
52
+ } )
53
+
54
+ Element.create( [:backslash ], {},false,
55
+ { :html => '\\',
56
+ :latex => '\ensuremath{\backslash}'
57
+ } )
58
+
59
+ Element.create( [:radic], {},false,
60
+ { :html => '&radic;',
61
+ :latex => '\ensuremath{\sqrt{}}'
62
+ } )
63
+
64
+ Element.create( [:rarr, :rightarrow, :'->'], {},false,
65
+ { :html => '&rarr;',
66
+ :latex => '\ensuremath{\rightarrow}'
67
+ } )
68
+
69
+ Element.create( [:rArr, :Rightarrow, :'=>'], {},false,
70
+ { :html => '&rArr;',
71
+ :latex => '\ensuremath{\Rightarrow}'
72
+ } )
73
+ Element.create( [:larr, :leftarrow, :'<-'], {},false,
74
+ { :html => '&larr;',
75
+ :latex => '\ensuremath{\leftarrow}'
76
+ } )
77
+
78
+ Element.create( [:lArr, :Leftarrow, :'<='], {},false,
79
+ { :html => '&lArr;',
80
+ :latex => '\ensuremath{\Lefttarrow}'
81
+ } )
82
+
83
+ Element.create( [:uArr, :Uparrow ], {},false,
84
+ { :html => '&uArr;',
85
+ :latex => '\ensuremath{\Uparrow}'
86
+ } )
87
+
88
+ Element.create( [:lt, :'<'], {},false,
89
+ { :html => '&lt;',
90
+ :latex => '\ensuremath{<}'
91
+ } )
92
+ Element.create( [:gt, :'>'], {},false,
93
+ { :html => '&gt;',
94
+ :latex => '\ensuremath{>}'
95
+ } )
96
+
97
+ Element.create( [:infin, :infty], {},false,
98
+ { :html => '&infin;',
99
+ :latex => '\ensuremath{\infty}'
100
+ } )
101
+
102
+ Element.create( [:divide ], {},false,
103
+ { :html => '&divide;',
104
+ :latex => '\ensuremath{\div}'
105
+ } )
106
+
107
+ Element.create( [:yen], {},false,
108
+ { :html => '&yen;',
109
+ #~ :latex => '\ensuremath{\infty}'
110
+ } )
111
+
112
+ Element.create( [:sim ], {},false,
113
+ { :html => '&sim;',
114
+ :latex => '\ensuremath{\sim}'
115
+ } )
116
+
117
+ Element.create( [:brvbar ], {},false, #durchbrochener Strich
118
+ { :html => '&brvbar;',
119
+ :latex => '|' #not really correct
120
+ #~ :latex => '\ensuremath{\sim}'
121
+ } )
122
+
123
+ Element.create( [:euros], {},true,
124
+ { :html => '#{@content}&euro;',
125
+ :latex => '\euros{#{@content}}'
126
+ } )
127
+
128
+
129
+ Element.create( [:neg, :not], {},false,
130
+ { :html => '&not;',
131
+ :latex => '\ensuremath{\neg}'
132
+ } )
133
+
134
+ Element.create( [:times], {},false,
135
+ { :html => '&times;',
136
+ :latex => '\ensuremath{\times}'
137
+ } )
138
+
139
+ Element.create( [:otimes], {},false,
140
+ { :html => '&otimes;',
141
+ :latex => '\ensuremath{\otimes}'
142
+ } )
143
+
144
+ Element.create( [:empty], {},false,
145
+ { :html => '&empty;',
146
+ :latex => '\ensuremath{\emptyset}' #fixme richtig?
147
+ } )
148
+
149
+ Element.create( [:'_', :underscore], {},false,
150
+ { :html => '_',
151
+ :latex => '\_',
152
+ } )
153
+
154
+ Element.create( [:bullet], {},false,
155
+ { :html => '&#149;',
156
+ :latex => '\ensuremath{\bullet}'
157
+ } )
158
+ Element.create( [:'--', :ndash], {},false,
159
+ { :html => '&ndash;', #'&#8211;'
160
+ #:html => '&#150;',
161
+ :latex => '--'
162
+ } )
163
+ Element.create( [:'---', :mdash], {},false,
164
+ { :html => '&mdash;', #'&#8212;'
165
+ #:html => '&#151;',
166
+ :latex => '---'
167
+ } )
168
+ Element.create( [:dagger], {},false,
169
+ { :html => '&dagger;',
170
+ :latex => '\dag'
171
+ } )
@@ -0,0 +1,207 @@
1
+ if __FILE__ == $0
2
+ require 'docgenerator'
3
+ end
4
+
5
+ #~ Element.create( [:style], {
6
+ #~ :type => Attribute.create( [ :html, :required ], "text/css", 1 ),
7
+ #~ }, true,
8
+ #~ { :htmltag => 'style',
9
+ #~ :html => "\n<style type=\"text/css\">\n" + '#{@content}' + "</style>\n",
10
+ #~ :latex => nil
11
+ #~ } )
12
+
13
+ class Style < Element
14
+ Element.add( [:style], self)
15
+ #~ add_attributes( HTML_ATTR_ALL )
16
+ add_output( :latex, '')
17
+ #Prepare HTML-Output for Style-Tag.
18
+ #The values can be overwritten, if different CSS-Elements are inside.
19
+ def to_html()
20
+ res = ""
21
+ res << "\n" if @crbefore
22
+ res << "<style type=\"text/css\">\n"
23
+ @content.each{|c|
24
+ if c.is_a?(CSS)
25
+ res << c.to_tab.join(";\n")
26
+ res << ";\n"
27
+ else #For compatibility
28
+ res << "#{c};\n"
29
+ end
30
+ }
31
+ res << "</style>"
32
+ res << "\n" if @crafter
33
+ return res
34
+ end
35
+ end
36
+
37
+ CSS_COLORS = [ /rgb\((\d+%?,?){3,3}\)/,
38
+ #rgb(R,G,B), rgb(%,%,%) oder #XXXXXX
39
+ #/gray\d{1,3}/
40
+ 'black','gray','maroon','red', 'green', 'lime', 'olive', 'yellow', 'navy', 'blue', 'purple', 'fuchsia', 'teal', 'aqua', 'silver', 'white',
41
+ #Netscape-Farbnamen (120 zus�tzliche Farben)
42
+ #Falsche Darstellungen, siehe http://www.rzuser.uni-heidelberg.de/~x22/ht/farben2.html
43
+ 'lightblue', 'lightcoral', 'lightcyan', 'lightgoldenrodyellow', 'lightgreen', 'lightgrey', 'lightpink', 'lightsalmon', 'lightseagreen', 'lightskyblue', 'lightslategray', 'lightsteelblue', 'lightyellow',
44
+ 'greenyellow', 'palegreen', 'darkgreen',
45
+ 'darkred', 'firebrick',
46
+ 'salmon',
47
+ ]
48
+ CSS_BORDER = [ 'none', 'hidden', 'dotted', 'dashed', 'solid', 'double', 'groove', 'ridge', 'inset', 'outset' ]
49
+ CSS_WIDTH = [ /\d*(cm|mm|px|em|%)/, 'thin', 'medium', 'thick' ]
50
+ #Class to collect css-settings for a Element.
51
+ #This values can be used inline (style-Attribute) and inside style>-Tags
52
+ class CSS
53
+ #List of all allowed values.
54
+ #The first value is a regular expression, coninued by fixed values.
55
+ @@values = {
56
+ 'font-size' => [ /\A\d+(pt|px|em)/, 'xx-small', 'x-small', 'small', 'medium', 'large','x-large','xx-large','smaller','larger' ],
57
+ 'font-style' => ['italic', 'oblique', 'normal'],
58
+ 'font-weight' => ['bold' ], #fixme complete it
59
+ 'color' => CSS_COLORS,
60
+ 'background-color' => CSS_COLORS,
61
+ 'visibility' => ['hidden', 'visible' ],
62
+ 'text-decoration' => ['underline', 'overline', 'line-through', 'blink', 'none'],
63
+ #Ausrichtung
64
+ 'float' => ['left', 'right', 'none' ],
65
+ 'text-align' => ['left', 'center', 'right', 'justify', 'char'],
66
+ 'vertical-align' => ['top', 'middle','bottom','baseline','sub','super','text-top','text-bottom'],
67
+ 'clear' => ['left', 'right','both','none'], #Fortsetzung bei Textumfluss
68
+ 'white-space' => [ 'normal', 'pre', 'nowrap' ], #Textumbruch innererhalb des tags
69
+ #Borders: CSS-Eigenschaften: Au�enrand/Abstand
70
+ 'margin' => CSS_WIDTH,
71
+ 'margin-top' => CSS_WIDTH,
72
+ 'margin-bottom' => CSS_WIDTH,
73
+ 'margin-left' => CSS_WIDTH,
74
+ 'margin-right' => CSS_WIDTH,
75
+ #Borders: CSS-Eigenschaften: Innenabstand
76
+ 'padding' => CSS_WIDTH,
77
+ 'padding-top' => CSS_WIDTH,
78
+ 'padding-bottom' => CSS_WIDTH,
79
+ 'padding-left' => CSS_WIDTH,
80
+ 'padding-right' => CSS_WIDTH,
81
+ #Tabulars
82
+ 'border-style' => CSS_BORDER,
83
+ 'border-left-style' => CSS_BORDER,
84
+ 'border-right-style' => CSS_BORDER,
85
+ 'border-top-style' => CSS_BORDER,
86
+ 'border-bottom-style' => CSS_BORDER,
87
+ 'border-width' => CSS_WIDTH,
88
+ 'border-left-width' => CSS_WIDTH,
89
+ 'border-right-width' => CSS_WIDTH,
90
+ 'border-top-width' => CSS_WIDTH,
91
+ 'border-bottom-width' => CSS_WIDTH,
92
+ 'border-color' => CSS_COLORS,
93
+ 'border-left-color' => CSS_COLORS,
94
+ 'border-right-color' => CSS_COLORS,
95
+ 'border-top-color' => CSS_COLORS,
96
+ 'border-bottom-color' => CSS_COLORS,
97
+ 'table-layout' => ['auto', 'fixed'], #Not in Opera
98
+ 'empty-cells' => ['show', 'hide'],
99
+ 'border-collapse' => ['separate', 'collapse'],
100
+ #Positionierung und Anzeige von Elementen
101
+ 'position' => ['absolute', 'fixed', 'relative', 'static'],
102
+ 'top' => CSS_WIDTH,
103
+ 'left' => CSS_WIDTH,
104
+ 'bottom' => CSS_WIDTH,
105
+ 'right' => CSS_WIDTH,
106
+ 'width' => CSS_WIDTH,
107
+ 'min-width' => CSS_WIDTH,
108
+ 'max-width' => CSS_WIDTH,
109
+ 'height' => CSS_WIDTH,
110
+ 'min-height' => CSS_WIDTH,
111
+ 'max-height' => CSS_WIDTH,
112
+ 'overflow' => ['visible', 'hidden', 'scroll', 'auto' ],
113
+ #Lists
114
+ 'list-style-type' => [
115
+ 'decimal', 'lower-roman', 'upper-roman', 'lower-alpha', 'upper-alpha', 'lower-greek', 'hebrew', 'decimal-leading-zero',
116
+ 'cjk-ideographic', 'hiragana', 'katakana', 'hiragana-iroha', 'katakana-iroha', #Japanese
117
+ 'disc', 'circle', 'square', #ul
118
+ 'none'],
119
+ 'list-style-position' => [ 'inside', 'outside'],
120
+ 'list-style-image' => String, #URI
121
+ #~ 'list-style' => @@values['list-style-type'] + @@values['list-style-position'],
122
+ #Generell settings
123
+ #~ ['bottom', 'top', 'middle', 'baseline'],
124
+ }
125
+ def initialize( values ={} )
126
+ @values = {}
127
+ values.each{|k,v|
128
+ self[k] = v
129
+ }
130
+ @cr = nil
131
+ end
132
+ #Make key unique. convert symbol to String...
133
+ def generalize_key( k )
134
+ key = nil
135
+ if k.is_a?(Symbol)
136
+ key = k.to_s.gsub('_','-')
137
+ else
138
+ key = k
139
+ end
140
+ return key
141
+ end
142
+ def []( k )
143
+ return @values[generalize_key( k )]
144
+ end
145
+ #Add a setting.
146
+ #
147
+ #If an existing value is overwritten, you get a warning.
148
+ #To replace a value, use
149
+ # css[key].replace( value ) (But the you have no check)
150
+ def []=( k, v )
151
+ key = generalize_key( k )
152
+ if @values[key]
153
+ puts "CSS: Overwrite #{k.inspect}"
154
+ end
155
+ if ! @@values[key]
156
+ puts "CSS: Undefined key #{k.inspect}"
157
+ elsif @@values[key].include?(v) #Fine
158
+ elsif @@values[key][0].is_a?(Regexp) and @@values[key][0] =~ v.to_s
159
+ else
160
+ puts "CSS: #{v} not allowed for #{key}"
161
+ end
162
+
163
+ @values[key] = v
164
+ end
165
+ #returns the values for a direct css in the style-attribute for a HTML-tag.
166
+ def to_s()
167
+ return self.to_tab.join(';')
168
+ end
169
+ #Returns a tab with the textes for each characteristic.
170
+ def to_tab()
171
+ s = []
172
+ @values.each{|k,v|
173
+ s << "#{k}: #{v}"
174
+ }
175
+ return s
176
+ end
177
+ end
178
+
179
+ if __FILE__ == $0
180
+ require 'docgenerator'
181
+ css = CSS.new({ :text_align => 'AA', :font_size => 'large'})
182
+ css2 = CSS.new({ :font_size => '12px'})
183
+ puts '-'*10
184
+ style = element(:style)
185
+ style << 'a'
186
+ style << css
187
+ style << css
188
+ puts css.to_s()
189
+ puts '-'*5
190
+ puts style.to_s(:html)
191
+ #~ puts style.to_s(:latex)
192
+
193
+ end
194
+
195
+ __END__
196
+ <style type="text/css">
197
+ <!--
198
+ test {
199
+ font-family: monospace;
200
+ font-size: xx-large;
201
+ font-weight: bold;
202
+ font-style: italic;
203
+ text-decoration: underline;
204
+ text-align: center;
205
+ }
206
+ -->
207
+ </style>