diff options
| author | Ralph Amissah <ralph.amissah@gmail.com> | 2021-04-02 19:37:00 -0400 | 
|---|---|---|
| committer | Ralph Amissah <ralph.amissah@gmail.com> | 2021-04-02 20:03:27 -0400 | 
| commit | 90051a7ea55acb043434b1c2483b878d602246ba (patch) | |
| tree | 9e803c11a0ac4e37023b3c79f19f5b372d4175ee /org/abstraction.org | |
| parent | nix ruby 3.0 (available) (diff) | |
org mode (ruby code within)
Diffstat (limited to 'org/abstraction.org')
| -rw-r--r-- | org/abstraction.org | 7291 | 
1 files changed, 7291 insertions, 0 deletions
| diff --git a/org/abstraction.org b/org/abstraction.org new file mode 100644 index 00000000..103c9218 --- /dev/null +++ b/org/abstraction.org @@ -0,0 +1,7291 @@ +-*- 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 + +* ao.rb +** ao.rb + +#+BEGIN_SRC ruby  :tangle "../lib/sisu/ao.rb" +# <<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 + +#+BEGIN_SRC ruby  :tangle "../lib/sisu/ao_appendices.rb" +# <<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 + +#+BEGIN_SRC ruby  :tangle "../lib/sisu/ao_character_check.rb" +# <<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 + +#+BEGIN_SRC ruby  :tangle "../lib/sisu/ao_composite.rb" +# <<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 + +#+BEGIN_SRC ruby  :tangle "../lib/sisu/ao_doc_objects.rb" +# <<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 + +#+BEGIN_SRC ruby  :tangle "../lib/sisu/ao_doc_str.rb" +# <<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 + +#+BEGIN_SRC ruby  :tangle "../lib/sisu/ao_endnotes.rb_" +# <<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 + +#+BEGIN_SRC ruby  :tangle "../lib/sisu/ao_expand_insertions.rb" +# <<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 + +#+BEGIN_SRC ruby  :tangle "../lib/sisu/ao_hash_digest.rb" +# <<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 + +#+BEGIN_SRC ruby  :tangle "../lib/sisu/ao_idx.rb" +# <<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 + +#+BEGIN_SRC ruby  :tangle "../lib/sisu/ao_images.rb" +# <<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 + +#+BEGIN_SRC ruby  :tangle "../lib/sisu/ao_metadata.rb" +# <<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 + +#+BEGIN_SRC ruby  :tangle "../lib/sisu/ao_misc_arrange.rb" +# <<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 + +#+BEGIN_SRC ruby  :tangle "../lib/sisu/ao_numbering.rb" +# <<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 + +#+BEGIN_SRC ruby  :tangle "../lib/sisu/ao_persist.rb" +# <<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 + +#+BEGIN_SRC ruby  :tangle "../lib/sisu/ao_syntax.rb" +# <<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 + +#+BEGIN_SRC ruby  :tangle "../lib/sisu/ao_endnotes.rb" +# <<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 | 
