docgenerator 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
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>