=begin
* Name: SiSU
* Description: a framework for document structuring, publishing and search
* Author: Ralph Amissah
* Copyright: (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
2007 Ralph Amissah All Rights Reserved.
* License: GPL 3 or later:
SiSU, a framework for document structuring, publishing and search
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
2007 Ralph Amissah
This program is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the Free
Software Foundation, either version 3 of the License, or (at your option)
any later version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program. If not, see .
If you have Internet connection, the latest version of the GPL should be
available at these locations:
* SiSU uses:
* Standard SiSU markup syntax,
* Standard SiSU meta-markup syntax, and the
* Standard SiSU object citation numbering and system
* Hompages:
* Download:
* Ralph Amissah
** Description: opendocument text generation
=end
module SiSU_ODF
require "#{SiSU_lib}/dal"
require "#{SiSU_lib}/sysenv"
include SiSU_Env
include SiSU_Param
include SiSU_Viz
require "#{SiSU_lib}/odf_format"
include OD_format
require "#{SiSU_lib}/shared_txt"
@@alt_id_count,@@alt_id_count,@@tablehead,@@number_of_cols=0,0,0,0
class Source
require 'zlib'
require 'find'
require 'fileutils'
include FileUtils
def initialize(opt)
@opt=opt
@@endnotes_para=[]
end
def read
begin
@md=SiSU_Param::Parameters.new(@opt).get
@env=SiSU_Env::Info_env.new(@opt.fns)
@env.odf_structure
opendoc=@md.fn[:odf]
path=@env.path.output_tell
tool=if @opt.cmd =~/[MVv]/; "#{@env.program.odf_viewer} #{path}/#{@md.fnb}/#{opendoc}"
else ''
end
tell=SiSU_Screen::Ansi.new(@opt.cmd,'Opendocument (ODF:ODT)',tool)
tell.green_hi_blue unless @opt.cmd =~/q/
tell=SiSU_Screen::Ansi.new(@opt.cmd,@opt.fns,"#{@env.path.output_tell}/#{@md.fnb}/#{opendoc}")
tell.flow if @opt.cmd =~/[MV]/
my_make=SiSU_Env::Create_file.new(@opt.cmd,@opt.fns)
@dal_array=SiSU_DAL::Source.new(@opt).get # dal file drawn here
SiSU_ODF::Source::Scroll.new(@dal_array,@md).songsheet
SiSU_Env::Info_skin.new(@md).select
rescue; SiSU_Errors::Info_error.new($!,$@,@opt.cmd,@opt.fns).error
ensure
end
end
private
class Split_text_object ).+?<~(\d+);(?:\w|[0-6]:)\d+;\w\d+><#@dp:#@dp>$/
if /^(([1-6])~(\S+))\s+(\S.+?)<~(\d+);(?:\w|[0-6]:)\d+;\w\d+><#@dp:#@dp>$/m.match(@para)
@format,@lev,segname,@text,@ocn=$1,$2,$3,$4,$5
elsif /^(([1-6])~)\s+(\S.+?)<~(\d+);(?:\w|[0-6]:)\d+;\w\d+><#@dp:#@dp>$/m.match(@para)
@format,@lev,@text,@ocn=$1,$2,$3,$4
elsif /<:(.+?)>\s*(\S.+?)<~(\d+);(?:\w|[0-6]:)\d+;\w\d+><#@dp:#@dp>$/m.match(@para)
@format,@text,@ocn=$1,$2,$3
elsif /^(([1-6])~(\S+))\s+(\S.+?)<~(\d+);(?:\w|[0-6]:)\d+;[um]\d+><#@dp:#@dp>$/m.match(@para)
@@alt_id_count+=1
@format,@lev,segname,@text,@ocn=$1,$2,$3,$4,"x#{@@alt_id_count}"
elsif /^(([1-6])~)\s+(\S.+?)<~(\d+);[um]\d+;\w\d+><#@dp:#@dp>$/m.match(@para)
@@alt_id_count+=1
@format,@lev,@text,@ocn=$1,$2,$3,"x#{@@alt_id_count}"
end
else
if /(.+?)<~(\d+);(?:\w|[0-6]:)\d+;\w\d+><#@dp:#@dp>$/m.match(@para)
@text,@ocn=$1,$2
end
if @para !~/<~(\d+);(?:\w|[0-6]:)\d+;\w\d+><#@dp:#@dp>$|^$/
@text=/(.+?)/im.match(@para)[1]
end
if /^((\d)~(?:~\S+)?)\s+(.+)/m.match(@para)
@format,@lev,@text=$1,$2,$3
end
end
format=@format.dup
@lev_para_ocn=if @para =~/.+<~\d+;(?:\w|[0-6]:)\d+;\w\d+><#@dp:#@dp>$/
OD_format::Format_text_object.new(format,@text,@ocn)
else
OD_format::Format_text_object.new(format,@text,"<~(\d+);[um]\d+;\w\d+><#@dp:#@dp>")
end
self
end
end
class Scroll [],:open=>[],:close=>[],:head=>[],:metadata=>[],:tail=>[],:endnotes=>[] }
@@docstart=true
@@fns,@@dp=nil,nil
def initialize(data='',md='')
@data,@md=data,md
@env=SiSU_Env::Info_env.new(@md.fns)
@vz=SiSU_Env::Get_init.instance.skin
@dp=@@dp ||=SiSU_Env::Info_env.new.digest.pattern
@regx=/^(?:(?:<:p[bn]>\s*)?\d~(?:(\S+))?\s+)?(.+?)\s*<~(\d+);(?:\w|[0-6]:)\d+;\w\d+><#@dp:#@dp>$/
@serial=/\s*<~\d+;(?:\w|[0-6]:)\d+;\w\d+><#@dp:#@dp>\s*/
@tab="\t"
@url_brace=SiSU_Viz::Skin.new.url_decoration
@br=if @md.cmd =~/M/; "\n"
else ''
end
end
def songsheet
pre
@data=markup(@data)
post
publish
end
# Used for extraction of endnotes from paragraphs
def extract_endnotes(para='')
notes=para.scan(/~\{(\d+\s+.+?)\s*<#@dp>\}~/)
@n=[]
notes.each do |n| #high cost to deal with appropriately within odf, consider
n=n.dup.to_s
if n =~/<:?br(?: \/)?>/
fix=n.split(/<:?br(?: \/)?>/) #watch #added
fix.each do |x|
if x =~/\S+/; @n << x
end
end
else @n << n
end
end
end
def odf_metadata(meta)
#meta.el,meta.txt,meta.type,meta.attrib
end
def odf_tail
generator="Generated by: #{@md.sisu_version[:project]} #{@md.sisu_version[:version]} of #{@md.sisu_version[:date_stamp]} (#{@md.sisu_version[:date]})" if @md.sisu_version[:version]
lastdone="Last Generated on: #{Time.now}"
rubyv="Ruby version: #{@md.ruby_version}"
sc=if @md.sc_info
"Source file: #{@md.sc_filename}\nVersion number: #{@md.sc_number}\nVersion date: #{@md.sc_date}\n"
else ''
end
url=@md.fnb
fn=@md.fn[:manifest]
manifest="#{@vz.url_root_http}/#{url}/#{fn}"
@@odf[:tail] << %{Available document outputs: <#{manifest} > }
@@odf[:tail] << %{\nSiSU: <www.jus.uio.no/sisu > and <www.sisudoc.org > }
@@odf[:tail] << "\n"
end
def heading(para,no)
para.gsub!(@serial,'')
para.gsub!(/<:name#\S+?>/,'')
para.gsub!(/^([1-6])~\S*\s/,'')
m=/#{$1}/
breakpage=''
if @md.fns and @md.fns != '' and @md.fns !=@@fns
@@docstart=true
@@fns=@md.fns
end
unless @@docstart
breakpage=if (@md.pagenew or @md.pagebreak) and (@md.pagenew =~ m or @md.pagebreak =~m); ' '
else ''
end
end
@@docstart=false
%{#{breakpage}#{para} }
end
def image_src(i)
image_source=if @md.fns =~/\._?ss[tm]$/ and FileTest.file?("#{@env.path.image_source_local_tex}/#{i}")
@env.path.image_source_local_tex
elsif @md.fns =~/\.-ss[tm]$/ and FileTest.file?("#{@env.path.image_source_remote_tex}/#{i}")
@env.path.image_source_remote_tex
elsif FileTest.file?("#{@env.path.image_source_tex}/#{i}")
@env.path.image_source_tex
else
tell=SiSU_Screen::Ansi.new(@md.cmd,"ERROR - image:",%{"#{i}" missing},"search locations: #{@env.path.image_source_local_tex},#{@env.path.image_source_remote_tex} and #{@env.path.image_source_tex}")
tell.error2 unless @md.cmd =~/q/
nil
end
end
def image_odf(img)
# copy image to od image directory (unless exists)
# divide pixel dimension by 37.79485 and retain 3 decimal places
# x=str.scan(/(aa[^a]+)/)
m,u=img[1],img[2]
i=/^(\S+?\.(?:png|jpg|gif))/.match(m).captures.join if m =~/^(\S+?\.(?:png|jpg|gif))/
c=/^\S+?\.(?:png|jpg|gif)\s+.+?"(.*?)"/.match(m).captures.join if m =~/^\S+?\.(?:png|jpg|gif)\s+.+?"(.*?)"/
w,h=/(\d+)x(\d+)/.match(m).captures if m =~/\d+x\d+/
w=(w.to_i/37.79485).to_s
h=(h.to_i/37.79485).to_s
h=/([0-9]+\.\d{0,3})/.match(h).captures.join
w=/([0-9]+\.\d{0,3})/.match(w).captures.join
image_source=image_src(i)
pwd=Dir.pwd
cp("#{image_source}/#{i}","#{@env.path.odf}/Pictures/#{i}") if image_source
img=if i.to_s =~/jpg|png|gif/ and h.to_s =~/\d/ and w.to_s =~/\d/
@@img_count +=1
%{ #{c}} #anchor-type: as-char or paragraph or char or ...
else %{[image omitted] }
end
end
def image(para)
para.gsub!(@serial,'')
m=para.scan(/(\{\s*(.+?)\}((?:https?|ftp)\S+|image))/)
if m; m.each do |i|
cont,url=i[1],i[2]
cont.gsub!(/([)(\]\[])/,"\\\\\\1")
cont.gsub!(/([+?])/,"\\\\\\1") # incorrect handling of +
url.gsub!(/([+?])/,"\\\\\\1")
para.sub!(/\{\s*#{cont}\}#{url}/m,image_odf(i)) #watch
para.gsub!(/\\([)(\]\[?])/,'\1') #clumsy fix
end
m=nil
end
para
end
def text_link_odf(txt,url,trail)
txt.gsub!(/(\\\+)/,'+') #this is convoluted, and risky :-(
url.gsub!(/(\\\+)/,'+') #this is convoluted, and risky :-(
%{#{txt.strip} #{trail}}
end
def text_link(para)
para.gsub!(@serial,'')
m=para.scan(/(\{([^}]+?)\}((?:https?|ftp)\S+?))([;.,]?(?=\s|$))/) #sort
if m
m.each do |i|
txt,url,trail=i[1],i[2]
txt.gsub!(/([)(\]\[])/,"\\\\\\1")
txt.gsub!(/([+?])/,"\\\\\\1") # problems with +
url.gsub!(/([+?])/,"\\\\\\1") # problems with +
para.gsub!(/\{\s*#{txt}\}#{url}/m,text_link_odf(txt,url,trail)) #make sure trailing ']' are not caught in url
para.gsub!(/\\([)(\]\[?])/,'\1') #clumsy fix
end
m=nil
end
para
end
def normal(para) #P1 - P3
para.gsub!(@serial,'')
para.gsub!(/\b[_\\]((?:https?|ftp):\/\/\S+?\.[^'"><\s]+?)([;.,]?(?:\s|$))/,
%{\\1 \\2}) #http ftp matches escaped, no decoration
para.gsub!(/((?:^|\s)[}])((?:https?|ftp):\/\/\S+?\.[^'"><\s]+?)([;.,]?(?=\s|$))/,
'\1\2 \3') #special case \{ e.g. \}http://url
para.gsub!(/(^|\s)((?:https?|ftp):\/\/\S+?\.[^'"><\s]+?)([;.,]?(?=\s|$))/,
%{\\1#{@url_brace.xml_open}\\2 #{@url_brace.xml_close}\\3}) #http ftp matches with decoration
#para.gsub!(/\b((?:https?|ftp):\/\/\S+?\.[^'"><\s]+?)([;.,]?(?:\s|$))/, also works
#%{#{@url_brace.xml_open}\\1 #{@url_brace.xml_close}\\2}) #http ftp matches with decoration
para.gsub!(/([a-zA-Z0-9._-]+@[a-zA-Z0-9._-]+)/,
%{#{@url_brace.xml_open}\\1 #{@url_brace.xml_close}})
para=case para
when /^<:i([1-9])>\s/m
m=$1
para.gsub!(/^<:i#{m}>\s/m,'')
%{#{para} }
else %{#{para} }
end
para
end
def fontface(para)
#para=para.gsub(/(.+?)<\/b>/,%{\\1 })
#para=para.gsub(/(.+?)<\/i>/,%{\\1 })
end
def footnote(para)
@astx||=10000
para.gsub!(/<#@dp>([}\]]~)/,'\1')
#para.gsub!(/ <:i[1-9]>/,' ')
if para =~/~\{\d+\s+/
para=para.gsub(/~\{(\d+)\s+(.+?)\}~/,'\1 \2 ')
end
if para=~/~\[[*+]\d+\s/ #editor notes, squre bracket series
asterisk=para.scan(/~\[([*+]\d+)\s+(.+?)\]~/)
asterisk.each do |x|
a=x[0].gsub(/([*+])/,"\\\\\\1")
para=para.gsub(/~\[(#{a})\s+(.+?)\]~/,%{\\1 \\2 })
@astx+=1
end
end
if para=~/~\{[*+]+\s/
asterisk=para.scan(/~\{([*+]+)\s+(.+?)\}~/)
asterisk.each do |x|
a=x[0].gsub(/([*+])/,"\\\\\\1")
para=para.gsub(/~\{(#{a})\s+(.+?)\}~/,%{\\1 \\2 })
@astx+=1
end
end
para
end
def group_clean(para)
para.gsub!(/ | /,' ')
para.gsub!(/,'<'); para.gsub!(/>/,'>')
para.gsub!(/<(text:span text:style-name="T[1-5]"|\/text:span)>/,'<\1>') #works, not ideal
para.gsub!(/<br(?:\s+\/)?>/,' ')
#para.gsub!(/\s\s/,' ')
para
end
def poem(para) #P4 #same as group
para.gsub!(@serial,'')
para.gsub!(/<:verse(?:-end)?>\s*/m,'')
parray=[]
para.split(/<:?br(?: \/)?>/).each do |parablock|
parablock=group_clean(parablock)
parray << %{#{parablock} } if parablock =~/\S+/
end
para=parray.join + ' '
end
def group(para) #P4 #same as verse
para.gsub!(@serial,'')
para.gsub!(/<:group(?:-end)?>\s*/m,'')
parray=[]
para.split(/<:?br(?: \/)?>/).each do |parablock|
parablock=group_clean(parablock)
parray << %{#{parablock} } if parablock =~/\S+/
end
para=parray.join + ' '
end
def code(para) #P5
para.gsub!(@serial,'')
para.gsub!(/<:code(?:-end)?>\s*/m,'')
para.gsub!(/\s\s/,' ')
parray=[]
para.split(/<:?br(?: \/)?>/).each do |parablock|
parablock=group_clean(parablock)
parablock.gsub!(/\b[_\\]((?:https?|ftp):\/\/\S+?\.[^'"><\s]+?)([;.,]?(?:\s|$))/,
%{\\1 \\2}) #http ftp matches escaped, no decoration
parray << %{#{parablock} } if parablock =~/\S+/
end
para=parray.join + ' '
para
end
def table(para) #
if para =~//
@@odf[:body] << poem(para)
@@odf[:body] << @br*2
elsif para =~ /<:group(?:-end)?>/
@@odf[:body] << group(para)
@@odf[:body] << @br*2
elsif para =~ /<:code(?:-end)?>/
@@odf[:body] << code(para)
@@odf[:body] << @br*2
elsif para =~ /<\-_&!@%~#\]\[*=$| \n+`¡]/
dir=SiSU_Env::Info_env.new(@md.fns)
@data_mod,@endnotes,@level,@cont,@copen,@odf_contents_close=Array.new(6){[]}
@rcdc=false
(0..6).each { |x| @cont[x]=@level[x]=false }
(4..6).each { |x| @odf_contents_close[x]='' }
odf_tail #($1,$2)
fix=[]
bullet=image_src('bullet_red.png')
cp("#{bullet}/bullet_red.png","#{@env.path.odf}/Pictures/.") #if image_src('bullet_red.png')
data.each do |para|
#p para if para =~safe_characters and @md.cmd =~/V/ #KEEP
#para.gsub!(/<(~\d+;(?:\w|[0-6]:)\d+;\w\d+)><(#@dp:#@dp)>/,'<\1><\2>')
para_array=[]
word=para.scan(/\S+|\n/)
if word
word.each do |w| # _ - / # | : ! ^ ~
unless para =~/^(?:0~|%+ )/m
w.gsub!(/(?:126|152);/,'~') #126 usual
if w !~/&\S{1,7};/ or w =~/ /; w.gsub!(/&/,'&') #watch
end
end
para_array << w
end
para=para_array.join(' ')
para=para.strip
end
para.gsub!(/^(<:i[1-9]>\s+)?_\*\s+/,'\\1 ') # bullet_red.png
#para.gsub!(/^_\*\s+/,'· ') #bullet
para.gsub!(/^(<:i[1-9]>)\s+_\*\s+/,'\1 · ') #bullet
#para.gsub!(/^(<:i[1-9]>\s+)?_\*\s+/,'\\1 ') # bullet_red.png
#para.gsub!(/^(<:i[1-9]>)\s+_\*\s+/,'\1 · ') #bullet
para.gsub!(/ /,' ')
para.gsub!(/<:p[bn]>/,' ')
para.gsub!(/©/,'©') #too arbitrary
para.gsub!(/.+?<-#>/,'') # remove dummy headings (used by html) #check
#para.gsub!(/_\*\s+/,'* ') # bullet markup, marked down
para.gsub!(/(.+?)<\/b>/,'\1 ')
para.gsub!(/(.+?)<\/i>/,'\1 ')
para.gsub!(/(.+?)<\/u>/,'\1 ')
para.gsub!(/(.+?)<\/sup>/,'\1 ')
para.gsub!(/(.+?)<\/sub>/,'\1 ')
para.gsub!(/`/,"'")
para.gsub!(//,'-')
para.gsub!(/·/,'*')
para.gsub!(/[“”]/,'""')
para.gsub!(/[–—]/,'-') #— – chk
para.gsub!(/ < /i,'<')
para.gsub!(/\\copy(?:right)?\b/,'©')
para.gsub!(/\\trademark\b|\\tm\b/,'®')
#para.gsub!(/\43/,'#') ## watch
#para.gsub!(/$/,'$') #$ watch
para.gsub!(/\44/,'$') #$ watch
#para.gsub!(/^·/,'_*') #$ watch
#para.gsub!(/·/,'*') #$ watch
para.gsub!(/<:p[bn]>/,'') # remove page breaks
para.gsub!(/^\s*<~\d+;(?:\w|[0-6]:)\d+;\w\d+><#@dp:#@dp>/,'') # remove empty lines
para.gsub!(/(.+?)<\/a>/,'\1')
para.gsub!(/<:name#\S+?>/,'') # remove name links
# para.gsub!(/ (.+?)<\/a>/im,'\1')
#para.gsub!(/ /,' ') # decide on
#para.gsub!(/\{(\S+?\.(?:png|jpg)) .+?\}(?:http:\/\/\S+|image)/," [ \\1 ]") #"[ #{@env.url.images_local}\/\\1 ]")
#para.gsub!(/");
#p para if para =~safe_characters and @md.cmd =~/M/ #KEEP
#para.gsub!(/^(\{\S+?\.(?:png|jpg)\s+.+?"(.*?)"\s*\}\S+)/,"\\1 \n [image: \"\\2\"]")
wordlist=para.scan(/\S+/)
para=tidywords(wordlist).join(' ').strip
if para =~/^0~(\S+)\s+(.+?)\Z/m # for headers
d_meta=SiSU_text_utils::Header_scan.new(@md,para).meta
if d_meta; odf_metadata(d_meta)
end
end
@rcdc=true if @rcdc==false and (para =~/~metadata/ or para =~/1~\s+Document Information/)
if para !~/(^0~||)/
if para =~@regx #/.+?<~\d+;\w\d+;\w\d+>.*/ #watch change
paranum=para[@regx,3]
@p_num=OD_format::Paragraph_number.new(paranum)
end
@sto=Split_text_object.new(para).lev_segname_para_ocn
#yyyy-mm-ddT00:00:00 #{ocn} #followed immediately by paragraph closure
### problem in scroll, it appears tables are getting paragraph numbers
unless @rcdc
m=/<~(\d+);(?:\w|[0-6]:)\d+;\w\d+><#@dp:#@dp>$/
if para =~m and para=~/\S+/
para=case @sto.format
when /^(1)~(?:(\S+))?/; odf_structure(para,$1,@sto.ocn,$2)
para
when /^(2)~(?:(\S+))?/; odf_structure(para,$1,@sto.ocn,$2)
para
when /^(3)~(?:(\S+))?/; odf_structure(para,$1,@sto.ocn,$2)
para
when /^(4)~(\S+)/; odf_structure(para,$1,@sto.ocn,$2)
# work on see SiSU_text_parts::Split_text_object
para
when /^(5)~(?:(\S+))?/; odf_structure(para,$1,@sto.ocn,$2)
para
when /^(6)~(?:(\S+))?/; odf_structure(para,$1,@sto.ocn,$2)
para
#@sto.lev_para_ocn.heading_body6
#when /^(i1)$/
# #formatMono.gsubBody
# #para=@sto[:lev_para_ocn].scrIndent1
#when /^(i2)$/
# formatMono.gsubBody
# para=@sto[:lev_para_ocn].scrIndent2
#when /^(center)$/
# para.gsub!(/(.+)/,
# %{(\\1) })
# para=@sto[:lev_para_ocn].scrPara
#when /^(b|bold)$/
# para.gsub!(/(.+)/,
# %{(\\1) })
# para=@sto[:lev_para_ocn].scrPara
#when /null/ # see whether u can improve
# if (para !~/#{@margin.txt_0}|#{@margin.txt_1}|#{@margin.txt_2}/)
# #formatMono.gsubBody
# #para=@sto[:lev_para_ocn].scrPara
# end
else odf_structure(para,nil,nil,nil) #watch may be problematic
para
end
elsif para =~/(.*)(.*)/
one,two=$1,$2
format_text=OD_format::Format_text_object.new(one,two)
para=format_text.seg_no_paranum
end
para='' if para =~// and para =~/^(-\{{2}~\d+|)/ # -endnote
if (para !~/#{@vz.margin_txt_0}|#{@vz.margin_txt_1}|#{@vz.margin_txt_2}/)
# i don't get the condition for no paranum
end
if para =~/<:center>/
one,two=/(.*)<:center>(.*)/.match(para)[1,2]
format_text=OD_format::Format_text_object.new(one,two)
para=format_text.center
end
else
if para =~ /^(4)~(\S+)/
odf_structure(para,$1,@sto.ocn,$2)
para
elsif para =~/<~(\d+);m\d+;[mdv]\d+><#@dp:#@dp>$/
odf_structure(para,nil,nil,nil) #watch may be problematic
para
end
end
para.gsub!(//,' ') if para ## Clean Prepared Text
para.gsub!(/<:\S+>/,' ') if para ## Clean Prepared Text
end
end
end
def pre
table=if @md.flag_tables
%{ #@br} +
%{ #@br} +
%{ #@br} +
%{ #@br} +
%{ #@br} +
%{ #@br} +
%{ #@br} +
%{ #@br} +
%{ #@br} +
%{ #@br} +
%{ #@br} +
%{ #@br} +
%{ #@br} +
%{ #@br} +
%{ #@br} +
%{ #@br} +
%{ #@br} +
%{ #@br} +
%{ #@br} +
%{ #@br} +
%{ #@br} +
%{ #@br} +
%{ #@br} +
%{ #@br}
else ''
end
breakpage=if @md.pagenew or @md.pagebreak; ' fo:break-before="page"'
else ''
end
@@odf[:head]<<%{#@br} +
%{ #@br} +
%{ #@br} +
%{#@br} +
%{#{table}#@br} +
%{ #@br} +
%{ #@br} + # P1
%{ #@br} + # P1
%{ #@br} +
%{ #@br} +
%{ #@br} +
%{ #@br} +
%{ #@br} +
%{ #@br} +
%{ #@br} + # P1
%{ #@br} +
%{ #@br} +
%{ #@br} +
%{ #@br} +
%{ #@br} +
%{ #@br} +
%{ #@br} +
%{ #@br} +
%{ #@br} +
%{ #@br} +
%{ #@br} +
%{ #@br} +
%{ #@br} +
%{ #@br} +
%{ #@br} +
%{ #@br} +
%{ #@br} +
%{ #@br} +
%{ #@br} +
%{#@br} +
%{ #@br} +
%{ }
end
def post
end
def publish
divider='='
content=[]
data=@data
content << @@odf[:open]
content << @@odf[:head]
content << @@odf[:body]
content << @@odf[:metadata]
#content << @@odf[:owner_details] if @md.stmp =~/\w+/ #not used?
content << @@odf[:tail]
Output.new(content,@md).odf
@@odf[:head],@@odf[:body],@@odf[:tail],@@odf[:metadata]=[],[],[],[]
end
end
class Output