From 26767cc88c0548ad7978021796d0ccc4c9f7ffed Mon Sep 17 00:00:00 2001 From: Ralph Amissah Date: Sat, 2 Jun 2007 11:27:06 +0100 Subject: 0.53.0, pre-build, see changelog, library naming changed for scm, placed under v0 (instead of 0.53) --- lib/sisu/v0/odf.rb | 719 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 719 insertions(+) create mode 100644 lib/sisu/v0/odf.rb (limited to 'lib/sisu/v0/odf.rb') diff --git a/lib/sisu/v0/odf.rb b/lib/sisu/v0/odf.rb new file mode 100644 index 00000000..caf86a39 --- /dev/null +++ b/lib/sisu/v0/odf.rb @@ -0,0 +1,719 @@ +=begin + * Name: SiSU information Structuring Universe - Structured information, Serialized Units + * Author: Ralph Amissah + * http://www.jus.uio.no/sisu + * http://www.jus.uio.no/sisu/SiSU/download.html + + * Description: opendocument text generation + + * Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Ralph Amissah + + * License: GPL 2 or later + + Summary of GPL 2 + + 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 2 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, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + + If you have Internet connection, the latest version of the GPL should be + available at these locations: + http://www.fsf.org/licenses/gpl.html + http://www.gnu.org/copyleft/gpl.html + http://www.jus.uio.no/sisu/gpl2.fsf + + SiSU was first released to the public on January 4th 2005 + + SiSU uses: + + * Standard SiSU markup syntax, + * Standard SiSU meta-markup syntax, and the + * Standard SiSU object citation numbering and system + + © Ralph Amissah 1997, current 2007. + All Rights Reserved. + + * Notes: tidy -ascii index.xml >> index.tidy + + * Ralph Amissah: ralph@amissah.com + ralph.amissah@gmail.com +=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" + @br=if @md.cmd =~/M/; "\n" + else '' + end + end + def songsheet + pre + @data=markup + 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 =~// + fix=n.split(//) #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 + @@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) + txt.gsub!(/(\\\+)/,'+') #this is convoluted, and risky :-( + url.gsub!(/(\\\+)/,'+') #this is convoluted, and risky :-( + %{#{txt}} + end + def text_link(para) + para.gsub!(@serial,'') + m=para.scan(/(\{([^}]+?)\}((?:https?|ftp)\S+))/) #sort + if m + m.each do |i| + txt,url=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)) + para.gsub!(/\\([)(\]\[?])/,'\1') #clumsy fix + end + m=nil + end + para + end + def normal(para) #P1 - P3 + para.gsub!(@serial,'') + para.gsub!(/(^|\s)(https?:\/\/[^'">< ]+)/,'\1\2') + para.gsub!(/([a-zA-Z0-9._-]+@[a-zA-Z0-9._-]+)/,'\1') + par=case para + when /^<:i1>\s/m; para.gsub!(/^<:i1>\s/m,'') + %{#{para}} + when /^<:i2>\s/m; para.gsub!(/^<:i2>\s/m,'') + %{#{para}} + else %{#{para}} #%{#{para}} + end + para=par #+ %{} + 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!(/
<:i1>/,'
') + 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!(/&nbsp;| /,' ') + para.gsub!(//,'>') + #para.gsub!(//,'
') + 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,'') + para=group_clean(para) + parray=[] + para.split(//).each do |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,'') + para=group_clean(para) + parray=[] + para.split(//).each do |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=group_clean(para) + para.gsub!(/\s\s/,'  ') + parray=[] + para.split(/<:br>/).each do |parablock| + parray << %{#{parablock}} if parablock =~/\S+/ + end + para=parray.join + '' + 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[12]>\s+)?_\*\s+/,'\\1 ') # bullet_red.png + #para.gsub!(/^_\*\s+/,'· ') #bullet + para.gsub!(/^(<:i[12]>)\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 + case para #remove + when /<:i1>/ + if para =~/.*<:#>.*$/ + format_text=OD_format::Format_text_object.new(para,'') + para=format_text.scr_indent_one_no_paranum + end + when /<:i2>/ + if para =~/.*<:#>.*$/ + format_text=OD_format::Format_text_object.new(para,'') + para=format_text.scr_indent_one_no_paranum + end + end + 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} + + %{#@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