-*- mode: org -*- #+TITLE: sisu abstraction #+DESCRIPTION: documents - structuring, various output representations & search #+FILETAGS: :sisu:abstraction: #+AUTHOR: Ralph Amissah #+EMAIL: [[mailto:ralph.amissah@gmail.com][ralph.amissah@gmail.com]] #+COPYRIGHT: Copyright (C) 2015 - 2021 Ralph Amissah #+LANGUAGE: en #+STARTUP: content hideblocks hidestars noindent entitiespretty #+OPTIONS: H:3 num:nil toc:t \n:nil @:t ::t |:t ^:nil _:nil -:t f:t *:t <:t #+PROPERTY: header-args :exports code #+PROPERTY: header-args+ :noweb yes #+PROPERTY: header-args+ :eval no #+PROPERTY: header-args+ :results no #+PROPERTY: header-args+ :cache no #+PROPERTY: header-args+ :padline no #+PROPERTY: header-args+ :mkdirp yes * ao.rb ** ao.rb #+HEADER: :tangle "../lib/sisu/ao.rb" #+BEGIN_SRC ruby #<<sisu_document_header>> module SiSU_AO require_relative 'se' # se.rb include SiSU_Env require_relative 'dp' # dp.rb include SiSU_Param require_relative 'ao_doc_objects' # ao_doc_objects.rb require_relative 'ao_syntax' # ao_syntax.rb include SiSU_AO_Syntax require_relative 'ao_doc_str' # ao_doc_str.rb require_relative 'ao_appendices' # ao_appendices.rb require_relative 'ao_idx' # ao_idx.rb require_relative 'ao_numbering' # ao_numbering.rb require_relative 'ao_hash_digest' # ao_hash_digest.rb require_relative 'ao_endnotes' # ao_endnotes.rb require_relative 'ao_images' # ao_images.rb require_relative 'ao_metadata' # ao_metadata.rb require_relative 'ao_character_check' # ao_character_check.rb require_relative 'ao_misc_arrange' # ao_misc_arrange.rb require_relative 'ao_expand_insertions' # ao_expand_insertions.rb require_relative 'ao_persist' # ao_persist.rb require_relative 'prog_text_translation' # prog_text_translation.rb require_relative 'shared_sem' # shared_sem.rb class Instantiate < SiSU_Param::Parameters::Instructions def initialize @@flag_vocab=0 @@line_mode='' end end class Source <Instantiate def initialize(opt,fnx=nil,process=:complete) @opt,@fnx,@process=opt,fnx,process @per ||=SiSU_AO_Persist::Persist.new.persist_init @per.fns ||=opt.fns fn_use=if fnx \ and fnx =~/\.ss[tmi]$/ fnx elsif opt.fns =~/\.ssm$/ opt.fns + '.sst' else opt.fns end @make_fns=SiSU_Env::InfoFile.new(fn_use) @fnm=@make_fns.marshal.ao_metadata @fnc=@make_fns.marshal.ao_content @idx_sst=@make_fns.marshal.ao_idx_sst_rel_html_seg @idx_raw=@make_fns.marshal.ao_idx_sst_rel @idx_html=@make_fns.marshal.ao_idx_html @idx_xhtml=@make_fns.marshal.ao_idx_xhtml @map_nametags=@make_fns.marshal.ao_map_nametags @map_ocn_htmlseg=@make_fns.marshal.ao_map_ocn_htmlseg @env=SiSU_Env::InfoEnv.new end def read #creates ao begin @per=SiSU_AO_Persist::Persist.new @per.ao_arr=[] @per.fns=(@fnx && @fnx =~/\.ss[tmi]$/) \ ? @fnx : @opt.fns create_ao rescue SiSU_Errors::Rescued.new($!,$@,@opt.selections,@per.fns).location do __LINE__.to_s + ':' + __FILE__ end ensure SiSU_AO_Persist::Persist.new.persist_init SiSU_AO::Instantiate.new end end def get #reads ao, unless does not exist then creates first begin ao=[] unless @per.fns==@opt.fns \ or @per.fns==@fnx @per.fns=(@fnx && @fnx =~/\.ss[tmi]$/) \ ? @fnx : @opt.fns @per.ao_arr=[] end ao=(@per.ao_arr.empty?) \ ? read_fnc : @per.ao_arr.dup rescue SiSU_Errors::Rescued.new($!,$@,@opt.selections,@opt.fns).location do __LINE__.to_s + ':' + __FILE__ end ensure SiSU_AO::Instantiate.new end end def get_idx_sst #reads ao idx.sst, #unless does not exist then creates first begin ao=[] unless @per.fns==@opt.fns \ or @per.fns==@fnx @per.fns=(@fnx && @fnx =~/\.ss[tmi]$/) \ ? @fnx : @opt.fns @per.idx_arr_sst=[] end ao=(@per.idx_arr_sst.empty?) \ ? read_idx_sst : @per.idx_arr_sst.dup #check rescue SiSU_Errors::Rescued.new($!,$@,@opt.selections,@opt.fns).location do __LINE__.to_s + ':' + __FILE__ end ensure SiSU_AO::Instantiate.new end end def get_idx_raw begin ao=[] unless @per.fns==@opt.fns \ or @per.fns==@fnx @per.fns=(@fnx && @fnx =~/\.ss[tmi]$/) \ ? @fnx : @opt.fns @per.idx_arr_tex=[] end ao=(@per.idx_arr_tex.empty?) \ ? read_idx_raw : @per.idx_arr_tex.dup #check rescue SiSU_Errors::Rescued.new($!,$@,@opt.selections,@opt.fns).location do __LINE__.to_s + ':' + __FILE__ end ensure SiSU_AO::Instantiate.new end end def get_idx_html #reads ao idx.html, #unless does not exist then creates first begin ao=[] unless @per.fns==@opt.fns \ or @per.fns==@fnx @per.fns=(@fnx && @fnx =~/\.ss[tmi]$/) \ ? @fnx : @opt.fns @per.idx_arr_html=[] end ao=(@per.idx_arr_html.empty?) \ ? read_idx_html : @per.idx_arr_html.dup rescue SiSU_Errors::Rescued.new($!,$@,@opt.selections,@opt.fns).location do __LINE__.to_s + ':' + __FILE__ end ensure SiSU_AO::Instantiate.new end end def get_idx_xhtml #reads ao idx.xhtml, #unless does not exist then creates first begin ao=[] unless @per.fns==@opt.fns \ or @per.fns==@fnx @per.fns=(@fnx && @fnx =~/\.ss[tmi]$/) \ ? @fnx : @opt.fns @per.idx_arr_xhtml=[] #... end ao=(@per.idx_arr_xhtml.empty?) \ ? read_idx_xhtml : @per.idx_arr_xhtml.dup rescue SiSU_Errors::Rescued.new($!,$@,@opt.selections,@opt.fns).location do __LINE__.to_s + ':' + __FILE__ end ensure SiSU_AO::Instantiate.new end end def get_map_nametags #reads ao map.nametags, #unless does not exist then creates first begin ao=[] unless @per.fns==@opt.fns \ or @per.fns==@fnx @per.fns=(@fnx && @fnx =~/\.ss[tmi]$/) \ ? @fnx : @opt.fns @per.map_arr_nametags=[] end ao=(@per.map_arr_nametags.empty?) \ ? read_map_nametags : @per.map_arr_nametags.dup rescue SiSU_Errors::Rescued.new($!,$@,@opt.selections,@opt.fns).location do __LINE__.to_s + ':' + __FILE__ end ensure SiSU_AO::Instantiate.new end end def get_map_ocn_htmlseg #reads ao map.ocn_htmlseg, #unless does not exist then creates first begin ao=[] unless @per.fns==@opt.fns \ or @per.fns==@fnx @per.fns=(@fnx && @fnx =~/\.ss[tmi]$/) \ ? @fnx : @opt.fns @per.map_arr_ocn_htmlseg=[] end ao=(@per.map_arr_ocn_htmlseg.empty?) \ ? read_map_ocn_htmlseg : @per.map_arr_ocn_htmlseg.dup rescue SiSU_Errors::Rescued.new($!,$@,@opt.selections,@opt.fns).location do __LINE__.to_s + ':' + __FILE__ end ensure SiSU_AO::Instantiate.new end end protected def create_ao ao_array=[] fnp = @fnx ? "#{@opt.fno} #{@fnx}" : @opt.fno unless @opt.act[:quiet][:set]==:on tell=(@opt.act[:verbose][:set]==:on \ || @opt.act[:verbose_plus][:set]==:on \ || @opt.act[:maintenance][:set]==:on) \ ? SiSU_Screen::Ansi.new( @opt.act[:color_state][:set], 'Document Abstraction' ) : SiSU_Screen::Ansi.new( @opt.act[:color_state][:set], 'Document Abstraction', "[#{@opt.f_pth[:lng_is]}] #{fnp}" ) tell.blue_title_hi end fn=(@fnx && @fnx =~/\.ss[tmi]$/) \ ? @fnx : @opt.fns if @opt.fno =~/\.txz$/ Dir.chdir(@opt.f_pth[:pth]) end meta=file_array=@env.source_file_processing_array(fn) @md=SiSU_Param::Parameters::Instructions.new(meta,@opt).extract meta=nil ao=SiSU_AO::Make.new(fn,@md,file_array,@fnx,@process).song if (@opt.act[:verbose][:set]==:on \ || @opt.act[:verbose_plus][:set]==:on \ || @opt.act[:maintenance][:set]==:on) cf=SiSU_Env::CreateFile.new(fn) if (@opt.act[:verbose][:set]==:on \ || @opt.act[:verbose_plus][:set]==:on) SiSU_Screen::Ansi.new( @opt.act[:color_state][:set], @opt.fns, "~meta/#{@opt.fns}.meta" ).output elsif @opt.act[:maintenance][:set]==:on SiSU_Screen::Ansi.new( @opt.act[:color_state][:set], "ao -> #{cf.meta}" ).txt_grey end end ao.each {|s| ao_array << s} if @opt.act[:maintenance][:set]==:on ao_array.each do |obj| if defined? obj.parent if defined? obj.ln if defined? obj.node puts %{#{obj.ln}: #{obj.ocn} : #{obj.parent} : #{obj.node} - #{obj.lc}} else puts %{#{obj.ln}: #{obj.ocn} : #{obj.parent}} end else if defined? obj.node puts %{ #{obj.ocn} : #{obj.parent} : #{obj.node} - #{obj.lc}} else puts %{ #{obj.ocn} : #{obj.parent}} end end end end end ao_array end def read_fnm ao=[] ao=(FileTest.file?(@fnm)) \ ? (File.open(@fnm,'r:utf-8'){ |f| ao=Marshal.load(f)}) : SiSU_AO::Source.new(@opt).create_ao end def read_fnc ao=[] ao=(FileTest.file?(@fnc)) \ ? (File.open(@fnc,'r:utf-8'){ |f| ao=Marshal.load(f)}) : SiSU_AO::Source.new(@opt,@fnx,@process).create_ao end def read_idx_sst m=[] m=(FileTest.file?(@idx_sst)) \ ? (File.open(@idx_sst,'r:utf-8'){ |f| m=Marshal.load(f)}) : nil end def read_idx_raw m=[] m=(FileTest.file?(@idx_raw)) \ ? (File.open(@idx_raw,'r:utf-8'){ |f| m=Marshal.load(f)}) : nil end def read_idx_html m=[] m=(FileTest.file?(@idx_html)) \ ? (File.open(@idx_html,'r:utf-8'){ |f| m=Marshal.load(f)}) : nil end def read_idx_xhtml m=[] m=(FileTest.file?(@idx_xhtml)) \ ? (File.open(@idx_xhtml,'r:utf-8'){ |f| m=Marshal.load(f)}) : nil end def read_map_nametags m=[] m=(FileTest.file?(@map_nametags)) \ ? (File.open(@map_nametags,'r:utf-8'){ |f| m=Marshal.load(f)}) : nil end def read_map_ocn_htmlseg m=[] m=(FileTest.file?(@map_ocn_htmlseg)) \ ? (File.open(@map_ocn_htmlseg,'r:utf-8'){ |f| m=Marshal.load(f)}) : nil end end class Output def initialize(fn,md,data) @fn,@md,@data=fn,md,data @cf=SiSU_Env::CreateFile.new(@fn) @make=SiSU_Env::InfoFile.new(@fn) @dir=SiSU_Env::InfoEnv.new(@fn) end def screen_dump(o) if defined? o.of print %{OF: #{o.of}; } end if defined? o.is print %{IS: #{o.is.to_s}; } end if defined? o.ocn print %{OCN: #{o.ocn}; } end if defined? o.node print %{NODE: #{o.node}; } end if defined? o.parent print %{Parent: #{o.parent}; } end if defined? o.obj and not o.obj.empty? puts %{\n#{o.obj}; } else "\n" end end def screen_print(t_o) if defined? t_o print ' ' + t_o.to_s end end def screen_output(data) data.each do |o| print o.class screen_print(o.ocn) screen_print(o.obj) puts "\n" end end def hard_output if @md.opt.act[:maintenance][:set]==:on filename_meta=@cf.metaverse.file_meta @data.each {|o| filename_meta.puts o.inspect.sub(/:0x[0-9a-f]{8}\s/,': ')} #to make diffing easier filename_txt=@cf.metaverse.file_txt @data.each do |o| if defined? o.ocn filename_txt.puts case o.is when :heading "[#{o.is.to_s} #{o.lv}~#{o.name} [#{o.ocn}]] #{o.obj}" else "[#{o.is.to_s} [#{o.ocn}]] #{o.obj}" end else filename_txt.puts case o.is when :meta "[m~#{o.tag}] #{o.obj}" else "[#{o.is.to_s}] #{o.obj}" end end end filename_debug=@cf.file_debug @data.each do |o| if defined? o.ocn case o.is when :heading filename_debug.puts "#{o.is.to_s} #{o.lv}~#{o.name} odv=#{o.odv} osp=#{o.osp} [#{o.ocn}] -->\n\t#{o.obj}" end end end else hard="#{@dir.processing_path.ao}/#{@md.fns}.meta" File.unlink(hard) if FileTest.file?(hard) hard="#{@dir.processing_path.ao}/#{@md.fns}.txt" File.unlink(hard) if FileTest.file?(hard) hard="#{@dir.processing_path.ao}/#{@md.fns}.debug.txt" File.unlink(hard) if FileTest.file?(hard) end end def make_marshal_content marshal_ao=@make.marshal.ao_content File.open(marshal_ao,'w'){|f| Marshal.dump(@data,f)} if @data.is_a?(Array) end def make_marshal_metadata marshal_ao=@make.marshal.ao_metadata File.open(marshal_ao,'w'){|f| Marshal.dump(@data,f)} if @data.is_a?(Array) end def idx_html_hard_output if @md.book_idx \ and @md.opt.act[:maintenance][:set]==:on filename_meta=@cf.file_meta_idx_html if @data.is_a?(Array) @data.each {|s| p s.inspect + "\n" unless s.is_a?(String)} @data.each {|s| filename_meta.puts s.strip + "\n" unless s.strip.empty?} end else hard_idx_html="#{@dir.processing_path.ao}/#{@md.fns}.idx.html" File.unlink(hard_idx_html) if FileTest.file?(hard_idx_html) end end def make_marshal_idx_sst_html_seg marshal_ao=@make.marshal.ao_idx_sst_rel_html_seg File.open(marshal_ao,'w'){|f| Marshal.dump(@data,f)} \ if @data.is_a?(Array) end def make_marshal_idx_sst_rel marshal_ao=@make.marshal.ao_idx_sst_rel File.open(marshal_ao,'w'){|f| Marshal.dump(@data,f)} \ if @data.is_a?(Array) end def make_marshal_idx_html marshal_ao=@make.marshal.ao_idx_html File.open(marshal_ao,'w'){|f| Marshal.dump(@data,f)} \ if @data.is_a?(Array) end def make_marshal_idx_xhtml marshal_ao=@make.marshal.ao_idx_xhtml File.open(marshal_ao,'w'){|f| Marshal.dump(@data,f)} \ if @data.is_a?(Array) end def make_marshal_map_nametags marshal_ao=@make.marshal.ao_map_nametags File.open(marshal_ao,'w'){|f| Marshal.dump(@data,f)} \ if @data.is_a?(Hash) end def make_marshal_map_name_ocn_htmlseg marshal_ao=@make.marshal.ao_map_ocn_htmlseg File.open(marshal_ao,'w'){|f| Marshal.dump(@data,f)} \ if @data.is_a?(Hash) end end class Make def initialize(fn,md,data,fnx,process) @fn,@md,@data,@fnx,@process=fn,md,data,fnx,process @env=SiSU_Env::InfoEnv.new(@md.fns) end def reset @@flag_vocab=0 @@line_mode='' end def song reset data_txt=@data data_txt= SiSU_AO_Insertions::Insertions.new(@md,data_txt). # ao_expand_insertions.rb expand_insertions? data_txt= SiSU_AO_MiscArrangeText::SI.new(@md,data_txt). # ao_misc_arrange.rb prepare_text data_obj, metadata, bibliography= SiSU_AO_DocumentStructureExtract::Build.new(@md,data_txt). # ao_doc_str.rb identify_parts data_obj= SiSU_AO_Syntax::Markup.new(@md,data_obj,bibliography).songsheet # ao_syntax.rb data_obj, endnote_array= SiSU_AO_CharacterCheck::Check.new(data_obj). # ao_character_check.rb character_check_and_oldstyle_endnote_array data_obj= SiSU_AO_Images::Images.new(@md,data_obj).images # ao_images.rb data_obj, tags_map, ocn_html_seg_map= SiSU_AO_Numbering::Numbering.new(@md,data_obj,@fnx,@process). # ao_numbering.rb numbering_song data_obj, book_index_rel, book_index_rel_html_seg, html_idx, xhtml_idx= SiSU_AO_BookIndex::BookIndex.new(@md,data_obj,@env). # ao_idx.rb indexing_song if @md.book_idx data_obj= SiSU_AO_Endnotes::Endnotes.new(@md,data_obj,endnote_array). # ao_endnotes.rb endnotes outputdata=data_obj if (@md.opt.act[:ao][:set]==:on \ || @md.opt.act[:maintenance][:set]==:on) SiSU_AO::Output.new(@fn,@md,outputdata).hard_output SiSU_AO::Output.new(@fn,@md,outputdata).make_marshal_content SiSU_AO::Output.new(@fn,@md,metadata).make_marshal_metadata SiSU_AO::Output.new(@fn,@md,html_idx).idx_html_hard_output SiSU_AO::Output.new(@fn,@md,book_index_rel_html_seg).make_marshal_idx_sst_html_seg SiSU_AO::Output.new(@fn,@md,book_index_rel).make_marshal_idx_sst_rel SiSU_AO::Output.new(@fn,@md,html_idx).make_marshal_idx_html SiSU_AO::Output.new(@fn,@md,xhtml_idx).make_marshal_idx_xhtml SiSU_AO::Output.new(@fn,@md,tags_map).make_marshal_map_nametags SiSU_AO::Output.new(@fn,@md,ocn_html_seg_map).make_marshal_map_name_ocn_htmlseg end reset outputdata end protected end end __END__ #+END_SRC ** ao_appendices.rb #+HEADER: :tangle "../lib/sisu/ao_appendices.rb" #+BEGIN_SRC ruby #<<sisu_document_header>> module SiSU_AO_Appendices class Glossary def initialize(md,data) @md,@data=md,data end def glossary_extraction glossary=[] glossaryflag=false code_flag=false flag_code_curly=:not_code_curly flag_code_tics=:not_code_tics @data=@data.select do |t_o| if t_o =~/^code\{/ flag_code_curly=:code_curly elsif t_o =~/^\}code/ flag_code_curly=:not_code_curly elsif t_o =~/^``` code/ flag_code_tics=:code_tics elsif flag_code_tics ==:code_tics \ and t_o =~/^```/ flag_code_tics=:not_code_tics end code_flag=if flag_code_curly==:code_curly \ or flag_code_tics==:code_tics true else false end unless code_flag if @md.flag_glossary if t_o =~/^1~!glossary/ glossaryflag = true next elsif t_o =~/^:?[B-D]~/ next elsif t_o =~/^:?[B-D1]~/ glossaryflag = false t_o elsif glossaryflag if t_o !~/\A%+ / glossary << t_o next else t_o end else t_o end else t_o end else t_o end end.compact [@data,glossary] end end class Bibliography def initialize(md,data) @md,@data=md,data end def sort_bibliography_array_by_deemed_author_year_title(bib) if bib bib.compact.sort_by do |c| [c[:deemed_author],c[:ymd],c[:title]] end end end def citation_in_prepared_bibliography(cite) @cite=cite def generic { is: nil, # :book, :article, :magazine, :newspaper, :blog, :other author_raw: nil, author: nil, author_arr: nil, editor_raw: nil, editor: nil, editor_arr: nil, title: nil, subtitle: nil, fulltitle: nil, language: nil, trans: nil, src: nil, journal: nil, in: nil, volume: nil, edition: nil, year: nil, place: nil, publisher: nil, url: nil, pages: nil, note: nil, #format: nil, #consider list of fields arranged with markup short_name: nil, id: nil, } end def citation_metadata type=:generic if type citation=generic citeblock=@cite.split("\n") citeblock.select do |meta| case meta when /^((?:au|author):\s+)\S+/ #req citation[:author_raw]=/^#{$1}(.+)/.match(meta)[1] when /^((?:ti|title):\s+)\S+/ #req citation[:title]=/^#{$1}(.+)/.match(meta)[1] when /^((?:st|subtitle):\s+)\S+/ citation[:subtitle]=/^#{$1}(.+)/.match(meta)[1] when /^((?:lng|language):\s+)\S+/ citation[:language]=/^#{$1}(.+)/.match(meta)[1] when /^((?:edr?|editor):\s+)\S+/ citation[:editor_raw]=/^#{$1}(.+)/.match(meta)[1] when /^((?:tr|trans(:?lator)?):\s+)\S+/ citation[:editor_raw]=/^#{$1}(.+)/.match(meta)[1] when /^((?:pb|publisher):\s+)\S+/ citation[:publisher]=/^#{$1}(.+)/.match(meta)[1] when /^((?:edn|edition):\s+)\S+/ citation[:edition]=/^#{$1}(.+)/.match(meta)[1] when /^((?:yr|year):\s+)\S+/ #req? citation[:year]=/^#{$1}(.+)/.match(meta)[1] when /^((?:pl|publisher_state):\s+)\S+/ citation[:place]=/^#{$1}(.+)/.match(meta)[1] when /^((?:jo|journal):\s+)\S+/ #req? citation[:journal]=/^#{$1}(.+)/.match(meta)[1] when /^((?:vol?|volume):\s+)\S+/ citation[:volume]=/^#{$1}(.+)/.match(meta)[1] when /^((?:in):\s+)\S+/ citation[:in]=/^#{$1}(.+)/.match(meta)[1] when /^((?:src):\s+)\S+/ citation[:src]=/^#{$1}(.+)/.match(meta)[1] when /^((?:pg|pages?):\s+)\S+/ citation[:pages]=/^#{$1}(.+)/.match(meta)[1] when /^(url:\s+)\S+/ citation[:url]=/^#{$1}(.+)/.match(meta)[1] when /^(note:\s+)\S+/ citation[:note]=/^#{$1}(.+)/.match(meta)[1] when /^((?:sn|shortname):\s+)\S+/ # substitution: (/#{id}/,"#{sn}") citation[:short_name]=/^#{$1}(.+)/.match(meta)[1] when /^(id:\s+)\S+/ # substitution: (/#{id}/,"#{sn}") citation[:id]=/^#{$1}(.+)/.match(meta)[1] end end if citation[:subtitle] citation[:fulltitle] = citation[:title] \ + ' - ' \ + citation[:subtitle] else citation[:fulltitle] = citation[:title] end if citation[:author_raw] citation[:author_arr]=citation[:author_raw].split(/;\s*/) citation[:author]=citation[:author_arr].map do |author| author.gsub(/(.+?),\s+(.+)/,'\2 \1').strip end.join(', ').strip end if citation[:editor_raw] citation[:editor_arr]=citation[:editor_raw].split(/;\s*/) citation[:editor]=citation[:editor_arr].map do |editor| editor.gsub(/(.+?),\s+(.+)/,'\2 \1').strip end.join(', ').strip end citation[:ymd]=if not citation[:year] =~/^[0-9]{4}/ '9999' else citation[:year] end citation[:deemed_author]=if not citation[:author_raw] \ and citation[:editor_raw] citation[:editor_arr][0] elsif citation[:author_raw] citation[:author_arr][0] else SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia). warn('Citation needs an author or editor, title: "' \ + citation[:title] + '"') '000' end unless citation[:short_name] citation[:short_name]=%{#{citation[:author]}, "#{citation[:title]}" (#{citation[:date]})} end end citation end self end def biblio_format def generic(c) cite=%{#{c[:author]}. /{"#{c[:fulltitle]}".}/} cite=(c[:journal]) \ ? cite + %{ #{c[:journal]},} : cite cite=(c[:source]) \ ? cite + %{ #{c[:source]},} : cite cite=(c[:in]) \ ? cite + %{ in #{c[:in]},} : cite cite=(c[:volume]) \ ? cite + %{ #{c[:volume]},} : cite cite=(c[:trans]) \ ? cite + %{ trans. #{c[:trans]},} : cite cite=(c[:editor]) \ ? cite + %{ ed. #{c[:editor]},} : cite cite=(c[:place]) \ ? cite + %{ #{c[:place]},} : cite cite=(c[:publisher]) \ ? cite + %{ #{c[:publisher]},} : cite cite=(c[:year]) \ ? cite + %{ (#{c[:year]})} : cite cite=(c[:pages]) \ ? cite + %{ #{c[:pages]}} : cite cite=(c[:url]) \ ? cite + %{ #{c[:url]}} : cite cite=(c[:note]) \ ? cite + %{ #{c[:note]}} : cite cite end def generic_editor(c) cite=%{#{c[:editor]} ed. /{"#{c[:fulltitle]}".}/} cite=(c[:journal]) \ ? cite + %{ #{c[:journal]}, } : cite cite=(c[:source]) \ ? cite + %{ #{c[:source]}, } : cite cite=(c[:in]) \ ? cite + %{ in #{c[:in]},} : cite cite=(c[:volume]) \ ? cite + %{ #{c[:volume]},} : cite cite=(c[:trans]) \ ? cite + %{ trans. #{c[:trans]},} : cite cite=(c[:place]) \ ? cite + %{ #{c[:place]},} : cite cite=(c[:publisher]) \ ? cite + %{ #{c[:publisher]}} : cite cite=(c[:year]) \ ? cite + %{ (#{c[:year]})} : cite cite=(c[:pages]) \ ? cite + %{ #{c[:pages]}} : cite cite=(c[:url]) \ ? cite + %{ #{c[:url]}} : cite cite=(c[:note]) \ ? cite + %{ #{c[:note]}} : cite cite end self end def biblio_make(cite) if cite[:author] biblio_format.generic(cite) elsif cite[:editor] biblio_format.generic_editor(cite) else biblio_format.generic(cite) end end def biblio_extraction bibliography=[] biblioflag=false code_flag=false flag_code_curly=:not_code_curly flag_code_tics=:not_code_tics @data=@data.select do |t_o| if t_o =~/^code\{/ flag_code_curly=:code_curly elsif t_o =~/^\}code/ flag_code_curly=:not_code_curly elsif t_o =~/^``` code/ flag_code_tics=:code_tics elsif flag_code_tics ==:code_tics \ and t_o =~/^```/ flag_code_tics=:not_code_tics end code_flag=if flag_code_curly==:code_curly \ or flag_code_tics==:code_tics true else false end unless code_flag if @md.flag_auto_biblio if t_o =~/^1~!biblio(?:graphy)?/ biblioflag = true t_o elsif t_o =~/^:?[B-D1]~/ biblioflag = false t_o elsif biblioflag if t_o !~/\A%+ / bibliography << citation_in_prepared_bibliography(t_o).citation_metadata next else t_o end else t_o end elsif @md.flag_biblio if t_o =~/^1~!biblio(?:graphy)?/ biblioflag = true next elsif t_o =~/^:?[B-D]~/ next elsif t_o =~/^:?[B-D1]~/ biblioflag = false t_o elsif biblioflag if t_o !~/\A%+ / bibliography << t_o next else t_o end else t_o end else t_o end else t_o end end.compact if @md.flag_auto_biblio \ and bibliography.length > 0 data_new=[] bib=sort_bibliography_array_by_deemed_author_year_title(bibliography) biblio_done=[] @data.select do |t_o| if t_o =~/^1~!biblio(?:graphy)?/ bib.each do |c| d=c d.store(:obj, biblio_make(c)) biblio_done << d #biblio_done << { obj: biblio_make(c), id: c[:id] } end else data_new << t_o end end @data=data_new end [@data,biblio_done] end end class Citations def initialize(md='',data='') @md,@data=md,data #@biblio=[] end def songsheet tuned_file,citations=citations_scan(@data) [tuned_file,citations] end def sort_bibliography_array_by_author_year(bib) bib.sort_by do |c| [c[:author_raw],c[:year]] #[c[:author_arr][0],c[:year],c[:title]] end end def citations_regex def pages_pattern %r{(?:[,.:]?\s+(?:p{1,2}\.?\s+)?(?:\d+--?\d+)[,.]?\s+)?} end def editor_pattern %r{(?<editor>(?:editor|edited by)\s+.+?)} end def year_pattern %r{[(\[]?(?<year>\d{4})[\])]?[.,]?} end def authors_year_title_publication_editor_pages /(?<authors>.+?)\s+#{year_pattern}\s+"(?<title>.+?)"\s+(?:#{Mx[:fa_italics_o]}|#{Mx[:srcrgx_italics_o]})(?<publication>.+?)(?:#{Mx[:fa_italics_c]}|#{Mx[:srcrgx_italics_c]})\s+#{editor_pattern}#{pages_pattern}/m # note ed. is usually edition rather than editor end def authors_title_publication_year_editor_pages /(?<authors>.+?)\s+"(?<title>.+?)"\s+(?:#{Mx[:fa_italics_o]}|#{Mx[:srcrgx_italics_o]})(?<publication>.+?)(?:#{Mx[:fa_italics_c]}|#{Mx[:srcrgx_italics_c]})\s+#{year_pattern}\s+#{editor_pattern}#{pages_pattern}/m # note ed. is usually edition rather than editor end def authors_title_publication_editor_year_pages ### /(?<authors>.+?)\s+"(?<title>.+?)"\s+(?:#{Mx[:fa_italics_o]}|#{Mx[:srcrgx_italics_o]})(?<publication>.+?)(?:#{Mx[:fa_italics_c]}|#{Mx[:srcrgx_italics_c]})\s+ed.\s+#{editor_pattern}#{year_pattern}#{pages_pattern}/m # note ed. is usually edition rather than editor end def authors_title_publication_editor_pages_year ### /(?<authors>.+?)\s+"(?<title>.+?)"\s+(?:#{Mx[:fa_italics_o]}|#{Mx[:srcrgx_italics_o]})(?<publication>.+?)(?:#{Mx[:fa_italics_c]}|#{Mx[:srcrgx_italics_c]})\s+#{editor_pattern}#{pages_pattern}#{year_pattern}/m # note ed. is usually edition rather than editor end def authors_year_title_publication_pages /(?<authors>.+?)\s+#{year_pattern}\s+"(?<title>.+?)"\s+(?:#{Mx[:fa_italics_o]}|#{Mx[:srcrgx_italics_o]})(?<publication>.+?)(?:#{Mx[:fa_italics_c]}|#{Mx[:srcrgx_italics_c]})[,.;]?#{pages_pattern}/m end def authors_title_publication_year_pages /(?<authors>.+?)\s+"(?<title>.+?)"\s+(?:#{Mx[:fa_italics_o]}|#{Mx[:srcrgx_italics_o]})(?<publication>.+?)(?:#{Mx[:fa_italics_c]}|#{Mx[:srcrgx_italics_c]})\s+#{year_pattern}\s+#{pages_pattern}/m end def authors_title_publication_pages_year ### /(?<authors>.+?)\s+"(?<title>.+?)"\s+(?:#{Mx[:fa_italics_o]}|#{Mx[:srcrgx_italics_o]})(?<publication>.+?)(?:#{Mx[:fa_italics_c]}|#{Mx[:srcrgx_italics_c]})#{pages_pattern}#{year_pattern}/m end def authors_year_publication_pages /(?<authors>.+?)\s+#{year_pattern}\s+(?:#{Mx[:fa_italics_o]}|#{Mx[:srcrgx_italics_o]})(?<publication>.+?)(?:#{Mx[:fa_italics_c]}|#{Mx[:srcrgx_italics_c]})#{pages_pattern}/m end def authors_publication_year_pages /(?<authors>.+?)\s+(?:#{Mx[:fa_italics_o]}|#{Mx[:srcrgx_italics_o]})(?<publication>.+?)(?:#{Mx[:fa_italics_c]}|#{Mx[:srcrgx_italics_c]})[,.;]?\s+(?<publisher>.+?)?#{year_pattern}#{pages_pattern}[.;]?/m end self end def authors?(citations) citations.each.map do |b| if b =~ /^.+\s+::.+?:$/ c=/^(?<citation>.+?)\s+::(?<shortref>.+?):$/.match(b) { citation: c[:citation], shortref: c[:shortref], c[:shortref].to_s => c[:citation] } else { citation: b } end end end def long_and_short_ref?(citations) #could be useful, keep ... ectract shortref citations.each.map do |b| if b =~ /^.+\s+::.+?:$/ c=/^(?<citation>.+?)\s+::(?<shortref>.+?):$/.match(b) { citation: c[:citation], shortref: c[:shortref], c[:shortref].to_s => c[:citation] } else { citation: b } end end end def citation_detail(citations) #could be useful, keep ... extract shortref bibahash=[] number=0 missed=0 citations.select do |b| z=if b =~citations_regex.authors_year_title_publication_editor_pages c=citations_regex.authors_year_title_publication_editor_pages.match(b) { is: :article, author_raw: c[:authors], year: c[:year], title: c[:title], publication: c[:publication], editor: c[:editor], } elsif b =~citations_regex.authors_title_publication_year_editor_pages c=citations_regex.authors_title_publication_year_editor_pages.match(b) { is: :article, author_raw: c[:authors], year: c[:year], title: c[:title], publication: c[:publication], editor: c[:editor], } elsif b =~citations_regex.authors_title_publication_editor_year_pages c=citations_regex.authors_title_publication_editor_year_pages.match(b) { is: :article, author_raw: c[:authors], year: c[:year], title: c[:title], publication: c[:publication], editor: c[:editor], } elsif b =~citations_regex.authors_title_publication_editor_pages_year c=citations_regex.authors_title_publication_editor_pages_year.match(b) { is: :article, author_raw: c[:authors], year: c[:year], title: c[:title], publication: c[:publication], editor: c[:editor], } elsif b =~citations_regex.authors_year_title_publication_pages c=citations_regex.authors_year_title_publication_pages.match(b) { is: :article, author_raw: c[:authors], year: c[:year], title: c[:title], publication: c[:publication], } elsif b =~citations_regex.authors_title_publication_year_pages c=citations_regex.authors_title_publication_year_pages.match(b) { is: :article, author_raw: c[:authors], year: c[:year], title: c[:title], publication: c[:publication], } elsif b =~citations_regex.authors_year_publication_pages c=citations_regex.authors_year_publication_pages.match(b) { is: :book, author_raw: c[:authors], year: c[:year], publication: c[:publication], } elsif b =~citations_regex.authors_publication_year_pages c=citations_regex.authors_publication_year_pages.match(b) { is: :book, author_raw: c[:authors], year: c[:year], publication: c[:publication], } else b end if not z.is_a?(NilClass) \ and z.is_a?(Hash) \ and z[:author_raw].length > 0 z[:author_arr]=z[:author_raw].split(/;\s*/) z[:author]=z[:author_arr].map do |author| author.gsub(/(.+?),\s+(.+)/,'\2 \1').strip end.join(', ').strip if @md.opt.act[:verbose_plus][:set]==:on \ || @md.opt.act[:maintenance][:set]==:on number +=1 if z.is_a?(Hash) missed +=1 if z.is_a?(String) (z.is_a?(Hash)) \ ? (p '[' + number.to_s + '] ' + z.to_s) : (p '<' + missed.to_s + '> ' + z.to_s) end end bibahash << z if z.is_a?(Hash) end bibahash=sort_bibliography_array_by_author_year(bibahash.compact) bibahash end def citations_scan(data) citations=[] #short_ref=[] tuned_file = data.compact.select do |dob| if dob.is !=:meta \ && dob.is !=:comment \ && dob.is !=:code \ && dob.is !=:table if dob.obj =~/\.:.+?:\./ citations << dob.obj.scan(/\.:\s*(.+?)\s*:\./m) #short_ref << dob.obj.scan(/\.:\s+(.+?)\s+::([^:]+)::\./m) #look at later ##short_ref << dob.obj.scan(/\.:\s+(.+?)\s+::(.+?)::\./m) #look at later #short_ref << dob.obj.scan(/\.:\s*(.+?)\s*(::(.+?):)?:\./m) #look at later citations=citations.flatten.compact dob.obj=dob.obj. #remove citations delimiter & helpers from text gsub(/\.:|:\./,'') end end dob if dob.is_a?(Object) end #bib=long_and_short_ref?(citations) #could be useful, keep ... extract shortref citations=citation_detail(citations) [tuned_file,citations] end end end __END__ #+END_SRC ** ao_character_check.rb #+HEADER: :tangle "../lib/sisu/ao_character_check.rb" #+BEGIN_SRC ruby #<<sisu_document_header>> module SiSU_AO_CharacterCheck class Check def initialize(data) @data=data @comment='%' @endnote_array=[] end def character_check_and_oldstyle_endnote_array data=@data @endnote_array=[] endnote_no=1 @tuned_file=data.select do |dob| unless dob.is ==:table dob.obj=dob.obj.strip. gsub(/^[{~}]\s*$/,''). gsub(/~#\s*/,"#{Mx[:pa_non_object_no_heading]}"). gsub(/-#\s*/,"#{Mx[:pa_non_object_dummy_heading]}"). gsub(/(#{Mx[:en_a_o]})\s*\s+/,'\1 '). gsub(/(~\{\s*)\s+/,'\1 '). gsub(/ \/\//,"#{Mx[:br_line]}"). gsub(/<br>/,"#{Mx[:br_line]}"). #needed by xml, xhtml etc. gsub(/\t/,' '). gsub(/\342\200\231/u,"'"). #if dob =~/’/ #Avoid #‘ ’ #“ ” gsub(/\\copy(?:right)?\b/,'©'). gsub(/\\trademark\b|\\tm\b/,'®') dob.obj=dob.obj + "\n" unless dob.is ==:code case dob.obj when /\^~/ #% Note must do this first (earlier loop) and then enter gathered data into ~^\d+ sub_dob=dob.obj.dup @endnote_array << sub_dob.gsub(/\n/,''). gsub(/\^~\s+(.+)\s*/, %{#{Mx[:en_a_o]}#{endnote_no} \\1 #{Mx[:en_a_c]}}). strip endnote_no+=1 dob=nil if dob.obj =~/\^~ .+/ #watch, removes 'binary' endnote now in endnote array for later insertion end end end dob if dob.is_a?(Object) end.flatten.compact [@tuned_file,@endnote_array] end end end #+END_SRC ** ao_composite.rb #+HEADER: :tangle "../lib/sisu/ao_composite.rb" #+BEGIN_SRC ruby #<<sisu_document_header>> module SiSU_Assemble require_relative 'se' # se.rb require_relative 'utils_composite' # utils_composite.rb class RemoteImage def initialize @env=SiSU_Env::InfoEnv.new end def image(dir) images=[] images[0]=dir images end def download_images(images_info) path="#{@env.processing_path.processing}/external_document/image" FileUtils::mkdir_p(path) \ unless FileTest.directory?(path) download_from=images_info.shift images_info.each do |i| image="#{path}/#{i}" imagefile=File.new(image,'w+') open("#{download_from}/#{i}") do |g| imagefile << g.read end imagefile.close end output_path="#{@env.path.webserv}/#{@env.path.base_markup_dir_stub}/_sisu/image_external" FileUtils::mkdir_p(output_path) \ unless FileTest.directory?(output_path) SiSU_Env::SystemCall.new("#{path}/*",output_path,'q').rsync end end class Composite include SiSU_Composite_Doc_Utils # composite doc, .ssm, extract all related insert files, array of filenames test def initialize(opt) @opt=opt @env=SiSU_Env::InfoEnv.new end def read begin pwd=Dir.pwd Dir.chdir(@opt.f_pth[:pth]) if @opt.fno =~/\S+?\.ssm$/ SiSU_Screen::Ansi.new( @opt.act[:color_state][:set], 'Composite Document', "[#{@opt.f_pth[:lng_is]}] #{@opt.fno}", ).grey_title_hi unless @opt.act[:quiet][:set]==:on composite_and_imported_filenames_array(@opt.fno) # composite doc, .ssm, extract all related insert files, array of filenames test assembled=loadfile(@opt.fno) write(assembled) end Dir.chdir(pwd) rescue SiSU_Errors::Rescued.new($!,$@,@opt.selections.str,@opt.fns). location do __LINE__.to_s + ':' + __FILE__ end ensure end end def insert?(para) if para =~ /^<<\s+((?:https?|file):\/\/\S+?\.ss[it])$/ # and NetTest url($1.strip) elsif para =~/^<<\s+(\S+?\.ss[it])$/ loadfilename=$1.strip insert_array=loadfile(loadfilename) file=insertion(loadfilename,insert_array) file[:prepared] else para end end def loadfile(loadfilename) begin if FileTest.file?(loadfilename) insert_array=IO.readlines(loadfilename,'') if loadfilename =~/\S+?\.ss[itm]$/ if (@opt.act[:verbose][:set]==:on \ || @opt.act[:verbose_plus][:set]==:on \ || @opt.act[:maintenance][:set]==:on) SiSU_Screen::Ansi.new( @opt.act[:color_state][:set], 'loading:', loadfilename, ).txt_grey end tuned_file=if loadfilename =~/\S+?\.ss[im]$/ insert_array.each.map do |para| insert?(para) end elsif loadfilename =~/\S+?\.sst$/ insert_array.each.map do |para| para end end.flatten.compact end end rescue SiSU_Errors::Rescued.new($!,$@,@opt.selections.str,@opt.fns).location do __LINE__.to_s + ':' + __FILE__ end ensure end end def url(loadfilename) if loadfilename =~ /((?:https?|file):\/\/\S+?\.ss[it])$/ # and NetTest loadfilename=$1 begin require 'uri' require 'open-uri' require 'pp' rescue LoadError SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia). error('uri, open-uri or pp NOT FOUND (LoadError)') end insert=open(loadfilename) insert_array=insert.dup insert.close file=insertion(loadfilename,insert_array) file[:prepared] end end def write(assembled) assembled_file=File.new("#{@env.processing_path.composite_file}/#{@opt.fnb}.ssm.sst",'w+') assembled.each {|a| assembled_file << a } assembled_file.close end def download_images(download_from,images_array) path="#{@env.processing_path.processing}/external_document/image" FileUtils::mkdir_p(path) unless FileTest.directory?(path) images_array.each do |i| image="#{path}/#{i}" unless FileTest.exists?(image) imagefile=File.new(image,'w+') open("#{download_from}/#{i}") do |g| imagefile << g.read end imagefile.close end end end def insertion(fni,insert_array) file={ prepared: [], images: [] } rgx_image=/(?:^|[^_\\])\{\s*(\S+?\.(?:png|jpg|gif))/ file[:prepared] << "\n% |#{fni}|@|^|>>ok\n\n" @code_flag=false insert_array.each do |i| @code_flag=if i =~/^code\{/ then true elsif i =~/^\}code/ then false else @code_flag end if not @code_flag \ and i !~/^%+\s/ i=i. gsub(/^([123]|:?[ABCD])~\? /, '% [conditional heading:] \1~ ') #off conditional heading (consider syntax) if i =~/^@\S+?:/ i=i.gsub(/\n/m,"\n% "). gsub(/\n%\s+$/m,''). gsub(/^@\S+?:/m,"\n% [imported header:] ") #off imported headers end end file[:prepared] << i if i !~/^%+\s/ \ and i =~rgx_image file[:images] << i.scan(rgx_image).uniq end end file[:prepared] << "\n% end import" << "\n\n" if file[:images].length > 0 file[:images]=file[:images].flatten.uniq file[:images].delete_if {|x| x =~/https?:\/\// } end file end end class CompositeFileList def initialize(opt) @opt=opt @env=SiSU_Env::InfoEnv.new end def read begin @opt.fns=@opt.fns.gsub(/\.ssm\.sst$/,'.ssm') #FIX earlier, hub fns_array=IO.readlines(@opt.fns,'') insertions?(fns_array) rescue SiSU_Errors::Rescued.new($!,$@,@opt.selections.str,@opt.fns).location do __LINE__.to_s + ':' + __FILE__ end ensure end end def insertions?(fns_array) tuned_file=[] SiSU_Screen::Ansi.new( @opt.act[:color_state][:set], 'Composite Document', @opt.fno ).grey_title_hi unless @opt.act[:quiet][:set]==:on @ssm=[@opt.fns] fns_array.each do |para| if para =~/^<<\s+(\S+?\.ss[it])$/ loadfilename=$1.strip if (@opt.act[:verbose][:set]==:on \ || @opt.act[:verbose_plus][:set]==:on \ || @opt.act[:maintenance][:set]==:on) SiSU_Screen::Ansi.new( @opt.act[:color_state][:set], 'loading:', loadfilename, ).txt_grey end tuned_file << if loadfilename =~ /(?:https?|file):\/\/\S+?\.ss[it]$/ @ssm << loadfilename elsif loadfilename =~ /\.ss[it]$/ \ and FileTest.file?(loadfilename) @ssm << loadfilename else STDERR.puts %{SKIPPED processing file: [#{@opt.lng}] "#{@opt.fns}" it requires an invalid or non-existent file: "#{loadfilename}"} $process_document = :skip; break #remove this line to continue processing documents that have missing include files para end end end @ssm end end end __END__ #+END_SRC ** ao_doc_objects.rb #+HEADER: :tangle "../lib/sisu/ao_doc_objects.rb" #+BEGIN_SRC ruby #<<sisu_document_header>> module SiSU_AO_DocumentStructure class Extract def extract(h,o) h ? h : o end end class ObjectMetadata attr_accessor :is,:of,:tags,:obj,:digest def initialize @tags={} @is=@tmp=@digest=nil @of=:meta end def metadata(tags) of = @of #Symbol, classification - group is = :meta #Symbol, classification - specific type tags = tags || ((defined? o.tags) ? o.tags : {}) #String, metadata type/tag obj = nil @of,@is,@tags,@obj=of,is,tags,obj self end end class ObjectMeta attr_accessor :obj,:is,:of,:tag,:digest,:tmp def initialize @is=@obj=@tag=@digest=@digest=@tmp=nil @of=:meta end def metadata(h,o=nil) of = @of #Symbol, classification - group is = :meta #Symbol, classification - specific type tag = h[:tag] || ((defined? o.tag) ? o.tag : nil) #String, metadata type/tag obj = h[:obj] || ((defined? o.obj) ? o.obj : nil) #String, text content tmp = h[:tmp] || ((defined? o.tmp) ? o.tmp : nil) #available for processing, empty after use digest = h[:digest] || ((defined? o.digest) ? o.digest : nil) #hash digests, sha512, sha256 or md5 @of,@is,@tag,@obj,@digest,@tmp=of,is,tag,obj,digest,tmp self end end class ObjectHeading attr_accessor :obj,:is,:tags,:of,:lv,:ln,:lc,:use_,:name,:idx,:ocn,:odv,:osp,:node,:parent,:ocn_,:note_,:autonum_,:digest,:tmp def initialize @of=:para @is=@obj=@lv=@ln=@lc=@use_=@name=@idx=@size=@ocn=@odv=@osp=@node=@parent=@ocn_=@note_=@autonum_=@digest=@tmp=nil @tags=[] end def heading_ln(lv) case lv when /A/ then 0 when /B/ then 1 when /C/ then 2 when /D/ then 3 when /1/ then 4 when /2/ then 5 when /3/ then 6 when /4/ then 7 when /5/ then 8 when /6/ then 9 end end def heading_lv(ln) case ln.to_s when /0/ then 'A' when /1/ then 'B' when /2/ then 'C' when /3/ then 'D' when /4/ then '1' when /5/ then '2' when /6/ then '3' when /7/ then '4' when /8/ then '5' when /9/ then '6' end end def heading(h,o=nil) if not h[:ln] \ and (h[:lv] and h[:lv]=~/[1-6A-D]/) h[:ln]=heading_ln(h[:lv]) elsif not h[:lv] \ and (h[:ln] and h[:ln].to_s=~/[0-9]/) h[:lv]=heading_lv(h[:ln]) end of = @of #Symbol, classification - group is = :heading #Symbol, classification - specific type name = h[:name] || ((defined? o.name) ? o.name : nil) #String, named object? tags = h[:tags] || ((defined? o.tags) ? o.tags : []) #Array, associated object tags, names if any obj = h[:obj] || ((defined? o.obj) ? o.obj : nil) #String, text content idx = h[:idx] || ((defined? o.idx) ? o.idx : nil) #String, book index provided? ocn = h[:ocn] || ((defined? o.ocn) ? o.ocn : nil) #Integer, sequential on substantive-content objects odv = h[:odv] || ((defined? o.odv) ? o.odv : nil) osp = h[:osp] || ((defined? o.osp) ? o.osp : nil) node = h[:node] || ((defined? o.node) ? o.node : nil) #[Node relationship doc structure info] parent = h[:parent] || ((defined? o.parent) ? o.parent : nil) #[Node parent] lv = h[:lv] || ((defined? o.lv) ? o.lv : nil) #Alpha-numeric, document structure as used in markup, A-D then 1-6 ln = h[:ln] || ((defined? o.ln) ? o.ln : nil) #Integer, document structure level, for convenience in processing 1-9 lc = h[:lc] || ((defined? o.lc) ? o.lc : nil) #Integer, document structure collapsed level, convenience (collapse sisu's dual level document structure for markup with simple linear structure) use_ = if lv \ and lv == '1' h[:use_] || ((defined? o.use_) ? o.use_ : :ok) elsif not lv.empty? \ and lv =~ /[A-D2-3]/ :ok else h[:use_] || ((defined? o.use_) ? o.use_ : :ok) end ocn_ = if h[:ocn_].nil? ((defined? o.ocn_) ? o.ocn_ : true) #Bool? no ocn, non-substantive content, do not include in toc #consider else h[:ocn_] end autonum_ = if h[:autonum_].nil? ((defined? o.autonum_) ? o.autonum_ : true) #Bool? auto-numbering if requested default on, false suppresses else h[:autonum_] end note_ = h[:note_] || ((defined? o.note_) ? o.note_ : false) #Bool, endnotes/footnotes? (processing optimization) digest = h[:digest] || ((defined? o.digest) ? o.digest : nil) #hash digests, sha512, sha256 or md5 tmp = h[:tmp] || ((defined? o.tmp) ? o.tmp : nil) #available for processing, empty after use @of,@is,@lv,@ln,@lc,@name,@tags,@obj,@idx,@ocn,@odv,@osp,@node,@parent,@use_,@ocn_,@note_,@autonum_,@digest,@tmp= of, is, lv, ln, lc, name, tags, obj, idx, ocn, odv, osp, node, parent, use_, ocn_, note_, autonum_, digest, tmp self end def heading_insert(h,o=nil) heading(h,o=nil) @is = :heading_insert #String, classification - specific type self end end class ObjectPara attr_accessor :obj,:is,:tags,:of,:name,:idx,:quote_,:bullet_,:indent,:hang,:ocn,:odv,:osp,:parent,:note_,:image_,:ocn_,:digest,:tmp def initialize @of=:para @is=@obj=@name=@idx=@quote_=@bullet_=@indent=@hang=@size=@ocn=@odv=@osp=@parent=@note_=@image_=@ocn_=@digest=@tmp=nil @tags=[] end def paragraph(h,o=nil) of = @of #Symbol, classification - group is = :para #Symbol, classification - specific type name = h[:name] || ((defined? o.name) ? o.name : nil) #String, named object? tags = h[:tags] || ((defined? o.tags) ? o.tags : []) #Array, associated object tags, names if any obj = h[:obj] || ((defined? o.obj) ? o.obj : nil) #String, text content idx = h[:idx] || ((defined? o.idx) ? o.idx : nil) #String, book index provided? ocn = h[:ocn] || ((defined? o.ocn) ? o.ocn : nil) #Integer, sequential on substantive-content objects odv = h[:odv] || ((defined? o.odv) ? o.odv : nil) osp = h[:osp] || ((defined? o.osp) ? o.osp : nil) parent = h[:parent] || ((defined? o.parent) ? o.parent : nil) #[Node parent] indent = h[:indent].to_s || ((defined? o.indent) ? o.indent.to_s : nil) #Integer, indent level hang = h[:hang].to_s || ((defined? o.hang) ? o.hang.to_s : nil) #Integer, hanging indent level bullet_ = h[:bullet_] || ((defined? o.bullet_) ? o.bullet_ : false) #Bool, bulleted? quote_ = h[:quote_] || ((defined? o.quote_) ? o.quote_ : false) #Bool, quote (blockquote)? note_ = h[:note_] || ((defined? o.note_) ? o.note_ : false) #Bool, endnotes/footnotes? (processing optimization) image_ = h[:image_] || ((defined? o.image_) ? o.image_ : false) #Bool, images? (processing optimization) ocn_ = if h[:ocn_].nil? ((defined? o.ocn_) ? o.ocn_ : true) #Bool? no ocn, non-substantive content, do not include in toc #consider else h[:ocn_] end digest = h[:digest] || ((defined? o.digest) ? o.digest : nil) #hash digests, sha512, sha256 or md5 tmp = h[:tmp] || ((defined? o.tmp) ? o.tmp : nil) #available for processing, empty after use @of,@is,@name,@tags,@obj,@indent,@hang,@bullet_,@quote_,@idx,@ocn,@odv,@osp,@parent,@image_,@note_,@ocn_,@digest,@tmp= of, is, name, tags, obj, indent, hang, bullet_, quote_, idx, ocn, odv, osp, parent, image_, note_, ocn_, digest, tmp self end def docinfo(h,o=nil) of = @of #String, classification - group is = :docinfo #String, classification - specific type name = h[:name] || ((defined? o.name) ? o.name : nil) #String, named object? tags = h[:tags] || ((defined? o.tags) ? o.tags : nil) #Array, associated object tags, names if any obj = h[:obj] || ((defined? o.obj) ? o.obj : nil) #String, text content idx = nil #String, book index provided? ocn = nil #Integer, sequential on substantive-content objects odv = h[:odv] || ((defined? o.odv) ? o.odv : nil) osp = h[:osp] || ((defined? o.osp) ? o.osp : nil) parent = h[:parent] || ((defined? o.parent) ? o.parent : nil) #[Node parent] indent = nil #Integer, indent level hang = nil #Integer, indent level bullet_ = false #Bool, bulleted? note_ = false #Bool, endnotes/footnotes? (processing optimization) image_ = h[:image_] || ((defined? o.image_) ? o.image_ : false) #Bool, images? (processing optimization) ocn_ = if h[:ocn_].nil? ((defined? o.ocn_) ? o.ocn_ : true) #Bool? no ocn, non-substantive content, do not include in toc #consider else h[:ocn_] end digest = h[:digest] || ((defined? o.digest) ? o.digest : nil) #hash digests, sha512, sha256 or md5 tmp = h[:tmp] || ((defined? o.tmp) ? o.tmp : nil) #available for processing, empty after use @of,@is,@name,@tags,@obj,@indent,@hang,@bullet_,@idx,@ocn,@odv,@osp,@parent,@image_,@note_,@ocn_,@digest,@tmp= of, is, name, tags, obj, indent, hang, bullet_, idx, ocn, odv, osp, parent, image_, note_, ocn_, digest, tmp self end end class ObjectBlockTxt attr_accessor :obj,:is,:of,:tags,:lngsyn,:idx,:ocn,:odv,:osp,:parent,:note_,:number_,:ocn_,:digest,:tmp def initialize @of=:block @is=@obj=@lngsyn=@idx=@ocn=@odv=@osp=@parent=@note_=@number_=@ocn_=@digest=@tmp=nil @tags=[] end def code(h,o=nil) of = @of #Symbol, classification - group #alt 'code' is = :code #Symbol, classification - specific type tags = h[:tags] || ((defined? o.tags) ? o.tags : []) #Array, associated object tags, names if any obj = h[:obj] || ((defined? o.obj) ? o.obj : nil) #String, text content lngsyn = h[:lngsyn] || ((defined? o.lngsyn) ? o.lngsyn : :txt) #symbol, code lngsyn idx = h[:idx] || ((defined? o.idx) ? o.idx : nil) #String, book index provided? ocn = h[:ocn] || ((defined? o.ocn) ? o.ocn : nil) #Integer, sequential on substantive-content objects odv = h[:odv] || ((defined? o.odv) ? o.odv : nil) osp = h[:osp] || ((defined? o.osp) ? o.osp : nil) parent = h[:parent] || ((defined? o.parent) ? o.parent : nil) #[Node parent] number_ = h[:number_] || ((defined? o.number_) ? o.number_ : false) #Bool, numbered or not? note_ = h[:note_] || ((defined? o.note_) ? o.note_ : false) #Bool, endnotes/footnotes? (processing optimization) ocn_ = if h[:ocn_].nil? ((defined? o.ocn_) ? o.ocn_ : true) #Bool? no ocn, non-substantive content, do not include in toc #consider else h[:ocn_] end num = h[:num] || ((defined? o.num) ? o.num : nil) digest = h[:digest] || ((defined? o.digest) ? o.digest : nil) #hash digests, sha512, sha256 or md5 tmp = h[:tmp] || ((defined? o.tmp) ? o.tmp : nil) #available for processing, empty after use @of,@is,@tags,@obj,@lngsyn,@idx,@ocn,@odv,@osp,@parent,@number_,@note_,@ocn_,@num,@digest,@tmp= of, is, tags, obj, lngsyn, idx, ocn, odv, osp, parent, number_, note_, ocn_, num, digest, tmp self end def box(h,o=nil) of = @of #Symbol, classification - group is = :box #Symbol, classification - specific type tags = h[:tags] || ((defined? o.tags) ? o.tags : []) #Array, associated object tags, names if any obj = h[:obj] || ((defined? o.obj) ? o.obj : nil) #String, text content idx = h[:idx] || ((defined? o.idx) ? o.idx : nil) #String, book index provided? ocn = h[:ocn] || ((defined? o.ocn) ? o.ocn : nil) #Integer, sequential on substantive-content objects odv = h[:odv] || ((defined? o.odv) ? o.odv : nil) osp = h[:osp] || ((defined? o.osp) ? o.osp : nil) parent = h[:parent] || ((defined? o.parent) ? o.parent : nil) #[Node parent] note_ = h[:note_] || ((defined? o.note_) ? o.note_ : false) #Bool, endnotes/footnotes? (processing optimization) ocn_ = if h[:ocn_].nil? ((defined? o.ocn_) ? o.ocn_ : true) #Bool? no ocn, non-substantive content, do not include in toc #consider else h[:ocn_] end num = h[:num] || ((defined? o.num) ? o.num : nil) digest = h[:digest] || ((defined? o.digest) ? o.digest : nil) #hash digests, sha512, sha256 or md5 tmp = h[:tmp] || ((defined? o.tmp) ? o.tmp : nil) #available for processing, empty after use @of,@is,@tags,@obj,@idx,@ocn,@odv,@osp,@parent,@note_,@ocn_,@num,@digest,@tmp= of, is, tags, obj, idx, ocn, odv, osp, parent, note_, ocn_, num, digest, tmp self end def block(h,o=nil) of = @of #Symbol, classification - group is = :block #Symbol, classification - specific type tags = h[:tags] || ((defined? o.tags) ? o.tags : []) #Array, associated object tags, names if any obj = h[:obj] || ((defined? o.obj) ? o.obj : nil) #String, text content idx = h[:idx] || ((defined? o.idx) ? o.idx : nil) #String, book index provided? ocn = h[:ocn] || ((defined? o.ocn) ? o.ocn : nil) #Integer, sequential on substantive-content objects odv = h[:odv] || ((defined? o.odv) ? o.odv : nil) osp = h[:osp] || ((defined? o.osp) ? o.osp : nil) parent = h[:parent] || ((defined? o.parent) ? o.parent : nil) #[Node parent] note_ = h[:note_] || ((defined? o.note_) ? o.note_ : false) #Bool, endnotes/footnotes? (processing optimization) ocn_ = if h[:ocn_].nil? ((defined? o.ocn_) ? o.ocn_ : true) #Bool? no ocn, non-substantive content, do not include in toc #consider else h[:ocn_] end num = h[:num] || ((defined? o.num) ? o.num : nil) digest = h[:digest] || ((defined? o.digest) ? o.digest : nil) #hash digests, sha512, sha256 or md5 tmp = h[:tmp] || ((defined? o.tmp) ? o.tmp : nil) #available for processing, empty after use @of,@is,@tags,@obj,@idx,@ocn,@odv,@osp,@parent,@note_,@ocn_,@num,@digest,@tmp= of, is, tags, obj, idx, ocn, odv, osp, parent, note_, ocn_, num, digest, tmp self end def group(h,o=nil) of = @of #Symbol, classification - group is = :group #Symbol, classification - specific type tags = h[:tags] || ((defined? o.tags) ? o.tags : []) #Array, associated object tags, names if any obj = h[:obj] || ((defined? o.obj) ? o.obj : nil) #String, text content idx = h[:idx] || ((defined? o.idx) ? o.idx : nil) #String, book index provided? ocn = h[:ocn] || ((defined? o.ocn) ? o.ocn : nil) #Integer, sequential on substantive-content objects odv = h[:odv] || ((defined? o.odv) ? o.odv : nil) osp = h[:osp] || ((defined? o.osp) ? o.osp : nil) parent = h[:parent] || ((defined? o.parent) ? o.parent : nil) #[Node parent] note_ = h[:note_] || ((defined? o.note_) ? o.note_ : false) #Bool, endnotes/footnotes? (processing optimization) ocn_ = if h[:ocn_].nil? ((defined? o.ocn_) ? o.ocn_ : true) #Bool? no ocn, non-substantive content, do not include in toc #consider else h[:ocn_] end num = h[:num] || ((defined? o.num) ? o.num : nil) digest = h[:digest] || ((defined? o.digest) ? o.digest : nil) #hash digests, sha512, sha256 or md5 tmp = h[:tmp] || ((defined? o.tmp) ? o.tmp : nil) #available for processing, empty after use @of,@is,@tags,@obj,@idx,@ocn,@odv,@osp,@parent,@note_,@ocn_,@num,@digest,@tmp= of, is, tags, obj, idx, ocn, odv, osp, parent, note_, ocn_, num, digest, tmp self end def alt(h,o=nil) #see block of = @of #Symbol, classification - group is = :alt #Symbol, classification - specific type tags = h[:tags] || ((defined? o.tags) ? o.tags : []) #Array, associated object tags, names if any obj = h[:obj] || ((defined? o.obj) ? o.obj : nil) #String, text content idx = h[:idx] || ((defined? o.idx) ? o.idx : nil) #String, book index provided? ocn = h[:ocn] || ((defined? o.ocn) ? o.ocn : nil) #Integer, sequential on substantive-content objects odv = h[:odv] || ((defined? o.odv) ? o.odv : nil) osp = h[:osp] || ((defined? o.osp) ? o.osp : nil) parent = h[:parent] || ((defined? o.parent) ? o.parent : nil) #[Node parent] note_ = h[:note_] || ((defined? o.note_) ? o.note_ : false) #Bool, endnotes/footnotes? (processing optimization) ocn_ = if h[:ocn_].nil? ((defined? o.ocn_) ? o.ocn_ : true) #Bool? no ocn, non-substantive content, do not include in toc #consider else h[:ocn_] end num = h[:num] || ((defined? o.num) ? o.num : nil) digest = h[:digest] || ((defined? o.digest) ? o.digest : nil) #hash digests, sha512, sha256 or md5 tmp = h[:tmp] || ((defined? o.tmp) ? o.tmp : nil) #available for processing, empty after use @of,@is,@tags,@obj,@idx,@ocn,@odv,@osp,@parent,@note_,@ocn_,@num,@digest,@tmp= of, is, tags, obj, idx, ocn, odv, osp, parent, note_, ocn_, num, digest, tmp self end def verse(h,o=nil) #part of poem decide how you deal with this of = @of #Symbol, classification - group is = :verse #Symbol, classification - specific type tags = h[:tags] || ((defined? o.tags) ? o.tags : []) #Array, associated object tags, names if any obj = h[:obj] || ((defined? o.obj) ? o.obj : nil) #String, text content idx = h[:idx] || ((defined? o.idx) ? o.idx : nil) #String, book index provided? ocn = h[:ocn] || ((defined? o.ocn) ? o.ocn : nil) #Integer, sequential on substantive-content objects odv = h[:odv] || ((defined? o.odv) ? o.odv : nil) osp = h[:osp] || ((defined? o.osp) ? o.osp : nil) parent = h[:parent] || ((defined? o.parent) ? o.parent : nil) #[Node parent] ocn_ = if h[:ocn_].nil? ((defined? o.ocn_) ? o.ocn_ : true) #Bool? no ocn, non-substantive content, do not include in toc #consider else h[:ocn_] end num = h[:num] || ((defined? o.num) ? o.num : nil) digest = h[:digest] || ((defined? o.digest) ? o.digest : nil) #hash digests, sha512, sha256 or md5 tmp = h[:tmp] || ((defined? o.tmp) ? o.tmp : nil) #available for processing, empty after use @of,@is,@tags,@obj,@idx,@ocn,@odv,@osp,@parent,@note_,@ocn_,@num,@digest,@tmp= of, is, tags, obj, idx, ocn, odv, osp, parent, note_, ocn_, num, digest, tmp @h=nil self end end class ObjectTable attr_accessor :obj,:is,:of,:lv,:tags,:name,:idx,:indent,:hang,:size,:ocn,:num,:head_,:cols,:widths,:odv,:osp,:parent,:note_,:ocn_,:digest,:tmp def initialize @of=:block @is=@obj=@lv=@name=@idx=@indent=@hang=@size=@ocn,@num,@head_,@cols,@widths=@odv=@osp=@parent=@note_=@ocn_=@num=@digest=@tmp=nil @tags=[] end def table(h,o=nil) of = @of #Symbol, classification - group is = :table #Symbol, classification - specific type tags = h[:tags] || ((defined? o.tags) ? o.tags : []) #Array, associated object tags, names if any cols = h[:cols] || ((defined? o.cols) ? o.cols : nil) widths = h[:widths] || ((defined? o.widths) ? o.widths : nil) obj = h[:obj] || ((defined? o.obj) ? o.obj : nil) #String, text content idx = h[:idx] || ((defined? o.idx) ? o.idx : nil) #String, book index provided? ocn = h[:ocn] || ((defined? o.ocn) ? o.ocn : nil) #Integer, sequential on substantive-content objects odv = h[:odv] || ((defined? o.odv) ? o.odv : nil) osp = h[:osp] || ((defined? o.osp) ? o.osp : nil) parent = h[:parent] || ((defined? o.parent) ? o.parent : nil) #[Node parent] head_ = h[:head_] || ((defined? o.head_) ? o.head_ : false) note_ = h[:note_] || ((defined? o.note_) ? o.note_ : false) #Bool, endnotes/footnotes? (processing optimization) ocn_ = if h[:ocn_].nil? ((defined? o.ocn_) ? o.ocn_ : true) #Bool? no ocn, non-substantive content, do not include in toc #consider else h[:ocn_] end num = h[:num] || ((defined? o.num) ? o.num : nil) digest = h[:digest] || ((defined? o.digest) ? o.digest : nil) #hash digests, sha512, sha256 or md5 tmp = h[:tmp] || ((defined? o.tmp) ? o.tmp : nil) #available for processing, empty after use @of,@is,@tags,@cols,@widths,@obj,@idx,@ocn,@odv,@osp,@parent,@head_,@note_,@ocn_,@num,@digest,@tmp= of, is, tags, cols, widths, obj, idx, ocn, odv, osp, parent, head_, note_, ocn_, num, digest, tmp self end end class ObjectImage attr_accessor :obj,:is,:of,:lv,:idx,:size,:ocn,:parent,:note_,:ocn_,:digest,:tmp def initialize @of=:image @is=@obj=@lv=@idx=@size=@ocn=@parent=@note_=@ocn_=@tmp=@digest=nil @tags=[] end def image(h,o=nil) #not yet used, and what of a paragraph containing several images, consider of= @of #Symbol, classification - group is= :image #Symbol, classification - specific type tags= h[:tags] || ((defined? o.tags) ? o.tags : []) #Array, associated object tags, names if any obj= h[:obj] || ((defined? o.obj) ? o.obj : nil) #String, text content size= h[:size] || ((defined? o.size) ? o.size : nil) idx= h[:idx] || ((defined? o.idx) ? o.idx : nil) #String, book index provided? ocn= h[:ocn] || ((defined? o.ocn) ? o.ocn : nil) #Integer, sequential on substantive-content objects odv= h[:odv] || ((defined? o.odv) ? o.odv : nil) osp= h[:osp] || ((defined? o.osp) ? o.osp : nil) parent= h[:parent] || ((defined? o.parent) ? o.parent : nil) #[Node parent] note_= h[:note_] || ((defined? o.note_) ? o.note_ : false) #Bool, endnotes/footnotes? (processing optimization) ocn_=if h[:ocn_].nil? ((defined? o.ocn_) ? o.ocn_ : true) #Bool? no ocn, non-substantive content, do not include in toc #consider else h[:ocn_] end digest= h[:digest] || ((defined? o.digest) ? o.digest : nil) #hash digests, sha512, sha256 or md5 tmp= h[:tmp] || ((defined? o.tmp) ? o.tmp : nil) #available for processing, empty after use @of,@is,@tags,@obj,@size,@idx,@ocn,@odv,@osp,@parent,@note_,@ocn_,@digest,@tmp=of,is,tags,obj,size,idx,ocn,odv,osp,parent,note_,ocn_,digest,tmp self end end class ObjectStructure attr_accessor :obj,:tag,:node,:lv,:ln,:lc,:status,:is,:of,:tmp def initialize @of=:structure @is=@obj=@node=@lv=@ln=@lc=@status=@tmp=nil end def xml_dom(h,o=nil) of= @of #Symbol, classification - group is= :xml_dom #Symbol, classification - specific type obj= h[:obj] || ((defined? o.obj) ? o.obj : '') #String, text content lv= h[:lv] || ((defined? o.lv) ? o.lv : nil) #Alpha-numeric, document structure as used in markup, A-D then 1-6 ln= h[:ln] || ((defined? o.ln) ? o.ln : nil) #Integer, document structure level, for convenience in processing 1-9 lc= h[:lc] || ((defined? o.lc) ? o.lc : nil) #Integer, document structure collapsed level, convenience (collapse sisu's dual level document structure for markup with simple linear structure) node= h[:node] || ((defined? o.node) ? o.node : nil) #[Node relationship doc structure info] status= h[:status] || ((defined? o.status) ? o.status : nil) #tag status Symbol :open or :close tmp= h[:tmp] || ((defined? o.tmp) ? o.tmp : nil) #available for processing, empty after use @of,@is,@obj,@status,@node,@lv,@ln,@lc,@tmp=of,is,obj,status,node,lv,ln,lc,tmp self end end class ObjectFlag attr_accessor :obj,:is,:of,:flag,:act,:selections,:tmp def initialize @of=:flag @is=@obj=@flag=@act=@selections=@tmp=nil end def flag(h,o=nil) of= @of #Symbol, classification - group is= :flag #Symbol, classification - specific type obj= nil #String, text content flag= h[:flag] || ((defined? o.flag) ? o.flag : nil) #String, text content act= h[:act] || ((defined? o.act) ? o.act : nil) #String, text content selections= h[:selections] || ((defined? o.selections) ? o.selections : nil) #String, text content tmp= h[:flag] || ((defined? o.tmp) ? o.tmp : nil) #available for processing, empty after use @of, @is,@obj,@flag,@act,@selections,@tmp= of,is, obj, flag, act, selections, tmp self end def flag_ocn(h,o=nil) of= @of #Symbol, classification - group is= :flag_ocn #Symbol, classification - specific type obj= nil #String, text content flag= h[:flag] || ((defined? o.flag) ? o.flag : nil) #String, text content act= h[:act] || ((defined? o.act) ? o.act : nil) #String, text content selections= h[:selections] || ((defined? o.selections) ? o.selections : nil) #String, text content tmp= h[:flag] || ((defined? o.tmp) ? o.tmp : nil) #available for processing, empty after use @of, @is,@obj,@flag,@act,@selections,@tmp= of,is, obj, flag, act, selections,tmp self end def flag_lng(h,o=nil) of= @of #Symbol, classification - group is= :flag_lng obj= nil #String, text content flag= h[:flag] || ((defined? o.flag) ? o.flag : nil) #Symbol, :lng_on or :lng_off act= h[:act] || ((defined? o.act) ? o.act : nil) #Symbol, language set to :en etc. selections= h[:selections] || ((defined? o.selections) ? o.selections : nil) #String, text content tmp= h[:act] || ((defined? o.tmp) ? o.tmp : nil) #available for processing, empty after use @of, @is,@obj,@flag,@act,@selections,@tmp= of,is, obj, flag, act, selections,tmp self end end class ObjectLayout attr_accessor :obj,:sym,:attr,:is,:is_for,:of,:from,:tmp,:num def initialize @of=:layout @is=@is_for=@obj=@from=@tmp=@num=nil end def break(h,f=nil) #decide how to deal with of= @of #Symbol, classification - group is= :break #Symbol, classification - specific type obj= h[:obj] #String, text content from= f tmp= h[:tmp] #available for processing, empty after use @of,@is,@obj,@from,@tmp=of,is,obj,from,tmp self end def insert(h,o=nil) #decide how to deal with, could mimic paragraph? of= @of #Symbol, classification - group is= :insert #Symbol, classification - specific type obj= h[:obj] || ((defined? o.obj) ? o.obj : nil) #String, text content tmp= h[:tmp] || ((defined? o.tmp) ? o.tmp : nil) #available for processing, empty after use @of,@is,@obj,@tmp=of,is,obj,tmp self end def open_close(h,o=nil) #useful for poem & quote of= @of #Symbol, classification - group is= :open_close_tags #Symbol, classification - specific type is_for= h[:is_for] || ((defined? o.is_for) ? o.is_for : nil) #String, text content obj= h[:obj] || ((defined? o.obj) ? o.obj : nil) #String, text content sym= h[:sym] || ((defined? o.sym) ? o.sym : nil) #Symbol tag_open, tag_close attr= h[:attr] || ((defined? o.attr) ? o.attr : nil) #String, text content tmp= h[:tmp] || ((defined? o.tmp) ? o.tmp : nil) #available for processing, empty after use num= h[:num] || ((defined? o.num) ? o.num : nil) @of,@is,@is_for,@obj,@sym,@attr,@tmp,@num= of, is, is_for, obj, sym, attr, tmp, num self end end class ObjectComment attr_accessor :obj,:is,:of,:tmp def initialize @of=:comment @is=@obj=@tmp=nil end def comment(h,o=nil) of= @of #Symbol, classification - group is= :comment #Symbol, classification - specific type obj= h[:obj] || ((defined? o.obj) ? o.obj : nil) #String, text content tmp= h[:tmp] || ((defined? o.tmp) ? o.tmp : nil) #available for processing, empty after use @of,@is,@obj,@tmp=of,is,obj,tmp self end end end __END__ # ~# |-# no paragraph number # -# not included in toc #+END_SRC ** ao_doc_str.rb #+HEADER: :tangle "../lib/sisu/ao_doc_str.rb" #+BEGIN_SRC ruby #<<sisu_document_header>> module SiSU_AO_DocumentStructureExtract require_relative 'ao_persist' # ao_persist.rb class Instantiate < SiSU_Param::Parameters::Instructions def initialize @@counter=@@column=@@columns=0 @@line_mode='' end end class Build def initialize(md,data) @md,@data=md,data SiSU_AO_DocumentStructureExtract::Instantiate.new @pb=SiSU_AO_DocumentStructure::ObjectLayout.new.break(Hx[:br_page]) @pbn=SiSU_AO_DocumentStructure::ObjectLayout.new.break(Hx[:br_page_new]) @pbl=SiSU_AO_DocumentStructure::ObjectLayout.new.break(Hx[:br_page_line]) @per=SiSU_AO_Persist::PersistDocStructExt.new @make=SiSU_Env::ProcessingSettings.new(@md) end def ln_get(lv) case lv when /A/ then 0 when /B/ then 1 when /C/ then 2 when /D/ then 3 when /1/ then 4 when /2/ then 5 when /3/ then 6 when /4/ then 7 when /5/ then 8 when /6/ then 9 end end def image_test(str) str=~/\{\s*\S+?\.png.+?\}https?:\/\/\S+/ \ ? true : false end def bullet_test(str) (str=~/\*/) \ ? true : false end def quotes? @per.quote==:open \ ? true : false end def hang_and_indent_test(str) hang_indent=if str=~/^_([1-9])[^_]/ [$1,$1] elsif str=~/^__([1-9])/ [0,$1] elsif str=~/^_([0-9])_([0-9])/ [$1,$2] else [0,0] end hang,indent=hang_indent[0],hang_indent[1] [hang,indent] end def hang_and_indent_def_test(str1,str2) hang_indent=if str1=~/^_([1-9])[^_]/ [$1,$1] elsif str1=~/^__([1-9])/ [0,$1] elsif str1=~/^_([0-9])_([0-9])/ [$1,$2] else [0,0] end obj=if str2 =~/^(.+?)\s+\\\\(?:\s+|\n)/ str2.gsub(/^(.+?)(\s+\\\\(?:\s+|\n))/, "#{Mx[:fa_bold_o]}\\1#{Mx[:fa_bold_c]}\\2") else str2.gsub(/^(.+?)\n/, "#{Mx[:fa_bold_o]}\\1#{Mx[:fa_bold_c]}\n") end hang,indent=hang_indent[0],hang_indent[1] [ hang, indent, obj, ] end def endnote_test?(str) (str=~/~\{.+?\}~|~\[.+?\]~/) \ ? true : false end def extract_tags(str,nametag=nil) tags=[] if str.nil? else if str =~/(?:^|[ ])\*~([a-z0-9._-]+)(?=[ #{Mx[:br_nl]}]|$)/ str=str.gsub(/(^|[ ])\*~([a-z0-9._-]+)(?=[ #{Mx[:br_nl]}]|$)/i, "\\1#{Mx[:tag_o]}\\2#{Mx[:tag_c]}"). gsub(/ [ ]+/i,' ') tags=str.scan(/#{Mx[:tag_o]}(\S+?)#{Mx[:tag_c]}/).flatten.uniq str=str.gsub(/[ ]?#{Mx[:tag_o]}\S+?#{Mx[:tag_c]}[ ]?/,' ') #may be issues with spaces would leave one, but "code" blocks? end tags=nametag ? (tags << nametag) : tags tags.each do |t| t.gsub!(/[^a-z0-9._-]/,'') end end [ str, tags, ] end def rgx_idx_ocn_seg @rgx_idx_ocn_seg=/(.+?)\s*[+](\d+)/ end def construct_idx_array_and_hash(idxraw) idx_array_raw=idxraw.scan(/[^;]+/) idx_hash,idx_array,idx_lst={},[],[] idx_array_raw.each do |idx| idx=idx.strip idx_lst=case idx when /\S+?\s*:/ idx_couplet_tmp=[] idx_couplet=idx.scan(/\s*[^:]+\s*/) if idx_couplet[1] =~/[|]/ idx_couplet_tmp << idx_couplet[0] << idx_couplet[1].scan(/\s*[^|]+\s*/) else idx_couplet_tmp << idx_couplet[0] << [idx_couplet[1]] end idx_couplet=idx_couplet_tmp else [idx] end term_nodes=[] idx_lst.each do |term_node| case term_node when String term_node= term_node[0].chr.capitalize + term_node[1,term_node.length] term_node=(term_node =~/.+?[+]\d+/) \ ? term_node : (term_node + '+0') term_nodes << term_node use,plus=rgx_idx_ocn_seg.match(term_node)[1,2] @use=use.strip unless idx_hash[@use] \ and defined? idx_hash[@use] idx_hash[@use]= { sub: [], plus: plus } end when Array subterm_nodes=[] term_node.each do |subterm_node| subterm_node=(subterm_node =~/.+?[+]\d+/) \ ? subterm_node : (subterm_node + '+0') subterm_nodes << subterm_node sub,sub_plus=rgx_idx_ocn_seg.match(subterm_node)[1,2] unless idx_hash[@use] \ and defined? idx_hash[@use] idx_hash[@use]= { sub: [], plus: 0 } end idx_hash[@use][:sub] << { sub.strip => { plus: sub_plus } } end term_nodes << subterm_nodes end end idx_array << term_nodes end { hash: idx_hash, array: idx_array, } end def extract_structure_loop(data,tuned_file) data.each do |t_o| if t_o =~/^--([+~-])[#]$/ h=case $1 when /[+]/ @per.ocn=:on { flag: :ocn_on, } when /[~]/ @per.ocn=:ocn_off_headings_keep { flag: :ocn_off, mod: :headings_keep, } when /[-]/ #of particular relevance with level 1~ which is required to precede substantive text & used e.g. in html segmented text @per.ocn=:ocn_off_headings_dummy_lev1 { flag: :ocn_off, mod: :headings_exclude, } else @per.ocn=:on { flag: :ocn_on, } end t_o=SiSU_AO_DocumentStructure::ObjectFlag.new.flag_ocn(h) next end if t_o =~/^:[~](#{SiSU_is.language_list_regex?}|-)$/ # work with for identifying language of objects lng=$1 h=case lng when /(?:#{SiSU_is.language_list_regex?})/ @per.lng=:on @per.lng_is=lng.to_sym { flag: :lng_on, act: lng.to_sym, } else # ^:~- if @per.lng==:on @per.lng=:off @per.lng_is=:doc_default { flag: :lng_off, act: :doc_default, } end end t_o=SiSU_AO_DocumentStructure::ObjectFlag.new.flag_lng(h) next end t_o=t_o.gsub(/(?:\n\s*\n)+/m,"\n") if @per.code==:off unless t_o =~/^(?:@\S+?:|%+)\s/ # extract book index for paragraph if any idx=if t_o=~/^=\{\s*(.+)\s*\}\s*$\Z/m m=$1 m=m.split(/[ ]*\n/).join(' '). gsub(/\s+([|:;])\s+/,'\1'). gsub(/\s+([+]\d+)\s+/,'\1') t_o=t_o.gsub(/\n=\{.+?\}\s*$/m,'') idx_array_and_hash=construct_idx_array_and_hash(m) idx_array_and_hash[:hash] else nil end end if (t_o.is_a?(String) \ && t_o !~/^(?:code(?:\.[a-z][0-9a-z_]+)?(?:\(.+?\))?|box(?:\.[a-z_]+)?|poem|alt|group|block)\{|^\}(?:code|poem|alt|group|block)|^(?:table\(.+?\)\{|\{table\()|^(?:table\{|\{table)[ ~]/ \ && t_o !~/^```[ ]+(?:code(?:\.[a-z][0-9a-z_]+)?(?:\(.+?\))?|box(?:\.[a-z_]+)?|poem|alt|group|block|table)|^```(?:\s+[~-][#]|\s+\~\{.+?\}\~)?\s*$|^`:quote_(?:open|close)`/ \ and @per.code==:off \ and @per.poem==:off \ and @per.group==:off \ and @per.block==:off \ and @per.alt==:off \ and @per.box==:off \ and @per.table==:off ) t_o=case t_o when /^#{Mx[:meta_o]}\S+?#{Mx[:meta_c]}/ #metadata, header if t_o=~/^#{Mx[:meta_o]}(\S+?)#{Mx[:meta_c]}\s*(.+)/m tag,obj=$1,$2 @metadata[tag]=obj end t_o=nil when /^%+\s/ #comment t_o=if t_o=~/^%+\s+(.+)/ h={ obj: $1 } SiSU_AO_DocumentStructure::ObjectComment.new.comment(h) else nil end when /^:?([A-D1-6])\~/ #heading / lv lv=$1 ln=ln_get(lv) t_o=if t_o=~/^:?[A-D1-6]\~\s+(.+)/m obj=$1 note=endnote_test?(obj) obj,tags=extract_tags(obj) if @per.ocn==:ocn_off_headings_dummy_lev1 \ or @per.ocn==:ocn_off_headings_keep unless obj =~ /[~-][#]\s*$/ if @per.ocn==:ocn_off_headings_dummy_lev1 \ and t_o =~/^1\~\S*\s+/m obj << ' -#' elsif @per.ocn==:ocn_off_headings_dummy_lev1 \ or @per.ocn==:ocn_off_headings_keep obj << ' ~#' end end end h={ lv: lv, ln: ln, obj: obj, idx: idx, tags: tags, } SiSU_AO_DocumentStructure::ObjectHeading.new.heading(h) elsif t_o=~/^:?[A-D1-6]\~(\S+?)-\s+(.+)/m name,obj=$1,$2 note=endnote_test?(obj) obj,tags=extract_tags(obj) if @per.ocn==:ocn_off_headings_dummy_lev1 \ or @per.ocn==:ocn_off_headings_keep unless obj =~ /[~-][#]\s*$/ if @per.ocn==:ocn_off_headings_dummy_lev1 \ and t_o =~/^1\~\S*\s+/m obj << ' -#' elsif @per.ocn==:ocn_off_headings_dummy_lev1 \ or @per.ocn==:ocn_off_headings_keep obj << ' ~#' end end end h={ lv: lv, name: name, obj: obj, idx: idx, autonum_: false, tags: tags, } SiSU_AO_DocumentStructure::ObjectHeading.new.heading(h) elsif t_o=~/^:?[A-D1-6]\~(\S+)\s+(.+)/m name,obj=$1,$2 note=endnote_test?(obj) obj,tags=extract_tags(obj,name) if @per.ocn==:ocn_off_headings_dummy_lev1 \ or @per.ocn==:ocn_off_headings_keep unless obj =~ /[~-][#]\s*$/ if @per.ocn==:ocn_off_headings_dummy_lev1 \ and t_o =~/^1\~\S*\s+/m obj << ' -#' elsif @per.ocn==:ocn_off_headings_dummy_lev1 \ or @per.ocn==:ocn_off_headings_keep obj << ' ~#' end end end h={ lv: lv, name: name, obj: obj, idx: idx, tags: tags, } SiSU_AO_DocumentStructure::ObjectHeading.new.heading(h) else nil end when /^_(?:[1-9]!?|[1-9]?\*)\s+/ #indented and/or bullet paragraph t_o=if t_o=~/^(_(?:[1-9]?\*|[1-9]!?)\s+)(.+)/m tst,obj=$1,$2 if t_o=~/^_[1-9]!\s+.+/m hang,indent,obj=hang_and_indent_def_test(tst,obj) else hang,indent=hang_and_indent_test(tst) end bullet=bullet_test(tst) image=image_test(obj) note=endnote_test?(obj) obj,tags=extract_tags(obj) unless obj=~/\A\s*\Z/m if @per.ocn==:ocn_off_headings_dummy_lev1 \ or @per.ocn==:ocn_off_headings_keep unless obj =~ /[~-][#]\s*$/ obj << ' ~#' end end h={ bullet_: bullet, hang: hang, indent: indent, obj: obj, idx: idx, note_: note, image_: image, tags: tags, quote: quotes?, } SiSU_AO_DocumentStructure::ObjectPara.new.paragraph(h) end else nil end when /^_[0-9]?_[0-9]!?\s+/ #hanging indent paragraph t_o=if t_o=~/^(_[0-9]?_[0-9]!?\s+)(.+)/m tst,obj=$1,$2 if t_o=~/^_[0-9]?_[0-9]!\s+.+/m hang,indent,obj=hang_and_indent_def_test(tst,obj) else hang,indent=hang_and_indent_test(tst) end image=image_test(obj) note=endnote_test?(obj) obj,tags=extract_tags(obj) unless obj=~/\A\s*\Z/m if @per.ocn==:ocn_off_headings_dummy_lev1 \ or @per.ocn==:ocn_off_headings_keep unless obj =~ /[~-][#]\s*$/ obj << ' ~#' end end h={ hang: hang, indent: indent, obj: obj, idx: idx, note_: note, image_: image, tags: tags, quote: quotes?, } SiSU_AO_DocumentStructure::ObjectPara.new.paragraph(h) end else nil end when /^<(?:br)?:(?:pa?r|o(?:bj|---)?)>\s*$/ #[br:par] #[br:obj] SiSU_AO_DocumentStructure::ObjectLayout.new.break(Hx[:br_obj]) when /^(?:-\\\\-|<:pb>)\s*$/ #[br:pg] SiSU_AO_DocumentStructure::ObjectLayout.new.break(Hx[:br_page],:markup) when /^(?:=\\\\=|<:pn>)\s*$/ #[br:pgn] SiSU_AO_DocumentStructure::ObjectLayout.new.break(Hx[:br_page_new],:markup) when /^-\.\.-\s*$/ #[br:pgl] SiSU_AO_DocumentStructure::ObjectLayout.new.break(Hx[:br_page_line],:markup) else #paragraph image=image_test(t_o) note=endnote_test?(t_o) obj,tags=extract_tags(t_o) if @per.ocn==:ocn_off_headings_dummy_lev1 \ or @per.ocn==:ocn_off_headings_keep unless obj =~ /[~-][#]\s*$/ obj << ' ~#' end end unless obj=~/\A\s*\Z/m h={ bullet_: false, indent: 0, hang: 0, obj: obj, idx: idx, note_: note, image_: image, tags: tags, quote: quotes?, } t_o=SiSU_AO_DocumentStructure::ObjectPara.new.paragraph(h) end t_o=SiSU_AO_DocumentStructureExtract::Structure.new(@md).structure_markup(t_o) #must happen earlier, node info etc. require end elsif @per.code==:off if t_o =~/^(?:code(?:\.[a-z][0-9a-z_]+)?(?:\(.+?\))?\{|```[ ]+code(?:\.[a-z][0-9a-z_]+)?(?:\(.+?\))?)/ @per.code=case t_o when /^code(?:\.[a-z][0-9a-z_]+)?(?:\(.+?\))?\{/ then :curls when /^```[ ]+code/ then :tics else @per.code #error end @per.lngsyn=if t_o =~/^(?:code\.[a-z][0-9a-z_]+(?:\(.+?\))?\{|```[ ]+code\.[a-z_]+)/ case t_o when /^code\.([a-z][0-9a-z_]+)(?:\(.+?\))?\{/ :"#{$1}" when /^```[ ]+code\.([a-z][0-9a-z_]+)/ :"#{$1}" else :txt end else :txt end @@counter=1 @codeblock_numbered= (t_o =~/^(?:code(?:\.[a-z][0-9a-z_]+)?\(.*number(?:lines)?.*?\)\{|```[ ]+code(?:\.[a-z][0-9a-z_]+)?\(.*number(?:lines)?.*?\)|code(?:\.[a-z][0-9a-z_]+)?\{#|```[ ]+code(?:\.[a-z][0-9a-z_]+)?\s[#])/) \ ? true : false if (t_o =~/^(?:code(?:\.[a-z][0-9a-z_]+)?\{#|```[ ]+code(?:\.[a-z][0-9a-z_]+)?\s[#])/) puts "WARNING document using depreciated markup for numbering codeblocks\nuse: code(numberlines){ ... or: ```code(numberlines) ..." end @num_id[:code_block] +=1 h={ is_for: :code, obj: '', sym: :code_block_open, num: @num_id[:code_block], syntax: @per.lngsyn, } t_o=SiSU_AO_DocumentStructure::ObjectLayout.new.open_close(h) elsif t_o =~/^(?:poem\{|```[ ]+poem)/ @per.poem=case t_o when /^poem\{/ then :curls when /^```[ ]+poem/ then :tics else @per.poem #error end @num_id[:poem] +=1 h={ is_for: :poem, obj: '', sym: :poem_open, num: @num_id[:poem], } t_o=SiSU_AO_DocumentStructure::ObjectLayout.new.open_close(h) tuned_file << t_o elsif t_o =~/^(?:box(?:\.[a-z_]+)?\{|```[ ]+box(?:\.[a-z_]+)?)/ @per.box=case t_o when /^box\{/ then :curls when /^```[ ]+box/ then :tics else @per.box #error end @num_id[:box] +=1 h={ is_for: :box, obj: '', sym: :box_open, num: @num_id[:box], } t_o=SiSU_AO_DocumentStructure::ObjectLayout.new.open_close(h) tuned_file << t_o elsif t_o =~/^(?:group\{|```[ ]+group)/ @per.group=case t_o when /^group\{/ then :curls when /^```[ ]+group/ then :tics else @per.group #error end @num_id[:group] +=1 h={ is_for: :group, obj: '', sym: :group_open, num: @num_id[:group], } t_o=SiSU_AO_DocumentStructure::ObjectLayout.new.open_close(h) tuned_file << t_o elsif t_o =~/^(?:block\{|```[ ]+block)/ @per.block=case t_o when /^block\{/ then :curls when /^```[ ]+block/ then :tics else @per.block #error end @num_id[:block] +=1 h={ is_for: :block, obj: '', sym: :block_open, num: @num_id[:block], } t_o=SiSU_AO_DocumentStructure::ObjectLayout.new.open_close(h) tuned_file << t_o elsif t_o =~/^(?:alt\{|```[ ]+alt)/ @per.alt=case t_o when /^alt\{/ then :curls when /^```[ ]+alt/ then :tics else @per.alt #error end @num_id[:alt] +=1 h={ is_for: :alt, obj: '', sym: :alt_open, num: @num_id[:alt], } t_o=SiSU_AO_DocumentStructure::ObjectLayout.new.open_close(h) tuned_file << t_o elsif t_o =~/^`:quote_open`/ @per.quote=:open @num_id[:quote] +=1 h={ is_for: :quote, obj: '', sym: :quote_open, num: @num_id[:quote], } t_o=SiSU_AO_DocumentStructure::ObjectLayout.new.open_close(h) #tuned_file << t_o #% find second source, entered twice, should be once so closed off here elsif t_o =~/^(?:table\(.+?\)\{|```[ ]+table\(.+?\)|\{table\(.+?\))/ @num_id[:table] +=1 h={ is_for: :table, obj: '', sym: :table_open, num: @num_id[:table], } ins_o=SiSU_AO_DocumentStructure::ObjectLayout.new.open_close(h) tuned_file << ins_o if t_o=~/^table\((?:.*?\bh;\s+)?.+?\)\{/ @per.table=:curls @rows='' case t_o when /table\(.*?\bh;\s+c(\d+):\s+(.+?)\)\{/ cols=$1 col=$2.scan(/\d+/) heading=true when /table\(.*?c(\d+):\s+(.+?)\)\{/ cols=$1 col=$2.scan(/\d+/) heading=false end @h={ head_: heading, cols: cols, widths: col, idx: idx, } elsif t_o=~/^```[ ]+table\((?:.*?\bh;)?\s+c\d+:/ @per.table=:tics @rows='' case t_o when /^```[ ]+table\(.*?\bh;\s+c(\d+):\s+(.+?)\)/ cols=$1 col=$2.scan(/\d+/) heading=true when /^```[ ]+table\(\s*c(\d+):\s+(.+?)\)/ cols=$1 col=$2.scan(/\d+/) heading=false end @h={ head_: heading, cols: cols, widths: col, idx: idx, } elsif t_o=~/^\{table\((?:.*?\bh;\s+)?(?:\s+\d+,?)?\)\s*\}\n.+\Z/m m1,m2,hd=nil,nil,nil tbl=/^\{table\((?:.*?\bh;\s+)?(?:\s+\d+,?)*\)\s*\}\n(.+)\Z/m.match(t_o)[1] # fix hd=((t_o =~/^\{table\(.*?\bh;\s+/) ? true : false) tbl,tags=extract_tags(tbl) rws=tbl.split(/\n/) rows='' cols=nil rws.each do |r| cols=(cols ? cols : (r.scan('|').length) +1) r=r.gsub(/\s*\|\s*/m,"#{Mx[:tc_p]}") #r.gsub!(/\|/m,"#{Mx[:tc_p]}") rows += r + Mx[:tc_c] end col=[] if t_o =~/^\{table\((?:.*?\bh;\s+)?\s+c(\d+):.*?\)\s*\}/ #width of col 1 given as %, usually when wider than rest that are even c1=$1.to_i width=(100 - c1)/(cols - 1) col=[ c1 ] (cols - 1).times { col << width } else #all columns of equal width width=100.00/cols cols.times { col << width } end h={ head_: hd, cols: cols, widths: col, obj: rows, idx: idx, tags: tags, num: @num_id[:table], } t_o=SiSU_AO_DocumentStructure::ObjectTable.new.table(h) \ unless h.nil? tuned_file << t_o h={ is_for: :table, obj: '', sym: :table_close, num: @num_id[:table], } t_o=SiSU_AO_DocumentStructure::ObjectLayout.new.open_close(h) t_o elsif t_o=~/^```[ ]+table\((?:.*?\bh;)?\s+/ m1,m2,hd=nil,nil,nil h=case t_o when /^```[ ]+table\(.*?\bh;\s+(.+?)\)\n(.+)\Z/m #two table representations should be consolidated as one m1,tbl,hd=$1,$2,true when /^```[ ]+table\((.+?)\)\n(.+)\Z/m #two table representations should be consolidated as one m1,tbl,hd=$1,$2,false else nil end tbl,tags=extract_tags(tbl) col=m1.scan(/\d+/) rws=tbl.split(/\n/) rows='' rws.each do |r| r=r.gsub(/\s*\|\s*/m,"#{Mx[:tc_p]}") #r.gsub!(/\|/m,"#{Mx[:tc_p]}") rows += r + Mx[:tc_c] end h={ head_: hd, cols: col.length, widths: col, obj: rows, idx: idx, tags: tags, num: @num_id[:table], } t_o=SiSU_AO_DocumentStructure::ObjectTable.new.table(h) \ unless h.nil? tuned_file << t_o h={ is_for: :table, obj: '', sym: :table_close, num: @num_id[:table], } t_o=SiSU_AO_DocumentStructure::ObjectLayout.new.open_close(h) t_o elsif t_o=~/^\{table\((?:.*?\bh;)?/ m1,m2,hd=nil,nil,nil h=case t_o when /\{table\(.*?\bh;\s+(.+?)\)\s*\}\n(.+)\Z/m #two table representations should be consolidated as one m1,tbl,hd=$1,$2,true when /\{table\((.+?)\)\s*\}\n(.+)\Z/m #two table representations should be consolidated as one m1,tbl,hd=$1,$2,false else nil end tbl,tags=extract_tags(tbl) col=m1.scan(/\d+/) rws=tbl.split(/\n/) rows='' rws.each do |r| r=r.gsub(/\s*\|\s*/m,"#{Mx[:tc_p]}") #r.gsub!(/\|/m,"#{Mx[:tc_p]}") rows += r + Mx[:tc_c] end h={ head_: hd, cols: col.length, widths: col, obj: rows, idx: idx, tags: tags, num: @num_id[:table], } t_o=SiSU_AO_DocumentStructure::ObjectTable.new.table(h) \ unless h.nil? tuned_file << t_o h={ is_for: :table, obj: '', sym: :table_close, num: @num_id[:table], } t_o=SiSU_AO_DocumentStructure::ObjectLayout.new.open_close(h) t_o end ## depreciated markup, code should work for new markup after removal { elsif t_o =~/^(?:table\{|```[ ]+table|\{table)[ ~]/ puts "WARNING document using depreciated markup for tables" puts "use table([table attributes]) instead:" puts "table(){" puts "``` table()" puts "{table()}" @num_id[:table] +=1 h={ is_for: :table, obj: '', sym: :table_open, num: @num_id[:table], } ins_o=SiSU_AO_DocumentStructure::ObjectLayout.new.open_close(h) tuned_file << ins_o if t_o=~/^table\{(?:~h)?\s+/ @per.table=:curls @rows='' case t_o when /table\{~h\s+c(\d+);\s+(.+)/ cols=$1 col=$2.scan(/\d+/) heading=true when /table\{\s+c(\d+);\s+(.+)/ cols=$1 col=$2.scan(/\d+/) heading=false end @h={ head_: heading, cols: cols, widths: col, idx: idx, } elsif t_o=~/^```[ ]+table(?:~h)?\s+c\d+/ @per.table=:tics @rows='' case t_o when /^```[ ]+table~h\s+c(\d+);\s+(.+)/ cols=$1 col=$2.scan(/\d+/) heading=true when /^```[ ]+table\s+c(\d+);\s+(.+)/ cols=$1 col=$2.scan(/\d+/) heading=false end @h={ head_: heading, cols: cols, widths: col, idx: idx, } elsif t_o=~/^\{table(?:~h)?(?:\s+\d+;?)?\}\n.+\Z/m m1,m2,hd=nil,nil,nil tbl=/^\{table(?:~h)?(?:\s+\d+;?)?\}\n(.+)\Z/m.match(t_o)[1] hd=((t_o =~/^\{table~h/) ? true : false) tbl,tags=extract_tags(tbl) rws=tbl.split(/\n/) rows='' cols=nil rws.each do |r| cols=(cols ? cols : (r.scan('|').length) +1) r=r.gsub(/\s*\|\s*/m,"#{Mx[:tc_p]}") #r.gsub!(/\|/m,"#{Mx[:tc_p]}") rows += r + Mx[:tc_c] end col=[] if t_o =~/^\{table(?:~h)?\s+(\d+);?\}/ #width of col 1 given as %, usually when wider than rest that are even c1=$1.to_i width=(100 - c1)/(cols - 1) col=[ c1 ] (cols - 1).times { col << width } else #all columns of equal width width=100.00/cols cols.times { col << width } end h={ head_: hd, cols: cols, widths: col, obj: rows, idx: idx, tags: tags, num: @num_id[:table], } t_o=SiSU_AO_DocumentStructure::ObjectTable.new.table(h) \ unless h.nil? tuned_file << t_o h={ is_for: :table, obj: '', sym: :table_close, num: @num_id[:table], } t_o=SiSU_AO_DocumentStructure::ObjectLayout.new.open_close(h) t_o elsif t_o=~/^```[ ]+table(?:~h)?\s+/ m1,m2,hd=nil,nil,nil h=case t_o when /^```[ ]+table~h\s+(.+?)\n(.+)\Z/m #two table representations should be consolidated as one m1,tbl,hd=$1,$2,true when /^```[ ]+table\s+(.+?)\n(.+)\Z/m #two table representations should be consolidated as one m1,tbl,hd=$1,$2,false else nil end tbl,tags=extract_tags(tbl) col=m1.scan(/\d+/) rws=tbl.split(/\n/) rows='' rws.each do |r| r=r.gsub(/\s*\|\s*/m,"#{Mx[:tc_p]}") #r.gsub!(/\|/m,"#{Mx[:tc_p]}") rows += r + Mx[:tc_c] end h={ head_: hd, cols: col.length, widths: col, obj: rows, idx: idx, tags: tags, num: @num_id[:table], } t_o=SiSU_AO_DocumentStructure::ObjectTable.new.table(h) \ unless h.nil? tuned_file << t_o h={ is_for: :table, obj: '', sym: :table_close, num: @num_id[:table], } t_o=SiSU_AO_DocumentStructure::ObjectLayout.new.open_close(h) t_o elsif t_o=~/^\{table(?:~h)?\s+/ m1,m2,hd=nil,nil,nil h=case t_o when /\{table~h\s+(.+?)\}\n(.+)\Z/m #two table representations should be consolidated as one m1,tbl,hd=$1,$2,true when /\{table\s+(.+?)\}\n(.+)\Z/m #two table representations should be consolidated as one m1,tbl,hd=$1,$2,false else nil end tbl,tags=extract_tags(tbl) col=m1.scan(/\d+/) rws=tbl.split(/\n/) rows='' rws.each do |r| r=r.gsub(/\s*\|\s*/m,"#{Mx[:tc_p]}") #r.gsub!(/\|/m,"#{Mx[:tc_p]}") rows += r + Mx[:tc_c] end h={ head_: hd, cols: col.length, widths: col, obj: rows, idx: idx, tags: tags, num: @num_id[:table], } t_o=SiSU_AO_DocumentStructure::ObjectTable.new.table(h) \ unless h.nil? tuned_file << t_o h={ is_for: :table, obj: '', sym: :table_close, num: @num_id[:table], } t_o=SiSU_AO_DocumentStructure::ObjectLayout.new.open_close(h) t_o ## } depreciated markup, code should (continue to) work for new markup after removal, # when removing depreciated markup check only pass-through for new table attributes format # table(.+?){ ``` table(.+?) {table(.+?)} formats end end t_o end if @per.table==:curls or @per.table==:tics if (@per.table==:curls \ and (t_o.is_a?(String) and t_o =~/^\}table/)) \ or (@per.table==:tics \ and (t_o.is_a?(String) and t_o =~/^```(?:\s+[~-][#]|\s+\~\{.+?\}\~)?\s*$/)) @per.table=:off headings,columns,widths,idx=@h[:head_],@h[:cols],@h[:widths],@h[:idx] @h={ head_: headings, cols: columns, widths: widths, idx: idx, obj: @rows, } t_o=SiSU_AO_DocumentStructure::ObjectTable.new.table(@h) tuned_file << t_o @h,@rows=nil,'' h={ is_for: :table, obj: '', sym: :table_close, num: @num_id[:table], } t_o=SiSU_AO_DocumentStructure::ObjectLayout.new.open_close(h) t_o else if t_o.is_a?(String) \ and t_o !~/^(?:table\{|```[ ]+table)/ t_o=t_o.gsub(/^\n+/m,''). gsub(/\n+/m,"#{Mx[:tc_p]}") @rows += t_o + Mx[:tc_c] end t_o=nil end end if @per.code==:curls \ or @per.code==:tics if (@per.code==:curls \ && (t_o.is_a?(String) && t_o =~/^\}code/)) \ or (@per.code==:tics \ && (t_o.is_a?(String) && t_o =~/^```(?:\s+[~-][#]|\s+\~\{.+?\}\~)?\s*$/m) \ ) @per.code=:off if @tuned_code[-1] @tuned_code[-1]. gsub!(/\s*(?:#{Mx[:br_line]}|#{Mx[:br_nl]})\s*\Z/m,'') end obj=@tuned_code.join("\n") tags=[] h={ obj: obj, idx: idx, syntax: @per.lngsyn, tags: tags, num: @num_id[:code_block], number_: @codeblock_numbered, } @per.lngsyn=:txt t_o=SiSU_AO_DocumentStructure::ObjectBlockTxt.new.code(h) @tuned_code=[] tuned_file << t_o h={ is_for: :code, obj: '', sym: :code_close, num: @num_id[:code_block], } t_o=SiSU_AO_DocumentStructure::ObjectLayout.new.open_close(h) end if (@per.code==:curls \ || @per.code==:tics) \ and t_o.is_a?(String) sub_array=t_o.dup + "#{Mx[:br_nl]}" @line_mode=[] sub_array.scan(/.+/) {|w| @line_mode << w if w =~/[\S]+/} t_o=SiSU_AO_DocumentStructureExtract::Build.new(@md,@line_mode).build_lines(:code).join @tuned_code << t_o t_o=nil end elsif (@per.poem==:curls \ || @per.poem==:tics) \ or (@per.box==:curls \ || @per.box==:tics) \ or (@per.group==:curls \ || @per.group==:tics) \ or (@per.block==:curls \ || @per.block==:tics) \ or (@per.alt==:curls \ || @per.alt==:tics) \ or (@per.quote==:open \ && (t_o.is_a?(String) && t_o =~/`:quote_close`/m)) if (@per.poem==:curls \ && (t_o.is_a?(String) && t_o.to_s =~/^\}poem$/m)) \ or (@per.poem==:tics \ && (t_o.is_a?(String) && t_o =~/^```(?:\s+[~-][#]|\s+\~\{.+?\}\~)?\s*$/)) @per.poem=:off h={ is_for: :poem, obj: '', idx: idx, sym: :poem_close, num: @num_id[:poem], } t_o=SiSU_AO_DocumentStructure::ObjectLayout.new.open_close(h) elsif (@per.box==:curls \ && (t_o.is_a?(String) && t_o =~/^\}box/)) \ or (@per.box==:tics \ && (t_o.is_a?(String) && t_o.to_s =~/^```(?:\s+[~-][#]|\s+\~\{.+?\}\~)?\s*$/)) @per.box=:off obj,tags=extract_tags(@tuned_block.join("\n")) h={ obj: obj, idx: idx, tags: tags, num: @num_id[:box], } @tuned_block=[] t_o=SiSU_AO_DocumentStructure::ObjectBlockTxt.new.box(h) tuned_file << t_o h={ is_for: :box, obj: '', idx: idx, sym: :box_close, num: @num_id[:box], } t_o=SiSU_AO_DocumentStructure::ObjectLayout.new.open_close(h) elsif (@per.group==:curls \ && ( t_o.is_a?(String) && t_o.to_s =~/^\}group/)) \ or (@per.group==:tics \ && (t_o.is_a?(String) && t_o.to_s =~/^```(?:\s+[~-][#]|\s+\~\{.+?\}\~)?\s*$/)) @per.group=:off obj,tags=extract_tags(@tuned_block.join("\n")) h={ obj: obj, idx: idx, tags: tags, num: @num_id[:group], } @tuned_block=[] t_o=SiSU_AO_DocumentStructure::ObjectBlockTxt.new.group(h) tuned_file << t_o h={ is_for: :group, obj: '', sym: :group_close, num: @num_id[:group], } t_o=SiSU_AO_DocumentStructure::ObjectLayout.new.open_close(h) elsif (@per.block==:curls \ && t_o.to_s =~/^\}block/) \ or (@per.block==:tics \ && (t_o.is_a?(String) \ && t_o =~/^```(?:\s+[~-][#]|\s+\~\{.+?\}\~)?\s*$/) \ ) @per.block=:off obj,tags=extract_tags(@tuned_block.join("\n")) h={ obj: obj, idx: idx, tags: tags, num: @num_id[:block], } @tuned_block=[] t_o=SiSU_AO_DocumentStructure::ObjectBlockTxt.new.block(h) tuned_file << t_o h={ is_for: :block, obj: '', sym: :block_close, num: @num_id[:block], } t_o=SiSU_AO_DocumentStructure::ObjectLayout.new.open_close(h) elsif (@per.alt==:curls \ && (t_o.is_a?(String) && t_o =~/^\}alt/)) \ or (@per.alt==:tics \ && t_o.is_a?(String) \ && (t_o =~/^```(?:\s+[~-][#]|\s+\~\{.+?\}\~)?\s*$/) ) @per.alt=:off obj,tags=extract_tags(@tuned_block.join("\n")) h={ obj: obj, idx: idx, tags: tags, num: @num_id[:alt], } t_o=SiSU_AO_DocumentStructure::ObjectBlockTxt.new.alt(h) @tuned_block=[] tuned_file << t_o h={ is_for: :alt, obj: '', sym: :alt_close, num: @num_id[:alt], } t_o=SiSU_AO_DocumentStructure::ObjectLayout.new.open_close(h) elsif @per.quote==:open \ and (t_o.is_a?(String) && t_o =~/`:quote_close`/m) @per.quote=:off h={ is_for: :quote, idx: idx, obj: '', sym: :quote_close, num: @num_id[:quote], } t_o=SiSU_AO_DocumentStructure::ObjectLayout.new.open_close(h) elsif @per.quote==:open t_o,tags=extract_tags(t_o) h={ indent: 1, obj: t_o, idx: idx, note_: note, image_: image, tags: tags, quote: quotes?, } SiSU_AO_DocumentStructure::ObjectPara.new.paragraph(h) end if (@per.poem==:curls \ || @per.poem==:tics) \ or (@per.group==:curls \ || @per.group==:tics) \ or (@per.block==:curls \ || @per.block==:tics) \ or (@per.alt==:curls \ || @per.alt==:tics) \ and (t_o.is_a?(String) \ and t_o.to_s =~/\S/ \ and t_o.to_s !~/^(?:\}(?:verse|code|box|alt|group|block)|(?:verse|code(?:\.[a-z][0-9a-z_]+)?|box(?:\.[a-z_]+)?|alt|group|block)\{)/ \ and t_o.to_s !~/^```[ ]+(?:code(?:\.[a-z][0-9a-z_]+)?|box(?:\.[a-z_]+)?|poem|alt|group|block)|^```(?:\s+[~-][#]|\s+\~\{.+?\}\~)?\s*$/ ) sub_array=t_o.to_s.dup @line_mode=sub_array.scan(/.+/) type=if @per.poem==:curls or @per.poem==:tics t_o=SiSU_AO_DocumentStructureExtract::Build.new(@md,@line_mode).build_lines(type).join poem=t_o.split(/\n\n/) poem.each do |v| v=v.gsub(/\n/m,"#{Mx[:br_nl]}\n") obj,tags=extract_tags(v) h={ obj: obj, tags: tags, num: @num_id[:poem], } t_o=SiSU_AO_DocumentStructure::ObjectBlockTxt.new.verse(h) tuned_file << t_o end :poem else :group end end @verse_count+=1 if @per.poem==:curls or @per.poem==:tics end if @per.code==:off if @per.poem==:curls or @per.poem==:tics \ or @per.box==:curls or @per.box==:tics \ or @per.group==:curls or @per.group==:tics \ or @per.block==:curls or @per.block==:tics \ or @per.alt==:curls or @per.alt==:tics \ or (@per.quote==:open and t_o =~/`:quote_close`/m) if t_o.is_a?(String) t_o=t_o.gsub(/\n/m,"#{Mx[:br_nl]}"). gsub(/[ ][ ]/m,"#{Mx[:nbsp]*2}"). gsub(/#{Mx[:nbsp]}\s/,"#{Mx[:nbsp]*2}") t_o=t_o + Mx[:br_nl] if t_o =~/\S+/ elsif t_o.is==:group \ || t_o.is==:block \ || t_o.is==:alt \ || t_o.is==:box \ || t_o.is==:verse t_o.obj=t_o.obj.gsub(/\n/m,"#{Mx[:br_nl]}"). gsub(/[ ][ ]/m,"#{Mx[:nbsp]*2}"). gsub(/#{Mx[:nbsp]}\s/,"#{Mx[:nbsp]*2}") end @tuned_block << t_o if t_o.to_s =~/\S+/ else tuned_file << t_o end else tuned_file << t_o end end tuned_file end def identify_parts tuned_file=[] @tuned_block,@tuned_code=[],[] @@counter,@verse_count=0,0 @num_id={ code_block: 0, poem: 0, box: 0, block: 0, group: 0, alt: 0, quote: 0, table: 0, } @metadata={} if @md.flag_auto_biblio \ or @md.flag_biblio @data,bibliography=SiSU_AO_Appendices::Bibliography.new(@md,@data).biblio_extraction end if @md.flag_glossary @data,glossary=SiSU_AO_Appendices::Glossary.new(@md,@data).glossary_extraction end tuned_file=extract_structure_loop(@data,tuned_file) if @md.flag_endnotes tuned_file << @pb h={ ln: 1, lc: 1, obj: 'Endnotes', autonum_: false, } tuned_file << SiSU_AO_DocumentStructure::ObjectHeading.new.heading_insert(h) h={ ln: 4, lc: 2, obj: 'Endnotes', name: 'endnotes', autonum_: false, } tuned_file << SiSU_AO_DocumentStructure::ObjectHeading.new.heading_insert(h) h={ obj: 'Endnotes' } end if @md.flag_glossary tuned_file << @pb h={ ln: 1, lc: 1, obj: 'Glossary', autonum_: false, } tuned_file << SiSU_AO_DocumentStructure::ObjectHeading.new.heading_insert(h) h={ ln: 4, lc: 2, obj: 'Glossary', name: 'glossary', autonum_: false, } tuned_file << SiSU_AO_DocumentStructure::ObjectHeading.new.heading_insert(h) h={ obj: 'Glossary' } if glossary.length > 0 tuned_file=extract_structure_loop(glossary,tuned_file) end end if @md.flag_auto_biblio tuned_file << @pb h={ ln: 1, lc: 1, obj: 'References', autonum_: false, } tuned_file << SiSU_AO_DocumentStructure::ObjectHeading.new.heading_insert(h) h={ ln: 4, lc: 2, obj: 'Bibliography', name: 'biblio', autonum_: false, } tuned_file << SiSU_AO_DocumentStructure::ObjectHeading.new.heading_insert(h) h={ obj: 'Bibliography' } citenumber=0 bibliography.each do |cite| citenumber +=1 if cite.is_a?(Hash) h={ obj: cite[:obj], #obj: %{[#{citenumber}] } + cite[:obj], tags: [cite[:id]], hang: 0, indent: 2, ocn_: false, } tuned_file << SiSU_AO_DocumentStructure::ObjectPara.new.paragraph(h) end elsif @md.flag_biblio tuned_file << @pb h={ ln: 1, lc: 1, obj: 'References', autonum_: false, } tuned_file << SiSU_AO_DocumentStructure::ObjectHeading.new.heading_insert(h) h={ ln: 4, lc: 2, obj: 'Bibliography', name: 'biblio', autonum_: false, } tuned_file << SiSU_AO_DocumentStructure::ObjectHeading.new.heading_insert(h) h={ obj: 'Bibliography' } if not bibliography.nil? \ and bibliography.length > 0 tuned_file=extract_structure_loop(bibliography,tuned_file) else tuned_file, citations = SiSU_AO_Appendices::Citations.new(@md,tuned_file).songsheet # ao_appendices.rb citenumber=0 citations.compact.each do |c| citenumber +=1 if c.is_a?(Hash) if c[:is]==:book h={ obj: %{#{c[:author]}. /{#{c[:publication]}}/ (#{c[:year]})}, #obj: %{[#{citenumber}] *{#{c[:author]}}* /{#{c[:publication]}}/ (#{c[:year]})}, hang: 0, indent: 2, ocn_: false, } tuned_file << SiSU_AO_DocumentStructure::ObjectPara.new.paragraph(h) elsif c[:is]==:article h={ obj: %{#{c[:author]}. /{"#{c[:title]}"}/ #{c[:publication]} editor #{c[:editor]} (#{c[:year]})}, #obj: %{[#{citenumber}] *{#{c[:author]}}* /{"#{c[:title]}"}/ #{c[:publication]} editor #{c[:editor]} (#{c[:year]})}, hang: 0, indent: 2, ocn_: false, } tuned_file << SiSU_AO_DocumentStructure::ObjectPara.new.paragraph(h) end end end end if @md.book_idx tuned_file << @pb h={ ln: 1, lc: 1, obj: 'Index', autonum_: false, } tuned_file << SiSU_AO_DocumentStructure::ObjectHeading.new.heading_insert(h) h={ ln: 4, lc: 2, obj: 'Index', name: 'book_index', autonum_: false, } tuned_file << SiSU_AO_DocumentStructure::ObjectHeading.new.heading_insert(h) h={ obj: 'Index' } end tuned_file << @pb if @make.build.metadata? h={ ln: 1, lc: 1, obj: 'Metadata', autonum_: false, ocn_: false, } tuned_file << SiSU_AO_DocumentStructure::ObjectHeading.new.heading_insert(h) h={ ln: 4, lc: 2, obj: 'SiSU Metadata, document information', name: 'metadata', autonum_: false, ocn_: false, } tuned_file << SiSU_AO_DocumentStructure::ObjectHeading.new.heading_insert(h) end h={ obj: 'eof', } meta=SiSU_AO_DocumentStructure::ObjectMetadata.new.metadata(@metadata) [tuned_file,meta,bibliography,glossary] end def table_rows_and_columns_array(table_str) table=[] table_str.split(/#{Mx[:tc_c]}/).each do |table_row| table_row_with_columns=table_row.split(/#{Mx[:tc_p]}/) table << table_row_with_columns end table end def meta_heading(h) h={ lv: h[:lv], ln: h[:ln], name: h[:name], obj: h[:obj], ocn: '0', } SiSU_AO_DocumentStructure::ObjectHeading.new.heading(h) end def meta_para(str) h={ obj: str, ocn_: false, } SiSU_AO_DocumentStructure::ObjectPara.new.paragraph(h) end def build_lines(type=:none) lines=@data lines.each.map do |line| line=if line =~/\S/ \ and line !~/^(?:code(?:\.[a-z][0-9a-z_]+)?\{|\}code)/ \ and line !~/^(?:```[ ]+code(?:\.[a-z][0-9a-z_]+)?|```(?:\s+[~-][#]|\s+\~\{.+?\}\~)?\s*$)/ \ and not line.is_a?(Hash) #watch @@counter+=1 if @per.code==:curls or @per.code==:tics line=line.gsub(/\s\s/,"#{Mx[:nbsp]*2}"). gsub(/#{Mx[:nbsp]}\s/,"#{Mx[:nbsp]*2}") line=line.gsub(/^/,"#{Mx[:gr_o]}codeline#{Mx[:gr_c]}") if type==:code # REMOVE try sort for texpdf special case line=if line =~/(?:https?|file|ftp):\/\/\S+$/ line.gsub(/\s*$/," #{Mx[:br_nl]}") else line.gsub(/\s*$/,"#{Mx[:br_nl]}") #unless type=='code' end elsif line =~/^\s*$/ line.gsub(/\s*$/,"#{Mx[:br_nl]}") else line end line end end end class Structure # this must happen early def initialize(md) @md=md end def structure(data) data.compact.each do |dob| structure_markup(dob) end end def structure_markup(dob) #build structure where structure provided only in meta header dob=if dob.is==:para \ && (((dob.hang !~/[1-9]/) && (dob.indent !~/[1-9]/)) \ || (dob.hang != dob.indent)) \ and not dob.bullet_ dob=case dob.obj when /^#{@md.lv0}/ h={ is: :heading, lv: 'A', ln: 0, } SiSU_AO_DocumentStructure::ObjectHeading.new.heading(h,dob) when /^#{@md.lv1}/ h={ is: :heading, lv: 'B', ln: 1, } SiSU_AO_DocumentStructure::ObjectHeading.new.heading(h,dob) when /^#{@md.lv2}/ h={ is: :heading, lv: 'C', ln: 2, } SiSU_AO_DocumentStructure::ObjectHeading.new.heading(h,dob) when /^#{@md.lv3}/ h={ is: :heading, lv: 'D', ln: 3, } SiSU_AO_DocumentStructure::ObjectHeading.new.heading(h,dob) when /^#{@md.lv4}/ h={ is: :heading, lv: '1', ln: 4, } SiSU_AO_DocumentStructure::ObjectHeading.new.heading(h,dob) when /^#{@md.lv5}/ h={ is: :heading, lv: '2', ln: 5, } SiSU_AO_DocumentStructure::ObjectHeading.new.heading(h,dob) when /^#{@md.lv6}/ h={ is: :heading, lv: '3', ln: 6, } SiSU_AO_DocumentStructure::ObjectHeading.new.heading(h,dob) else dob end else dob end dob end end class OCN def initialize(md,data,fnx,process) @md,@data,@fnx,@process=md,data,fnx,process end def structure_info def lv %w[A~ B~ C~ D~ 1 2 3 4] end def possible_parents(child) case child when /A~/ then 'none' when /B~/ then 'A~' when /C~/ then 'B~' when /D~/ then 'C~' when /1/ then 'A~, B~, C~, D~' when /2/ then '1' when /3/ then '2' when /4/ then '3' end end def possible_children(parent) case parent when /A~/ then 'B~, 1' when /B~/ then 'C~, 1' when /C~/ then 'D~, 1' when /D~/ then '1' when /1/ then '2' when /2/ then '3' when /3/ then '4' when /4/ then 'none' end end self end def document_structure_check_info(node,node_parent,status=:ok) node_ln=/^([0-7])/.match(node)[1].to_i node_parent_ln=/^([0-7])/.match(node_parent)[1].to_i if status==:error \ or @md.opt.act[:maintenance][:set]==:on puts %{node: #{node}, parent node: #{node_parent} #{status.upcase}} if status==:error node_ln=/^([0-7])/.match(node)[1].to_i node_parent_ln=/^([0-7])/.match(node_parent)[1].to_i STDERR.puts %{current level: #{structure_info.lv[node_ln]} (possible parent levels: #{structure_info.possible_parents(structure_info.lv[node_ln])}) parent level: #{structure_info.lv[node_parent_ln]} (possible child levels: #{structure_info.possible_children(structure_info.lv[node_parent_ln])}) SKIPPED processing file: [#{@md.opt.lng}] "#{@md.fns}"} if @md.opt.act[:no_stop][:set]==:on $process_document = :skip else exit end end end end def warning_incorrect_parent_level_or_level(txt) puts %{ERROR. There is an error in markup of heading levels either here or in the parent heading. The current header reads: "#{txt}" has incorrect level and/or parent level --} end def required_headers_present? if @process == :complete unless (defined? @md.title \ and @md.title.full) STDERR.puts %{required header missing: @title: SKIPPED processing file: [#{@md.opt.lng}] "#{@md.fns}" } if @md.opt.act[:no_stop][:set]==:on $process_document = :skip else exit end end unless (defined? @md.creator.author \ and @md.creator.author) STDERR.puts %{required header missing: @creator: :author: anonymous? SKIPPED processing file: [#{@md.opt.lng}] "#{@md.fns}" } if @md.opt.act[:no_stop][:set]==:on $process_document = :skip else exit end end end end def ocn #and auto segment numbering increment required_headers_present? data=@data @o_array=[] node=ocn=ocn_dv=ocn_sp=ocnh=ocnh0=ocnh1=ocnh2=ocnh3=ocnh4=ocnh5=ocnh6=ocnh7=ocno=ocnp=ocnt=ocnc=ocng=ocni=ocnu=0 # h heading, o other, t table, g group, i image regex_exclude_ocn_and_node = /#{Rx[:meta]}|^@\S+?:\s|^4~endnotes|^#{Mx[:lv_o]}4:endnotes#{Mx[:lv_c]}|^\^~ |<:e[:_]\d+?>|^<:\#|<:- |<[:!]!4|<hr width|#{Mx[:br_endnotes]}|\A\s*\Z/mi #ocn here # added with Tune.code #¡ parent=node1=node2=node3=node4=node5=node6=node7=nil node0='0:0;0' @collapsed_lv0=0 @lev_occurences={ a: 0, b: 0, c: 0, d: 0, l1: 0, l2: 0, l3: 0, l4: 0 } data.each do |dob| h={} if (dob.obj !~ regex_exclude_ocn_and_node || dob.is==:code) \ && (dob.of !=:comment \ && dob.of !=:layout \ && dob.of !=:meta) \ && dob.ocn_ #dob.ln now is determined, and set earlier, check how best to remove this --> if dob.is==:heading @ln=ln=case dob.lv when 'A' then 0 when 'B' then 1 when 'C' then 2 when 'D' then 3 when '1' then 4 when '2' then 5 when '3' then 6 when '4' then 7 when '5' then 8 when '6' then 9 end end if not dob.obj =~/~#|-#/ ocn+=1 end if @process == :complete \ or (@fnx == @md.opt.fns \ && @md.opt.fns =~/.sst$/) if dob.is==:heading \ and (ln.to_s =~/^[0-9]/ \ or ln.to_s =~@md.lv0 \ or ln.to_s =~@md.lv1 \ or ln.to_s =~@md.lv2 \ or ln.to_s =~@md.lv3 \ or ln.to_s =~@md.lv4 \ or ln.to_s =~@md.lv5 \ or ln.to_s =~@md.lv6 \ or ln.to_s =~@md.lv7) if not dob.obj =~/~#|-#/ ocnh+=1 end if ln==0 \ or ln.to_s =~@md.lv0 @lev_occurences[:a] += 1 if not dob.obj =~/~#|-#/ ocn_flag=true ocnh0+=1 #heading node0="0:#{ocnh0};#{ocn}" else #document_structure_check_info(node0,node0,:error) #fix ocn_flag=false node0="0:0;0" end document_structure_check_info(node0,node0) @collapsed_lv0=0 collapsed_level=@collapsed_lv0 node,ocn_sp,parent=node0,"h#{ocnh}",'ROOT' elsif ln==1 \ or ln.to_s =~@md.lv1 @lev_occurences[:b] += 1 if not dob.obj =~/~#|-#/ ocn_flag=true ocnh1+=1 #heading node1="1:#{ocnh1};#{ocn}" else #document_structure_check_info(node0,node0,:error) #fix ocn_flag=false node1="1:0;0" end parent=if node0 document_structure_check_info(node1,node0) @collapsed_lv1=@collapsed_lv0+1 node0 else warning_incorrect_parent_level_or_level(dob.obj) document_structure_check_info(node0,node0,:error) node0 end collapsed_level=@collapsed_lv1 node,ocn_sp,parent=node1,"h#{ocnh}",node0 #FIX elsif ln==2 \ or ln.to_s =~@md.lv2 @lev_occurences[:c] += 1 if not dob.obj =~/~#|-#/ ocn_flag=true ocnh2+=1 node2="2:#{ocnh2};#{ocn}" else #document_structure_check_info(node0,node0,:error) #fix ocn_flag=false node2="2:0;0" end parent=if node1 document_structure_check_info(node2,node1) @collapsed_lv2=@collapsed_lv1+1 node1 else warning_incorrect_parent_level_or_level(dob.obj) document_structure_check_info(node2,node0,:error) node0 end collapsed_level=@collapsed_lv2 node,ocn_sp=node2,"h#{ocnh}" elsif ln==3 \ or ln.to_s =~@md.lv3 @lev_occurences[:d] += 1 if not dob.obj =~/~#|-#/ ocn_flag=true ocnh3+=1 node3="3:#{ocnh3};#{ocn}" else #document_structure_check_info(node0,node0,:error) #fix ocn_flag=false node3="3:0;0" end parent=if node2 document_structure_check_info(node3,node2) @collapsed_lv3=@collapsed_lv2+1 node2 elsif node1 warning_incorrect_parent_level_or_level(dob.obj) puts %{parent is :A~ & this level #{dob.lv} either parent should be level :B~ or this level should be level :B~ rather than #{dob.lv}} document_structure_check_info(node3,node1,:error) @collapsed_lv3=@collapsed_lv1+1 node1 else document_structure_check_info(node3,node0,:error) warning_incorrect_parent_level_or_level(dob.obj) node0 end collapsed_level=@collapsed_lv3 node,ocn_sp=node3,"h#{ocnh}" elsif ln==4 \ or ln.to_s =~@md.lv4 @lev_occurences[:l1] += 1 if not dob.obj =~/~#|-#/ ocn_flag=true ocnh4+=1 node4="4:#{ocnh4};#{ocn}" else ocn_flag=false node4="4:0;0" end parent=if node3 document_structure_check_info(node4,node3) @collapsed_lv4=@collapsed_lv3+1 node3 elsif node2 document_structure_check_info(node4,node2) @collapsed_lv4=@collapsed_lv2+1 node2 elsif node1 document_structure_check_info(node4,node1) @collapsed_lv4=@collapsed_lv1+1 node1 elsif node0 document_structure_check_info(node4,node0) @collapsed_lv4=@collapsed_lv0+1 node0 else warning_incorrect_parent_level_or_level(dob.obj) document_structure_check_info(node4,node0,:error) node0 end collapsed_level=@collapsed_lv4 node,ocn_sp=node4,"h#{ocnh}" elsif ln==5 \ or ln.to_s =~@md.lv5 @lev_occurences[:l2] += 1 if not dob.obj =~/~#|-#/ ocn_flag=true ocnh5+=1 node5="5:#{ocnh5};#{ocn}" else ocn_flag=false node5="5:0;0" end parent=if node4 document_structure_check_info(node5,node4) @collapsed_lv5=@collapsed_lv4+1 node4 elsif node3 warning_incorrect_parent_level_or_level(dob.obj) document_structure_check_info(node5,node3,:error) @collapsed_lv5=@collapsed_lv3+1 node3 elsif node2 warning_incorrect_parent_level_or_level(dob.obj) document_structure_check_info(node5,node2,:error) @collapsed_lv5=@collapsed_lv2+1 node2 elsif node1 warning_incorrect_parent_level_or_level(dob.obj) document_structure_check_info(node5,node1,:error) @collapsed_lv5=@collapsed_lv1+1 node1 else warning_incorrect_parent_level_or_level(dob.obj) document_structure_check_info(node5,node0,:error) node0 end collapsed_level=@collapsed_lv5 node,ocn_sp=node5,"h#{ocnh}" elsif ln==6 \ or ln.to_s =~@md.lv6 @lev_occurences[:l3] += 1 if not dob.obj =~/~#|-#/ ocn_flag=true ocnh6+=1 node6="6:#{ocnh6};#{ocn}" else ocn_flag=false node6="6:0;0" end parent=if node5 document_structure_check_info(node6,node5) @collapsed_lv6=@collapsed_lv5+1 node5 elsif node4 warning_incorrect_parent_level_or_level(dob.obj) puts "parent is level #4 (1~) & this level ##{dob.ln} (#{dob.lv}~) either parent should be level #5 (2~) or this level should be #5 (2~) rather ##{dob.ln} (#{dob.lv}~)" document_structure_check_info(node6,node4,:error) @collapsed_lv6=@collapsed_lv4+1 node4 elsif node3 warning_incorrect_parent_level_or_level(dob.obj) document_structure_check_info(node6,node3,:error) @collapsed_lv6=@collapsed_lv3+1 node3 elsif node2 warning_incorrect_parent_level_or_level(dob.obj) document_structure_check_info(node6,node2,:error) @collapsed_lv6=@collapsed_lv2+1 node2 elsif node1 warning_incorrect_parent_level_or_level(dob.obj) document_structure_check_info(node6,node1,:error) @collapsed_lv6=@collapsed_lv1+1 node1 else warning_incorrect_parent_level_or_level(dob.obj) document_structure_check_info(node6,node0,:error) node0 end collapsed_level=@collapsed_lv6 node,ocn_sp=node6,"h#{ocnh}" elsif ln==7 \ or ln.to_s =~@md.lv7 @lev_occurences[:l4] += 1 if not dob.obj =~/~#|-#/ ocn_flag=true ocnh7+=1 node7="7:#{ocnh7};#{ocn}" else ocn_flag=false node7="7:0;0" end parent=if node6 document_structure_check_info(node7,node6) @collapsed_lv7=@collapsed_lv6+1 node5 elsif node5 warning_incorrect_parent_level_or_level(dob.obj) puts "parent is level #5 (2~) & this level ##{dob.ln} (#{dob.lv}~) either parent should be level #6 (3~) or this level should be #6 (3~) rather ##{dob.ln} (#{dob.lv}~)" document_structure_check_info(node7,node5,:error) @collapsed_lv6=@collapsed_lv5+1 node5 elsif node4 warning_incorrect_parent_level_or_level(dob.obj) puts "parent is level #4 (1~) & this level ##{dob.ln} (#{dob.lv}~) either parent should be level 6~ or this level should be #6 (3~) rather ##{dob.ln} (#{dob.lv}~)" document_structure_check_info(node7,node4,:error) @collapsed_lv6=@collapsed_lv4+1 node4 elsif node3 warning_incorrect_parent_level_or_level(dob.obj) document_structure_check_info(node7,node3,:error) @collapsed_lv6=@collapsed_lv3+1 node3 elsif node2 warning_incorrect_parent_level_or_level(dob.obj) document_structure_check_info(node7,node2,:error) @collapsed_lv6=@collapsed_lv2+1 node2 elsif node1 warning_incorrect_parent_level_or_level(dob.obj) document_structure_check_info(node7,node1,:error) @collapsed_lv6=@collapsed_lv1+1 node1 else warning_incorrect_parent_level_or_level(dob.obj) document_structure_check_info(node7,node0,:error) node0 end collapsed_level=@collapsed_lv7 node,ocn_sp=node7,"h#{ocnh}" end else unless @lev_occurences[:l1] > 0 STDERR.puts %{Substantive text objects must follow a level 1~ heading and there are none at this point in processing: #{@lev_occurences[:l1]} SKIPPED processing file: [#{@md.opt.lng}] "#{@md.fns}"} puts dob.obj #.gsub(/^(.{1,80})/,'"\1"') exit end unless @ln >= 4 lev=case @ln when 0 then 'A' when 1 then 'B' when 2 then 'C' when 3 then 'D' when 4 then '1' when 5 then '2' when 6 then '3' when 7 then '4' when 8 then '5' when 9 then '6' end STDERR.puts %{Substantive text objects must follow a level 1~ 2~ or 3~ heading: #{lev}~ SKIPPED processing file: [#{@md.opt.lng}] "#{@md.fns}"} puts dob.obj.gsub(/^(.{1,80})/,'"\1"') if @md.opt.act[:no_stop][:set]==:on $process_document = :skip break else exit end end if not dob.obj =~/~#|-#/ ocn_flag=true else ocn_flag=false end ocno+=1 if dob.is==:table ocnt+=1 ocn_sp,parent="t#{ocnt}",node elsif dob.is==:code ocnc+=1 ocn_sp,parent="c#{ocnc}",node elsif dob.is==:group \ || dob.is==:box \ || dob.is==:block \ || dob.is==:alt \ || dob.is==:verse ocng+=1 #group, poem ocn_sp,parent="g#{ocng}",node elsif dob.is==:image #check ocni+=1 ocn_sp,parent="i#{ocni}",node else ocnp+=1 #paragraph ocn_sp,parent="p#{ocnp}",node end end end if dob.is==:heading if ocn_flag==true dob.ln,dob.node,dob.ocn,dob.ocn_,dob.odv,dob.osp,dob.parent,dob.lc= ln, node, ocn, ocn_flag, ocn_dv,ocn_sp, parent, collapsed_level else ocnu+=1 heading_use=:ok if dob.obj=~/#{Mx[:pa_non_object_no_heading]}/ dob.obj=dob.obj.gsub(/#{Mx[:pa_non_object_no_heading]}/,'') heading_use=:ok elsif dob.obj=~/#{Mx[:pa_non_object_dummy_heading]}/ dob.obj=dob.obj.gsub(/#{Mx[:pa_non_object_dummy_heading]}/,'') heading_use=:dummy end dob.ln,dob.node,dob.ocn,dob.ocn_,dob.use_, dob.odv,dob.osp,dob.parent,dob.lc= ln, node, nil, ocn_flag,heading_use,ocn_dv, ocn_sp, parent, collapsed_level end else if dob.of !=:meta \ && dob.of !=:comment \ && dob.of !=:layout if ocn_flag == true dob.ocn,dob.ocn_,dob.odv,dob.osp,dob.parent= ocn, ocn_flag,ocn_dv, ocn_sp, parent else ocnu+=1 dob.obj=dob.obj.gsub(/#{Mx[:fa_o]}[~-]##{Mx[:fa_c]}/,'') if dob.obj ocn_dv,ocn_sp="u#{ocnu}","u#{ocnu}" dob.ocn,dob.ocn_,dob.odv,dob.osp,dob.parent= nil, ocn_flag,ocn_dv, ocn_sp, parent end end end h else dob end if dob.is==:code \ || dob.is==:verse \ || dob.is==:alt \ || dob.is==:box \ || dob.is==:group \ || dob.is==:block dob.obj=dob.obj.gsub(/\n+/,"\n") #newlines taken out end @o_array << dob end if @process == :complete \ or (@fnx == @md.opt.fns \ && @md.opt.fns =~/.sst$/) unless @lev_occurences[:a] == 1 STDERR.puts %{The number of level A~ in this document: #{@lev_occurences[:a]} There must be one level A~ (no more and no less) SKIPPED processing file: [#{@md.opt.lng}] "#{@md.fns}"} if @md.opt.act[:no_stop][:set]==:on $process_document = :skip else exit end end unless @lev_occurences[:l1] > 0 STDERR.puts %{The number of level 1~ in this document: #{@lev_occurences[:l1]} There must be at least one level 1~ (and as many as required) SKIPPED processing file: [#{@md.opt.lng}] "#{@md.fns}"} if @md.opt.act[:no_stop][:set]==:on $process_document = :skip else exit end end end @o_array end end class XML def initialize(md,data) @data,@md=data,md end def dom @s=[ 'A', 'B', 'C', 'D', '1', '2', '3' ] tuned_file=structure_build tuned_file end def spaces Ax[:spaces] end def structure_build data=@data tuned_file=[] hs=[0,false,false,false] t={ lv: @s[0], status: :open, } tuned_file << tags(t) if @md.opt.act[:verbose_plus][:set]==:on puts "\nXML sisu structure outline --->\n" puts "<#{@s[0]}>" end data.each_with_index do |o,i| if o.is==:heading \ || o.is==:heading_insert case o.ln when 0 tuned_file << tag_close(o.ln,hs) tuned_file << tag_open(o,@s) if @md.opt.act[:verbose_plus][:set]==:on puts_tag_close(o.ln,hs) puts_tag_open(o,@s) end hs=[0,true,false,false,false] when 1 tuned_file << tag_close(o.ln,hs) tuned_file << tag_open(o,@s) if @md.opt.act[:verbose_plus][:set]==:on puts_tag_close(o.ln,hs) puts_tag_open(o,@s) end hs=[1,true,true,false,false] when 2 tuned_file << tag_close(o.ln,hs) tuned_file << tag_open(o,@s) if @md.opt.act[:verbose_plus][:set]==:on puts_tag_close(o.ln,hs) puts_tag_open(o,@s) end hs=[2,true,true,true,false] when 3 tuned_file << tag_close(o.ln,hs) tuned_file << tag_open(o,@s) if @md.opt.act[:verbose_plus][:set]==:on puts_tag_close(o.ln,hs) puts_tag_open(o,@s) end hs=[3,true,true,true,true] when 4 tuned_file << tag_close(o.ln,hs) tuned_file << tag_open(o,@s) if @md.opt.act[:verbose_plus][:set]==:on puts_tag_close(o.ln,hs) puts_tag_open(o,@s) end hs[0]=4 when 5 tuned_file << tag_close(o.ln,hs) tuned_file << tag_open(o,@s) if @md.opt.act[:verbose_plus][:set]==:on puts_tag_close(o.ln,hs) puts_tag_open(o,@s) end hs[0]=5 when 6 tuned_file << tag_close(o.ln,hs) tuned_file << tag_open(o,@s) if @md.opt.act[:verbose_plus][:set]==:on puts_tag_close(o.ln,hs) puts_tag_open(o,@s) end hs[0]=6 end end tuned_file << o end if @md.opt.act[:verbose_plus][:set]==:on puts_tag_close(0,hs) end tuned_file << tag_close(0,hs) tuned_file=tuned_file.flatten end def tags(o) tag=(o[:status]==:open) \ ? %{<#{o[:lv]} id="#{o[:node]}">} : "</#{o[:lv]}>" ln=case o[:lv] when 'A' then 0 when 'B' then 1 when 'C' then 2 when 'D' then 3 when '1' then 4 when '2' then 5 when '3' then 6 when '4' then 7 when '5' then 8 when '6' then 9 end h={ tag: tag, node: o[:node], lv: o[:lv], ln: ln, status: o[:status], } SiSU_AO_DocumentStructure::ObjectStructure.new.xml_dom(h) #downstream code utilise else ignore like comments end def tag_open(o,tag) t={ lv: tag[o.ln], node: o.node, status: :open } t_o=tags(t) t_o end def tag_close(lev,hs) ary=[] case hs[0] when 0 if (lev <= 0) and hs[0] t={ lv: @s[0], status: :close, } ary << tags(t) end when 1 if (lev <= 1) and hs[1] t={ lv: @s[1], status: :close, } ary << tags(t) end if (lev==0) t={ lv: @s[0], status: :close, } ary << tags(t) end when 2 if (lev <= 2) and hs[2] t={ lv: @s[2], status: :close, } ary << tags(t) end if (lev <= 1) and hs[1] t={ lv: @s[1], status: :close, } ary << tags(t) end if (lev==0) t={ lv: @s[0], status: :close, } ary << tags(t) end when 3 if (lev <= 3) and hs[3] t={ lv: @s[3], status: :close, } ary << tags(t) end if (lev <= 2) and hs[2] t={ lv: @s[2], status: :close, } ary << tags(t) end if (lev <= 1) and hs[1] t={ lv: @s[1], status: :close, } ary << tags(t) end if (lev==0) t={ lv: @s[0], status: :close, } ary << tags(t) end when 4 if (lev <= 4) t={ lv: @s[4], status: :close, } ary << tags(t) end if (lev <= 3) and hs[3] t={ lv: @s[3], status: :close, } ary << tags(t) end if (lev <= 2) and hs[2] t={ lv: @s[2], status: :close, } ary << tags(t) end if (lev <= 1) and hs[1] t={ lv: @s[1], status: :close, } ary << tags(t) end if (lev==0) t={ lv: @s[0], status: :close, } ary << tags(t) end when 5 if (lev <= 5) t={ lv: @s[5], status: :close, } ary << tags(t) end if (lev <= 4) t={ lv: @s[4], status: :close, } ary << tags(t) end if (lev <= 3) and hs[3] t={ lv: @s[3], status: :close, } ary << tags(t) end if (lev <= 2) and hs[2] t={ lv: @s[2], status: :close, } ary << tags(t) end if (lev <= 1) and hs[1] t={ lv: @s[1], status: :close, } ary << tags(t) end if (lev==0) t={ lv: @s[0], status: :close, } ary << tags(t) end when 6 if (lev <= 6) t={ lv: @s[6], status: :close, } ary << tags(t) end if (lev <= 5) t={ lv: @s[5], status: :close, } ary << tags(t) end if (lev <= 4) t={ lv: @s[4], status: :close, } ary << tags(t) end if (lev <= 3) and hs[3] t={ lv: @s[3], status: :close, } ary << tags(t) end if (lev <= 2) and hs[2] t={ lv: @s[2], status: :close, } ary << tags(t) end if (lev <= 1) and hs[1] t={ lv: @s[1], status: :close, } ary << tags(t) end if (lev==0) t={ lv: @s[0], status: :close, } ary << tags(t) end end ary end def puts_tag_open(o,tag) puts %{#{spaces*o.ln}<#{tag[o.ln]} id="#{o.node}">} end def puts_tag_close(lev,hs) case hs[0] when 0 #puts "#{spaces*0}</#{@s[0]}>" if (lev <= 0) and hs[0] puts "</#{@s[0]}>" if (lev==0) when 1 puts "#{spaces*1}</#{@s[1]}>" if (lev <= 1) and hs[1] puts "</#{@s[0]}>" if (lev==0) when 2 puts "#{spaces*2}</#{@s[2]}>" if (lev <= 2) and hs[2] puts "#{spaces*1}</#{@s[1]}>" if (lev <= 1) and hs[1] puts "</#{@s[0]}>" if (lev==0) when 3 puts "#{spaces*3}</#{@s[3]}>" if (lev <= 3) and hs[3] puts "#{spaces*2}</#{@s[2]}>" if (lev <= 2) and hs[2] puts "#{spaces*1}</#{@s[1]}>" if (lev <= 1) and hs[1] puts "</#{@s[0]}>" if (lev==0) when 4 puts "#{spaces*4}</#{@s[4]}>" if (lev <= 4) puts "#{spaces*3}</#{@s[3]}>" if (lev <= 3) and hs[3] puts "#{spaces*2}</#{@s[2]}>" if (lev <= 2) and hs[2] puts "#{spaces*1}</#{@s[1]}>" if (lev <= 1) and hs[1] puts "</#{@s[0]}>" if (lev==0) when 5 puts "#{spaces*5}</#{@s[5]}>" if (lev <= 5) puts "#{spaces*4}</#{@s[4]}>" if (lev <= 4) puts "#{spaces*3}</#{@s[3]}>" if (lev <= 3) and hs[3] puts "#{spaces*2}</#{@s[2]}>" if (lev <= 2) and hs[2] puts "#{spaces*1}</#{@s[1]}>" if (lev <= 1) and hs[1] puts "</#{@s[0]}>" if (lev==0) when 6 puts "#{spaces*6}</#{@s[6]}>" if (lev <= 6) puts "#{spaces*5}</#{@s[5]}>" if (lev <= 5) puts "#{spaces*4}</#{@s[4]}>" if (lev <= 4) puts "#{spaces*3}</#{@s[3]}>" if (lev <= 3) and hs[3] puts "#{spaces*2}</#{@s[2]}>" if (lev <= 2) and hs[2] puts "#{spaces*1}</#{@s[1]}>" if (lev <= 1) and hs[1] puts "</#{@s[0]}>" if (lev==0) end end end end __END__ #+END_SRC ** ao_endnotes.rb #+HEADER: :tangle "../lib/sisu/ao_endnotes.rb_" #+BEGIN_SRC ruby #<<sisu_document_header>> module SiSU_AO_Endnotes class Endnotes def initialize(md,data,endnote_array=nil) @md,@data,@endnote_array= md, data, endnote_array @endnote_counter, @endnote_counter_asterisk, @endnote_counter_dag= 1,1,1 end def endnotes data=@data endnote_ref=1 @tuned_file=data.each.map do |dob| # manually numbered endnotes <!e(\d)!> <!e_(\d)!> --> if @md.opt.selections.str =~/--no-asterisk|--no-annotate/ dob.obj=dob.obj. gsub(/#{Mx[:en_b_o]}\s.+?#{Mx[:en_b_c]}/,'') end if @md.opt.selections.str =~/--no-dagger|--no-annotate/ dob.obj=dob.obj. gsub(/#{Mx[:en_b_o]}[+]\s.+?#{Mx[:en_b_c]}/,'') end if (defined? dob.obj) \ && (defined? dob.is) \ && dob.is !=:code case dob.obj # auto-numbered endnotes <!e!> <!e_!> --> when /#{Mx[:en_a_o]}.+?#{Mx[:en_a_c]}|#{Mx[:en_b_o]}[*+]\s+.+?#{Mx[:en_b_c]}/ dob.obj=dob.obj. gsub(/\s*(#{Mx[:en_a_c]}|#{Mx[:en_b_c]})/,'\1') word_mode=dob.obj.scan(/\S+/m) word_mode=endnote_call_number(word_mode) dob.obj=word_mode.join(' ') endnote_ref+=1 when /~\^(?:\s|$)/ #%note inserts endnotes previously gathered from /^(<!e[:_]!>|[-~]\{{3})/ (in earlier loop) word_mode=dob.obj.scan(/\S+/m) word_mode=endnote_call_number(word_mode) dob.obj=word_mode.join(' ') endnote_ref+=1 end end dob end.flatten @endnote_counter, @endnote_counter_asterisk, @endnote_counter_dag= 1,1,1 @tuned_file end def endnote_call_number(words) words.each do |word| case word when /#{Mx[:en_a_o]}/ unless word =~/#{Mx[:en_a_o]}[*+]+/ word.gsub!(/#{Mx[:en_a_o]}/, "#{Mx[:en_a_o]}#{@endnote_counter} ") @endnote_counter+=1 end when /#{Mx[:en_b_o]}/ if word =~/#{Mx[:en_b_o]}[+]/ word.gsub!(/#{Mx[:en_b_o]}[+]/, "#{Mx[:en_b_o]}\+#{@endnote_counter_dag} ") @endnote_counter_dag+=1 else word.gsub!(/#{Mx[:en_b_o]}[*]?/, "#{Mx[:en_b_o]}\*#{@endnote_counter_asterisk} ") @endnote_counter_asterisk+=1 end when /~\^/ if @endnote_array word.gsub!(/~\^/, "#{@endnote_array[@endnote_counter-1]}") @endnote_counter+=1 end end end end end end __END__ #+END_SRC ** ao_expand_insertions.rb #+HEADER: :tangle "../lib/sisu/ao_expand_insertions.rb" #+BEGIN_SRC ruby #<<sisu_document_header>> module SiSU_AO_Insertions class Insertions def initialize(md,data) @md,@data=md,data end def output_filetypes_in_cmd(cmd_shortcut,lnk=nil) #make list of file types in shortcut command (as configured), e.g. when sisu -3 is used act_defaults=SiSU_Env::InfoProcessingFlag.new cmd_list=case cmd_shortcut.inspect #check on expectation, string v array when /0/ then act_defaults.act_0.str when /1/ then act_defaults.act_1.str when /2/ then act_defaults.act_2.str when /3/ then act_defaults.act_3.str when /4/ then act_defaults.act_4.str when /5/ then act_defaults.act_5.str when /6/ then act_defaults.act_6.str when /7/ then act_defaults.act_7.str when /8/ then act_defaults.act_8.str when /9/ then act_defaults.act_9.str end file_type_names={} file_type_names[:gen],file_type_names[:src]=[],[] file_type_names[:gen] <<= if cmd_list =~ /\b--manifest\b/ "~^ { document manifest }#{lnk[:manifest]}" end file_type_names[:gen] <<= if cmd_list =~ /\b--html\b/ [ " { html, segmented text }#{lnk[:html_toc]}", " { html, scroll, document in one }#{lnk[:html_doc]}", ] end file_type_names[:gen] <<= if cmd_list =~ /\b--epub\b/ [" { epub }#{lnk[:epub]}"] end file_type_names[:gen] <<= if cmd_list =~ /\b--pdf\b/ \ or cmd_list =~ /--pdf-landscape/ [ " { pdf, landscape }#{lnk[:pdf_landscape]}", ] end file_type_names[:gen] <<= if cmd_list =~ /\b--pdf\b/ \ or cmd_list =~ /--pdf-portrait/ [ " { pdf, portrait }#{lnk[:pdf_portrait]}", ] end file_type_names[:gen] <<= if cmd_list =~ /\b(?:--odt|--odf)\b/ " { odf:odt, open document text }#{lnk[:odt]}" end file_type_names[:gen] <<= if cmd_list =~ /\b--xhtml\b/ " { xhtml scroll }#{lnk[:xhtml]}" end file_type_names[:gen] <<= if cmd_list =~ /\b--docbook\b/ " { docbook }#{lnk[:docbook]}" #CHECK end file_type_names[:gen] <<= if cmd_list =~ /\b--xml-sax\b/ " { xml, sax }#{lnk[:xml_sax]}" end file_type_names[:gen] <<= if cmd_list =~ /\b--xml-dom\b/ " { xml, dom }#{lnk[:xml_dom]}" end file_type_names[:gen] <<= if cmd_list =~ /\b(?:--txt|--text|--plaintext)\b/ " { plain text utf-8 }#{lnk[:txt]}" end #file_type_names[:gen] <<= if cmd_list =~ /g/ # 'wiki.txt' #end file_type_names[:gen] <<= if cmd_list =~ /\b--concordance\b/ " { concordance }#{lnk[:html_concordance]}" end file_type_names[:gen] <<= if cmd_list =~ /\b--digest\b/ " { dcc, document content certificate (digests) }#{lnk[:digest]}" end file_type_names[:src] <<= if source and cmd_shortcut =~ /\b--source\b/ " { markup source text }#{lnk[:source]}" end file_type_names[:src] <<= if cmd_shortcut =~ /\b--sisupod\b/ " { markup source (zipped) pod }#{lnk[:sisupod]}" end file_type_names[:gen]=file_type_names[:gen].flatten file_type_names[:src]=file_type_names[:src].flatten file_type_names end def by_language(linked_doc,lng,src=nil) @linked_doc,@lng,@src=linked_doc,lng,src @base_path="#{@md.file.output_path.base.url}/#{lng}" def fnh { fn: @linked_doc, } end def path_and_file(fn,pth) @base_path + '/' + pth + '/' + fn end def manifest fn=@md.file.base_filename.manifest(fnh) path_and_file(fn,'manifest') end def html_toc fn=@md.file.base_filename.html_segtoc(fnh) @base_path + '/html/' + @linked_doc + '/' + fn end def html_doc fn=@md.file.base_filename.html_scroll(fnh) path_and_file(fn,'html') end def html_concordance fn=@md.file.base_filename.html_concordance @base_path + '/html/' + @linked_doc + '/' + fn end def epub fn=@md.file.base_filename.epub(fnh) path_and_file(fn,'epub') end def pdf_landscape fn=@md.file.base_filename.pdf_l_a4(fnh) path_and_file(fn,'pdf') end def pdf_portrait fn=@md.file.base_filename.pdf_p_a4(fnh) path_and_file(fn,'pdf') end def odt fn=@md.file.base_filename.odt(fnh) path_and_file(fn,'odt') end def xhtml fn=@md.file.base_filename.xhtml(fnh) path_and_file(fn,'xhtml') end def docbook fn=@md.file.base_filename.xml_docbook_book(fnh) path_and_file(fn,'docbook') end def xml_sax fn=@md.file.base_filename.xml_sax(fnh) path_and_file(fn,'xml_sax') end def xml_dom fn=@md.file.base_filename.xml_dom(fnh) path_and_file(fn,'xml_dom') end def txt fn=@md.file.base_filename.txt(fnh) path_and_file(fn,'txt') end def digest fn=@md.file.base_filename.hash_digest(fnh) path_and_file(fn,'digest') end def source @base_path + '/src/' + @src end def sisupod @base_path + '/src/' + @src + '.zip' end self end def by_filetype(linked_doc,lng,src=nil) @linked_doc,@lng,@src=linked_doc,lng,src @lc=SiSU_Env::FilenameLanguageCodeInsert.new(@md.opt,lng). language_code_insert @base_path="#{@md.file.output_path.base.url}" def fnh { fn: @linked_doc, lng: @lc, } end def path_and_file(fn,pth) @base_path + '/' + pth + '/' + fn end def manifest fn=@md.file.base_filename.manifest(fnh) path_and_file(fn,'manifest') end def html_toc fn=@md.file.base_filename.html_segtoc(fnh) path_and_file(fn,'html') end def html_doc fn=@md.file.base_filename.html_scroll(fnh) path_and_file(fn,'html') end def html_concordance fn=@md.file.base_filename.html_concordance path_and_file(fn,'html') end def epub fn=@md.file.base_filename.epub(fnh) path_and_file(fn,'epub') end def pdf_landscape fn=@md.file.base_filename.pdf_l_a4(fnh) path_and_file(fn,'pdf') end def pdf_portrait fn=@md.file.base_filename.pdf_p_a4(fnh) path_and_file(fn,'pdf') end def odt fn=@md.file.base_filename.odt(fnh) path_and_file(fn,'odt') end def xhtml fn=@md.file.base_filename.xhtml(fnh) path_and_file(fn,'xhtml') end def docbook fn=@md.file.base_filename.xml_docbook_book(fnh) path_and_file(fn,'docbook') end def xml_sax fn=@md.file.base_filename.xml_sax(fnh) path_and_file(fn,'xml_sax') end def xml_dom fn=@md.file.base_filename.xml_dom(fnh) path_and_file(fn,'xml_dom') end def txt fn=@md.file.base_filename.txt(fnh) path_and_file(fn,'txt') end def digest fn=@md.file.base_filename.hash_digest(fnh) path_and_file(fn,'digest') end def source @base_path + '/src/' + @src end def sisupod @base_path + '/src/' + @src + '.zip' end self end def by_filename(linked_doc,lng,src=nil) @linked_doc,@lng,@src=linked_doc,lng,src @lc=SiSU_Env::FilenameLanguageCodeInsert.new(@md.opt,lng).language_code_insert @base_path="#{@md.file.output_path.base.url}/#{@linked_doc}" def fnh { fn: @linked_doc, lng: @lc, } end def path_and_file(fn,pth=nil) (pth.nil?) \ ? @base_path + '/' + fn : @base_path + '/' + pth + '/' + fn end def manifest fn=@md.file.base_filename.manifest(fnh) path_and_file(fn) end def html_toc fn=@md.file.base_filename.html_segtoc(fnh) path_and_file(fn) end def html_doc fn=@md.file.base_filename.html_scroll(fnh) path_and_file(fn) end def html_concordance fn=@md.file.base_filename.html_concordance path_and_file(fn) end def epub fn=@md.file.base_filename.epub(fnh) path_and_file(fn,'epub') end def pdf_landscape fn=@md.file.base_filename.pdf_l_a4(fnh) path_and_file(fn) end def pdf_portrait fn=@md.file.base_filename.pdf_p_a4(fnh) path_and_file(fn) end def odt fn=@md.file.base_filename.odt(fnh) path_and_file(fn) end def xhtml fn=@md.file.base_filename.xhtml(fnh) path_and_file(fn) end def docbook fn=@md.file.base_filename.xml_docbook_book(fnh) path_and_file(fn) end def xml_sax fn=@md.file.base_filename.xml_sax(fnh) path_and_file(fn) end def xml_dom fn=@md.file.base_filename.xml_dom(fnh) path_and_file(fn) end def txt fn=@md.file.base_filename.txt(fnh) path_and_file(fn) end def digest fn=@md.file.base_filename.hash_digest(fnh) path_and_file(fn) end def source @base_path + '/' + @src end def sisupod @base_path + '/' + @src + '.zip' end self end def expand_insertions? data=@data tuned_file,tuned_file_tmp=[],[] codeblock_={ status: :false, type: :na, } data.each do |para| codeblock_=if para =~/^code(?:\.[a-z][0-9a-z_]+)?\{/ \ and codeblock_[:status]==:false { status: :true, type: :curl, } elsif para =~/^```[ ]+code(?:\.[a-z][0-9a-z_]+)?/ \ and codeblock_[:status]==:false { status: :true, type: :tics, } elsif codeblock_[:type]==:curl \ and para =~/^\}code/m { status: :false, type: :na, } elsif codeblock_[:type]==:tics \ and para =~/^```(?:\s|$)/m { status: :false, type: :na, } else codeblock_ end if para !~/^%+\s/ \ and codeblock_[:status] != :true \ and para =~/\{(?:~\^\s+)?(.+?)\s\[(?:\d(?:[sS]*))\]\}(?:\.\.\/\S+?\/|\S+?\.ss[tm]\b)/ @u=SiSU_Env::InfoEnv.new.url m_cmd='' if defined? @u.remote if /(?<m_pre>.+?)\{(?<m_txt>.+?)\s\[(?<m_cmd>\d[sS]*)\]\}(?<m_source>(?<m_linked_doc>\S+?)\.ss[tm]\b)(?<m_note>.*)/m =~ para m_pre=m_pre.strip elsif /\{(?<m_txt>.+?)\s\[(?<m_cmd>\d[sS]*)\]\}(?<m_source>(?<m_linked_doc>\S+?)\.ss[tm]\b)(?<m_note>.*)/m =~ para end if m_linked_doc =~ /(\S+?)\/(\S+)/ m_linked_doc,m_linked_doc_lang=$1,$2 else m_linked_doc,m_linked_doc_lang=m_linked_doc,@md.opt.lng_base end else puts "error, does currently support relative paths (reltive paths were removed, as had problems for citation, and was not suited to all output types should possibly reconsider) #{__FILE__} #{__LINE__}" if /\{(?:~\^\s+)?(?<m_txt>.+?)\s\[(?<m_cmd>\d[sS]*)\]\}\.\.\/(?<m_linked_doc>\S+?)\/(?<m_note>\s+#{Mx[:en_a_o]}.+?#{Mx[:en_a_c]})?/ =~ para end end lnk=case @md.opt.dir_structure_by when :language { manifest: by_language(m_linked_doc,m_linked_doc_lang).manifest, html_toc: by_language(m_linked_doc,m_linked_doc_lang).html_toc, html_doc: by_language(m_linked_doc,m_linked_doc_lang).html_doc, epub: by_language(m_linked_doc,m_linked_doc_lang).epub, pdf_landscape: by_language(m_linked_doc,m_linked_doc_lang).pdf_landscape, pdf_portrait: by_language(m_linked_doc,m_linked_doc_lang).pdf_landscape, odt: by_language(m_linked_doc,m_linked_doc_lang).odt, xhtml: by_language(m_linked_doc,m_linked_doc_lang).xhtml, docbook: by_language(m_linked_doc,m_linked_doc_lang).docbook, xml_sax: by_language(m_linked_doc,m_linked_doc_lang).xml_sax, xml_dom: by_language(m_linked_doc,m_linked_doc_lang).xml_dom, txt: by_language(m_linked_doc,m_linked_doc_lang).txt, html_concordance: by_language(m_linked_doc,m_linked_doc_lang).html_concordance, digest: by_language(m_linked_doc,m_linked_doc_lang).digest, sisupod: by_language(m_linked_doc,m_linked_doc_lang,m_source).sisupod, source: by_language(m_linked_doc,m_linked_doc_lang,m_source).source, } when :filetype { manifest: by_filetype(m_linked_doc,m_linked_doc_lang).manifest, html_toc: by_filetype(m_linked_doc,m_linked_doc_lang).html_toc, html_doc: by_filetype(m_linked_doc,m_linked_doc_lang).html_doc, epub: by_filetype(m_linked_doc,m_linked_doc_lang).epub, pdf_landscape: by_filetype(m_linked_doc,m_linked_doc_lang).pdf_landscape, pdf_portrait: by_filetype(m_linked_doc,m_linked_doc_lang).pdf_landscape, odt: by_filetype(m_linked_doc,m_linked_doc_lang).odt, xhtml: by_filetype(m_linked_doc,m_linked_doc_lang).xhtml, docbook: by_filetype(m_linked_doc,m_linked_doc_lang).docbook, xml_sax: by_filetype(m_linked_doc,m_linked_doc_lang).xml_sax, xml_dom: by_filetype(m_linked_doc,m_linked_doc_lang).xml_dom, txt: by_filetype(m_linked_doc,m_linked_doc_lang).txt, html_concordance: by_filetype(m_linked_doc,m_linked_doc_lang).html_concordance, digest: by_filetype(m_linked_doc,m_linked_doc_lang).digest, sisupod: by_filetype(m_linked_doc,m_linked_doc_lang,m_source).sisupod, source: by_filetype(m_linked_doc,m_linked_doc_lang,m_source).source, } else { manifest: by_filename(m_linked_doc,m_linked_doc_lang).manifest, html_toc: by_filename(m_linked_doc,m_linked_doc_lang).html_toc, html_doc: by_filename(m_linked_doc,m_linked_doc_lang).html_doc, epub: by_filename(m_linked_doc,m_linked_doc_lang).epub, pdf_landscape: by_filename(m_linked_doc,m_linked_doc_lang).pdf_landscape, pdf_portrait: by_filename(m_linked_doc,m_linked_doc_lang).pdf_landscape, odt: by_filename(m_linked_doc,m_linked_doc_lang).odt, xhtml: by_filename(m_linked_doc,m_linked_doc_lang).xhtml, docbook: by_filename(m_linked_doc,m_linked_doc_lang).docbook, xml_sax: by_filename(m_linked_doc,m_linked_doc_lang).xml_sax, xml_dom: by_filename(m_linked_doc,m_linked_doc_lang).xml_dom, txt: by_filename(m_linked_doc,m_linked_doc_lang).txt, html_concordance: by_filename(m_linked_doc,m_linked_doc_lang).html_concordance, digest: by_filename(m_linked_doc,m_linked_doc_lang).digest, sisupod: by_filename(m_linked_doc,m_linked_doc_lang,m_source).sisupod, source: by_filename(m_linked_doc,m_linked_doc_lang,m_source).source, } end linked_title="#{m_pre}{#{m_txt} }#{lnk[:manifest]}#{m_note}\n\n" tuned_file_tmp << linked_title output_filetypes=output_filetypes_in_cmd(m_cmd,lnk) output_filetypes[:gen].each do |desc| if desc tuned_file_tmp << if @u.remote "#{Mx[:nbsp]*4} #{desc} " else # remove ... "[provide document placement host location]" end end end output_filetypes[:src].each do |desc| if desc tuned_file_tmp << if @u.remote "#{Mx[:nbsp]*4} #{desc} " else "[provide document placement host location]" end end end tuned_file << 'group{' << tuned_file_tmp.join("\n") << '}group' tuned_file_tmp=[] else tuned_file << para end end tuned_file end end end __END__ #+END_SRC ** ao_hash_digest.rb #+HEADER: :tangle "../lib/sisu/ao_hash_digest.rb" #+BEGIN_SRC ruby #<<sisu_document_header>> module SiSU_AO_Hash require_relative 'shared_markup_alt.rb' #shared_markup_alt.rb class ObjectDigest def initialize(md,data,env=nil) @md,@data,@env=md,data,env @env ||=SiSU_Env::InfoEnv.new(@md.fns,@md) end def object_digest # 1. clean/stripped text without any markup, paragraph, headings etc. without endnotes # 2. endnotes clean/stripped text digest only (there may be several endnotes within a paragraph) # 3. whole object, text with markup and any endnotes, (question: with or without the endnote digests??? presumption better without, [however may be easier to check with?]) # [digests should not include other digests] data=@data.compact @tuned_file=[] sha_ =@env.digest(@md.opt).type begin sha_ ? (require 'digest/sha2') : (require 'digest/md5') rescue LoadError SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia).error(sha_ + ' NOT FOUND') end data.each do |t_o| unless t_o.obj.is_a?(Array) t_o.obj=t_o.obj.strip end if (t_o.of !=:structure \ && t_o.of !=:comment \ && t_o.of !=:layout) \ && t_o.ocn.is_a?(Fixnum) case sha_ when :sha512 for hash_class in [ Digest::SHA512 ] @tuned_file << stamped(t_o,hash_class) end when :sha256 for hash_class in [ Digest::SHA256 ] @tuned_file << stamped(t_o,hash_class) end when :md5 for hash_class in [ Digest::MD5 ] @tuned_file << stamped(t_o,hash_class) end end else @tuned_file << t_o unless t_o.nil? end end @tuned_file=@tuned_file.flatten #use md5 or to create hash of each ao object including ocn, & add into to each ao object end def endnote_digest(data) data.each.map do |en_plus| case en_plus when /#{Mx[:en_a_o]}|#{Mx[:en_b_o]}/ if en_plus =~/#{Mx[:en_a_o]}.+?#{Mx[:en_a_c]}|#{Mx[:en_b_o]}.+?#{Mx[:en_b_c]}/ t_o_txt,en_open,en_txt,en_close= /(.*?)(#{Mx[:en_a_o]}|#{Mx[:en_b_o]})(.+?)(#{Mx[:en_a_c]}|#{Mx[:en_b_c]})/m. match(en_plus)[1..4] stripped_en=SiSU_TextRepresentation::Alter.new(en_txt).strip_clean_of_markup digest_en_strip=case @env.digest(@md.opt).type when :sha512 Digest::SHA512.hexdigest(stripped_en) when :sha256 Digest::SHA256.hexdigest(stripped_en) when :md5 Digest::MD5.hexdigest(stripped_en) else Digest::SHA256.hexdigest(stripped_en) end t_o_txt + en_open + en_txt + Mx[:id_o] + digest_en_strip + Mx[:id_c] + en_close else STDERR.puts "Error Exception - problem encountered with:\n#{en_plus}" #arbitrary exception, tidy up end else en_plus end end.join end def stamped(t_o,hash_class) #decide what hash information is most useful, is compromise necessary? t_o.obj=SiSU_TextRepresentation::Alter.new(t_o).strip_clean_of_extra_spaces #SiSU_TextRepresentation::Alter.new(t_o).strip_clean_of_markup #check #SiSU_TextRepresentation::Alter.new(t_o).semi_revert_markup #check #SiSU_TextRepresentation::ModifiedTextPlusHashDigest.new(@md,t_o).composite.dgst #check unless t_o.is==:code case t_o.obj when /#{Mx[:en_a_o]}[\d*+]+\s+.+?#{Mx[:en_a_c]}|#{Mx[:en_b_o]}[*+]\d+\s+.+?#{Mx[:en_b_c]}/m en_and_t_o_digest=[] t_o.obj=t_o.obj. gsub(/\s*(#{Mx[:en_a_c]}|#{Mx[:en_b_c]})/m,' \1') #watch t_o_plus_en=t_o.obj. scan(/.*?#{Mx[:en_a_o]}.+?#{Mx[:en_a_c]}|.*?#{Mx[:en_b_o]}.+?#{Mx[:en_b_c]}/m) t_o_tail=if t_o.obj =~/(?:.*?#{Mx[:en_a_o]}.+?#{Mx[:en_a_c]}|.*?#{Mx[:en_b_o]}.+?#{Mx[:en_b_c]})+([\s\S]+)/m /(?:.*?#{Mx[:en_a_o]}.+?#{Mx[:en_a_c]}|.*?#{Mx[:en_b_o]}.+?#{Mx[:en_b_c]})+.*/m.match(t_o.obj)[1] else '' end t_o_plus_en << t_o_tail en_and_t_o_digest << endnote_digest(t_o_plus_en) en_and_t_o_digest.join(' ') else #@tuned << t_o + Mx[:id_o] + digest_strip + ':' + digest_all + Mx[:id_c] unless t_o.nil? end else #@tuned << t_o + Mx[:id_o] + digest_strip + ':' + digest_all + Mx[:id_c] unless t_o.nil? end t_o #KEEP intact end def strip_clean_extra_spaces(s) # ao output tuned s=s.dup s=s.gsub(/[ ]+([,.;:?](?:$|\s))/,'\1') unless s =~/#{Mx[:en_a_o]}|#{Mx[:en_b_o]}/ s=s.gsub(/ [ ]+/,' '). gsub(/^ [ ]+/,''). gsub(/ [ ]+$/,''). gsub(/((?:#{Mx[:fa_bold_c]}|#{Mx[:fa_italics_c]})')[ ]+(s )/,'\1\2'). gsub(/((?:#{Mx[:fa_bold_c]}|#{Mx[:fa_italics_c]})')[ ]+(s )/,'\1\2') end end end __END__ #+END_SRC ** ao_idx.rb #+HEADER: :tangle "../lib/sisu/ao_idx.rb" #+BEGIN_SRC ruby #<<sisu_document_header>> module SiSU_AO_BookIndex class BookIndex def initialize(md,data,env=nil) @md,@data,@env=md,data,env @rgx_idx=/#{Mx[:idx_o]}(?:.+?)#{Mx[:idx_c]}\s*/ @rgx_idx_ocn_seg=/(.+?)~(\d+)~(\S+)/ @rgx_idx_ocn=/(.+?)~(\d+)/ @env ||=SiSU_Env::InfoEnv.new(@md.fns) end def indexing_song data=@data data, sisu_markup_idx_rel, sisu_markup_idx_rel_html_seg, html_idx,xhtml_idx= extract_book_index(data) data= clean_and_insert_index( data, sisu_markup_idx_rel_html_seg ) [ data, sisu_markup_idx_rel, sisu_markup_idx_rel_html_seg, html_idx, xhtml_idx, ] end def extract_book_index(data) tuned_file=[] idx_array=[] data.each do |dob| if (dob.is ==:heading \ || dob.is ==:heading_insert) \ && dob.ln==4 @seg=dob.name end if defined? dob.idx \ and dob.idx.is_a?(Hash) idx_array << { idx: dob.idx, ocn: dob.ocn, seg: @seg } end tuned_file << dob if dob end if idx_array.length > 0 the_idx=construct_book_index(idx_array) if @md.book_idx idx=index(the_idx) sisu_markup_idx_rel,sisu_markup_idx_rel_html_seg,html_idx, xhtml_idx= idx[:sst_rel], idx[:sst_rel_html_seg], idx[:html],idx[:xhtml] else sisu_markup_idx_rel= sisu_markup_idx_rel_html_seg= html_idx= xhtml_idx= nil end end [ tuned_file, sisu_markup_idx_rel, sisu_markup_idx_rel_html_seg, html_idx, xhtml_idx, ] end def construct_book_index(idx_array) the_idx={} idx_array.each do |idx| idx[:idx].each_pair do |term,term_info| location=(term_info[:plus].to_i > 0) \ ? (%{#{idx[:ocn]}-#{idx[:ocn].to_i + term_info[:plus].to_i}}) : idx[:ocn].to_s the_idx[term]={} \ unless the_idx[term] \ and defined? the_idx[term] the_idx[term]['node_0_terms']=[] \ unless the_idx[term]['node_0_terms'] \ and defined? the_idx[term]['node_0_terms'] the_idx[term]['node_0_terms'] << { ocn: idx[:ocn], range: location, seg: idx[:seg] } if term_info[:sub].is_a?(Array) \ and term_info[:sub].length > 0 term_info[:sub].each do |y| y.each_pair do |subterm,subterm_info| location=(subterm_info[:plus].to_i > 0) \ ? (%{#{idx[:ocn]}-#{idx[:ocn].to_i + subterm_info[:plus].to_i}}) : idx[:ocn].to_s the_idx[term]={} \ unless the_idx[term] \ and defined? the_idx[term] the_idx[term]['node_0_terms']=[] \ unless the_idx[term]['node_0_terms']\ and defined? the_idx[term]['node_0_terms'] the_idx[term]['node_1_subterms']={} \ unless the_idx[term]['node_1_subterms'] \ and defined? the_idx[term]['node_1_subterms'] the_idx[term]['node_1_subterms'][subterm]=[] \ unless the_idx[term]['node_1_subterms'][subterm] \ and defined? the_idx[term]['node_1_subterms'][subterm] the_idx[term]['node_1_subterms'][subterm] << { ocn: idx[:ocn], range: location, seg: idx[:seg] } end end end end end the_idx=the_idx.sort the_idx end def clean_xml(str) str=str.gsub(/&/,'&') str end def index(the_idx) @x=1 idx={} idx[:sst_rel_html_seg],idx[:sst_rel],idx[:html],idx[:xhtml]= [], [], [], [] h={ obj: Mx[:br_page] } o=SiSU_AO_DocumentStructure::ObjectLayout.new.break(h) idx[:sst_rel_html_seg] << o idx[:sst_rel] << o h={ lv: '1', name: 'index', obj: "Index" } o=SiSU_AO_DocumentStructure::ObjectHeading.new.heading(h) idx[:sst_rel_html_seg] << o idx[:sst_rel] << o h={ lv: '4', name: 'idx', obj: " [Index] #{Mx[:pa_non_object_dummy_heading]}" } o=SiSU_AO_DocumentStructure::ObjectHeading.new.heading(h) idx[:sst_rel_html_seg] << o idx[:sst_rel] << o alph=%W[9 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z] idx[:html] << '<p>' idx[:xhtml] << '<p>' alph.each do |x| if x =~/[0-9]/ idx[:html] << '' idx[:xhtml] << '' else idx[:html] << %{<a href="##{x}">#{x}</a>,#{$ep[:hsp]}} idx[:xhtml] << %{<a href="##{x.downcase}">#{x}</a>,#{$ep[:hsp]}} end end idx[:html] << '</p>' idx[:xhtml] << '</p>' letter=alph.shift idx[:html] << %{\n<p class="book_index_lev1"><a name="numeral"></a></p>} idx[:xhtml] << %{\n<p class="letter" id="numeral">0 - 9</p>} the_idx.each do |i| i.each do |x| if x.is_a?(String) f=/^(\S)/.match(x)[1] if letter < f while letter < f if alph.length > 0 letter=alph.shift idx[:html] << %{\n<p class="letter"><a name="#{letter}">#{letter}</a></p><p class="book_index_lev1"><a name="#{letter.downcase}"> </a></p>} idx[:xhtml] << %{\n<p class="letter" id="#{letter.downcase}">#{letter}</p>} else break end end end idx[:sst_rel_html_seg] << %{\n\n#{Mx[:fa_bold_o]}#{x},#{Mx[:fa_bold_c]} } idx[:sst_rel] << %{\n\n#{Mx[:fa_bold_o]}#{x},#{Mx[:fa_bold_c]} } aname=x.gsub(/\s+/,'_') idx[:html] << %{\n<p class="book_index_lev1"><a name="#{aname}"><b>#{x}</b></a>, } c=clean_xml(x.dup) idx[:xhtml] << %{\n<p class="book_index_lev1"><b>#{c}</b>, } @o=idx[:sst_rel_html_seg].index(idx[:sst_rel_html_seg].last) @t=idx[:sst_rel].index(idx[:sst_rel].last) @q=idx[:html].index(idx[:html].last) @r=idx[:xhtml].index(idx[:xhtml].last) print "\n" + x + ', ' if @md.opt.act[:verbose_plus][:set]==:on elsif x.is_a?(Array) p 'array error? -->' print x elsif x.is_a?(Hash) if x['node_0_terms'].is_a?(Array) x['node_0_terms'].each do |a| if a[:range] idx[:sst_rel_html_seg][@o]= idx[:sst_rel_html_seg][@o] + %{#{Mx[:lnk_o]}#{a[:range]}#{Mx[:lnk_c]}#{Mx[:rel_o]}/#{a[:seg]}.html##{a[:ocn]}#{Mx[:rel_c]}, } idx[:sst_rel][@t]= idx[:sst_rel][@t] + %{#{Mx[:lnk_o]}#{a[:range]}#{Mx[:lnk_c]}#{Mx[:rel_o]}#{a[:ocn]}#{Mx[:rel_c]}, } idx[:html][@q]= idx[:html][@q] + %{<a href="#{a[:seg]}.html##{a[:ocn]}">#{a[:range]}</a>, } idx[:xhtml][@q]= idx[:xhtml][@q] + %{<a href="#{a[:seg]}.xhtml#o#{a[:ocn]}">#{a[:range]}</a>, } print a[:range] + ', ' if @md.opt.act[:verbose_plus][:set]==:on elsif a[:ocn] idx[:sst_rel_html_seg][@o]= idx[:sst_rel_html_seg][@o] + %{#{Mx[:lnk_o]}#{a[:ocn]}#{Mx[:lnk_c]}#{Mx[:rel_o]}#{a[:seg]}.html##{a[:ocn]}#{Mx[:rel_c]}, } idx[:sst_rel][@t]= idx[:sst_rel][@t] + %{#{Mx[:lnk_o]}#{a[:ocn]}#{Mx[:lnk_c]}#{Mx[:rel_o]}#{a[:ocn]}#{Mx[:rel_c]}, } idx[:html][@q]= idx[:html][@q] + %{<a href="#{a[:seg]}.html##{a[:ocn]}">#{a[:ocn]}</a>, } idx[:xhtml][@q]= idx[:xhtml][@q] + %{<a href="#{a[:seg]}.xhtml#o#{a[:ocn]}">#{a[:ocn]}</a>, } print a[:ocn] + ', ' if @md.opt.act[:verbose_plus][:set]==:on else p 'error' end end idx[:html][@q]=idx[:html][@q] + '</p>' idx[:xhtml][@r]=idx[:xhtml][@r] + '</p>' end if x['node_1_subterms'] x['node_1_subterms'].sort.each do |k,y| if k !~/node_0_terms/ idx[:sst_rel_html_seg][@o]= idx[:sst_rel_html_seg][@o] + %{#{k}, } idx[:sst_rel][@t]= idx[:sst_rel][@t] + %{#{k}, } idx[:html][@q]= idx[:html][@q] + %{\n<p class="book_index_lev2">#{k}, } c=clean_xml(k.dup) idx[:xhtml][@r]= idx[:xhtml][@r] + %{\n<p class="book_index_lev2">#{c}, } print "\n\t" + k + ', ' if @md.opt.act[:verbose_plus][:set]==:on y.each do |z| if z[:range] idx[:sst_rel_html_seg][@o]= idx[:sst_rel_html_seg][@o] + %{#{Mx[:lnk_o]}#{z[:range]}#{Mx[:lnk_c]}#{Mx[:rel_o]}#{z[:seg]}.html##{z[:ocn]}#{Mx[:rel_c]}, } idx[:sst_rel][@t]= idx[:sst_rel][@t] + %{#{Mx[:lnk_o]}#{z[:range]}#{Mx[:lnk_c]}#{Mx[:rel_o]}#{z[:ocn]}#{Mx[:rel_c]}, } idx[:html][@q]= idx[:html][@q] + %{<a href="#{z[:seg]}.html##{z[:ocn]}">#{z[:range]}</a>, } idx[:xhtml][@q]= idx[:xhtml][@q] + %{<a href="#{z[:seg]}.xhtml#o#{z[:ocn]}">#{z[:range]}</a>, } print z[:range] + ', ' if @md.opt.act[:verbose_plus][:set]==:on elsif z[:ocn] idx[:sst_rel_html_seg][@o]= idx[:sst_rel_html_seg][@o] + %{#{Mx[:lnk_o]}#{z[:ocn]}#{Mx[:lnk_c]}#{Mx[:rel_o]}#{z[:seg]}.html##{z[:ocn]}#{Mx[:rel_c]}, } idx[:sst_rel][@t]= idx[:sst_rel][@t] + %{#{Mx[:lnk_o]}#{z[:ocn]}#{Mx[:lnk_c]}#{Mx[:rel_o]}#{z[:ocn]}#{Mx[:rel_c]}, } idx[:html][@q]= idx[:html][@q] + %{<a href="#{z[:seg]}.html##{z[:ocn]}">#{z[:ocn]}</a>, } idx[:xhtml][@q]= idx[:xhtml][@q] + %{<a href="#{z[:seg]}.xhtml#o#{z[:ocn]}">#{z[:ocn]}</a>, } print z[:ocn] + ', ' if @md.opt.act[:verbose_plus][:set]==:on else p 'error' end end idx[:html][@q]=idx[:html][@q] + '</p>' idx[:xhtml][@r]=idx[:xhtml][@r] + '</p>' end end end @x +=1 end end end print "\n" if @md.opt.act[:verbose_plus][:set]==:on idx end def screen_print(the_idx) the_idx.each do |i| i.each do |x| if x.is_a?(String) print "\n" + x + ', ' elsif x.is_a?(Array) p 'array error? -->' print x elsif x.is_a?(Hash) if x['node_0_terms'].is_a?(Array) x['node_0_terms'].each do |a| if a[:range] print a[:range] + ', ' elsif a[:ocn] print a[:ocn] + ', ' else p 'error' end end end if x['node_1_subterms'] x['node_1_subterms'].sort.each do |k,y| if k !~/node_0_terms/ print "\n\t" + k + ', ' y.each do |z| if z[:range] print z[:range] + ', ' elsif z[:ocn] print z[:ocn] + ', ' else p 'error' end end end end end end end end end def output_idx(idx) if @md.book_idx path="#{@env.path.output}/#{@md.fnb}" Dir.mkdir(path) unless FileTest.directory?(path) puts "#{path}/#{@md.fn[:book_idx_html]} #{__FILE__}::#{__LINE__}" html_index_file=File.new("#{path}/#{@md.fn[:book_idx_html]}",'w') idx[:html].each {|x| html_index_file << x } html_index_file.close end end def clean_and_insert_index(data,sisu_markup_idx) tuned_file=[] data.each do |dob| tuned_file << dob if dob.obj =~/#{Mx[:br_endnotes]}/ \ and sisu_markup_idx sisu_markup_idx.each do |idx| tuned_file << idx end end end tuned_file end def clean_index(data) #check on use of dob data.each.map do |para| para.gsub(/\n*#{@rgx_idx}/m,'') end end end end __END__ #+END_SRC ** ao_images.rb #+HEADER: :tangle "../lib/sisu/ao_images.rb" #+BEGIN_SRC ruby #<<sisu_document_header>> module SiSU_AO_Images class Images begin require 'rmagick' include Magick rescue LoadError #SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia).mark('rmagic NOT FOUND') end def initialize(md,data) @md,@data=md,data end def images data=@data @rmgk=false imagemagick_=true #imagemagick_=SiSU_Env::InfoSettings.new.program?('rmagick') if imagemagick_ begin @rmgk=SiSU_Env::Load.new('rmagick').prog rescue @rmgk=false end else if (@md.opt.act[:verbose_plus][:set]==:on \ || @md.opt.act[:maintenance][:set]==:on) SiSU_Screen::Ansi.new( @md.opt.act[:color_state][:set], '*WARN* use of rmagick is not enabled in sisurc.yml' ).warn end end data.select do |dob| unless dob.is ==:table dob.obj=dob.obj.strip if dob.obj =~/#{Mx[:lnk_o]}\s*\S+\.(?:png|jpg|gif)(?:\s*|\s+.+)?#{Mx[:lnk_c]}(?:#{Mx[:url_o]}\S+?#{Mx[:url_c]}|image)/ if dob.obj !~/#{Mx[:lnk_o]}\s*\S+\.(?:png|jpg|gif)\s+\d+x\d+/ m=/#{Mx[:lnk_o]}\s*(\S+\.(?:png|jpg|gif))/ if imagemagick_ imgs=dob.obj.scan(m).flatten img_col=img_row=nil images=imgs.each do |image| dir=SiSU_Env::InfoEnv.new(@md.fns) path_image=[ dir.path.image_source_include_local, dir.path.image_source_include_remote, dir.path.image_source_include ] image_path=nil path_image.each do |img_pth| image_path=img_pth break if FileTest.exist?("#{img_pth}/#{image}") end if FileTest.exist?("#{image_path}/#{image}") if @rmgk img=Magick::ImageList.new("#{image_path}/#{image}") img_col,img_row=img.columns,img.rows else if (@md.opt.act[:verbose_plus][:set]==:on \ || @md.opt.act[:maintenance][:set]==:on) SiSU_Screen::Ansi.new( @md.opt.act[:color_state][:set], '*WARN* rmagick not present, will attempt to use imagemagick (identify) directly' ).warn end imgk=SiSU_Env::SystemCall.new.imagemagick gmgk=SiSU_Env::SystemCall.new.graphicsmagick if imgk or gmgk if imgk imgsys=`identify #{image_path}/#{image}`.strip #system call elsif gmgk imgsys=`gm identify #{image_path}/#{image}`.strip #system call end img_col,img_row=/(\d+)x(\d+)/m.match(imgsys)[1,2] img_col,img_row=img_col.to_i,img_row.to_i else errmsg='imagemagick or graphicsmagick are required to process images' if @md.opt.act[:no_stop][:set]==:on SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia). error("#{errmsg}, proceeding (as requested) without image processing") break else SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia). error("#{errmsg}, STOPPING") exit end end end row=((img && defined? img.rows) ? img.rows : img_row) col=((img && defined? img.columns) ? img.columns : img_col) if img_col > img_row #landscape if img_col> 640 img_col=640 img_row=((1.00*img_col/col)*row).round end else #portrait if img_col> 640 img_col=640 img_row=((1.00*img_col/col)*row).round end if img_row > 640 img_row=640 img_col=((1.00*img_row/row)*col).round end end dob.obj=dob.obj.gsub(/(#{image})/,"#{image} #{img_col}x#{img_row}") else dob.obj=dob.obj. gsub(/#{Mx[:lnk_o]}\s*(\S+)\.(png|jpg|gif).+?#{Mx[:lnk_c]}(#{Mx[:url_o]}\S+?#{Mx[:url_c]}|image)/, '[ \1 (\2 missing) ]') end end else images=dob.obj.scan(m) do |image| SiSU_Screen::Ansi.new( @md.opt.act[:color_state][:set], '*WARN* where image dimensions have not been provided rmagick or imagemagick is required',image ).warn unless @md.opt.act[:quiet][:set]==:on end end end end if dob.obj =~/#{Mx[:lnk_o]}\s*\S+\.(?:png|jpg|gif).+?#{Mx[:lnk_c]}(?:#{Mx[:url_o]}\S+?#{Mx[:url_c]}|image)/ dob.obj=dob.obj.gsub(/(#{Mx[:lnk_o]})\s*(\S+\.(?:png|jpg|gif))\s+/i,'\1\2 ') end end dob unless dob.nil? end end end end __END__ imgsys=`identify #{image_path}/#{image}`.strip #+END_SRC ** ao_metadata.rb #+HEADER: :tangle "../lib/sisu/ao_metadata.rb" #+BEGIN_SRC ruby #<<sisu_document_header>> module SiSU_AO_Metadata class Metadata def initialize(md,metad) @md,@metadata=md,metad l=SiSU_Env::StandardiseLanguage.new(@md.opt.lng).language language=l[:n] @tr=SiSU_Translate::Source.new(md,language) end def make_para(obj,ocn) h={ obj: obj, ocn: 0 } SiSU_AO_DocumentStructure::ObjectPara.new.paragraph(h) end def make_heading(obj,ocn,name,lv,ln) h={ lv: lv, ln: ln, name: name, obj: obj, ocn: 0 } SiSU_AO_DocumentStructure::ObjectHeading.new.heading(h) end def metadata end end end __END__ #+END_SRC ** ao_misc_arrange.rb #+HEADER: :tangle "../lib/sisu/ao_misc_arrange.rb" #+BEGIN_SRC ruby #<<sisu_document_header>> module SiSU_AO_MiscArrangeText class SI def initialize(md,data) @md,@data=md,data end def conditional_headings(para) para=para.gsub(/^(:?A~)\s*$/,'\1~ @title @author'). #conditional header gsub(/^((?:[1-9]|:?[A-D])~\S*)\s*$/, '\1~ [Note: heading marker::required title missing]~#') #conditional header for incorporated document 2004w12 if para =~/^@\S+?:/ para=para.gsub(/^@(\S+?):(\s+|$)/, "#{Mx[:meta_o]}\\1#{Mx[:meta_c]}\\2"). gsub(/^@(\S+?):([+-])(\s+|$)/, "#{Mx[:meta_o]}\\1\\2#{Mx[:meta_c]}\\3") end para end def markup_blocks(para) def ticks(para) block_open,block_close,text=nil,nil,nil if para =~/\A```[ ]+(?:code(?:\.[a-z][0-9a-z_]+)?|box(?:\.[a-z_]+)?|poem|alt|group|block|table).*?\n.+?\n```(?:\s+[~-][#]|\s+\~\{.+?\}\~)?\s*\Z/m @flag=:close block_open,text,block_close= /\A(```[ ]+(?:code(?:\.[a-z][0-9a-z_]+)?|box(?:\.[a-z_]+)?|poem|alt|group|block|table).*?)\n(.+?)\n(```([ ]+[~-][#]|\s+\~\{.+?\}\~)?)\s*\Z/m. match(para)[1..3] ((para=~/^```[ ]+table(?:~h)?\s+/) \ and (para !~/^```[ ]+table(?:~h)?\s+c\d+/)) \ ? para : (para=[]; para << block_open << text << block_close) elsif para =~/\A```[ ]+(?:code(?:\.[a-z][0-9a-z_]+)?|box(?:\.[a-z_]+)?|poem|alt|group|block|table).*?\n.*?\Z/m #look at, study @flag=:open block_open,text=/\A(```(?:[ ]+.+?))\n(.*?)\Z/m.match(para)[1,2] para=[] if not text.to_s.empty? para << block_open << text else para << block_open end elsif para =~/\A.+?\n```(?:\s+\~\{.+?\}\~)?(?:\s+[~-][#])?(\s*=\{.+?\})?\s*\Z/m \ and @flag==:open @flag=:close text,block_close= /\A(.+?)\n(```(?:\s+\~\{.+?\}\~)?(?:\s+[~-][#])?(?:\s+=\{.+?\})?)\s*\Z/m.match(para)[1,2] para=[] if not text.to_s.empty? para << text.to_s << block_close else para << block_close end else para end para end def ticks_remove(para) unless @md.opt.act[:quiet][:set] ==:on SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia). mark("ticks not recognized, ticks removed from pargraph\n#{para}") end para=para.gsub(/```[ ]+\S+[ ]*/m,''). gsub(/```\s*/m,''). strip end def ticks_quote(para) @flag=:quote_open text=para para=[] if text =~ /```[ ]+quote/m para << '`:quote_open`' text=text.gsub(/```[ ]+quote/m,'') end text=if text =~/(?:\n|\A)=\{.+?\}/m #exclude book index from indent markup txt,bkidx,tail=/(.+?)((?:\n|\A)=\{.+?\}$)(.*)/m.match(text).captures txt=txt.gsub(/(?:\n|\A)([^`\n]+)/m,'_1 \1') txt + bkidx + tail else text.gsub(/(?:\n|\A)([^`\n]+)/m,'_1 \1') end para << text.gsub(/```/m,'') if text =~/```/m @flag=:quote_close para << '`:quote_close`' end para end def curly_braces(para) block_open,block_close,text=nil,nil,nil para=if para =~/\A(?:code(?:\.[a-z][0-9a-z_]+)?|box(?:\.[a-z_]+)?|poem|alt|group|block|table)\{ .+?\n.+?\n\}(?:code|box|poem|alt|group|block|table)(?: [~-][#])?\s*\Z/m block_open,text,block_close= /\A((?:code(?:\.[a-z][0-9a-z_]+)?|box(?:\.[a-z_]+)?|poem|alt|group|block|table)\{ .+?)\n(.+?)\n(\}(?:code|box|poem|alt|group|block|table)(?: [~-][#])?)\s*\Z/m. match(para)[1..3] para=[] para << block_open << text << block_close elsif para =~/\A(?:code(?:\.[a-z][0-9a-z_]+)?|box(?:\.[a-z_]+)?|poem|alt|group|block|table)\{ .+?\n.+?\Z/m block_open,text= /\A((?:code(?:\.[a-z][0-9a-z_]+)?|box(?:\.[a-z_]+)?|poem|alt|group|block|table)\{ .+?)\n(.+?)\Z/m. match(para)[1,2] para=[] if not text.to_s.empty? para << block_open << text else para << block_open end elsif para =~/\A.+?\n\}(?:code|box|poem|alt|group|block|table)(?: [~-][#])?\s*\Z/m text,block_close= /\A(.+?)\n(\}(?:code|box|poem|alt|group|block|table)(?: [~-][#])?)\s*\Z/m. match(para)[1,2] para=[] if not text.to_s.empty? para << text.to_s << block_close else para << block_close end else para end para end para=if (para =~/\A```[ ]+quote/m \ and @flag !=:open) \ or @flag==:quote_open ticks_quote(para) elsif para =~/\A```[ ]+(?:code(?:\.[a-z][0-9a-z_]+)?|box(?:\.[a-z_]+)?|poem|alt|group|block|table).*?\n.*?\Z/m \ or @flag==:open ticks(para) elsif para =~/```/m ticks_remove(para) else para end para=if para =~/^(?:code(?:\.[a-z][0-9a-z_]+)?|box(?:\.[a-z_]+)?|poem|alt|group|block|table)\{|^\}(?:code|box|poem|alt|group|block|table)/m curly_braces(para) else para end end def prepare_text data=@data if data[0] =~ /^#!\s*(?:\/usr\/bin\/env sisu|\/usr\/bin\/sisu)/ # remove bang from top #! (however file is stripped, so will be removed provided no content precedes it) data[0]=data[0].gsub(/^#!\s*\/usr\/bin\/sisu/,''). gsub(/^#!\s*\/usr\/bin\/env sisu/,'') end if data[0] =~ /^(SiSU\s+[\d.]*|sisu-[\d.]+)$/ # SiSU identifier data[0]=data[0].gsub(/^(SiSU\s*[\d.]*)$/,'% \1'). gsub(/^(sisu-[\d.]+)$/,'% \1') end data.each.map do |para| para=conditional_headings(para) markup_blocks(para) end.flatten end end end __END__ #+END_SRC ** ao_numbering.rb #+HEADER: :tangle "../lib/sisu/ao_numbering.rb" #+BEGIN_SRC ruby #<<sisu_document_header>> module SiSU_AO_Numbering class Numbering attr_accessor :obj,:osp,:ocn,:lv,:name,:index,:comment @@segments_count=0 def initialize(md,data,fnx,process) @md,@data,@fnx,@process=md,data,fnx,process @obj=@type=@ocn=@lv=@name=@index=@comment=nil @chosen_seg_names=[] end def chosen_seg_names(chosen,chosen_seg_name,dob,md,type) @chosen_seg_names=if chosen.compact.uniq.length \ == chosen.compact.length chosen else if md.opt.act[:maintenance][:set]==:on SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:green). mark( "duplicated auto segment name: #{type} #{chosen}\n" \ + "#{chosen}\n" \ + " manually name level 1 segments '1~given_name'\n" \ + 'filename: ' + md.fns + "\n" \ + 'heading text: "' + dob.obj + '"' + "\n" \ + 'duplication: "' + chosen_seg_name + '" (level: ' + dob.lv + '; numbering type: ' + type.to_s + ')' ) end chosen=chosen[0..-2] chosen_seg_name=auto_numbering_exceptions(chosen,md,dob) chosen << chosen_seg_name end end def number_of_segments? if @@segments_count==0 @data.each do |dob| if dob.is == :heading \ and dob.lv == '1' @@segments_count += 1 end end @@segments_count else @@segments_count end end def numbering_song begin data=@data data=number_plaintext_para(data) data=auto_number_heading_ie_title(data.compact) #tr issue data=ocn(data.compact) #watch data=xml(data.compact) data=minor_numbering(data.compact) if @process==:complete data,tags_map,ocn_html_seg_map=name_para_seg_filename(data) end data=set_heading_top(data) unless @md.set_heading_top [data,tags_map,ocn_html_seg_map] ensure @@segments_count=0 end end def set_tags(tags,tag) tags=if not tag.empty? \ and tag !~/^\d+$/ tag=tag.gsub(/[^a-z0-9._-]/,'') [tag,tags].flatten else tags end end def number_plaintext_para(data) @tuned_file=[] data.each do |dob| if (dob.of !=:block \ && dob.of !=:comment \ && dob.of !=:layout) \ && dob.ocn_ #and dob.obj !~ /#{Mx[:gr_o]}Th|#{Mx[:tc_o]}#{Mx[:tc_p]}#{Mx[:tc_p]}/ #FIX dob.obj=dob.obj.gsub(/(.+)\n/,'\1 ') #messy, but idea is that tables should retain breaks end unless dob.obj.is_a?(Array) dob.obj=dob.obj.gsub(/^\s+/,''). gsub(/\s$/,"\n") end @tuned_file << dob end @tuned_file=@tuned_file.flatten end def number_sub_heading(dob,num,title_no) unless dob.obj =~/\d+\.|(?:chapter|article|section|clause)\s+\d+/i #name selection arbitrary, fix dob.obj=case dob.name when /-/ then dob.obj.gsub(/^/,"#{title_no} ") when /^#/ then dob.obj.gsub(/^/,"#{title_no} ") when /^[a-z_\.]+/ then dob.obj.gsub(/^/,"#{title_no} ") else dob.name=title_no if dob.name=~/^$/ #where title contains title number dob.obj.gsub(/^/,"#{title_no} ") if title_no =~/\d+/ #main, where title number is to be provided #watch changed placement end if @md.toc_lev_limit \ and @md.toc_lev_limit < num dob.obj=dob.obj.gsub(/^/,'!_ ') #bold line, watch end end dob end def heading_tag_clean(heading_tag) heading_tag=heading_tag. gsub(/[ ]+/,'_'). gsub(/["']/,''). gsub(/[\/]/,'-'). gsub(/#{Mx[:fa_bold_o]}|#{Mx[:fa_bold_c]}/,''). gsub(/#{Mx[:fa_italics_o]}|#{Mx[:fa_italics_c]}/,''). gsub(/#{Mx[:fa_underscore_o]}|#{Mx[:fa_underscore_c]}/,''). gsub(/#{Mx[:fa_cite_o]}|#{Mx[:fa_cite_c]}/,''). gsub(/#{Mx[:fa_insert_o]}|#{Mx[:fa_insert_c]}/,''). gsub(/#{Mx[:fa_strike_o]}|#{Mx[:fa_strike_c]}/,''). gsub(/#{Mx[:fa_superscript_o]}|#{Mx[:fa_superscript_c]}/,''). gsub(/#{Mx[:fa_subscript_o]}|#{Mx[:fa_subscript_c]}/,''). gsub(/#{Mx[:fa_hilite_o]}|#{Mx[:fa_hilite_c]}/,''). gsub(/#{Mx[:gl_bullet]}/,'') end def auto_number_heading_ie_title(data) #also does some segment naming if defined? @md.make.num_top \ and @md.make.num_top \ and @md.make.num_top !~/^$/ input||=@md.make.num_top end num_top=(input ? input.to_i : nil) t_no1=t_no2=t_no3=0 if num_top no1=num_top; no2=(num_top + 1); no3=(num_top + 2) end chapter_number_counter=0 data=data.compact @tuned_file=data.each.map do |dob| #@md.seg_names << [additions to segment names] title_no=nil if dob.is ==:heading \ && dob.autonum_ \ and defined? @md.make.num_top \ and @md.make.num_top !~/^$/ if dob.lv=='1' \ and dob.obj =~/^#\s|\s#(?:\s|$)/ chapter_number_counter +=1 dob.obj=dob.obj.gsub(/^#\s/,"#{chapter_number_counter} "). gsub(/#([:,]?\s|[.]?$)/,"#{chapter_number_counter}\\1") end if dob.ln==no1 @subnumber=1 @subnumber=0 if dob.ln==no1 end if dob.ln.to_s =~/^[0-6]/ \ and not dob.use_ ==:dummy \ and dob.obj !~/#{Mx[:fa_o]}(?:~#|-#)#{Mx[:fa_c]}/ # <-- fix if dob.ln==no1 t_no1+=1; t_no2=0; t_no3=0 title_no="#{t_no1}" if @md.seg_names.is_a?(Array) \ and not @md.seg_names.include?(title_no) if dob.ln==no1 dob.name="#{title_no}" if not dob.name dob.tags=set_tags(dob.tags,title_no) tag=dob.obj. gsub(/(Article|Clause|Section|Chapter)\s+/, "\\1_#{title_no}"). downcase tag=heading_tag_clean(tag) dob.tags=set_tags(dob.tags,tag) dob.obj=(dob.obj =~/(Article|Clause|Section)\s+/) \ ? (dob.obj.gsub(/(Article|Clause|Section)\s+/,"\\1 #{title_no} ")) : (dob.obj.gsub(/^/,"#{title_no}. ")) #fix stop later end if dob.ln !=no1 \ and dob.obj =~/^[\d.]+\s/ #fix -> if the title starts with a numbering scheme, do not auto-number, review dob.name ="#{title_no}" if not dob.name dob.tags=set_tags(dob.tags,title_no) dob.obj=dob.obj.gsub(/^/,"#{title_no}. ") end @md.seg_names << title_no end if dob.ln!=no1 \ and dob.name!~/^[a-z_\.]+$/ \ and dob.obj !~/[A-Z]\.?\s/ #bug -> tmp fix, excludes A. B. C. lettering, but not roman numerals, is arbitrary, review required # not fixed, work on dob.tags=set_tags(dob.tags,title_no) dob.obj=dob.obj.gsub(/^/i,"#{title_no}. ") end end if dob.ln==no1 #watch because here you change dob.name dob.tags=set_tags(dob.tags,"h#{title_no}") end if dob.ln==no2 #watch because here you change dob.name t_no2+=1; t_no3=0 title_no="#{t_no1}.#{t_no2}" dob.tags=set_tags(dob.tags,"h#{title_no}") dob=number_sub_heading(dob,no2,title_no) end if dob.ln==no3 #watch because here you change dob.name t_no3+=1 title_no="#{t_no1}.#{t_no2}.#{t_no3}" dob.tags=set_tags(dob.tags,"h#{title_no}") dob=number_sub_heading(dob,no3,title_no) end elsif dob.ln.to_s =~/^[0-6]/ \ and dob.name =~ /^[\w-]+-/ # endnotes, watch2005# endnotes, watch2005 dob.tags=set_tags(dob.tags,dob.name) dob.name.gsub(/^([a-z_\.]+)-$/,'\1') end elsif dob.is ==:heading \ and dob.autonum_ \ and @md.markup =~/num_extract/ #AS DANGEROUS force enable with document, note already does this type of numbering for cisg, locate and coordinate logic, is currently misplaced in code, chengwei inspired 2004w23/4 #here lies a bug, as is nil when run from -Dv --update, FIX if (dob.name.nil? or dob.name.empty?) \ and dob.ln.to_s =~/^[0-9]/ \ and dob.obj =~ /^([\d\.]+)/ #risky (must be unique) consider output to 4~~\d instead of 4~\d dob.name=$1 dob.tags=set_tags(dob.tags,dob.name) end if @md.toc_lev_limit end elsif defined? dob.name \ and dob.name dob.tags=set_tags(dob.tags,dob.name) end dob.tags=dob.tags.uniq if defined? dob.tags dob end.flatten end def ocn(data) #and auto segment numbering increment @tuned_file=SiSU_AO_DocumentStructureExtract::OCN.new(@md,data,@fnx,@process).ocn @tuned_file end def xml(data) @tuned_file=SiSU_AO_DocumentStructureExtract::XML.new(@md,data).dom @tuned_file end def minor_numbering(data) #and auto segment numbering increment number_small,letter_small=0,0 letter=%w( a b c d e f g h i j k l m n o p q r s t u v w x y z ) @tuned_file=data.each.map do |dob| if dob.of ==:heading \ || dob.of ==:heading_insert \ || dob.of ==:para \ || dob.of ==:block if dob.is ==:heading \ and dob.ln.to_s=~/^[0-9]/ #% sub-number system, (baby numbering) reset with any change of major number (more obviously should be placed in number titles, but that is conditionally executed, check and move later) number_small,letter_small=0,0 elsif dob.is ==:para if dob.obj =~/^#[ 1]/ \ and dob.obj !~/^#\s+(?:~#)?$/ letter_small=0 number_small=0 if dob.obj =~ /^#1/ number_small+=1 dob.obj=dob.obj.gsub(/^#[ 1]/,"#{number_small}. ") end if dob.obj =~/^_# / dob.obj=dob.obj.gsub(/^_# /,"#{letter[letter_small]}. ") dob.indent='1' letter_small+=1 end end end dob end.flatten end def leading_zeros_fixed_width_number(possible_seg_name) if possible_seg_name.to_s =~/^([0-9]+?\.|[0-9]+)$/m #!~/[.,:-]+/ possible_seg_name=possible_seg_name.to_s. gsub(/\.$/,'') nl=possible_seg_name.to_s.length zero='0' zeros_fixed_width=number_of_segments?.to_s.length zero_width=(zeros_fixed_width - nl) zero_width == 0 \ ? possible_seg_name.to_s : zero*zero_width + possible_seg_name.to_s end end def auto_numbering_exceptions(chosen_seg_names_,md,dob) number_make=case dob.lv.to_i when 1 @num_exc={ t1: @num_exc[:t1] += 1, t2: 0, t3: 0, t4: 0 } Mx[:segname_prefix_auto_num_other] + '_' \ + @num_exc[:t1].to_s when 2 @num_exc={ t1: @num_exc[:t1], t2: @num_exc[:t2] += 1, t3: 0, t4: 0 } Mx[:segname_prefix_auto_num_other] + '_' \ + @num_exc[:t1].to_s + '_' \ + @num_exc[:t2].to_s when 3 @num_exc={ t1: @num_exc[:t1], t2: @num_exc[:t2], t3: @num_exc[:t3] += 1, t4: 0 } Mx[:segname_prefix_auto_num_other] + '_' \ + @num_exc[:t1].to_s + '_' \ + @num_exc[:t2].to_s + '_' \ + @num_exc[:t3].to_s when 4 @num_exc[:t4] += 1 @num_exc={ t1: @num_exc[:t1], t2: @num_exc[:t2], t3: @num_exc[:t3], t4: @num_exc[:t4] += 1 } Mx[:segname_prefix_auto_num_other] + '_' \ + @num_exc[:t1].to_s + '_' \ + @num_exc[:t2].to_s + '_' \ + @num_exc[:t3].to_s + '_' \ + @num_exc[:t4].to_s end end def check_that_seg_names_are_unique(chosen_seg_names_,chosen_seg_name,type,md,dob) begin chosen_seg_names_ << chosen_seg_name chosen_seg_names_=chosen_seg_names(chosen_seg_names_,chosen_seg_name,dob,md,type) if chosen_seg_names_.compact.uniq.length \ == chosen_seg_names_.compact.length #check that all auto given seg names are unique chosen_seg_names_=chosen_seg_names(chosen_seg_names_,chosen_seg_name,dob,md,type) chosen_seg_name else SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:green). mark( "duplicated auto segment name: #{type} #{chosen_seg_name}\n" \ + "#{chosen_seg_names_}\n" \ + " manually name level 1 segments '1~given_name'\n" \ + 'filename: ' + md.fns + "\n" \ + 'heading text: "' + dob.obj + '"' + "\n" \ + 'duplication: "' + chosen_seg_name + '" (level: ' + dob.lv + '; numbering type: ' + type.to_s + ')' ) chosen_seg_name=auto_numbering_exceptions(chosen_seg_names_,md,dob) check_that_seg_names_are_unique(chosen_seg_names_,chosen_seg_name,:exception,md,dob) end rescue end end def auto_seg_name(possible_seg_name,heading_num_is,dob,type) prefix=case type when :auto then Mx[:segname_prefix_auto_num_provide] when :extract then Mx[:segname_prefix_auto_num_extract] else '_'*dob.lv.to_i #should not occur end if possible_seg_name =~/^[0-9]+?\.$/m #!~/[.,:-]+/ possible_seg_name=possible_seg_name. gsub(/\.$/,'') end @chosen_seg_name= if dob.lv=='4' \ and possible_seg_name.to_s =~/^[0-9]+(?:[.,:-][0-9]){3}/m possible_seg_name=possible_seg_name.to_s. gsub(/(?:[:,-]|\W)/,'.'). gsub(/\.$/,'') prefix + possible_seg_name elsif dob.lv=='3' \ and possible_seg_name.to_s =~/^[0-9]+(?:[.,:-][0-9]){2}/m possible_seg_name=possible_seg_name.to_s. gsub(/(?:[:,-]|\W)/,'.'). gsub(/\.$/,'') prefix + possible_seg_name elsif dob.lv=='2' \ and possible_seg_name.to_s =~/^[0-9]+(?:[.,:-][0-9]){1}/m possible_seg_name=possible_seg_name.to_s. gsub(/(?:[:,-]|\W)/,'.'). gsub(/\.$/,'') prefix + possible_seg_name elsif dob.lv=='1' \ and possible_seg_name.to_s =~/^[0-9]+[:,-]?$/m if possible_seg_name.to_i <= heading_num_is.to_i prefix + leading_zeros_fixed_width_number(possible_seg_name) else possible_seg_name=possible_seg_name.to_s. gsub(/(?:[:,-]|\W)/,'.'). gsub(/\.$/,'') prefix + possible_seg_name end else @chosen_seg_name=auto_numbering_exceptions(@chosen_seg_names,md,dob) end check_that_seg_names_are_unique(@chosen_seg_names,@chosen_seg_name,type,@md,dob) end def set_name_and_tags(dob,possible_seg_name) if @md.seg_names.is_a?(Array) \ and not @md.seg_names.include?(possible_seg_name) dob.name=possible_seg_name dob.tags=set_tags(dob.tags,dob.name) @md.seg_names << possible_seg_name elsif (@md.opt.act[:verbose_plus][:set]==:on \ or @md.opt.act[:maintenance][:set]==:on) puts 'warn, there may be a conflicting numbering scheme' end end def name_para_seg_filename(data) #segment naming, remaining # paragraph name/numbering rules # manual naming overrides, manual naming may be # alpha-numeric characters mixed, # numeric only (a number), if # all segments have been named, # the numbers used are over 1000 or # it is not minded that auto-numbering uses a funny scheme for naming segments (not yet implemented) # [for now a warning is printed for such documents on use of maintenance or very-verbose flag] # auto-naming takes the form of giving numbers to segments # the rules for which are as follows # if the title/heading text starts with a numeric, then that is used (1 3.1 3rd etc.) # otherwise the level 4 segment number from the embedded document structure info is used # if there is none a sequential number is designated, preceded by an underscore @tuned_file,@unique_auto_name=[],[] tags={} @art_filename_auto=0 @counter=1 if not @md.seg_autoname_safe \ and (@md.opt.act[:verbose_plus][:set]==:on \ || @md.opt.act[:maintenance][:set]==:on) puts 'manual segment names, numbers used as names, risk warning (segmented html)' end ocn_html_seg=[] @num_exc={ t1: 0, t2: 0, t3: 0, t4: 0 } data.each do |dob| if dob.is==:heading \ && dob.ln \ and dob.ln.to_s =~/^[4-7]/ heading_num_is=/^\d+:(\d+);\d/m.match(dob.node)[1] if dob.ln==4 \ and not dob.name \ and not @md.set_heading_seg @md.set_heading_seg=true end if dob.name !~/^\S+/ \ and dob.ln.to_s =~/^[5-7]/ \ and dob.obj =~/^\s*(?:\S+\s+)?([0-9]+(?:[.,:-][0-9])+)/m #heading starts with a recognised numeric #or word followed by a recognised numeric construct, #use that as name if dob.ln==7 \ and dob.obj =~/^\s*(?:\S+\s+)?([0-9]+(?:[.,:-][0-9]){3})/m possible_seg_name=$1. gsub(/(?:[:,-]|\W)/,'.'). gsub(/\.$/,'') possible_seg_name= auto_seg_name(possible_seg_name,heading_num_is,dob,:extract) set_name_and_tags(dob,possible_seg_name) elsif dob.ln==6 \ and dob.obj =~/^\s*(?:\S+\s+)?([0-9]+(?:[.,:-][0-9]){2})/m possible_seg_name=$1. gsub(/(?:[:,-]|\W)/,'.'). gsub(/\.$/,'') possible_seg_name= auto_seg_name(possible_seg_name,heading_num_is,dob,:extract) set_name_and_tags(dob,possible_seg_name) elsif dob.ln==5 \ and dob.obj =~/^\s*(?:\S+\s+)?([0-9]+(?:[.,:-][0-9]){1})/m possible_seg_name=$1. gsub(/(?:[:,-]|\W)/,'.'). gsub(/\.$/,'') possible_seg_name= auto_seg_name(possible_seg_name,heading_num_is,dob,:extract) set_name_and_tags(dob,possible_seg_name) end end if dob.ln==4 if dob.name !~/^\S+/ \ and dob.obj =~/^\s*(?:\S+\s+)?([0-9]+)/m #heading starts with a recognised numeric #or word followed by a recognised numeric construct, #use that as name possible_seg_name=$1 possible_seg_name= auto_seg_name(possible_seg_name,heading_num_is,dob,:extract) set_name_and_tags(dob,possible_seg_name) end if dob.name #extract segment name from embedded document structure info if @md.seg_names.is_a?(Array) \ and not @md.seg_names.include?(dob.name) dob.tags=set_tags(dob.tags,dob.name) @md.seg_names << dob.name end else #if no segment name, #provide a numerical one @art_filename_auto+=1 possible_seg_name= auto_seg_name(@art_filename_auto,heading_num_is,dob,:auto) if @md.seg_names.is_a?(Array) \ and not @md.seg_names.include?(possible_seg_name) dob.name=possible_seg_name dob.tags=set_tags(dob.tags,dob.name) @md.seg_names << possible_seg_name else puts 'segment name (numbering) error' end end if not dob.name #should not occur puts "e r r o r -\t#{__FILE__}::#{__LINE__}\n#{dob.inspect}" end end end if (dob.is ==:heading \ || dob.is ==:heading_insert) \ && dob.ln==4 @seg=dob.name end @tuned_file << if dob.is==:heading \ && (@md.pagenew || @md.pagebreak || @md.pageline) m=dob.ln.to_s dob_tmp=[] if @md.pagenew.inspect =~/#{m}/ dob_tmp << SiSU_AO_DocumentStructure::ObjectLayout.new.break(Hx[:br_page_new]) << dob elsif @md.pagebreak.inspect =~/#{m}/ dob_tmp << SiSU_AO_DocumentStructure::ObjectLayout.new.break(Hx[:br_page]) << dob elsif @md.pageline.inspect =~/#{m}/ dob_tmp << SiSU_AO_DocumentStructure::ObjectLayout.new.break(Hx[:br_page_line]) << dob end unless dob_tmp.length > 0; dob else dob_tmp end else dob end if defined? dob.ocn \ and dob.ocn @segname=((dob.is==:heading || dob.is==:heading_insert) && dob.ln==4 && (defined? dob.name)) \ ? (dob.name) : @segname tags["#{dob.ocn}"]={ segname: @segname } ocn_html_seg[dob.ocn]=if (dob.is==:heading || dob.is==:heading_insert) if dob.ln.to_s =~/[0-3]/ { seg: nil, level: dob.ln, } #elsif dob.ln =~/[4-6]/ else { seg: @seg, level: dob.ln, } end else { seg: @seg, level: nil, } end end dob.tags=dob.tags.uniq if defined? dob.tags if defined? dob.tags \ and dob.tags.length > 0 #@segname=((dob.is=='heading'|| dob.is=='heading_insert') && dob.ln==4 && (defined? dob.name)) \ #? (dob.name) \ #: @segname dob.tags.each do |y| tags[y]={ ocn: dob.ocn.to_s, segname: @segname } end end dob end ocn_html_seg.each_with_index do |ocn,i| if ocn \ and ocn[:level].to_s=~/[1-3]/ (1..4).each do |x| if ocn_html_seg[i+x] \ and ocn_html_seg[i+x][:level]==4 ocn[:seg]=ocn_html_seg[i+x][:seg] end end end end if @md.seg_names.length > 0 @md.set_heading_seg=true end tuned_file=@tuned_file.flatten [tuned_file,tags,ocn_html_seg] end def set_heading_top(data) #% make sure no false positives unless @md.set_heading_top if (@md.opt.act[:verbose_plus][:set]==:on \ or @md.opt.act[:maintenance][:set]==:on) puts "\tdocument contains no top level heading, (will have to manufacture one)" end @tuned_file=[] data.each do |t_o| unless @md.set_heading_top if t_o !~/^(?:#{Rx[:meta]}|@\S+:)\s/m \ and t_o !~/\A\s*\Z/m @md.set_heading_top=true if defined? @md.title \ and @md.title \ and defined? @md.title.full \ and defined? @md.creator \ and @md.creator head=@md.title.main \ ? ([@lv='1',@obj=@md.title.main]) : ([@lv='1',@obj='[no title provided]']) @tuned_file << head end end end @tuned_file << t_o end @tuned_file=@tuned_file.flatten end end def set_heading_seg(data) #% make sure no false positives unless @md.set_heading_seg if (@md.opt.act[:verbose_plus][:set]==:on \ or @md.opt.act[:maintenance][:set]==:on) puts "\tdocument contains no segment level, (will have to manufacture one)" end @tuned_file=[] data.each do |dob| unless @md.set_heading_seg if defined? dob.ln and dob.ln.to_s !~/^[0-3]/m \ and dob.obj !~/\A\s*\Z/m \ and dob.is !=:layout @md.set_heading_seg=true head=@md.title.main \ ? (dob.ln,dob.name,dob.obj=4,'seg',@md.title.main) : (dob.ln,dob.name,dob.obj=4,'seg','[segment]') @tuned_file << head end end @tuned_file << dob end @tuned_file=@tuned_file.flatten end end def set_header_title(data) #% make sure no false positives unless @md.set_header_title if (@md.opt.act[:verbose_plus][:set]==:on \ or @md.opt.act[:maintenance][:set]==:on) puts "\t no document title provided, (will have to manufacture one)" end @tuned_file=[] data.each do |t_o| unless @md.set_header_title if t_o !~/^%{1,2}\s/m \ and t_o !~/\A\s*\Z/m @tuned_file << "#{Mx[:meta_o]}title#{Mx[:meta_c]} #{@md.heading_seg_first}" @md.title.main=@md.heading_seg_first @md.set_header_title=true end end @tuned_file << t_o end @tuned_file=@tuned_file.flatten end end end end __END__ #+END_SRC ** ao_persist.rb #+HEADER: :tangle "../lib/sisu/ao_persist.rb" #+BEGIN_SRC ruby #<<sisu_document_header>> module SiSU_AO_Persist class Persist @@persistance=nil attr_accessor :fns, :ao_arr, :idx_arr_sst, :idx_arr_tex, :idx_arr_html, :idx_arr_xhtml, :map_arr_nametags, :map_arr_ocn_htmlseg def initialize(args=nil) @@persistance=args=(args ? args : (@@persistance || persist_init_hash_values)) @fns=args[:fns] @ao_arr=args[:ao_arr] @idx_arr_sst=args[:idx_arr_sst] @idx_arr_tex=args[:idx_arr_tex] @idx_arr_html=args[:idx_arr_html] @idx_arr_xhtml=args[:idx_arr_xhtml] @map_arr_nametags=args[:map_arr_nametags] @map_arr_ocn_htmlseg=args[:map_arr_ocn_htmlseg] end def fns @fns end def ao_arr @ao_arr end def idx_arr_sst @idx_arr_sst end def idx_arr_tex @idx_arr_tex end def idx_arr_html @idx_arr_html end def idx_arr_xhtml @idx_arr_xhtml end def map_arr_nametags @map_arr_nametags end def map_arr_ocn_htmlseg @map_arr_ocn_htmlseg end def persist_init_hash_values { fns: nil, ao_arr: [], idx_arr_sst: [], idx_arr_tex: [], idx_arr_html: [], idx_arr_xhtml: [], map_arr_nametags: [], map_arr_ocn_htmlseg: [], } end def persist_init @@persistance=nil Persist.new(persist_init_hash_values) end end class PersistDocStructExt @@persist=nil attr_accessor :ocn, :lng, :lng_is, :code, :lngsyn, :poem, :block, :box, :group, :alt, :quote, :table, :table_to def initialize(args=nil) @@persist=args=(args ? args : (@@persist || persist_init_hash_values)) @ocn=args[:ocn] @lng=args[:lng] @lng_is=args[:lng_is] @code=args[:code] @lngsyn=args[:lngsyn] @poem=args[:poem] @block=args[:block] @box=args[:box] @group=args[:group] @alt=args[:alt] @quote=args[:quote] @table=args[:table] @table_to=args[:table_to] end def ocn @ocn end def lng @lng end def lng_is @lng_is end def code @code end def lngsyn @lngsyn end def poem @poem end def block @block end def box @box end def group @group end def alt @alt end def quote @quote end def table @table end def table_to @table_to end def persist_init_hash_values { ocn: :on, lng: :off, lng_is: :doc_default, code: :off, lngsyn: :txt, poem: :off, block: :off, box: :off, group: :off, alt: :off, quote: :off, table: :off, table_to: :off, } end def persist_init @@persist=nil PersistDocStructExt.new(persist_init_hash_values) end end end __END__ #+END_SRC ** ao_syntax.rb #+HEADER: :tangle "../lib/sisu/ao_syntax.rb" #+BEGIN_SRC ruby #<<sisu_document_header>> module SiSU_AO_Syntax class Words def initialize(line,md,mkp) @line,@md,@mkp=line,md,mkp end end class Markup def initialize(md='',data='',biblio=[]) @md,@data,@bibliography=md,data,biblio @data_new=[] url_and_stub=SiSU_Env::InfoEnv.new.url @output_url="#{url_and_stub.remote}" @env=SiSU_Env::InfoEnv.new emph_set=if defined? @md.emphasis_set_to \ and not @md.emphasis_set_to.nil? @md.emphasis_set_to else @env.markup_emphasis end @emph=case emph_set when /bold/ emph_italics=false { o: Mx[:fa_bold_o], c: Mx[:fa_bold_c] } when /italics/ emph_italics=true { o: Mx[:fa_italics_o], c: Mx[:fa_italics_c] } when /underscore/ emph_italics=false { o: Mx[:fa_underscore_o], c: Mx[:fa_underscore_c] } else p __LINE__.to_s + '::' + __FILE__ end @http_m=%r{\{.+?\}https?://\S+|https?:\S+|:\S+|\.\.\/\S+|#\S+|\S+?\.png\b|[*]~\S+|^#{Mx[:meta_o]}.+|#{Mx[:gr_o]}(?:code(?:\.[a-z][0-9a-z_]+)?|box(?:\.[a-z_]+)?|block|group|alt|verse)(?:-end)?#{Mx[:gr_c]}|#{Mx[:fa_o]}:br#{Mx[:fa_c]}} @manmkp_ital=emph_italics \ ? '[i/*]\\{.+?\\}[i/*]' : '[i/]\\{.+?\\}[i/]' tail_m_ital=%q{(?:\s|'s\b|[.,;:?!'")]|~\^|~\\\{\s|$)} tail_m_bold=%{(?:(?:#{Mx[:fa_italics_c]})?(?:\s|'s\b|[.,;:?!'")]|~\^|~\\\{\s|$))?} bold_line=%{^!_\s.+?(?:#{Mx[:br_line]}|\n|$)} #ital_line=%{^/_\s.+?(?:#{Mx[:br_line]}|\n|$)} #not implemented @line_scan_ital=if defined? @md.italics_match_list[:str] /#{@http_m}|#{bold_line}|#{@manmkp_ital}#{tail_m_ital}|#{@md.italics_match_list[:str]}#{tail_m_ital}|\S+|\n/i end @manmkp_bold=emph_italics \ ? '^!_\s.+?(?:\n|$)|[!b]\\{.+?\\}[*!b]|[*!][a-zA-Z0-9\-_]+[!]' : '^!_\s.+?(?:\n|$)|[*!b]\\{.+?\\}[*!b]|[*!][a-zA-Z0-9\-_]+[*!]' @line_scan_bold=if defined? @md.bold_match_list[:str] \ and @md.bold_match_list[:str] /#{@http_m}|#{bold_line}|(?:#{@manmkp_bold}|#{@md.bold_match_list[:str]})#{tail_m_bold}|\S+|\n/i end end def songsheet @data=@data.compact @data.each do |dob| dob=breaks(dob) dob=if @md.sem_tag then sem(dob) else dob end #revisit dob=line_actions(dob) dob=paragraph_set(dob) dob=substitutions(dob) dob=wordlist_italics(dob) dob=wordlist_bold(dob) dob=bodymarkup(dob) @data_new << dob unless dob.nil? end @data_new end def sem(dob) #revisit dob=SiSU_Sem::Tags.new(dob,@md).rm.all end def breaks(dob) if dob.is !=:meta \ && dob.is !=:comment \ && dob.is !=:code \ && dob.is !=:table dob.obj=dob.obj. gsub(/^-\\\\-\s*$/,"#{Mx[:br_page]}"). gsub(/^=\\\\=\s*$/,"#{Mx[:br_page_new]}"). gsub(/ \\\\(?: |$)/,"#{Mx[:br_line]}"). gsub(/(?:<:?pb>)/,"#{Mx[:br_page]}"). # depreciated gsub(/(?:<:?pn>)/,"#{Mx[:br_page_new]}"). # depreciated gsub(/(?:<:?br>|<br \/>)/,"#{Mx[:br_line]}"). # depreciated gsub(/(?:^-\.\.-\s*$)/,"#{Mx[:br_page_line]}") end dob end def wordlist_italics(dob) dob=dob.dup if (defined? @md.italics_match_list[:str] \ and @md.italics_match_list[:str]) dob.obj=if dob.is !=:meta \ && dob.is !=:heading \ && dob.is !=:heading_insert \ && dob.is !=:code \ && dob.is !=:layout \ && dob.is !=:comment word=dob.obj.scan(@line_scan_ital) word=word.flatten.compact line_array=[] word.each do |w| unless /#{@manmkp_ital}|#{@http_m}/.match(w) if defined? @md.italics_match_list[:regx] \ and @md.italics_match_list[:regx] w=w.gsub(@md.italics_match_list[:regx], "#{Mx[:fa_italics_o]}\\1#{Mx[:fa_italics_c]}") else w end end line_array << w end line_array.join(' ') else dob.obj end end dob end def embolden(given) given=given. gsub(/^!_\s+((?:\{|#{Mx[:lnk_o]})(?:~^ )?.+?(?:\}|#{Mx[:lnk_o]})https?:\/\/\S+.*?)([#{Mx[:br_line]}#{Mx[:br_paragraph]}#{Mx[:br_nl]}])/, "#{Mx[:fa_bold_o]} \\1 #{Mx[:fa_bold_c]}\\2"). gsub(/^!_\s+((?:\{|#{Mx[:lnk_o]})(?:~^ )?.+?(?:\}|#{Mx[:lnk_o]})https?:\/\/\S+.*)/, "#{Mx[:fa_bold_o]} \\1 #{Mx[:fa_bold_c]}"). gsub(/(?:^!_|^#{Mx[:lv_o]}[7-9]:\S*?#{Mx[:lv_c]})\s*(.+?)([#{Mx[:br_line]}#{Mx[:br_paragraph]}#{Mx[:br_nl]}])/, "#{Mx[:fa_bold_o]}\\1#{Mx[:fa_bold_c]}\\2"). gsub(/(?:^!_|^#{Mx[:lv_o]}[7-9]:\S*?#{Mx[:lv_c]})\s*(.+?)\s+((?:[*]~\S+\s*)+)/, "#{Mx[:fa_bold_o]}\\1#{Mx[:fa_bold_c]}\\2"). gsub(/(?:^!_|^#{Mx[:lv_o]}[7-9]:\S*?#{Mx[:lv_c]})\s*(.+?)\s*([~-]#)$/, "#{Mx[:fa_bold_o]}\\1#{Mx[:fa_bold_c]}\\2"). gsub(/(?:^!_\s+|^#{Mx[:lv_o]}[7-9]:\S*?#{Mx[:lv_c]}\s*)(.*)?\s*$/, "#{Mx[:fa_bold_o]}\\1#{Mx[:fa_bold_c]}") end def italicise(given) given=given. gsub(/^\/_\s*(.+?)([#{Mx[:br_line]}#{Mx[:br_paragraph]}#{Mx[:br_nl]}])/, "#{Mx[:fa_italics_o]}\\1#{Mx[:fa_italics_c]}\\2"). gsub(/^\/_\s*(.+?)\s+((?:[*]~\S+\s*)+)/, "#{Mx[:fa_italics_o]}\\1#{Mx[:fa_italics_c]}\\2"). gsub(/^\/_\s*(.+?)\s*([~-]#)$/, "#{Mx[:fa_italics_o]}\\1#{Mx[:fa_italics_c]}\\2"). gsub(/^\/_\s+(.*)?\s*$/, "#{Mx[:fa_italics_o]}\\1#{Mx[:fa_italics_c]}") end def line_actions(dob) dob.obj=if (dob.is !=:heading \ && dob.is !=:heading_insert \ && dob.is !=:comment \ && dob.is !=:meta) \ and dob.obj =~ /^!_\s+/ embolden(dob.obj) elsif dob.obj =~ /^\/_\s+/ italicise(dob.obj) else dob.obj end dob end def paragraph_set(dob) dob.obj=if dob.is !=:meta \ && dob.is !=:heading \ && dob.is !=:heading_insert \ && dob.is !=:code \ && dob.is !=:comment \ && dob.is !=:table dob.obj.gsub(/\n/m,' '). gsub(/ \s+/m,' ') else dob.obj end dob end def substitutions(dob) dob=dob.dup dob=if @md.flag_auto_biblio \ and @bibliography.length > 0 dob=if dob.is !=:meta \ && dob.is !=:heading_insert \ && dob.is !=:code \ && dob.is !=:comment \ && dob.is !=:table @bibliography.each do |c| if c[:id] and not c[:id].nil? and not c[:id].empty? dob.obj=dob.obj.gsub(/#{c[:id]}/mi,c[:short_name]) end end dob else dob end dob else dob end dob=if defined? @md.substitution_match_list[:match_and_replace] \ and @md.substitution_match_list[:match_and_replace].is_a?(Array) dob=if dob.is !=:meta \ && dob.is !=:heading_insert \ && dob.is !=:code \ && dob.is !=:comment \ && dob.is !=:table if dob.obj =~/#{@md.substitution_match_list[:matches]}/ @md.substitution_match_list[:match_and_replace].each do |x| dob.obj=if x[:case_s]==:i dob.obj.gsub(/#{x[:match]}/mi,x[:replace]) else dob.obj.gsub(/#{x[:match]}/m,x[:replace]) end end end dob else dob end dob else dob end end def wordlist_bold(dob) dob=dob.dup if (defined? @md.bold_match_list[:str] \ and @md.bold_match_list[:str]) dob.obj=if dob.is !=:meta \ && dob.is !=:heading \ && dob.is !=:heading_insert \ && dob.is !=:code \ && dob.is !=:comment \ && dob.is !=:table line_array=[] word=dob.obj.scan(@line_scan_bold) word=word.flatten.compact word.each do |w| unless /#{@manmkp_bold}|#{@http_m}/.match(w) if defined? @md.bold_match_list[:regx] \ and @md.bold_match_list[:regx] #document header: @bold: [bold word list] w=w.gsub(@md.bold_match_list[:regx], "#{Mx[:fa_bold_o]}\\1#{Mx[:fa_bold_c]}") end else w=if w =~ /(?:^!_|^#{Mx[:lv_o]}[7-9]:\S*?#{Mx[:lv_c]})\s+/ embolden(w) #bold paragraph/emphasize #may wish to remove think about 7{ 8{ conversion not satisfactory, as information is lost! elsif w =~/^\/_\s+/ italicise(w) else w end end line_array << w end line_array.join(' ') else dob.obj end else dob.obj=if dob.is==:heading \ and dob.ln.to_s =~/[7-9]/ embolden(dob.obj) else dob.obj end end dob end def fontface_lines(dob,leader) while (dob.obj =~/#{Mx[:br_nl]}/ \ and dob.obj =~/(?:#{leader})([*!\/_#])\{(.+?)\}\1/m) \ and $2 =~/#{Mx[:br_nl]}/ dob=if dob.obj =~/#{Mx[:br_nl]}/ \ and dob.obj =~/(#{leader})([*!\/_#])\{(.+?)\}\2/m lead,fce,txt=$1,$2,$3 dob=if txt =~/#{Mx[:br_nl]}/ lead_break=if dob.obj =~/^#{Mx[:br_nl]}/ dob.obj=dob.obj.sub(/^#{Mx[:br_nl]}/,'') Mx[:br_nl] else '' end txt="#{lead_break}#{fce}\{" + txt.split(Mx[:br_nl]).join("\}#{fce}#{Mx[:br_nl]}#{fce}\{") + "\}#{fce}" dob.obj=dob.obj. sub(/(?:^|#{Mx[:gl_c]}|\s+|['"]|[#{Mx[:nbsp]}#{Mx[:fa_o_c]}#{Mx[:fa_c]}#{Mx[:lnk_o]}#{Mx[:br_nl]}#{Mx[:br_line]}#{Mx[:br_paragraph]}#{Mx[:tc_c]}#{Mx[:tc_p]}]|[\(\[\{]|\>)([*!\/_#])\{.+?\}\1/m, "#{lead}#{txt}") dob else dob end end dob end dob end def fontface(dob) leader=/^|#{Mx[:gl_c]}|\s+|['"]|[#{Mx[:nbsp]}#{Mx[:fa_o_c]}#{Mx[:fa_c]}#{Mx[:lnk_o]}#{Mx[:br_nl]}#{Mx[:br_line]}#{Mx[:br_paragraph]}#{Mx[:tc_c]}#{Mx[:tc_p]}]|[\(\[\{]|[、。「‹«¿¡]|\>/ dob=fontface_lines(dob,leader) dob.obj=dob.obj. gsub(/(#{leader})\*\{(.+?)\}\*/m, "\\1#{@emph[:o]}\\2#{@emph[:c]}"). #emphasis gsub(/(#{leader})!\{(.+?)\}!/m, "\\1#{Mx[:fa_bold_o]}\\2#{Mx[:fa_bold_c]}"). #bold gsub(/(#{leader})\/\{(.+?)\}\//m, "\\1#{Mx[:fa_italics_o]}\\2#{Mx[:fa_italics_c]}"). #italics gsub(/(#{leader})_\{(.+?)\}_/m, "\\1#{Mx[:fa_underscore_o]}\\2#{Mx[:fa_underscore_c]}"). #underscore gsub(/(#{leader})#\{(.+?)\}#/m, "\\1#{Mx[:fa_monospace_o]}\\2#{Mx[:fa_monospace_c]}"). #monospace gsub(/(^|#{Mx[:gl_c]}|\s+|['"]|[#{Mx[:nbsp]}#{Mx[:fa_o_c]}#{Mx[:fa_c]}]|\(|\>)\"\{(.+?)\}\"/m, "\\1#{Mx[:fa_cite_o]}\\2#{Mx[:fa_c_o]}cite#{Mx[:fa_c]}"). #cite /blockquote? gsub(/(^|[^\\])\^\{(.+?)\}\^/m, "\\1#{Mx[:fa_superscript_o]}\\2#{Mx[:fa_superscript_c]}"). #superscript gsub(/(^|[^\\]),\{(.+?)\},/m, "\\1#{Mx[:fa_subscript_o]}\\2#{Mx[:fa_subscript_c]}"). #subscript gsub(/(^|#{Mx[:gl_c]}|\s+|['"]|#{Mx[:nbsp]}|#{Mx[:fa_o_c]}|#{Mx[:fa_c]}|\(|\>)\+\{(.+?)\}\+/m, "\\1#{Mx[:fa_insert_o]}\\2#{Mx[:fa_insert_c]}"). #inserted text gsub(/(^|#{Mx[:gl_c]}|\s+|['"]|#{Mx[:nbsp]}|#{Mx[:fa_o_c]}|#{Mx[:fa_c]}|\(|\>)-\{(.+?)\}-/m, "\\1#{Mx[:fa_strike_o]}\\2#{Mx[:fa_strike_c]}"). #strikethrough - deleted text gsub(/(^|#{Mx[:gl_c]}|\s+|['"]|#{Mx[:nbsp]}|#{Mx[:fa_o_c]}|#{Mx[:fa_c]}|\(|\>|\d+)\^(\S+?)\^/, "\\1#{Mx[:fa_superscript_o]}\\2#{Mx[:fa_superscript_c]}") #superscript single word, watch digit added dob end def bodymarkup(dob) # << http://www.jus.uio.no/sisu/sisu_markup_table/markup >> # See: data/sisu/sample/document_samples_sisu_markup/ ## fontface # *{emphasis}* e{emphasis}e <strong>emphasis</strong> # !{bold text}! b{bold}b <b>bold text</b> # _{underline}_ u{underline}u <u>underline</u> # /{italics}/ i{italics}i <i>italics</i> # "{citation}" c{citation}c <cite>citation</cite> #blockquote? # ^{superscript}^ <sup>superscript</sup> # ,{subscript}, <sub>subscript</sub> # +{inserted text}+ <ins>inserted text</ins> # -{deleted text}- <del>deleted text</del> # #{monospace text}# # # {url address}:url # {image.png}imageurl # {image.png}png # ~{endnote}~ # !_ #bold/emphasise paragraph # _" #blockquote paragraph # _1 <:i1> #indent paragraph 1 step # _2 <:i2> #indent paragraph 2 steps # _3 <:i3> #indent paragraph 3 steps # _4 <:i4> #indent paragraph 4 steps # _* #bullet (list) ● # _1* #bullet (list) indented # _1* #bullet (list) indented # # #numbered (list) level 1 # _# #numbered (list) level 2 dob=dob.dup if dob.is !=:meta \ && dob.is !=:comment \ && dob.is !=:code \ && dob.is !=:table line_array=[] word=dob.obj.scan(/\S+|\n/) #unless line =~/^(?:#{Mx[:meta_o]}|%+\s)/ #visit if word word.each do |w| # _ - / # | : ! ^ ~ unless w =~/~\{|\}~|~\[|\]~|^\^~|~\^|\*~\S+|~#|\{t?~|\{table|https?:\/\/\S+/ # do something earlier about table!! w=w.gsub(/\\?~/,"#{Mx[:gl_o]}#126#{Mx[:gl_c]}") #escaped special character end w=w.gsub(/^\<$/, "#{Mx[:gl_o]}#lt#{Mx[:gl_c]}").gsub(/^\>$/,"#{Mx[:gl_o]}#gt#{Mx[:gl_c]}") #escaped special character line_array << w end dob.obj=line_array.join(' ') dob.obj=dob.obj.strip end dob.obj=dob.obj. gsub(/^([*#.-]{1,12})$/,'\1 ~#'). #ocn off for these paragraph separators gsub(/~\{(.+?)\}~/m,Mx[:en_a_o] + '\1' + Mx[:en_a_c]). gsub(/~\[([^*+].+?)\]~/m,Mx[:en_b_o] + '* \1' + Mx[:en_b_c]). #default if markup does not specify gsub(/~\[(.+?)\]~/m,Mx[:en_b_o] + '\1' + Mx[:en_b_c]) if dob.is ==:heading \ and dob.ln ==0 dob.obj=dob.obj.gsub(/\s*@title\b/," #{@md.title.full}") dob.obj=if defined? @md.creator.author \ and @md.creator.author dob.obj.gsub(/\s+(?:@creator|@author)/,",#{Mx[:br_line]}#{@md.creator.author}") else dob.obj.gsub(/\s+(?:@creator|@author)/,'') end end if defined? @md.title \ and @md.title \ and defined? @md.title.full \ and defined? @md.creator \ and @md.creator if dob.is ==:heading dob.obj=dob.obj.gsub(/^\s*@title\s*$/,@md.title.full) if dob.lv =~/1/ dob.obj=if dob.lv =~/[23]/ \ and defined? @md.creator.author \ and @md.creator.author dob.obj. gsub(/^\s*(?:(by\s+)?(?:@creator|@author))\s*$/, "\\1#{@md.creator.author}") else dob.obj.gsub(/^\s*(?:(by\s+)?(?:@creator|@author))\s*$/,'\1') end end end dob.obj=dob.obj.gsub(/<(https?:\/\/\S+?)>/,'< \1 >'). #catch problem markup gsub(/<:=(\S+?)>/,'{ c_\1.png 14x14 }image'). gsub(/<!(\S+)!>/,'<:\1>'). #escaped special character gsub(/ /,"#{Mx[:nbsp]}"). #escaped special character gsub(/\\~/,"#{Mx[:gl_o]}#126#{Mx[:gl_c]}"). #escaped special character gsub(/\\\{/,"#{Mx[:gl_o]}#123#{Mx[:gl_c]}"). #escaped special character gsub(/\\\}/,"#{Mx[:gl_o]}#125#{Mx[:gl_c]}"). #escaped special character gsub(/\\\<</,"#{Mx[:gl_o]}#lt#{Mx[:gl_c]}#{Mx[:gl_o]}#lt#{Mx[:gl_c]}"). #escaped special character gsub(/\\\>>/,"#{Mx[:gl_o]}#gt#{Mx[:gl_c]}#{Mx[:gl_o]}#gt#{Mx[:gl_c]}"). #escaped special character gsub(/\\\</,"#{Mx[:gl_o]}#lt#{Mx[:gl_c]}"). #escaped special character gsub(/\\\>/,"#{Mx[:gl_o]}#gt#{Mx[:gl_c]}"). #escaped special character gsub(/\\\_/,"#{Mx[:gl_o]}#095#{Mx[:gl_c]}"). #escaped special character gsub(/\\\-/,"#{Mx[:gl_o]}#045#{Mx[:gl_c]}"). #escaped special character gsub(/\\\+/,"#{Mx[:gl_o]}#043#{Mx[:gl_c]}"). #escaped special character gsub(/\\\//,"#{Mx[:gl_o]}#047#{Mx[:gl_c]}"). #escaped special character gsub(/\\\#/,"#{Mx[:gl_o]}#035#{Mx[:gl_c]}"). #escaped special character gsub(/\\\&/,"#{Mx[:gl_o]}#038#{Mx[:gl_c]}"). #& #escaped special character gsub(/\\\|/,"#{Mx[:gl_o]}#124#{Mx[:gl_c]}"). #not really a sisu special character but made available as possibility gsub(/\\\:/,"#{Mx[:gl_o]}#058#{Mx[:gl_c]}"). #not really a sisu special character but made available as possibility gsub(/\\\!/,"#{Mx[:gl_o]}#033#{Mx[:gl_c]}"). #not really a sisu special character but made available as possibility gsub(/\\\^/,"#{Mx[:gl_o]}#094#{Mx[:gl_c]}"). #not really a sisu special character but made available as possibility gsub(/\\\,/,"#{Mx[:gl_o]}#044#{Mx[:gl_c]}"). #not really a sisu special character but made available as possibility gsub(/\\\\/,"#{Mx[:gl_o]}#092#{Mx[:gl_c]}"). #escaped special character gsub(/\\\*/,"#{Mx[:gl_o]}#042#{Mx[:gl_c]}"). #escaped special character gsub(/\\\!/,"#{Mx[:gl_o]}#033#{Mx[:gl_c]}") #escaped special character if dob.obj=~/(?:https?:|ftp:|\{([^{}]+?)\}(?:#|:|[.]{1,2}\/))\S+/m if dob.obj=~/(?:^|[#{Mx[:gl_c]}#{Mx[:nbsp]} ])\{~\^ (?:.+?)\s*\}(?:(?:https?:|ftp:|:|[.]{1,2}\/)\S+?)\s*#{Mx[:en_a_o]}(.+?)#{Mx[:en_a_c]}/m dob.obj=dob.obj. gsub(/(^|[#{Mx[:gl_c]}#{Mx[:nbsp]} ])\{~\^ ([^}]+?)\s*\}((?:https?:|ftp:|:|[.]{1,2}\/)\S+?)\s*#{Mx[:en_a_o]}(.+?)#{Mx[:en_a_c]}/m, "\\1#{Mx[:lnk_o]}\\2#{Mx[:lnk_c]}\\3 #{Mx[:en_a_o]}\\3 \\4#{Mx[:en_a_c]}") # watch end if dob.obj=~/(?:^|[#{Mx[:gl_c]}#{Mx[:nbsp]} ])\{~\^ (?:.+?)\s*\}(?:(?:https?:|ftp:|:|[.]{1,2}\/)\S+?)([;,.]?)(?=\s|[#{Mx[:br_line]}#{Mx[:br_paragraph]}#{Mx[:br_nl]}]|$)/m dob.obj=dob.obj. gsub(/(^|[#{Mx[:gl_c]}#{Mx[:nbsp]} ])\{~\^ (.+?)\s*\}((?:https?:|ftp:|:|[.]{1,2}\/)\S+?)([;,.]?)(?=\s|[#{Mx[:br_line]}#{Mx[:br_paragraph]}#{Mx[:br_nl]}]|$)/m, "\\1#{Mx[:lnk_o]}\\2#{Mx[:lnk_c]}\\3\\4 #{Mx[:en_a_o]}\\3#{Mx[:en_a_c]} ") end dob.obj=dob.obj. gsub(/(^|[^#])\{\s*([^{}]+?)\s*\}((?:https?:|:|[.]{2}\/|#)\S+?)(?=\s|[#{Mx[:br_line]}#{Mx[:br_paragraph]}#{Mx[:br_nl]}#{Mx[:en_a_o]}#{Mx[:en_b_o]}]|$)/, "\\1#{Mx[:lnk_o]}\\2#{Mx[:lnk_c]}\\3"). #linked (text or image, however text cannot include modified face, e.g. bold, ital, underline) gsub(/(^|[#{Mx[:gl_c]}#{Mx[:lnk_c]}#{Mx[:en_a_o]}#{Mx[:en_b_o]}(\s])((?:https?|ftp):\/\/\S+?\.[^>< ]+?)([,.;'"]?)(?=[\s#{Mx[:en_a_c]}#{Mx[:en_b_c]}#{Mx[:br_line]}#{Mx[:br_paragraph]}#{Mx[:br_nl]}]|$)/m, %{\\1#{Mx[:url_o]}\\2#{Mx[:url_c]}\\3}). gsub(/#{Mx[:lnk_c]}#(\S+?[^>< ]+?)([()\[\]]*[,.;:!?'"]{0,2})(?=[\s#{Mx[:en_a_c]}#{Mx[:en_b_c]}#{Mx[:br_line]}#{Mx[:br_paragraph]}#{Mx[:br_nl]}]|$)/m, %{#{Mx[:lnk_c]}#{Mx[:rel_o]}\\1#{Mx[:rel_c]}\\2}). gsub(/#{Mx[:lnk_c]}:(\S+?[^>< ]+?)([()\[\]]*[,.;:!?'"]{0,2})(?=[\s#{Mx[:en_a_c]}#{Mx[:en_b_c]}#{Mx[:br_line]}#{Mx[:br_paragraph]}#{Mx[:br_nl]}]|$)/m, %{#{Mx[:lnk_c]}#{Mx[:rel_o]}:\\1#{Mx[:rel_c]}\\2}). gsub(/#{Mx[:lnk_c]}[.]{2}\/(\S+?[^>< ]+?)([()\[\]]*[,.;:!?'"]{0,2})(?=[\s#{Mx[:en_a_c]}#{Mx[:en_b_c]}#{Mx[:br_line]}#{Mx[:br_paragraph]}#{Mx[:br_nl]}]|$)/m, %{#{Mx[:lnk_c]}#{Mx[:rel_o]}:\\1#{Mx[:rel_c]}\\2}) end if dob.obj=~/_(?:https?|ftp):\S+/m # _http://url #CHECK dob.obj=dob.obj.gsub(/(^|[#{Mx[:gl_c]}#{Mx[:lnk_c]}#{Mx[:en_a_o]}#{Mx[:en_b_o]}(\s])(_(?:https?|ftp):\/\/\S+?\.[^>< ]+?)([,.;'"]?)(?=[\s#{Mx[:en_a_c]}#{Mx[:en_b_c]}#{Mx[:br_line]}#{Mx[:br_paragraph]}#{Mx[:br_nl]}]|$)/m, %{\\1#{Mx[:url_o]}\\2#{Mx[:url_c]}\\3}) end dob=fontface(dob) dob.obj=dob.obj. gsub(/<[:e]\s+(.+?)!?>/, "#{Mx[:en_a_o]}\\1#{Mx[:en_a_c]}"). #not tested gsub(/(^|#{Mx[:br_nl]})\s*_\*\s*/, "\\1#{Mx[:gl_bullet]}"). #bullets, shortcut gsub(/=\{(.+?)\}/, "#{Mx[:idx_o]}\\1#{Mx[:idx_c]}"). gsub(/^\s*_([1-9])\*\s*/, "#{Mx[:pa_o]}:i\\1:\\1#{Mx[:pa_c]}#{Mx[:gl_bullet]}"). #bullets, shortcut gsub(/^\s*_([1-9])\s+/, "#{Mx[:pa_o]}:i\\1:\\1#{Mx[:pa_c]}"). #indent gsub(/^\s*_([1-9])!\s+(.+?)\s*$/, "#{Mx[:pa_o]}:i\\1:\\1#{Mx[:pa_c]}#{Mx[:fa_bold_o]}\\2#{Mx[:fa_bold_c]} "). #indent bold gsub(/^\s*__([1-9])\s+/, "#{Mx[:pa_o]}:i0:\\1#{Mx[:pa_c]}"). #hang gsub(/^\s*__([1-9])!\s+(.+?)\s*$/, "#{Mx[:pa_o]}:i0:\\1#{Mx[:pa_c]}#{Mx[:fa_bold_o]}\\2#{Mx[:fa_bold_c]} "). #hangdef gsub(/^\s*_([0-9])_([0-9])\s+/, "#{Mx[:pa_o]}:i\\1:\\2#{Mx[:pa_c]}"). #hang gsub(/^\s*_([0-9])_([0-9])!\s+(.+?)\s*$/, "#{Mx[:pa_o]}:i\\1:\\2#{Mx[:pa_c]}#{Mx[:fa_bold_o]}\\3#{Mx[:fa_bold_c]} "). #hangdef gsub(/<:hi>/,"#{Mx[:fa_hilite_o]}"). #'<span style="background-color: rgb(255,240,196)">'). # bright yellow rgb(255,255,0) pale yellow rgb(255,255,200) gsub(/<:\/hi>/,"#{Mx[:fa_hilite_c]}"). #'</span>'). gsub(/(#{Mx[:gr_o]}verse#{Mx[:gr_c]}.+)/m,"\\1\n"). gsub(/[ ]+($)/,'\1'). gsub(/\{\s*(.+?)\s*\}(https?:\S+?)([;,.]?)(?=\s|[#{Mx[:br_line]}#{Mx[:br_paragraph]}#{Mx[:br_nl]}#{Mx[:en_a_o]}#{Mx[:en_b_o]}]|$)/, "#{Mx[:lnk_o]}\\1#{Mx[:lnk_c]}#{Mx[:url_o]}\\2#{Mx[:url_c]}\\3"). #any remaining linked text or image gsub(/\{\s*(.+?)\s*\}(#{Mx[:url_o]}\S+?#{Mx[:url_c]})/, "#{Mx[:lnk_o]}\\1#{Mx[:lnk_c]}\\2"). #any remaining linked text or image gsub(/(^|\s)([a-zA-Z0-9._-]+\@\S+?\.[a-zA-Z0-9._-]+)/,"\\1#{Mx[:url_o]}\\2#{Mx[:url_c]}"). gsub(/(^|[ ])\{\s*(.+?)\s*\}(\S+?)([;,.]?)(?=\s|[#{Mx[:br_line]}#{Mx[:br_paragraph]}#{Mx[:br_nl]}#{Mx[:en_a_o]}#{Mx[:en_b_o]}]|$)/, "\\1#{Mx[:lnk_o]}\\2#{Mx[:lnk_c]}\\3\\4"). #any remaining linked text or image gsub(/\{\s*(.+?)\s*\}#([a-zA-Z0-9][a-zA-Z0-9_-]*)([;,.]?)(?=\s|[#{Mx[:br_line]}#{Mx[:br_paragraph]}#{Mx[:br_nl]}#{Mx[:en_a_o]}#{Mx[:en_b_o]}]|$)/, "#{Mx[:lnk_o]}\\1#{Mx[:lnk_c]}#{Mx[:rel_o]}\\2#{Mx[:rel_c]}\\3"). #any remaining linked text or image, check need gsub(/\{\s*(.+?)\s*\}(#{Mx[:rel_o]}\S+?#{Mx[:rel_c]})/, "#{Mx[:lnk_o]}\\1#{Mx[:lnk_c]}\\2"). #any remaining linked text or image, check need gsub(/\{\s*(.+?)\s*\}(image)/, "#{Mx[:lnk_o]}\\1#{Mx[:lnk_c]}\\2") #linked image elsif dob.is==:table dob=fontface(dob) elsif dob.is ==:code dob.obj=dob.obj. gsub(/#{Mx[:meta_o]}(\S+?)#{Mx[:meta_c]}\s*/,'@\1: '). gsub(/(^|#{Mx[:gl_c]}|\s)<(?:br(?: \/)?)>([\s,.]|$)/,'\1<br>\2') #convert <br> <br /> back, clumsy if dob.number_ codeline=[] ln=1 dob.obj.split(/#{Mx[:gr_o]}codeline#{Mx[:gr_c]}|<br(?: \/)?>|\n/).each_with_index do |cl,i| unless i == 0 cl=cl.gsub(Mx[:br_nl],'') w=3-ln.to_s.length cl = "#{ln}#{Mx[:nbsp]*w}#{Mx[:vline]}#{cl}#{Mx[:br_nl]}" ln +=1 end codeline << cl end codeline= codeline.join("") dob.obj=codeline else dob.obj=dob.obj.gsub(/#{Mx[:gr_o]}codeline#{Mx[:gr_c]}/,"\n") end dob else # @\S+?: end dob end def tech #script markup planned to be more strict for technical documents # *{emphasis}* e{emphasis}e <strong>emphasis</strong> # !{bold text}! b{bold}b <b>bold text</b> # _{underline}_ u{underline}u <u>underline</u> # /{italics}/ i{italics}i <i>italics</i> # "{citation}" c{citation}c <cite>citation</cite> # ^{superscript}^ <sup>superscript</sup> # ,{subscript}, <sub>subscript</sub> # +{inserted text}+ <ins>inserted text</ins> # -{deleted text}- <del>deleted text</del> # #{monospace text}# # {url address}:url # {image.png}imageurl # {image.png}png # ~{endnote}~ # +1 <!i1!> # +2 <!i2!> puts 'tech' @data.each do |line| line=line. gsub(/(^|\s+|['"]|#{Mx[:fa_o_c]}|#{Mx[:fa_c]}|[\(\[]|\>)e\{(.+?)\}e/, "\\1#{@emph[:o]}\\2#{@emph[:c]}"). #emphasis gsub(/(^|\s+|['"]|#{Mx[:fa_o_c]}|#{Mx[:fa_c]}|[\(\[]|\>)b\{(.+?)\}b/, "\\1#{Mx[:fa_bold_o]}\\2#{Mx[:fa_bold_c]}"). #bold gsub(/(^|\s+|['"]|#{Mx[:fa_o_c]}|#{Mx[:fa_c]}|[\(\[]|\>)u\{(.+?)\}u/, "\\1#{Mx[:fa_underscore_o]}\\2#{Mx[:fa_underscore_c]}"). #underscore gsub(/(^|\s+|['"]|#{Mx[:fa_o_c]}|#{Mx[:fa_c]}|[\(\[]|\>)c\{(.+?)\}c/, "\\1#{Mx[:fa_cite_o]}\\2#{Mx[:fa_c_o]}cite#{Mx[:fa_c]}"). #cite gsub(/(^|\s+|['"]|#{Mx[:fa_o_c]}|#{Mx[:fa_c]}|[\(\[]|\>)i\{(.+?)\}i/, "\\1#{Mx[:fa_italics_o]}\\2#{Mx[:fa_italics_c]}"). #italics gsub(/(^|\s+|['"]|#{Mx[:fa_o_c]}|#{Mx[:fa_c]}|[\(\[]|\>)!\{(.+?)\}!/, "\\1#{Mx[:fa_bold_o]}\\2#{Mx[:fa_bold_c]}"). #bold gsub(/(^|\s+|['"]|#{Mx[:fa_o_c]}|#{Mx[:fa_c]}|[\(\[]|\>)\*\{(.+?)\}\*/, "\\1#{@emph[:o]}\\2#{@emph[:c]}"). #emphasis gsub(/(^|\s+|['"]|#{Mx[:fa_o_c]}|#{Mx[:fa_c]}|[\(\[]|\>)_\{(.+?)\}_/, "\\1#{Mx[:fa_underscore_o]}\\2#{Mx[:fa_underscore_c]}"). #underscore gsub(/(^|\s+|['"]|#{Mx[:fa_o_c]}|#{Mx[:fa_c]}|[\(\[]|\(|\>)\/\{(.+?)\}\//, "\\1#{Mx[:fa_italics_o]}\\2#{Mx[:fa_italics_c]}"). #italics gsub(/(^|\s+|['"]|#{Mx[:fa_o_c]}|#{Mx[:fa_c]}|\(|\>)\"\{(.+?)\}\"/, "\\1#{Mx[:fa_cite_o]}\\2#{Mx[:fa_c_o]}cite#{Mx[:fa_c]}"). gsub(/(^|\s+|['"]|#{Mx[:fa_o_c]}|#{Mx[:fa_c]}|\(|\>)\^\{(.+?)\}\^/, "\\1#{Mx[:fa_superscript_o]}\\2#{Mx[:fa_superscript_c]}"). gsub(/(^|\s+|['"]|#{Mx[:fa_o_c]}|#{Mx[:fa_c]}|\(|\>)9\{(.+?)\}9/, "\\1#{Mx[:fa_superscript_o]}\\2#{Mx[:fa_superscript_c]}"). gsub(/(^|\s+|['"]|#{Mx[:fa_o_c]}|#{Mx[:fa_c]}|\(|\>),\{(.+?)\},/, "\\1#{Mx[:fa_subscript_o]}\\2#{Mx[:fa_subscript_c]}"). gsub(/(^|\s+|['"]|#{Mx[:fa_o_c]}|#{Mx[:fa_c]}|\(|\>)6\{(.+?)\}6/, "\\1#{Mx[:fa_subscript_o]}\\2#{Mx[:fa_subscript_c]}"). gsub(/(^|\s+|['"]|#{Mx[:fa_o_c]}|#{Mx[:fa_c]}|\(|\>)\+\{(.+?)\}\+/, "\\1#{Mx[:fa_insert_o]}\\2#{Mx[:fa_insert_c]}"). gsub(/(^|\s+|['"]|#{Mx[:fa_o_c]}|#{Mx[:fa_c]}|\(|\>)v\{(.+?)\}v/, "\\1#{Mx[:fa_insert_o]}\\2#{Mx[:fa_insert_c]}"). gsub(/(^|\s+|['"]|#{Mx[:fa_o_c]}|#{Mx[:fa_c]}|\(|\>)-\{(.+?)\}-/, "\\1#{Mx[:fa_strike_o]}\\2#{Mx[:fa_strike_c]}"). gsub(/(^|\s+|['"]|#{Mx[:fa_o_c]}|#{Mx[:fa_c]}|\(|\>)x\{(.+?)\}x/, "\\1#{Mx[:fa_strike_o]}\\2#{Mx[:fa_strike_c]}"). gsub(/(^|\s+|['"]|#{Mx[:fa_o_c]}|#{Mx[:fa_c]}|\(|\>)\*(\S+?)\*/, "\\1#{@emph[:o]}\\2#{@emph[:c]}"). #emphasise single word, watch gsub(/(^|\s+|['"]|#{Mx[:fa_o_c]}|#{Mx[:fa_c]}|\(|\>)\!(\S+?)\!/, "\\1#{Mx[:fa_bold_o]}\\2#{Mx[:fa_bold_c]}"). #bold single word, watch gsub(/(^|\s+|['"]|#{Mx[:fa_o_c]}|#{Mx[:fa_c]}|\(|\>)\/([\(\)a-zA-Z0-9']+?)\/([ ,.;:'"~$]|[^a-zA-Z0-9])/, "\\1#{Mx[:fa_italics_o]}\\2#{Mx[:fa_italics_c]}\\3"). #italics single word, watch gsub(/(^|\s+|['"]|#{Mx[:fa_o_c]}|#{Mx[:fa_c]}|\(|\>)_(\S+?)_/, "\\1#{Mx[:fa_underscore_o]}\\2#{Mx[:fa_underscore_c]}"). #underscore single word, watch gsub(/(^|\s+|['"]|#{Mx[:fa_o_c]}|#{Mx[:fa_c]}|\(|\>)\^(\S+?)\^/, "\\1#{Mx[:fa_superscript_o]}\\2#{Mx[:fa_superscript_c]}"). #check #superscript single word, watch digit added gsub(/^\s*_\([1-9]\)\(\*\+\)\s*/, "#{Mx[:pa_o]}:i\\1#{Mx[:pa_c]}#{Mx[:fa_o]}\\2#{Mx[:fa_c_o]}"). #bullets, shortcut gsub(/^\s*_\([1-9]\)\s+/, "#{Mx[:pa_o]}:i\\1#{Mx[:pa_c]}"). #watch gsub(/^\s*__\([1-9]\)\s+/, "#{Mx[:pa_o]}:h\\1#{Mx[:pa_c]}"). #watch #line.gsub(/^\s*__\([1-9]\)!\s+/, # "#{Mx[:pa_o]}:hd\\1#{Mx[:pa_c]}"). #watch gsub(/#{Mx[:br_line]}\s*_[12]\s+/, "#{Mx[:br_line]} ") #indent used in endnotes, not implemented, replace when ready with: line.gsub(/(?:<br>|<br \/>)\s*_([12])\s+/,'<br><:i\1> ') end @data end end end __END__ #+END_SRC ** ao_endnotes.rb #+HEADER: :tangle "../lib/sisu/ao_endnotes.rb" #+BEGIN_SRC ruby #<<sisu_document_header>> module SiSU_AO_Endnotes class Endnotes def initialize(md,data,endnote_array=nil) @md,@data,@endnote_array= md, data, endnote_array @endnote_counter, @endnote_counter_asterisk, @endnote_counter_dag= 1,1,1 end def endnotes data=@data endnote_ref=1 @tuned_file=data.each.map do |dob| # manually numbered endnotes <!e(\d)!> <!e_(\d)!> --> if @md.opt.selections.str =~/--no-asterisk|--no-annotate/ dob.obj=dob.obj. gsub(/#{Mx[:en_b_o]}\s.+?#{Mx[:en_b_c]}/,'') end if @md.opt.selections.str =~/--no-dagger|--no-annotate/ dob.obj=dob.obj. gsub(/#{Mx[:en_b_o]}[+]\s.+?#{Mx[:en_b_c]}/,'') end if (defined? dob.obj) \ && (defined? dob.is) \ && dob.is !=:code case dob.obj # auto-numbered endnotes <!e!> <!e_!> --> when /#{Mx[:en_a_o]}.+?#{Mx[:en_a_c]}|#{Mx[:en_b_o]}[*+]\s+.+?#{Mx[:en_b_c]}/ dob.obj=dob.obj. gsub(/\s*(#{Mx[:en_a_c]}|#{Mx[:en_b_c]})/,'\1') word_mode=dob.obj.scan(/\S+/m) word_mode=endnote_call_number(word_mode) dob.obj=word_mode.join(' ') endnote_ref+=1 when /~\^(?:\s|$)/ #%note inserts endnotes previously gathered from /^(<!e[:_]!>|[-~]\{{3})/ (in earlier loop) word_mode=dob.obj.scan(/\S+/m) word_mode=endnote_call_number(word_mode) dob.obj=word_mode.join(' ') endnote_ref+=1 end end dob end.flatten @endnote_counter, @endnote_counter_asterisk, @endnote_counter_dag= 1,1,1 @tuned_file end def endnote_call_number(words) words.each do |word| case word when /#{Mx[:en_a_o]}/ unless word =~/#{Mx[:en_a_o]}[*+]+/ word.gsub!(/#{Mx[:en_a_o]}/, "#{Mx[:en_a_o]}#{@endnote_counter} ") @endnote_counter+=1 end when /#{Mx[:en_b_o]}/ if word =~/#{Mx[:en_b_o]}[+]/ word.gsub!(/#{Mx[:en_b_o]}[+]/, "#{Mx[:en_b_o]}\+#{@endnote_counter_dag} ") @endnote_counter_dag+=1 else word.gsub!(/#{Mx[:en_b_o]}[*]?/, "#{Mx[:en_b_o]}\*#{@endnote_counter_asterisk} ") @endnote_counter_asterisk+=1 end when /~\^/ if @endnote_array word.gsub!(/~\^/, "#{@endnote_array[@endnote_counter-1]}") @endnote_counter+=1 end end end end end end __END__ #+END_SRC * document header #+NAME: sisu_document_header #+BEGIN_SRC text encoding: utf-8 - Name: SiSU - Description: documents, structuring, processing, publishing, search abstraction - Author: Ralph Amissah <ralph.amissah@gmail.com> - Copyright: (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2019, 2020, 2021, Ralph Amissah, All Rights Reserved. - License: GPL 3 or later: SiSU, a framework for document structuring, publishing and search Copyright (C) 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 <http://www.gnu.org/licenses/>. If you have Internet connection, the latest version of the GPL should be available at these locations: <http://www.fsf.org/licensing/licenses/gpl.html> <http://www.gnu.org/licenses/gpl.html> <http://www.sisudoc.org/sisu/en/manifest/gpl.fsf.html> - SiSU uses: - Standard SiSU markup syntax, - Standard SiSU meta-markup syntax, and the - Standard SiSU object citation numbering and system - Homepages: <http://www.sisudoc.org> - Git <https://git.sisudoc.org/projects/> <https://git.sisudoc.org/projects/?p=software/sisu.git;a=summary> <https://git.sisudoc.org/projects/?p=markup/sisu-markup-samples.git;a=summary> #+END_SRC