Class: Docgenerator::Element

Inherits:
Object
  • Object
show all
Includes:
Docgenerator
Defined in:
lib/docgenerator/element.rb,
lib/docgenerator/element_meta.rb,
lib/docgenerator/compatibility_v1.rb

Overview

This class defines possible elements of a document. For each type of elements a class is defined. The definition can be done explicite or generic with Element.create.

All types of elements are stored in a hash, the elements can be created via the method Element.get (or element() ).

Direct Known Subclasses

Characters::Ampersand, Characters::Backslash, Characters::Bigspace, Characters::Brvbar, Characters::Bullet, Characters::DDownarrow, Characters::Dagger, Characters::Divide, Characters::Dollar, Characters::Doublelowquotemark, Characters::Downarrow, Characters::Empty, Characters::Euro, Characters::Euros, Characters::Gg, Characters::Gt, Characters::Hat, Characters::Infin, Characters::Iquest, Characters::LLeftarrow, Characters::Lbrace, Characters::Ldots, Characters::Leftarrow, Characters::Leftdoublequotemark, Characters::Leftsinglequotemark, Characters::Ll, Characters::Lt, Characters::Mdash, Characters::Nbsp, Characters::Ndash, Characters::Neg, Characters::Otimes, Characters::Percent, Characters::RRightarrow, Characters::Radic, Characters::Rbrace, Characters::Rightarrow, Characters::Rightdoublequotemark, Characters::Rightsinglequotemark, Characters::Shy, Characters::Sim, Characters::Singlelowquotemark, Characters::Space, Characters::Thinsp, Characters::Times, Characters::UUparrow, Characters::Underscore, Characters::Uparrow, Characters::Wbr, Characters::Yen, Characters::ZeroWidthSpace, Docgenerator::Elements::Addcontentsline, Docgenerator::Elements::Addtocontents, Docgenerator::Elements::Author, Docgenerator::Elements::Body, Docgenerator::Elements::Centering, Docgenerator::Elements::Clearpage, Docgenerator::Elements::Comment, Docgenerator::Elements::Creator, Docgenerator::Elements::Date, Docgenerator::Elements::Div, Docgenerator::Elements::Emph, Docgenerator::Elements::Ensuremath, Docgenerator::Elements::Font, Docgenerator::Elements::Footnotesize, Docgenerator::Elements::HHuge, Docgenerator::Elements::Head, Docgenerator::Elements::Hfill, Docgenerator::Elements::Href, Docgenerator::Elements::Hrulefill, Docgenerator::Elements::Hspace, Docgenerator::Elements::Htmldummy, Docgenerator::Elements::Huge, Docgenerator::Elements::Hypertarget, Docgenerator::Elements::Img, Docgenerator::Elements::Include, Docgenerator::Elements::Input, Docgenerator::Elements::Keywords, Docgenerator::Elements::LLarge, Docgenerator::Elements::Label, Docgenerator::Elements::Large, Docgenerator::Elements::Latexdummy, Docgenerator::Elements::Link, Docgenerator::Elements::Listoffigures, Docgenerator::Elements::Maketitle, Docgenerator::Elements::Meta, Docgenerator::Elements::Meta2, Docgenerator::Elements::Metadescription, Docgenerator::Elements::Newline, Docgenerator::Elements::Newpage, Docgenerator::Elements::Nobr, Docgenerator::Elements::Normalsize, Docgenerator::Elements::Pageref, Docgenerator::Elements::Pagestyle, Docgenerator::Elements::Par, Docgenerator::Elements::Ref, Docgenerator::Elements::Relax, Docgenerator::Elements::Scriptsize, Docgenerator::Elements::Sepline, Docgenerator::Elements::Small, Docgenerator::Elements::Span, Docgenerator::Elements::Stroke, Docgenerator::Elements::Sub, Docgenerator::Elements::Sup, Docgenerator::Elements::Tableofcontents, Docgenerator::Elements::Textbf, Docgenerator::Elements::Textsc, Docgenerator::Elements::Thispagestyle, Docgenerator::Elements::Tiny, Docgenerator::Elements::Title, Docgenerator::Elements::Title::Subtitle, Docgenerator::Elements::Twocolumn, Docgenerator::Elements::Underline, Docgenerator::Elements::Url, Docgenerator::Elements::Usepackage, Docgenerator::Elements::Verb, Docgenerator::Elements::Vfill, Docgenerator::Elements::Vspace, Docgenerator::Environments::Center, Docgenerator::Environments::Environment, Docgenerator::Environments::Landscape, Docgenerator::Environments::Minipage, Docgenerator::Environments::Quote, Footnote, Footnotemark, Index::Index, Index::Makeindex, Index::Newindex, Index::Printindex, Index::Sindex, Listings::Lstdefinestyle, Listings::Lstinline, Listings::Lstinputlisting, Listings::Lstlistoflistings, Listings::Lstloadlanguages, Listings::Lstset, Lists::DD, Lists::DT, Lists::Item, Packages::Attachfile::Attachfile, Packages::Attachfile::Noattachfile, Packages::Attachfile::Notextattachfile, Packages::Attachfile::Textattachfile, Packages::Caption::Captionof, Packages::Hyperref::Checkbox, Packages::Hyperref::Choicemenu, Packages::Hyperref::Pushbutton, Packages::Hyperref::Reset, Packages::Hyperref::Textfield, Packages::Letter::LoadLetterOption, Packages::Letter::Setkomavar, Packages::PDFPages::IncludePDF, Packages::Path, Packages::Scrpage2::Automark, Packages::Scrpage2::Cefoot, Packages::Scrpage2::Cehead, Packages::Scrpage2::Cfoot, Packages::Scrpage2::Chead, Packages::Scrpage2::Clearscrheadfoot, Packages::Scrpage2::Clearscrheadings, Packages::Scrpage2::Clearscrplain, Packages::Scrpage2::Cofoot, Packages::Scrpage2::Cohead, Packages::Scrpage2::Ifoot, Packages::Scrpage2::Ihead, Packages::Scrpage2::Lefoot, Packages::Scrpage2::Lehead, Packages::Scrpage2::Lofoot, Packages::Scrpage2::Lohead, Packages::Scrpage2::Manualmark, Packages::Scrpage2::Ofoot, Packages::Scrpage2::Ohead, Packages::Scrpage2::Refoot, Packages::Scrpage2::Rehead, Packages::Scrpage2::Rofoot, Packages::Scrpage2::Rohead, Packages::Todonotes::Listoftodos, Packages::Todonotes::Missingfigure, Packages::Todonotes::Todo, Sectioning::Addpart, Sectioning::Addsec, Sectioning::DummySectioning, Style, Tables::Bottomrule, Tables::Caption, Tables::Column, Tables::Endfirsthead, Tables::Endfoot, Tables::Endhead, Tables::Endlastfoot, Tables::Hline, Tables::Midrule, Tables::Row, Tables::Tabular, Tables::Toprule

Constant Summary collapse

SUPPORTED_TARGETS =
[ :latex, :html, :wiki, :text, :debug ]
@@level =
0
@@ids =

Hash with all ids and their corresponding classes.

Hash.new( )

Constants included from Docgenerator

ATTR_LANG, CSS_BORDER, CSS_COLORS, CSS_WIDTH, DOCGENERATOR_DEFAULT_LOGGER, DOCGENERATOR_LOGGER, ENDTAG, HTML_ATTR_ALIGN, HTML_ATTR_ALL, HTML_ATTR_CORE, HTML_ATTR_EVENTS, HTML_ATTR_I18N, HTML_ATTR_VALIGN, VERSION

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Docgenerator

#set_option_defaults, set_option_defaults, trace_off, trace_on, trace_on?

Constructor Details

#initialize(attr = {}, content = nil) ⇒ Element

Defines an element.

There are two ways to add values:

  • “named” values in an hash.

This named values can be attributes of a HTML-Tag or Parameters of a TeX-Makro.
There is a check, if the attribute exist.
  • Content. Values “inside” the element.

The content can be the content of a HTML-Tag or the content of a TeX-Environment.
There is a check, if this class allows content.

:log is the default attribute for the logger. In Elementto_doc you can give another logger!



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/docgenerator/element.rb', line 39

def initialize( attr={}, content = nil)
  #@attr is a hash containing the values for each attribute.
  @attr = Hash.new(  )
  #Attention! in to_doc another logger may be given.
  @log  = attr[:log] || DOCGENERATOR_DEFAULT_LOGGER
  attr.delete(:log) #remove from attr-interface
  #attr alias
  @attr_alias = Hash.new(  )
  if self.content?()
    @content  = []
  else
    @content  = nil
  end
  @crbefore  = false  #make \n before element
  @crmid  = false  #make \n before and after opening/closing html-tag
  @crafter  = false  #make \n after element
  #List of targets, where the element can be used.
  #Details see method restrict_to()
  #Default: allsupported targets
  @targets  = SUPPORTED_TARGETS.dup
  @suppressed_targets = []
  
  #Initialize the attribute hash.
  self.class.attributes.each{ |k,a|
    #type check on Attribute does not work .
    if a.kind_of?( Symbol )
      #Filled in the second run
      #~ @attr[k] = @attr[a]
    elsif a  #.kind_of?( Attribute )
      @attr[k] = a.new( k, self )
    else
      @attr[k] = Attribute.create().new( k, self )
    end
  }
  #Assign Alias-Attributes
  self.class.attributes.each{ |k,a|
    next if !a.kind_of?( Symbol )
    if @attr[a]
      @attr_alias[k] = @attr[a]
    else
      @log.warn("Undefined Alias-Attribute #{k}") if @log.warn?
      @attr[k] = Attribute.create().new( k, self )
    end
  }
  attr.each{ |k,v|
    if @attr[k]
      @attr[k] << v
    elsif @attr_alias[k]
      @attr_alias[k] << v
    else
      @log.warn("Usage of unknown attribute '#{k}' in #{self.inspect} (Available: #{@attr.keys})") if @log.warn?
      #~ @log.debug(caller) if @log.debug?
    end
  }
  #store info, where the element was created 
  @creation_caller = prepare_tracing_info() if Docgenerator.trace_on?
  self << content if  content 
end

Instance Attribute Details

#attrObject (readonly)

Accessor on attribute list



268
269
270
# File 'lib/docgenerator/element.rb', line 268

def attr
  @attr
end

#contentObject (readonly)

Accessor on content



152
153
154
# File 'lib/docgenerator/element.rb', line 152

def content
  @content
end

#logObject (readonly)

Logger of the element



154
155
156
# File 'lib/docgenerator/element.rb', line 154

def log
  @log
end

Class Method Details

.add(idlist, elementClass) ⇒ Object

Add a new element class or assign another name (synonym) for a class. The initial call is made by Element.inherited.

Element.add( [:element], Element )

Replaced by meta method Element.add_id



72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/docgenerator/compatibility_v1.rb', line 72

def  self.add( idlist, elementClass )
  #~ DOCGENERATOR_LOGGER.warn("Element.add called -> to be replaced") if DOCGENERATOR_LOGGER.warn?
  if ! elementClass.new.kind_of?( Element )
    raise "Element.add get no Element-class #{elementClass}"
  end
  idlist = [ idlist ] if ! idlist.kind_of?( Array )
  raise "Empty idlist for #{elementClass}" if idlist.empty?
  
  idlist.each{|id|
    elementClass.add_id(id)
  }
end

.add_attribute(id, attribute) ⇒ Object

Add a attribute to the metaclass

Example:

class XX < Element
  add_attribute :key, Attribute.create( ... )
    }
end


94
95
96
97
98
99
100
# File 'lib/docgenerator/element_meta.rb', line 94

def add_attribute(id, attribute)
  @attr = {} unless @attr
  #~ if ! attribute.is_a?(Attribute)
  #~ DOCGENERATOR_LOGGER.error("Attribute #{id} is no Docgenerator::Attribute but #{attribute.inspect}") if DOCGENERATOR_LOGGER.error?
  #~ end
  @attr[id] = attribute
end

.add_attributes(attr) ⇒ Object

Add possible attributes to an element class.

Attributes are defined in a hash, each key get a Attribute-instance.

Example:

class XX < Element
  add_attributes { 
      :key => Attribute.create( ... ),
    }
end


113
114
115
116
117
# File 'lib/docgenerator/element_meta.rb', line 113

def add_attributes( attr )
  attr.each{ |k,a |
    self.add_attribute(k,a)
  }
end

.add_context_output(output = nil, &cmd) ⇒ Object

Define the output routine for conTeXt. See Element.add_output for details.



265
266
267
# File 'lib/docgenerator/element_meta.rb', line 265

def add_context_output( output = nil, &cmd )
  self.add_output(:context, output, &cmd )
end

.add_creole_output(output = nil, &cmd) ⇒ Object

Define the output routine for creole. See Element.add_output for details.



286
287
288
# File 'lib/docgenerator/element_meta.rb', line 286

def add_creole_output( output = nil, &cmd )
  self.add_output(:creole, output, &cmd )
end

.add_html_output(output = nil, &cmd) ⇒ Object

Define the output routine for html. See Element.add_output for details.



251
252
253
# File 'lib/docgenerator/element_meta.rb', line 251

def add_html_output( output = nil, &cmd )
  self.add_output(:html, output, &cmd )
end

.add_html_tag(tag) ⇒ Object

Define the HTML-tag for the to_html method.



244
245
246
# File 'lib/docgenerator/element_meta.rb', line 244

def add_html_tag( tag )
  self.class_eval( "def htmltag()\n'#{tag}'\nend" )
end

.add_id(id) ⇒ Object

Add a new element class or assign another name (synonym) for a class. The initial call is made by Element.inherited.



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/docgenerator/element_meta.rb', line 56

def add_id(id)
  @element_ids ||= []
  if @@ids[ id ] == nil
    DOCGENERATOR_LOGGER.debug("Element id '#{id}' is new for #{self}") if DOCGENERATOR_LOGGER.debug?
    #All new ids are collected
    @@ids[ id ] = self
    @element_ids << id
  elsif  @@ids[ id ] == self
    DOCGENERATOR_LOGGER.warn("Element class '#{id}' is defined double: #{self}") if DOCGENERATOR_LOGGER.warn?
  else
    DOCGENERATOR_LOGGER.error("Error: ID '#{id}' is redefined #{@@ids[id]} -> #{self}") if DOCGENERATOR_LOGGER.error?
    @@ids[id] = self
    @element_ids << id
  end
end

.add_latex_output(output = nil, &cmd) ⇒ Object

Define the output routine for LaTeX. See Element.add_output for details.



258
259
260
# File 'lib/docgenerator/element_meta.rb', line 258

def add_latex_output( output = nil, &cmd )
  self.add_output(:latex, output, &cmd )
end

.add_output(target, string = nil, &proc) ⇒ Object

Add an output routine.

Called by

  • add_latex_output

  • add_context_output

  • add_html_output

  • add_text_output

  • add_wiki_output

  • add_creole_output

The definition can be made in two ways:

  • block

  • result string

For very complex elements, it may be better to use the block variant or to redefine to_latex, to_html …

Definition with block

Example:

add_output(:latex) {|options = {}|
    o = set_option_defaults(options) #define logger
    o[:log].debug("enter to_doc(#{target}) for #{self.inspect}") if o[:log].debug?
    ...
  }

The block must contain one optional parameter (default {}).

Definition with result string

Example:

add_output( :latex, '\section{#{@content}}' )

The string contains the result. The string will be interpreted, when the to_xxxx method is called.

Examples for string:

'#{linebreak(@crbefore)}\section{#{@content}}#{linebreak(@crafter)}'

Some special helper to build the result:

linebreaks

linebreak(xx) will create a #linebreak, when xx is true. xx may be @crbefore, @crmid, @crafter. The variables can be influenced by #cr, #Cr, #cR, #CR.

recursive content

‘@content}’ will be replaced by ‘@content.to_doc( target , o)}’

  • If you define something like @content.to_html…, please give attention for the options.

Attributes

Attributes can be accessed with @attr

Key-val attributes

#texkeyval add all attributes with flag :texkeyval. (see Attribute#texkeyval?)



192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
# File 'lib/docgenerator/element_meta.rb', line 192

def add_output( target, string = nil, &proc )
  
  if ! [ :latex, :context, :html, :text, :wiki, :creole ].include?(target)
    DOCGENERATOR_LOGGER.error("#{self}: Undefined target format #{target}") if DOCGENERATOR_LOGGER.error?
  end
  
  if block_given?
    if string
      DOCGENERATOR_LOGGER.error("add_output #{target} contains result string and block. Use the block definietion #{self.inspect}") if DOCGENERATOR_LOGGER.error?
    end
    #The (optional) parameter should be {} by default.
    if proc.respond_to?(:parameters) #since ruby 1.9.2
      if proc.parameters.size != 1  #Proc#parameters introduced with ruby 1.9.2
        DOCGENERATOR_LOGGER.error("add_output #{target}: Arity of block not 1 but #{proc.parameters.inspect} #{self.inspect}") if DOCGENERATOR_LOGGER.error?
      elsif proc.parameters.first.first != :opt
        DOCGENERATOR_LOGGER.error("add_output #{target}: Block parameter is not optional #{proc.parameters.inspect} #{self.inspect}") if DOCGENERATOR_LOGGER.error?
        #the optional parameter should have the default {}
        #no way to test it, see http://forum.ruby-portal.de/viewtopic.php?f=22&t=12384
      end
    else  #Proc#parameters not supported
      if proc.arity > 1  #makes arity 0 also for optional parameters.
        DOCGENERATOR_LOGGER.error("add_output #{target}: Arity of block not 1 but #{proc.arity} #{self.inspect}") if DOCGENERATOR_LOGGER.error?
      end
    end
    #Define the method.
    define_method( "to_#{target}".to_sym, &proc )
  else      #block_given?
=begin
Define the output routine, based on a string.
=end
    if ! string.kind_of?( String )
      DOCGENERATOR_LOGGER.error("<#{self.inspect}>#add_output: #{string.inspect} is no String")
    end
    cmd = <<-code
    def to_#{target}(options = {})
      o = set_option_defaults(options)
      o[:log].debug("enter to_#{target} for #{self.inspect}, options: \#{options.keys.inspect}") if o[:log].debug?
    code
    template = string.gsub(/\\/, '\\\\\\')
    template.gsub!(/"/, '\"')
    #define recursive to_doc for content.
    #the closing \} is important. Else you replace '@content.to_latex' with @content.to_doc.to_latex'
    template.gsub!(/@content\}/, "@content.to_doc(#{target.inspect}, o)}")
    cmd << "    \"#{template}\"\n"
    cmd << "end\n"
    class_eval( cmd )
    cmd #return cmd for unit test
  end #block_given? 
end

.add_text_output(output = nil, &cmd) ⇒ Object

Define the output routine for text. See Element.add_output for details.



272
273
274
# File 'lib/docgenerator/element_meta.rb', line 272

def add_text_output( output = nil, &cmd )
  self.add_output(:text, output, &cmd )
end

.add_wiki_output(output = nil, &cmd) ⇒ Object

Define the output routine for wiki. See Element.add_output for details.



279
280
281
# File 'lib/docgenerator/element_meta.rb', line 279

def add_wiki_output( output = nil, &cmd )
  self.add_output(:wiki, output, &cmd )
end

.attributesObject

Return the attributes for the metaclass.



121
122
123
# File 'lib/docgenerator/element_meta.rb', line 121

def attributes()
  @attr || {}
end

.create(name, attr = {}, content = false, output = {}) ⇒ Object

Generic creation of a new class to define a new element.

  • name must be defined.

  • attr is a hash with all attributes.

For details see Element.add_attributes
  • content is a flag, which defines if the element contains “content”.

Valid values are:
-  true:  content available and necessary (e.g. <p>)
-  :empty_ok: content available, but not necessary (e.g. <td> or iframe)
-  false:  no content, no endtag, but tag closed with / (example: <br />)
-  nil:    no content, no endtag, no closing  (example: <br>)
  • output contains a hash with logic, how to handle the output.

-:htmltag  Tag for html-output.
-:latex  Template for LaTeX-output
-:html    Template for HTML-output

This code is obsolete. Please use Element.create_convert_to_code to get a template to replace your Element#create.



104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
# File 'lib/docgenerator/compatibility_v1.rb', line 104

def  self.create( name, attr = {}, content = false, output = {} )
  if @@ids[name]
    DOCGENERATOR_LOGGER.error("Element.create for existing #{name.inspect} called -> ignored") if DOCGENERATOR_LOGGER.error?
    return
  else
    DOCGENERATOR_LOGGER.warn("Element.create for #{name.inspect} called -> to be replaced") if DOCGENERATOR_LOGGER.warn?
  end
  create_convert_to_code( [name].flatten, attr, content, output ) if DOCGENERATOR_LOGGER.warn?
  #First some checks
  if ! attr.kind_of?( Hash )
    raise "Type error Element.create: Expected Hash, get #{attr.class}"
  end
  
  #Generic class creation
  elementclass = Class.new( Element )
  #Add the id of the new class to central collection.
  Element.add( name, elementclass )

  #Set a flag, if the class can contain 'content'.
  #-true:  content available and necessary (e.g. <p>)
  #-:empty_ok: content available, but not necessary (e.g. <td>)
  #-false:  no content, no endtag, but tag closed with / (example: <br />)
  #-nil:    no content, no endtag, no closing  (example: <br>)
  elementclass.class_eval( %Q|
    def content?()
      return #{content.inspect}
    end|)
  
  output.each{ |k,v|
    case k
    when :latex
      elementclass.add_output( :latex,  v )
    when :context
      elementclass.add_output( :context,  v )
    when :html
      elementclass.add_output( :html,  v )
    when :text
      elementclass.add_output( :text,  v )
    when :wiki
      elementclass.add_output( :wiki,  v )
    when :creole
      elementclass.add_output( :creole,  v )
    when :htmltag
      if v
        elementclass.class_eval( "def htmltag()\n'#{v}'\nend" )
      else
        elementclass.class_eval( "def htmltag()\nnil\nend" )
      end
    else
      puts "#{__FILE__}##{__LINE__}: Unknown format #{k} for #{name}"
    end
  }
  elementclass.add_attributes( attr )
  #Return the class.
  return elementclass
end

.create_convert_to_code(name, attr = {}, content = false, output = {}) ⇒ Object

Transformer of old Element.create-Logic to metaprogramming.

Requires a manual postprocess to define Attributes correct.



166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
# File 'lib/docgenerator/compatibility_v1.rb', line 166

def  self.create_convert_to_code( name, attr = {}, content = false, output = {} )
  #First some checks
  if ! attr.kind_of?( Hash )
    raise "Type error Element.create: Expected Hash, get #{attr.class}"
  end
  #Build code for class creation
  code = "\n"
  code << <<comment
=begin rdoc
Define Element #{name.map{|x|x.inspect}.join(', ')}

Create an instance with
#{name.map{|x|
    "  element( #{x.inspect}, [ attributes, [content]] )"
  }.join("\n")
}
or
#{name.first.capitalize}.new( [ attributes, [content]] )
comment
  if attr.size == 0
    code << "Attributes are not defined for this element.\n"
  else
    code << "Attributes may be:\n"
  end
  attr.each{|key, att|
    code << "* #{key.inspect}: \n"  #fixme #{att.new.allowed_values.inspect}
  }
  code << "=end\n"
  code << "class #{name.first.capitalize} < Element\n"
  name[1..-1].each{|n|
    code << "  add_id #{n.inspect}\n"
  }
  if ! content
    code << "  has_no_content #{content.inspect}\n"
  end
  if ( HTML_ATTR_CORE.keys & attr.keys ) == HTML_ATTR_CORE.keys
    code << "  add_attributes HTML_ATTR_CORE\n"      
  end
  if ( HTML_ATTR_I18N.keys & attr.keys ) == HTML_ATTR_I18N.keys
    code << "  add_attributes HTML_ATTR_I18N\n"      
  end    
  if ( HTML_ATTR_EVENTS.keys & attr.keys ) == HTML_ATTR_EVENTS.keys
    code << "  add_attributes HTML_ATTR_EVENTS\n"      
  end    
  if attr.has_value?(ATTR_LANG)
    code << "  add_attribute #{attr.key(ATTR_LANG).inspect}, ATTR_LANG\n"      
  end    
  if attr.has_value?(HTML_ATTR_ALIGN)
    code << "  add_attribute #{attr.key(HTML_ATTR_ALIGN).inspect}, HTML_ATTR_ALIGN\n"      
  end    
  if attr.has_value?(HTML_ATTR_VALIGN)
    code << "  add_attribute #{attr.key(HTML_ATTR_VALIGN).inspect}, HTML_ATTR_VALIGN\n"      
  end    
  (   attr.keys - HTML_ATTR_CORE.keys - HTML_ATTR_I18N.keys - HTML_ATTR_EVENTS.keys
  ).each{|key|
    code << "  add_attribute #{key.inspect}, ?? )\n"  #?? - Definition aus Vorlag holen
  }
  output.each{ |k,v|
    case k
    when :latex
      code << "  add_latex_output '#{v}'\n"
    when :context
      code << "  add_context_output '#{v}'\n"
    when :html
      code << "  add_html_output '#{v}'\n"
    when :text
      code << "  add_text_output '#{v}'\n"
    when :wiki
      code << "  add_wiki_output '#{v}'\n"
    when :creole
      code << "  add_creole_output '#{v}'\n"
    when :htmltag
      if v
        code << "  add_html_tag '#{v}'\n"
      else
        #~ code << "  def htmltag(); nil; end\n" 
      end
    else
      puts "#{__FILE__}##{__LINE__}: Unknown format #{k} for #{name}"
    end
  }
  code << "end ##{name.first.capitalize}\n"
  puts code 
  #~ class_eval(code)
  #Return the class.
  return code
end

.element_idsObject

Define meta/class accessor to element_ids.



51
# File 'lib/docgenerator/element_meta.rb', line 51

def element_ids; @element_ids; end

.get(name) ⇒ Object

Return a element class.



72
73
74
# File 'lib/docgenerator/element_meta.rb', line 72

def get( name )
  return @@ids[name]
end

.get_attribute_listObject

Returns list of attributes. Can be used for copying attributes from one class to another class.



129
130
131
# File 'lib/docgenerator/element_meta.rb', line 129

def get_attribute_list()
  return self.attributes
end

.has_no_content(value = nil) ⇒ Object

Set flag, that the element does not support content.

See also Docgenerator::Element#content?



81
82
83
# File 'lib/docgenerator/element_meta.rb', line 81

def has_no_content(value = nil)
  self.class_eval( "def content?(); #{value.inspect}; end" )
end

.inherited(subclass) ⇒ Object

This method is called, when a subclass of this class is defined.

The class will be added to the element list with class name, converted to a symbol (modules are extracted in advance). The element may be created with element-method.



37
38
39
40
41
42
43
44
# File 'lib/docgenerator/element_meta.rb', line 37

def inherited( subclass )
  DOCGENERATOR_LOGGER.info("New Element class: #{subclass}") if DOCGENERATOR_LOGGER.debug?
  if subclass.name
    subclass.add_id(subclass.name.split('::').last.downcase.to_sym)
  else
    DOCGENERATOR_LOGGER.warn("New Element class without name: #{subclass}") if DOCGENERATOR_LOGGER.warn?
  end
end

.overview(list = @@ids.values.uniq) ⇒ Object

Prepares an overview on all Elements. Can be used for some debugging.



44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/docgenerator/compatibility_v1.rb', line 44

def self.overview( list = @@ids.values.uniq )
  if ! list.kind_of?(Array)
    list = [ list ]
  end
  result = '=' * 10 + "\nElement overview:"
  list.each{ |k|
    result += "\n#{k}\n"
    result += "\tId's:\t\t"
    result += k.new.element_ids.join("\n\t\t\t")
    result += "\n\tAttributes:\t"
    result += "can contain "
    result += "no " if ! k.new.content?
    result += "content\n\t\t\t"
    self.class.attributes.each{ |k2,v|
      result += "#{k2}:\t#{v.inspect}\n\t\t\t"
    }
  }
  return result
end

.trace=(val) ⇒ Object

#Set Element tracing on/off.

Obsolete. Please use

Docgenerator.trace_on


28
29
30
# File 'lib/docgenerator/compatibility_v1.rb', line 28

def self.trace=( val )
  Docgenerator.trace_on
end

Instance Method Details

#<<(content) ⇒ Object

Add something to the content. Only possible on elements, which supports “content”.



159
160
161
162
163
164
165
# File 'lib/docgenerator/element.rb', line 159

def << ( content )
  if @content
    @content << content
  else
    @log.warn("Add content to an element without this feature #{self.inspect}, #{content.inspect}") if @log.warn?
  end
end

#[](key) ⇒ Object

Return an attribute to add content.

Example:

sec = element(:section, {}, 'title' )
sec[:shorttitle] << 'shorttitle'

Normally, this is the better solution:

sec = element(:section, { :shorttitle => 'shorttitle'}, 'title' )


279
280
281
282
283
284
285
286
287
288
# File 'lib/docgenerator/element.rb', line 279

def [] (key)
  attr = @attr[key]
  #If Attribute does not exist, take a look, if it is an alias-name.
  attr = @attr_alias[key] if !attr
  if ! attr
    @log.warn("Request unknown attribute '#{key}', return a dummy (#{self.inspect})") if @log.warn?
    attr = Attribute.create( ).new(key, self)
  end
  return attr
end

#content?Boolean

Default setting, each element class may contain contents. Can be redefined by meta-method Elements.has_no_content

  • true: content available and necessary (e.g. Docgenerator::Elements::Paragraph)

  • :empty_ok: content available, but not necessary (e.g. Docgenerator::Tables::Column)

  • false: no content, no endtag, but tag closed with / (example: Docgenerator::Elements::Newline as < br/>)

  • nil: no content, no endtag, no closing (example: Docgenerator::Elements::Newline as < br>)

Returns:

  • (Boolean)


297
298
299
# File 'lib/docgenerator/element.rb', line 297

def content?()
  return true
end

#cRObject

Insert an empty line after the last entry and after the opening of the tag.

Example:

<tag>[CR]content</tag>[CR]

This feature has it reason for lists, when each :li-tag gets a cr. The first item gets also a cR.

Example:

<ul>
<li>item with cR</li>
<li>item with cr</li>
</ul>


247
248
249
250
251
252
# File 'lib/docgenerator/element.rb', line 247

def cR()
  @crbefore  = false
  @crmid  = true
  @crafter  = true
  self
end

#crObject

Insert an empty line after the last entry.

Example:

<tag>content</tag>[CR]


217
218
219
220
# File 'lib/docgenerator/element.rb', line 217

def cr()
  @crafter  = true
  self
end

#CrObject

Insert an empty line before and after the last entry.

Example:

[CR]<tag>content</tag>[CR]


227
228
229
230
231
# File 'lib/docgenerator/element.rb', line 227

def Cr()
  @crbefore  = true
  @crafter  = true
  self
end

#CRObject

Insert an empty line before and after the last entry and after the opening of the tag.

Example:

[CR]<tag>[CR]content</tag>[CR]


259
260
261
262
263
264
# File 'lib/docgenerator/element.rb', line 259

def CR()
  @crbefore  = true
  @crmid  = true
  @crafter  = true
  self
end

#delete(target) ⇒ Object

Delete the given object from content.



203
204
205
206
207
208
209
210
# File 'lib/docgenerator/element.rb', line 203

def delete(target )
  if @content
    @content.delete( target )
  else
    @log.warn("Delete content of an element without this feature") if @log.warn?
  end    
  self
end

#element_idsObject

Return all id’s of the class. The ids are filled via Element.add_id



296
297
298
299
300
# File 'lib/docgenerator/element_meta.rb', line 296

def element_ids()
  #~ myids = []
  #~ @@ids.each{|k,v| myids << k if v == self.class and k.class != Class }
  return self.class.element_ids
end

#empty?Boolean

check if there is content assigned.

Returns:

  • (Boolean)


303
304
305
# File 'lib/docgenerator/element.rb', line 303

def empty?()
  return @content.empty?
end

#htmltagObject

Define the tag for html-output.

If the method is redefined, the result is taken as a tag. Redfinition is made by Element.add_html_tag.

htmltag nil/false supress the output.



460
461
462
# File 'lib/docgenerator/element.rb', line 460

def htmltag()
  ''
end

#idsObject

Return all id’s of the class. @@ids is expanded in Element.add.

Replaced by Element.element_ids.



37
38
39
40
41
# File 'lib/docgenerator/compatibility_v1.rb', line 37

def ids( )
  myids = []
  @@ids.each{|k,v| myids << k if v == self.class and k.class != Class }
  return myids
end

#insert(target, pos, *obj) ⇒ Object

Insert content relative to a given target. The target must exist, pos defines the relative position (0=before, 1=one after the element). Method called by Element#insertbefore and Element#insertafter.



188
189
190
191
192
193
194
195
196
197
198
199
# File 'lib/docgenerator/element.rb', line 188

def insert(target,pos,*obj )
  if @content
    if @content.include?( target )
      @content[@content.index(target)+pos ,0] = obj
    else
      @log.warn("Insert content not possible. Reference object does not exist (#{target.inspect})") if @log.warn?
    end
  else
    @log.warn("Add content to an element without this feature") if @log.warn?
  end    
  self
end

#insertafter(target, *obj) ⇒ Object

Add content after a target (other content)

insertafter(target,*obj)

Requires the ability of “content”.



172
173
174
# File 'lib/docgenerator/element.rb', line 172

def insertafter(target,*obj)
  self.insert(target, 1, obj)
end

#insertbefore(target, *obj) ⇒ Object

Add content before a target (other content)

insertbefore(target,*obj)

Requires the ability of “content”.



180
181
182
# File 'lib/docgenerator/element.rb', line 180

def insertbefore(target,*obj)
  self.insert(target, 0, obj)
end

#inspectObject



128
129
130
# File 'lib/docgenerator/element.rb', line 128

def inspect()
  return "<#{self.class}#{inspect_creation_caller}>"
end

#inspect_creation_callerObject

Set a text for the inspect command.

Nil if the information was not collected at Element#new.



121
122
123
124
125
126
127
# File 'lib/docgenerator/element.rb', line 121

def inspect_creation_caller
  if @creation_caller
    ", created at #{@creation_caller}"
  else
    nil #'unknown. Please set Elements.trace if needed'
  end
end

#linebreak(flag = true) ⇒ Object

Method for definition inside Element.create.



402
403
404
# File 'lib/docgenerator/element.rb', line 402

def linebreak( flag = true )
  flag ? "\n" : ''
end

#prepare_tracing_infoObject

Only for debbuging reasons.

This method analyse the caller-stack and provides the first “no lib/docgenerator-place”. This should be the location, where the element is created.

Via Element#inspect you get access to this information.



106
107
108
109
110
111
112
113
114
115
# File 'lib/docgenerator/element.rb', line 106

def prepare_tracing_info()
  caller().each{|c|
    next if ( /lib\/(docgenerator|creole|wiki2doc)/ =~  c )
    return c
  }
  #--> No calling stack outside lib/docgenerator found --> Error    
  @log.error('Element#prepare_tracing_info: Found no starting place in caller stack') if @log.error?
  caller().each{|c| @log.debug("\t#{c}") } if @log.debug?
  return caller()
end

#restrict_to(*argv) ⇒ Object

List (array) of targets, where the element can be used. Default are all supported targets.

With restrictions of this attribute, elements can be restricted on special documents.



138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/docgenerator/element.rb', line 138

def restrict_to( *argv )
  @targets = []
  @suppressed_targets = SUPPORTED_TARGETS.dup
  @log.info("Element#restrict_to: #{self.inspect} restrict to #{argv.inspect}") if @log.warn?
  argv.each{ |arg|
    #~ if ! SUPPORTED_TARGETS.include?( arg )
    if ! @suppressed_targets.delete( arg )
      @log.warn("Restriction for unsupported target #{arg}") if @log.warn?
    end
    @targets  << arg
  }
  self
end

#texkeyvalObject

Build key-val options from attributs. Used e.g. by includegraphics.

If the value is true, the value is added without ‘=’. false-values are ignored.

If you need a “value=true”, then add ‘true’ as a string.

Example (Packages::IncludePDF):

class IncludePDF < Element
  add_attribute    :pages,  Attribute.create( [ :texkeyval], [ String ] )
  add_attribute    :nup,  Attribute.create( [ :texkeyval], [ /\d+x\d+/ ] )  #multiple logical pages onto each sheet of paper. 
  add_attribute    :landscape,  Attribute.create( [ :texkeyval], [ true, false ] )  #multiple logical pages onto each sheet of paper. 
  #...
  add_output( :latex,  '#{linebreak(@crbefore)}\includepdf[#{texkeyval()}]{#{@content}}#{linebreak(@crafter)}')
end

x = element(:includepdf, { :pages => '1-5', :nup => '2x2', :landscape => true }, 'filename')
puts x.texkeyval  #pages={1-5}, nup={2x2}, landscape

x = element(:includepdf, { :pages => '1-5', :nup => '2x2', :landscape => false }, 'filename')
puts x.texkeyval  #pages={1-5}, nup={2x2}


439
440
441
442
443
444
445
446
447
448
449
450
451
# File 'lib/docgenerator/element.rb', line 439

def texkeyval()
  keyval = []
  @attr.sort_by{|k,v| v.sortkey  }.each{|k,v|
    next unless v.texkeyval?
    case v.content
      when true, [true];   keyval << "#{k}" 
      when false, [false]  #ignore
      else  #take the value
        keyval << "#{k}={#{v}}" unless v.to_s.empty?
      end
  }
  return keyval.join(', ')
end

#texoptional(key) ⇒ Object

Prints the optional attribut key inside []. If empty, nil is returned



408
409
410
411
# File 'lib/docgenerator/element.rb', line 408

def texoptional(key)
  return nil unless @attr[key].filled?
  return "[#{@attr[key]}]"
end

#to_context(options = {}) ⇒ Object

Create context-output.

ConTeXt-support is added later and there are a lot of gaps (2009-07-01)



385
386
387
388
389
390
391
392
393
394
395
396
397
398
# File 'lib/docgenerator/element.rb', line 385

def to_context(options = {})
  o = set_option_defaults(options)
  makroname = 'dummy'
  self.element_ids.each{|id|
    makroname = id if id.is_a?(Symbol) or id.is_a?(String)
  }
  o[:log].error("Missing output routine for ConTeXt, use \\#{makroname} (#{self.inspect})")
  
  cmd  =  ''
  cmd  <<  "\n" if @crbefore
  cmd  <<  "\\#{makroname}{#{@content.to_context(options)}}"
  cmd  <<  "\n" if @crafter
  return cmd
end

#to_creole(options = {}) ⇒ Object

Return content in creole-Syntax.



521
522
523
524
525
# File 'lib/docgenerator/element.rb', line 521

def to_creole(options = {})
  o = set_option_defaults(options)
  o[:log].error("Missing output routine for creole (#{self.inspect})") if o[:log].error?
  return "#{@content.to_creole(options)}\n"
end

#to_doc(target, options = {}) ⇒ Object

Build a String to be used for the target document. Calls

  • Element#to_latex (target :latex),

  • Element#to_context (target :context)

  • Element#to_html (target :html)

  • Element#to_wiki (target :wiki) (support stopped)

  • Element#to_creole (target :creole) (not really good results)

  • Element#to_text (target :text) (not really good results)

Via the options-hash, you can transport additional information.



319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
# File 'lib/docgenerator/element.rb', line 319

def to_doc( target, options = {} )
  o = set_option_defaults(options)
  o[:log].debug("enter to_doc(#{target}) for #{self.inspect}, options: #{options.keys.inspect}") if o[:log].debug?
  #Return empty string, if target is not requested.
  if ! @targets.include?( target )
    if @suppressed_targets.include?(target) #an Element#restrict_to was defined.
      o[:log].debug("Element#to_doc: Content of #{self.inspect} suppressed for Target #{target.inspect}. (use of restrict_to ?)") if o[:log].debug?
    else
      o[:log].warn("Element#to_doc: Target #{target.inspect} not supported for #{self.inspect}.") if o[:log].warn?
    end
    return ''
  end
  #Some checks
  @attr.each{|k,v|
    if v.required? and v.to_s == '' and v.settings.include?(target)
      o[:log].error "#{self.inspect}: Attribut '#{k}' without required value" if o[:log].error?
    end
  }
  #Build the string.
  result = ''

  case target
  when :latex
    result = to_latex(o)  
  when :context
    result = to_context(o)  
  when :html
    result = to_html(o)
  when :wiki
    result = to_wiki(o)
  when :creole
    result = to_creole(o)
  when :text
    result = to_text(o)
  else
    o[:log].fatal("Undefined target format '#{target}'") if o[:log].fatal?
  end
  #Already added in submethods
  #~ result = "\n#{result}"   if @crbefore
  #~ result << "\n"       if @crafter
  return result
end

#to_html(options = {}) ⇒ Object

This is a dummy method, called from Element#to_doc for the target format HTML.

The tag from Element#htmltag is taken and all attributes and the content are used. If Element#htmltag is nil/false, nothing ” is returned.

This method can be overwritten from the element class.



471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
# File 'lib/docgenerator/element.rb', line 471

def to_html(options = {})
  o = set_option_defaults(options)
  tag = htmltag()
  if ! tag 
    o[:log].error("No HTML element available (#{self.inspect})") if o[:log].error?
    return ''
  elsif tag == ''
    tag = 'span' 
    o[:log].error("Missing output routine for HTML (#{self.inspect})") if o[:log].error?
  end
  #Test if the HTML-Tag should contain something, but there is nothing.
  #If :empty_ok it is ok, that there is no content (e.g <td>)
  #May make problems, if an empty tag is used to set a id-mark.
  if content?() and content? != :empty_ok and
    ( ! @content or @content == [] or @content == [nil] )
    o[:log].warn("HTML-Tag #{tag} without content -> ignored #{self.inspect}")  if o[:log].warn?
    return ''
  end
  html  = String.new()
  html  <<  "\n" if @crbefore
  html  << "<#{tag} "
  @attr.sort_by{|k,v|   v.sortkey }.each{|k,v|
    html << "#{k} = \"#{v}\" " if v.to_s != '' and v.html?
  }
  if @content
    html << ">"
    html  <<"\n" if @crmid
    html << "#{@content.to_html(options)}"
    html  << "\n" if @crmid and @content.size > 0 and html[-1,1] != "\n"
    html << "</#{tag}>"
  elsif  content?() == nil
    html  << '>'
  else
    html << '/>'
  end
  html  <<  "\n" if @crafter
  return html
end

#to_latex(options = {}) ⇒ Object

This is a dummy method, called from Element#to_s for the target format LaTeX. This method must be overwritten from the element class.

By default, the concatenation of all ids and the content is taken.



367
368
369
370
371
372
373
374
375
376
377
378
379
# File 'lib/docgenerator/element.rb', line 367

def to_latex(options = {})
  o = set_option_defaults(options)
  makroname = 'dummy'
  self.element_ids.each{|id|
    makroname = id if id.is_a?(Symbol) or id.is_a?(String)
  }
  o[:log].error("Missing output routine for LaTeX, use \\#{makroname} (#{self.inspect})")
  cmd  =  ''
  cmd  <<  "\n" if @crbefore
  cmd  <<  "\\#{makroname}{#{@content.to_latex(options)}}"
  cmd  <<  "\n" if @crafter
  return cmd
end

#to_sObject



538
539
540
# File 'lib/docgenerator/element.rb', line 538

def to_s()
  return self.inspect
end

#to_text(options = {}) ⇒ Object

Make an Text-Representation of the content.



529
530
531
532
533
534
535
536
537
# File 'lib/docgenerator/element.rb', line 529

def to_text(options = {})
  o = set_option_defaults(options)
  o[:log].error("Missing output routine for Text (#{self.inspect})") if o[:log].error?
  text = String.new()
  text  <<  "\n" if @crbefore
  text = "#{@content.to_text(options)}".strip
  text  <<  "\n" if @crafter
  return text
end

#to_wiki(options = {}) ⇒ Object

Return content in Wikimedia-Syntax. Support stopped.



513
514
515
516
517
# File 'lib/docgenerator/element.rb', line 513

def to_wiki(options = {})
  o = set_option_defaults(options)
  o[:log].error("Missing output routine for Wiki (#{self.inspect})") if o[:log].error?
  return "#{@content.to_wiki(options)}\n"
end