-*- mode: org -*-
#+TITLE:       sisu html
#+DESCRIPTION: documents - structuring, various output representations & search
#+FILETAGS:    :sisu:html:
#+AUTHOR:      Ralph Amissah
#+EMAIL:       [[mailto:ralph.amissah@gmail.com][ralph.amissah@gmail.com]]
#+COPYRIGHT:   Copyright (C) 2015 - 2021 Ralph Amissah
#+LANGUAGE:    en
#+STARTUP:     content hideblocks hidestars noindent entitiespretty
#+OPTIONS:     H:3 num:nil toc:t \n:nil @:t ::t |:t ^:nil _:nil -:t f:t *:t <:t
#+PROPERTY:    header-args  :exports code
#+PROPERTY:    header-args+ :noweb yes
#+PROPERTY:    header-args+ :eval no
#+PROPERTY:    header-args+ :results no
#+PROPERTY:    header-args+ :cache no
#+PROPERTY:    header-args+ :padline no
#+PROPERTY:    header-args+ :mkdirp yes

* html
** part
*** html.rb

#+HEADER: :tangle "../lib/sisu/html.rb"
#+BEGIN_SRC ruby
#<<sisu_document_header>>
module SiSU_HTML
  begin
    require 'pstore'
  rescue LoadError
    SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia).
      error('pstore NOT FOUND (LoadError)')
  end
  require_relative 'se_hub_particulars'                 # se_hub_particulars.rb
    include SiSU_Particulars
  require_relative 'html_table'                         # html_table.rb
  require_relative 'html_parts'                         # html_parts.rb
  require_relative 'html_format'                        # html_format.rb
    include SiSU_HTML_Format
  require_relative 'html_segments'                      # html_segments.rb
    include SiSU_HTML_Seg
  require_relative 'html_scroll'                        # html_scroll.rb
  require_relative 'html_promo'                         # html_promo.rb
    include SiSU_HTML_Promo
  require_relative 'html_tune'                          # html_tune.rb
    include SiSU_HTML_Tune
  class Source
    def initialize(opt)
      @opt=opt
      @particulars=SiSU_Particulars::CombinedSingleton.instance.get_all(opt)
    end
    def read
      begin
        songsheet
      ensure
        SiSU_Env::CreateSite.new(@opt).cp_css
        SiSU_Env::CreateSite.new(@opt).cp_base_images
        Dir.chdir(@opt.f_pth[:pth])
      end
    end
    def songsheet
      begin
        @md=@particulars.md
        @fnb=@md.fnb
        @env=@particulars.env
        primary_output_file=(@opt.act[:html_seg][:set]==:on) \
        ? (@md.file.output_path.html_seg.dir + '/' + @md.file.base_filename.html_segtoc)
        : (@md.file.output_path.html_scroll.dir + '/' + @md.file.base_filename.html_scroll)
        unless @opt.act[:quiet][:set]==:on
          tool=(@opt.act[:verbose][:set]==:on \
          || @opt.act[:verbose_plus][:set]==:on \
          || @opt.act[:maintenance][:set]==:on) \
          ? ("#{@env.program.web_browser} file://#{primary_output_file}")
          : ("[#{@opt.f_pth[:lng_is]}] #{@opt.fno}")
          (@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],
              'HTML',
              tool
            ).green_hi_blue
          : SiSU_Screen::Ansi.new(
              @opt.act[:color_state][:set],
              'HTML',
              tool
            ).green_title_hi
          if (@opt.act[:verbose_plus][:set]==:on \
          || @opt.act[:maintenance][:set]==:on)
            SiSU_Screen::Ansi.new(
              @opt.act[:color_state][:set],
              @opt.fns,
              "file://#{primary_output_file}"
            ).flow
          end
        end
        data=nil
        tuned_file_array=SiSU_HTML::Source::HTML_Environment.new(@particulars).tuned_file_instructions
        data=tuned_file_array
        if @opt.act[:html_scroll][:set]==:on
          scr_endnotes=SiSU_HTML::Source::Endnotes.new(data,@md).scroll
        end
        toc=SiSU_HTML::Source::Toc.new(@md,data).songsheet
        links_guide=SiSU_HTML::Source::LinksGuide.new(data,@md).toc
        data=tuned_file_array
        scr_toc=SiSU_HTML::Source::ScrollHeadAndSegToc.new(@md,toc,links_guide).in_common #watch
        if @opt.act[:html_seg][:set]==:on
          SiSU_HTML::Source::Seg.new(@md,data).songsheet
        end
        data=tuned_file_array
        if @opt.act[:html_scroll][:set]==:on
          scr=SiSU_HTML::Source::Scroll.new(@md,data,scr_endnotes).songsheet
          scroll=SiSU_HTML::Source::ScrollOutput.new(
            scr_toc,
            scr[:body],
            scr[:metadata],
            scr[:owner_details],
            scr[:tails],
            @md
          ).publish
          SiSU_HTML::Source::Output.new(scroll,@md).scroll
        end
      rescue
        SiSU_Errors::Rescued.new($!,$@,@opt.selections.str,@opt.fns).location do
          __LINE__.to_s + ':' + __FILE__
        end
      ensure
        unless (@opt.act[:verbose_plus][:set]==:on \
        || @opt.act[:maintenance][:set]==:on)
          texfiles=Dir["#{@env.processing_path.tune}/#{@opt.fns}*"]
          texfiles.each do |f|
            if FileTest.file?(f)
              File.unlink(f)
            end
          end
        end
        SiSU_Env::Clear.new(@opt.selections.str,@opt.fns,@md).param_instantiate
        @@flag,@@scr,@@seg,@@seg_endnotes,@@seg_subtoc={},{},{},{},{}
        @@tracker=0
        @@seg_name,@@seg_name_x,@@seg_subtoc_array,@@seg_endnotes_array,@@tablefoot=Array.new(5){[]}
        @@filename_seg,@@seg_url,@@to_lev4,@@get_hash_to,@@get_hash_fn='','','','',''
      end
    end
    private
    class HTML_Environment
      def initialize(particulars)
        @particulars=particulars
        @md,@env=particulars.md,particulars.env
        @env,@css=particulars.env,SiSU_Style::CSS.new
      end
      def tuned_file_instructions
        @tell=SiSU_Screen::Ansi.new(@md.opt.act[:color_state][:set])
        ao_array=@particulars.ao_array # ao file drawn here
        tuned_file_array=SiSU_HTML_Tune::Tune.new(ao_array,@md).songsheet
        tuned_file_array
      end
    end
    class LinksGuide
      @links_guide_toc=[]
      def initialize(data,md)
        @data,@md=data,md
        @links_guide_=SiSU_Env::CreateSite.new(@md.opt).html_quick_ref?
      end
      def toc
        @links_guide_toc=[]
        if @links_guide_
          format_head_toc=SiSU_HTML_Format::HeadToc.new(@md)
          guide_type='horzontal' #values: horizontal or vertical
          @links_guide_toc << format_head_toc.links_guide_open(guide_type)
          if defined? @md.lnk \
          and @md.lnk
            @md.lnk.each do |l|
              if defined? l[:say]
                target=(l[:url] !~/^\.(\.)?\//) \
                ? 'external'
                : '_top'
                s_lnk_url,s_lnk_lnk=l[:url],l[:say]
                txt_obj={
                  lnk_url: s_lnk_url,
                  lnk_txt: s_lnk_lnk,
                  target: target,
                }
                lev_dob_ocn=SiSU_HTML_Format::FormatToc.new(@md,txt_obj)
                @links_guide_toc << lev_dob_ocn.links_guide if s_lnk_lnk
              end
            end
          end
          format_head_toc=SiSU_HTML_Format::HeadToc.new(@md)
          @links_guide_toc << format_head_toc.links_guide_close #(guide_type)
          @links_guide_toc
        else ''
        end
      end
    end
    class Endnotes
      include SiSU_HTML_Format
      def initialize(data,md)
        @data,@md=data,md
      end
      def scroll
        @scr_endnotes=[]
        SiSU_HTML_Format::HeadScroll.new(@md)
        @data.each do |dob|
          pg=dob.dup
          unless pg.is ==:code
            if pg.obj =~/(?:#{Mx[:en_a_o]}|#{Mx[:en_b_o]})[\d*+]+ /
              endnote_array=[]
              if pg.obj=~/#{Mx[:en_a_o]}[\d*+].+?#{Mx[:en_a_c]}/m
                endnote_array = pg.obj.scan(/#{Mx[:en_a_o]}[\d*+]+(.+?)#{Mx[:en_a_c]}/m)
              end
              if pg.obj=~/#{Mx[:en_b_o]}[\d*]+\s.+?#{Mx[:en_b_c]}/m
                endnote_array = pg.obj.scan(/#{Mx[:en_b_o]}[\d*]+(.+?)#{Mx[:en_b_c]}/m)
              end
              if pg.obj=~/#{Mx[:en_b_o]}[\d+]+\s.+?#{Mx[:en_b_c]}/m
                endnote_array = pg.obj.scan(/#{Mx[:en_b_o]}[\d+]+(.+?)#{Mx[:en_b_c]}/m)
              end
              endnote_array.flatten.each do |note|
                txt_obj={ txt: note }
                format_scroll=SiSU_HTML_Format::FormatScroll.new(@md,txt_obj)
                @scr_endnotes << format_scroll.endnote_body
              end
            end
          end
        end
        @scr_endnotes
      end
    end
    class Toc <LinksGuide
      @@toc={ seg: [], seg_mini: [], scr: [] }
      @@seg_url=''
      @@firstseg=nil
      def initialize(md=nil,data='')
        @data,@md=data,md
        @tell=SiSU_Screen::Ansi.new(@md.opt.act[:color_state][:set]) if @md
      end
      def songsheet #extracts toc for scroll & seg
        if (@md.opt.act[:verbose][:set]==:on \
        || @md.opt.act[:verbose_plus][:set]==:on \
        || @md.opt.act[:maintenance][:set]==:on)
          SiSU_Screen::Ansi.new(
            @md.opt.act[:color_state][:set],
            'Toc'
          ).txt_grey
        end
        toc=nil
        @@firstseg=nil
        @@toc={ seg: [], seg_mini: [], scr: [] }
        @data.each do |dob|
          if dob.is==:heading \
          || dob.is==:heading_insert
            dob_toc=dob.dup
            toc=if dob_toc.is ==:heading \
            || dob.is==:heading_insert
              toc=case dob_toc.ln
              when 0 then SiSU_HTML::Source::Toc.new(@md,dob_toc).level_0
              when 1 then SiSU_HTML::Source::Toc.new(@md,dob_toc).level_1
              when 2 then SiSU_HTML::Source::Toc.new(@md,dob_toc).level_2
              when 3 then SiSU_HTML::Source::Toc.new(@md,dob_toc).level_3
              when 4 then SiSU_HTML::Source::Toc.new(@md,dob_toc).level_4
              when 5 then SiSU_HTML::Source::Toc.new(@md,dob_toc).level_5
              when 6 then SiSU_HTML::Source::Toc.new(@md,dob_toc).level_6
              else nil
              end
            end
            toc.each do |k,d|
              d.gsub!(/(?:#{Mx[:en_a_o]}.+?#{Mx[:en_a_c]}|#{Mx[:en_b_o]}.+?#{Mx[:en_b_c]})\s*/m,' ')
            end if toc
            if @@firstseg.nil? \
            and dob.ln==4 \
            and dob.name =~/\S+/
              @@firstseg=dob.name
            end
            if toc
              begin
                @@toc[:seg] << toc[:seg] if toc[:seg]
                @@toc[:seg_mini] << toc[:seg_mini] if toc[:seg_mini]
                @@toc[:scr] << toc[:scr] if toc[:scr]
              rescue
                SiSU_Errors::Rescued.new($!,$@,@md.opt.selections.str,@md.fns).location do
                  __LINE__.to_s + ':' + __FILE__
                end
              end
            end
          end
        end
        @md.firstseg=@@firstseg
        @@toc
      end
      def minitoc
        minitoc=@@toc[:seg_mini].join("\n")
        '<div class="toc">' + minitoc + '</div>'
      end
    protected
      def rss #sort all wrong, disabled but kept
        @@toc[:seg] <<<<WOK
<center>
<table><tr><td>
<p><font color="#222222" #{the_font.set_face} size="2">
(relatively static) RSS feeds for DOCUMENTS:<br>
<a href="../rssfeed/documents.xml"><img border="0" height="14" width="36" src="../_sisu/image/rss.png" alt="RSS feed"></a>&nbsp;http://www.jus.uio.no/lm/rssfeed/documents.xml<br>
<a href="../rssfeed/tradelaw.xml"><img border="0" height="14" width="36" src="../_sisu/image/rss.png" alt="RSS feed"></a>&nbsp;http://www.jus.uio.no/lm/rssfeed/tradelaw.xml<br>
<a href="../rssfeed/environmental.xml"><img border="0" height="14" width="36" src="../_sisu/image/rss.png" alt="RSS feed"></a>&nbsp;http://www.jus.uio.no/lm/rssfeed/environmental.xml<br>
<center><a href="mailto:info@address.com" target="_top">info@address.com</a></center>
</font></p>
</td></tr></table>
WOK
      end
#not used -->
      def level_endnotes
        if @md.flag_endnotes
          format_head_scroll=SiSU_HTML_Format::HeadScroll.new(@md)
          @@toc[:scr] << format_head_scroll.toc_endnote
        end
      end
      def level_concordance
        format_head_toc=SiSU_HTML_Format::HeadToc.new(@md)
        @@toc[:seg_mini] << format_head_toc.mini_seg_concordance
      end
      def level_metadata
        format_head_toc=SiSU_HTML_Format::HeadToc.new(@md)
        @@toc[:scr] << format_head_toc.metadata
        @@toc[:seg] << format_head_toc.seg_metadata
        @@toc[:seg_mini] << format_head_toc.mini_seg_metadata
      end
      def level_word_index
        format_head_toc=SiSU_HTML_Format::HeadToc.new(@d0c)
        @@toc[:scr] << format_head_toc.concordance
        @@toc[:seg] << format_head_toc.concordance
        @@toc[:seg_mini] << format_head_toc.mini_concordance
      end
# <-- not used
      def level_0
        dob=@data
        linkname,link=dob.obj.strip,dob.ocn
        if link \
        and link.to_s !~/#/ #% keep eye on link
          SiSU_HTML_Format::ParagraphNumber.new(@md,link)
        end
        title=linkname
        toc={}
        txt_obj={ txt: title }
        format_toc=SiSU_HTML_Format::FormatToc.new(@md,txt_obj)
        toc[:seg]=format_toc.lev0
        toc[:seg_mini]=format_toc.mini_lev0
        title=if dob.ocn ==0 then linkname
        else
          @@toc[:scr] <<  '<br>'
          %{<b><a href="##{dob.ocn}">#{linkname}</a></b>}
        end
        txt_obj={ txt: title }
        format_toc=SiSU_HTML_Format::FormatToc.new(@md,txt_obj)
        toc[:scr]=format_toc.lev0
        toc
      end
      def level_1
        dob=@data
        linkname,link=dob.obj.strip,dob.ocn
        if link \
        and link.to_s !~/#/ #% keep eye on link
          SiSU_HTML_Format::ParagraphNumber.new(@md,link)
        end
        title=if dob.obj !~/^Metadata$/ then linkname
        else
          link='metadata'
          %{<b><a href="#{link}#{@md.lang_code_insert}#{Sfx[:html]}">#{linkname}</a></b>}
        end
        toc={}
        txt_obj={ txt: title }
        format_toc=SiSU_HTML_Format::FormatToc.new(@md,txt_obj)
        toc[:seg]=if dob.name =~/^meta/ \
        and dob.obj =~/Document Information/
          format_toc.lev0
        else format_toc.lev1
        end
        toc[:seg_mini]=if dob.name =~/^meta/ \
        and dob.obj =~/Document Information/
          @md.concord_make \
          ? format_toc.mini_concord_tail
          : format_toc.mini_tail
        else format_toc.mini_lev1
        end
        title=if dob.ocn ==0
          if dob.name =~/^meta/ \
          and dob.obj =~/Document Information/
            %{<a href="#docinfo">#{linkname}</a>}
          else linkname
          end
        else
          @@toc[:scr] <<  '<br>'
          %{<b><a href="##{dob.ocn}">#{linkname}</a></b>}
        end
        txt_obj={ txt: title }
        format_toc=SiSU_HTML_Format::FormatToc.new(@md,txt_obj)
        toc[:scr]=if dob.obj =~/^Metadata$/ then ''
        elsif txt_obj[:txt] =~/<a href="#">/
          format_toc.lev1.gsub(/<a href="#">|<\/a>/,'')
        else format_toc.lev1
        end
        toc
      end
      def level_2
        dob=@data
        linkname,ocn=dob.obj.strip,dob.ocn
        p_num=if ocn \
        and ocn.to_s !~/#/
          SiSU_HTML_Format::ParagraphNumber.new(@md,ocn)
        else nil
        end
        txt_obj={ txt: linkname }
        format_toc=SiSU_HTML_Format::FormatToc.new(@md,txt_obj)
        toc={}
        toc[:seg]=format_toc.lev2
        toc[:seg_mini]=format_toc.mini_lev2
        if p_num
          title=%{#{p_num.goto}#{linkname}</a>}
          txt_obj={ txt: title }
          format_toc=SiSU_HTML_Format::FormatToc.new(@md,txt_obj)
          toc[:scr]=if txt_obj[:txt] =~/<a href="#">/
            format_toc.lev2.gsub(/<a href="#">|<\/a>/,'')
          else format_toc.lev2
          end
        end
        toc
      end
      def level_3
        dob=@data
        linkname,ocn=dob.obj.strip,dob.ocn
        p_num=if ocn \
        and ocn.to_s !~/#/
          SiSU_HTML_Format::ParagraphNumber.new(@md,ocn)
        else nil
        end
        txt_obj={ txt: linkname }
        format_toc=SiSU_HTML_Format::FormatToc.new(@md,txt_obj)
        toc={}
        toc[:seg]=format_toc.lev3
        toc[:seg_mini]=format_toc.mini_lev3
        if p_num
          title=%{#{p_num.goto}#{linkname}</a>}
          txt_obj={ txt: title }
          format_toc=SiSU_HTML_Format::FormatToc.new(@md,txt_obj)
          toc[:scr]=if txt_obj[:txt] =~/<a href="#">/
            format_toc.lev3.gsub(/<a href="#">|<\/a>/,'')
          else format_toc.lev3
          end
        end
        toc
      end
      def level_4
        dob=@data
        linkname,ocn=dob.obj.strip,dob.ocn
        p_num=SiSU_HTML_Format::ParagraphNumber.new(@md,ocn) if ocn
        if dob.ln ==4
          fnh={
            fn: dob.name,
          }
          f=@md.file.base_filename.html_seg(fnh)
          seg_link=%{  <a href="#{f}" target="_top">
    #{dob.obj}
  </a> }
          @@seg_url=dob.name
        elsif dob.obj =~/\d+.\d+.\d+.\d+|\d+.\d+.\d+|\d+.\d+|\d+/
          fn,hd=/^(\d+.\d+.\d+.\d+|\d+.\d+.\d+|\d+.\d+|\d+)(.*)/.match(dob.obj)[1,2]
          fnh={
            fn: fn,
          }
          f=@md.file.base_filename.html_seg(fnh)
          seg_link=%{<a href="#{f}" target="_top">#{fn} #{hd}</a> }
        end
        p_num=SiSU_HTML_Format::ParagraphNumber.new(@md,ocn) if ocn
        @file=SiSU_Env::FileOp.new(@md) if @md
        txt_obj=if seg_link=~/sisu_manifest\.html/
          man_link=if @file.output_dir_structure.by_language_code? \
          or @file.output_dir_structure.by_filetype?
            seg_link.gsub(/sisu_manifest\.html/,"../../manifest/#{@file.base_filename.manifest}")
          else seg_link
          end
          { txt: man_link }
        else { txt: seg_link }
        end
        format_toc=SiSU_HTML_Format::FormatToc.new(@md,txt_obj)
        toc={}
        toc[:seg]=format_toc.lev4
        toc[:seg_mini]=format_toc.mini_lev4
        title=%{#{p_num.goto}#{linkname}</a>} if p_num
        txt_obj=if title=~/sisu_manifest.html/
          man_link=title.gsub(/sisu_manifest.html/,"../manifest/#{@file.base_filename.manifest}")
          { txt: man_link }
        else { txt: title }
        end
        format_toc=SiSU_HTML_Format::FormatToc.new(@md,txt_obj)
        toc[:scr]=format_toc.lev4
        toc
       #end
      end
      def level_5
        dob=@data
        linkname,ocn=dob.obj.strip,dob.ocn
        toc={}
        if ocn \
        and ocn.to_s !~/#/
          fnh={
            fn: @@seg_url,
          }
          f=@md.file.base_filename.html_seg(fnh)
          p_num=SiSU_HTML_Format::ParagraphNumber.new(@md,ocn)
          lnk_n_txt=%{  <a href="#{f}##{ocn}">
    #{linkname}
  </a>}
          txt_obj={ txt: lnk_n_txt }
          format_toc=SiSU_HTML_Format::FormatToc.new(@md,txt_obj)
          toc[:seg]=format_toc.lev5
          toc[:seg_mini]=format_toc.mini_lev5
          title=%{#{p_num.goto}#{linkname}</a>}
          txt_obj={ txt: title }
          format_toc=SiSU_HTML_Format::FormatToc.new(@md,txt_obj)
          toc[:scr]=format_toc.lev5
        end
        toc
      end
      def level_6
        dob=@data
        linkname,ocn=dob.obj.strip,dob.ocn
        toc={}
        if ocn \
        and ocn.to_s !~/#/
          fnh={
            fn: @@seg_url,
          }
          f=@md.file.base_filename.html_seg(fnh)
          p_num=SiSU_HTML_Format::ParagraphNumber.new(@md,ocn)
          lnk_n_txt=%{  <a href="#{f}##{ocn}">
  #{linkname}
</a>}
          txt_obj={ txt: lnk_n_txt }
          format_toc=SiSU_HTML_Format::FormatToc.new(@md,txt_obj)
          toc[:seg]=format_toc.lev6
          toc[:seg_mini]=format_toc.mini_lev6
          title=%{#{p_num.goto}#{linkname}</a>}
          txt_obj={ txt: title }
          format_toc=SiSU_HTML_Format::FormatToc.new(@md,txt_obj)
          toc[:scr]=format_toc.lev6
        end
        toc
      end
      def level_crosslink
        dob=@data
        dob=if dob !~/^4~!/
          dob.gsub(/^4~!\s+(\S+)\s+(.+)/,
            %{<table><tr><td width =\"80\"></td>
  <td><a href="http://\\1" target="_top">
    #{@png.crosslink_ext}
      &nbsp;&nbsp;\\2
    <\/a>
  </td></tr></table>
})
        else
          dob.gsub(/^4~!\s+(\S+)\s+(.+)/,
            %{<table><tr><td width ="80">
  </td><td>
    <a href="\\1" target="_top">
      #{@png.crosslink}
        &nbsp;&nbsp;\\2
    <\/a>
  </td></tr></table>
})
        end
      end
    end
    class ScrollHeadAndSegToc < Toc
      include SiSU_Parts_HTML
      def initialize(md='',toc='',links_guide_toc='')
        @md,@toc,@links_guide_toc=md,toc,links_guide_toc
        @make=SiSU_Env::ProcessingSettings.new(@md)
      end
      def in_common
        toc_shared=[]
        @segtoc=[]
        if (@md.opt.act[:verbose][:set]==:on \
        || @md.opt.act[:verbose_plus][:set]==:on \
        || @md.opt.act[:maintenance][:set]==:on)
          SiSU_Screen::Ansi.new(
            @md.opt.act[:color_state][:set],
            'Scroll & Segtoc'
          ).txt_grey
        end
        format_head_toc=SiSU_HTML_Format::HeadToc.new(@md)
        dochead=format_head_toc.head
        dochead=dochead.gsub(/toc\.(html)/,'doc.\1') #kludge
        toc_shared << dochead
        @segtoc << format_head_toc.head
        if @make.build.html_top_band?
          toc_shared << format_head_toc.scroll_head_navigation_band
        end
        if defined? @md.rights.all
          rights=format_head_toc.rights.all
          rights=SiSU_HTML_Tune::CleanHTML.new(rights).clean
        end
        if @md.prefix_b
          prefix_b=format_head_toc.notes.prefix_b
          prefix_b=SiSU_HTML_Tune::CleanHTML.new(prefix_b).clean
        end
        if @make.build.html_top_band?
          @segtoc << format_head_toc.seg_head_navigation_band
        end
        toc_shared << format_head_toc.scroll_head_title_banner_open
        @segtoc << format_head_toc.seg_head_title_banner_open
        tmp_head=nil
        doc_title_endnote=@md.title.full.gsub(/(\*+)/,
          '<sup><a href="#endnotes">\1</a></sup>')
        tmp_head=doc_title_endnote + "\n"
        txt_obj={ txt: tmp_head }
        format_txt_obj=SiSU_HTML_Format::FormatTextObject.new(@md,txt_obj)
        toc_shared << format_txt_obj.center_bold
        @segtoc << format_txt_obj.center_bold
        if defined? @md.creator.author
          creator=SiSU_HTML_Tune::CleanHTML.new(@md.creator.author).clean_for_html
          creator_endnote=creator.gsub(/(\*+)/,
            %{&nbsp;<sup><a href="#notes">\\1</a></sup>})
          tmp_head=creator_endnote + "\n"
          txt_obj={ txt: tmp_head }
          format_txt_obj=SiSU_HTML_Format::FormatTextObject.new(@md,txt_obj)
          toc_shared << format_txt_obj.center_bold
          @segtoc << format_txt_obj.center_bold
        end
        toc_shared << "#{the_table_close*1}\n"
        @segtoc << "#{the_table_close*1}\n"
        tmp_head=nil
        if @md.prefix_a
          tmp_head ||= %{<p>#{@md.prefix_a}\n}
          toc_shared << tmp_head.dup
          @segtoc << tmp_head.dup
        end
        tmp_head=nil
        toc_shared << @links_guide_toc
        if defined? @md.rights.all #and ? @md.rights.all
          toc_shared << rights
        end
        if defined? @md.prefix_b
          toc_shared << prefix_b
        end
        if @make.build.toc? #Table of Contents added/appended here
          toc_shared << @toc[:scr]
        end
        @segtoc << @links_guide_toc
        @segtoc << @toc[:seg]
        if defined? @md.rights.all \
        and not @md.rights.all.empty?
          @segtoc << rights
        end
        @segtoc << prefix_b if @md.prefix_b
        #Segtoc tail added here
        @segtoc << "</p>\n" #bugfix sort later DEBUGNOW
        @segtoc << @seg_toc_band_bottom
        @segtoc << format_head_toc.seg_navigation_tail << format_head_toc.html_close
        @segtoc=@segtoc.flatten.compact #watch
        if @md.opt.act[:html_seg][:set]==:on
          SiSU_HTML::Source::Output.new(@segtoc,@md).segtoc
        end
        @segtoc=[]
        @toc[:scr],@toc[:seg]=[],[]
        toc_shared
      end
    end
    class Table < SiSU_HTML_Table::TableHTML
    end
    class Scroll < SiSU_HTML_Scroll::Scroll
    end
    class ScrollOutput
      def initialize(scr_toc,scr_body,scr_metadata,scr_owner_details,scr_tails,md)
        @scr_toc,@scr_body,@scr_metadata,@scr_owner_details,@scr_tails,@md=scr_toc,scr_body,scr_metadata,scr_owner_details,scr_tails,md
      end
      def publish
        scroll=[]
        scroll << @scr_toc << '<div class="scroll">' << @scr_body << @scr_endnotes << @scr_owner_details << '</div>' << @scr_tails
        scroll=scroll.flatten.compact #watch
      end
    end
    class Seg < SiSU_HTML_Seg::Seg
    end
    class Output
      def initialize(data='',md='')
        @data,@md=data,md
        @file=SiSU_Env::FileOp.new(md)
        @o_str ||=SiSU_Env::ProcessingSettings.new(md).output_dir_structure
      end
      def scroll
        if @md.opt.act[:html_scroll][:set]==:on
          begin
            @filename_html_scroll=@file.write_file.html_scroll
            @data.each do |para|
              para=para.strip.
                gsub(/<:.+?>/,'').
                gsub(Xx[:html_relative2],@file.path_rel_links.html_scroll_2).
                gsub(Xx[:html_relative1],@file.path_rel_links.html_scroll_1).
               #gsub(/#{Xx[:html_relative]}/,@file.path_rel_links.html_scroll).
                gsub(/#{Rx[:mx_fa_clean]}/,'')
              unless para =~/\A\s*\Z/
                @filename_html_scroll.puts para,"\n"
              end
            end
          rescue
            SiSU_Errors::Rescued.new($!,$@,@md.opt.selections.str,@md.fns).location do
              __LINE__.to_s + ':' + __FILE__
            end
          ensure
            @filename_html_scroll.close
          end
        end
      end
      def segtoc
        if @md.opt.act[:html_seg][:set]==:on
          begin
            @filename_html_segtoc=@file.write_file.html_segtoc
            @data.each do |para|
              para=para.strip.
                gsub(/<!.+?!>/,'').
                gsub(Xx[:html_relative2],@file.path_rel_links.html_seg_2).
                gsub(Xx[:html_relative1],@file.path_rel_links.html_seg_1)
              unless para =~/\A\s*\Z/
                @filename_html_segtoc.puts para,"\n"
              end
            end
          rescue
            SiSU_Errors::Rescued.new($!,$@,@md.opt.selections.str,@md.fns).location do
              __LINE__.to_s + ':' + __FILE__
            end
          ensure
            @filename_html_segtoc.close
            pwd_set=Dir.pwd
            idx_lnk=(@o_str.dump_or_redirect?) \
            ? @file.base_filename.manifest
            : @file.base_filename.html_segtoc
            mlnk=@file.base_filename.html_seg_index
            Dir.chdir(@file.output_path.html_seg.dir)
            FileUtils::rm_f(mlnk)
            FileUtils::ln_s(idx_lnk,mlnk)
            Dir.chdir(pwd_set)
          end
        end
      end
    end
  end
end
__END__
#+END_SRC

*** html_parts.rb

#+HEADER: :tangle "../lib/sisu/html_parts.rb"
#+BEGIN_SRC ruby
#<<sisu_document_header>>
module SiSU_Parts_HTML
  require_relative 'generic_parts'                       # generic_parts.rb
  include SiSU_Parts_Generic
  def the_line_break
    '<br>'
  end
  def the_table_close
    '</td></tr>
</table>'
  end
  def the_table_cellpad_box
    '"20"'
  end
  def the_color
    def white
      '#ffffff'
    end
    def black
      '#000000'
    end
    def grey_pale
      '#eeeeee'
    end
    def grey_medium
      '#cccccc'
    end
    def grey
      '#999999'
    end
    def blue_ink
      '#003399'
    end
    def blue_tinge
      '#e3ecef'
    end
    def yellow_light
      '#fff3b6'
    end
    def table1
      'ffffcc'
    end
    def table2
      'c0d0f0'
    end
    def band1
      %{"#{white}"}
    end
    def band2
      %{"#{white}"}
    end
    self
  end
  def the_url_decoration
    #def tex_open                     #'{\UseTextSymbol{OML}{<}}'
    #  Dx[:url_o]
    #end
    #def tex_close                    #'{\UseTextSymbol{OML}{>}}'
    #  Dx[:url_c]
    #end
    def xml_open                     #'&lt;'
      Dx[:url_o]
    end
    def xml_close                    #'&gt;'
      Dx[:url_c]
    end
    def txt_open
      '<'
    end
    def txt_close
      '>'
    end
    self
  end
  def the_width
    def table1
      '"100%"'
    end
    def table2
      '"99%"'
    end
    def table_txt
      '"94%"'
    end
    def table_txt_r
      '"96%"'
    end
    self
  end
  def the_png
    def _url_path_image_base #used for html image display
      "#{Xx[:html_relative2]}_sisu/image"
    end
    def ico
      %{  <link rel="shortcut icon" href="../_sisu/image/#{the_icon.i_ico}" />}
    end
    def png_home
      %{<img border="0" src="#{_url_path_image_base}/#{the_icon.home_button}" alt="#{the_text.home} --&gt;" />}
    end
    def png_home_button
      rel=@dir.path_rel_links.html_scroll_2
      %{<img border="0" src="#{rel}/#{the_icon.home_button}" alt="#{the_text.home} --&gt;" />}
    end
    self
  end
  def the_font
    def set_fonts
      'verdana, arial, georgia, tahoma, sans-serif, helvetica, times, roman'
     #'verdana, arial, georgia, tahoma, sans-serif, helvetica, "times new roman", times, roman'
    end
    def set_face
      %{face="#{set_fonts}"}
    end
    def set_color
      'color="#000000"'
    end
    def set_size_endnote
      'size="3"'
    end
    def set_small
      'size="3"'
    end
    def set_tiny
      'size="2"'
    end
    def paragraph_font_tiny
      %{<font #{set_tiny} #{set_face}>}
    end
    def paragraph_font_small
      %{<font #{set_small} #{set_face}>}
    end
    self
  end
  def the_nav
    def txt_homepage
      %{  <font face="#{the_font.set_fonts}" size="2">
    &nbsp;home&nbsp;
  </font> }
    end
    def txt_toc_link
      %{  <font face="#{the_font.set_fonts}" size="2">
    &nbsp;&nbsp;toc&nbsp;
  </font> }
    end
    def txt_doc_link
      %{  <font face="#{the_font.set_fonts}" size="2">
    &nbsp;scroll&nbsp;
  </font> }
    end
    def txt_manifest
      #{png_manifest}&nbsp;document&nbsp;manifest
      %{  <font face="#{the_font.set_fonts}" size="2">
    [&nbsp;document&nbsp;manifest&nbsp;]
  </font> }
    end
    def txt_concordance
      %{  <font face="#{the_font.set_fonts}" size="2">
    &nbsp;&nbsp;A-Z&nbsp;
  </font> }
    end
    self
  end
  def the_banner
    def home_button_only
      %{<a href="#{url.site}/">
  #{the_png.png_home_button}
  </a>}
    end
    def banner_band
      %{<table summary="home button" width="100%" border="0" cellpadding="3" align="center">
<tr><td align="left" valign="middle">
  <a href="#{url.site}/" target="_top">
    #{the_png.png_home}
  </a>
</td>
<td width="90%">
#{the_table_close}}
    end
    def instrument_cover_band_scr
      '<table summary="scroll instrument cover band" width="100%" border="0" cellpadding="8" align="center">
<tr><td align="center">'
    end
    def instrument_cover_band_seg
      '<table summary="segment instrument cover band, title, author, location" width="100%" border="0" cellpadding="8" align="center">
<tr><td align="center">'
    end
    self
  end
  def the_margin
    def txt_0
      %{<table summary="" width=#{the_width.table_txt} border="0" cellpadding="2" align="center">
<tr><td width=#{indent_level_0} align="right">
</td><td valign="top" align="justify">}
    end
    def txt_1
      %{<table summary="" width=#{the_width.table_txt} border="0" cellpadding="2" align="center">
<tr><td width=#{indent_level_1} align="right"></td><td valign="top" align="justify">}
    end
    def txt_2
      %{<table summary="" width=#{the_width.table_txt} border="0" cellpadding="2" align="center">
<tr><td width=#{indent_level_2} align="right">
</td>
<td valign="top" align="justify">}
    end
    def txt_3
      %{<table summary="" width=#{the_width.table_txt} border="0" cellpadding="2" align="center">
<tr><td width=#{indent_level_3} align="right">
</td>
<td valign="top" align="justify">}
    end
    def css
      '<table summary="normal text css" width="100%" border="0" cellpadding="2" align="center">
<tr><td valign="top" align="justify"> '
    end
    def num
      '</p> </td><td width="4%" align="right" valign="top">'
    end
    def numless
      '</td><td width="4%" align="right" valign="top">'
    end
    def num_css
      '</td>
<td width="2%" align="right" valign="top">  '
    end
    self
  end
end
module SiSU_Proj_HTML
  require_relative 'se'                                 # se.rb
  include SiSU_Env
  #require_relative 'css'                                # css.rb
  #  include SiSU_Style
  class Bits
    include SiSU_Parts_HTML
    def initialize
      @v=SiSU_Env::InfoVersion.instance.get_version
      #@dir=SiSU_Env::InfoEnv.new
      #@date=SiSU_Env::InfoDate.new #{@date.year}
    end
    def txt_generator
      %{  <meta name="generator" content="#{@v.project} #{@v.version} of #{@v.date_stamp} (#{@v.date}) (n*x and Ruby!)" />
    <link rel="generator" href="http://www.sisudoc.org/" />}
    end
    def widget_sisu_text
<<WOK
  <p class="tiny"><font color="#666666" size="2">
    Output generated by
    <a href="#{the_url.sisu}">
      #{@v.project}
    </a>
    #{@v.version} #{@v.date} (#{@v.date_stamp})
  </font></p>
WOK
    end
    def credits_sisu_manifest
      widget_sisu_text
    end
    def widget_sisu
<<WOK
<!-- widget sisu -->
<tr><td valign="top" width="100%">
<!-- SiSU Rights -->
#{widget_sisu_text}
</td></tr>
WOK
    end
    def credits_sisu
      %{<div class="substance">
<table summary="SiSU summary" cellpadding="4" border="0">
<tr><td>
  #{widget_sisu}
</table></div>}
      ''
    end
    def widget_promo # Array used to build promo from list.yml and promo.yml
    #  ['sisu_icon','sisu','sisu_search_libre','open_society','fsf','ruby']
    end
  end
  class Home
    def initialize
      @v=SiSU_Env::InfoVersion.instance.get_version
      @dir=SiSU_Env::InfoEnv.new
      @date=SiSU_Env::InfoDate.new #{@date.year}
    end
    def redirect
      <<WOK
<html><head>
<title>SiSU</title>
<meta http-equiv="refresh" content="0, url=http://www.sisudoc.org/sisu/SiSU/">
</head>
<body>
SiSU informtion provided at <a href="http://www.sisudoc.org/sisu/SiSU/">www.sisudoc.org/sisu/SiSU</a><p />
If your browser supports redirection, you will be escorted there shortly.
</body>
</html>
WOK
    end
    def homepage
      <<WOK
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<title>SiSU information Structuring Universe - Structured information, Serialized Units - software for electronic texts, documents, books, digital libraries in plaintext, HTML, EPUB, XHTML, XML, ODF (OpenDocument), LaTeX, PDF, SQL (PostgreSQL and SQLite), and for search</title>
<meta name="dc.title" content="SiSU - SiSU information Structuring Universe, Structured information Serialised Units, #{@date.year_static}" />
<meta name="dc.creator" content="Ralph Amissah" />
<meta name="dc.subject" content= "document structuring, ebook, publishing, PDF, LaTeX, XML, ODF, EPUB, SQL, postgresql, sqlite, electronic book, electronic publishing, electronic document, electronic citation, data structure, citation systems, granular search, digital library" />
<meta name="dc.publisher" content= "SiSU http://www.sisudoc.org/" />
<meta name="dc.language" content="en" />
<meta name="dc.rights" content="Copyright Ralph Amissah" />
<meta name="generator" content="#{@v.project} #{@v.version} of #{@v.date_stamp} (#{@v.date}) (n*x and Ruby!)" />
<link rel="generator" href="http://www.sisudoc.org/" />
<link rel="stylesheet" href="./#{@dir.path.style}/harvest.css" type="text/css" />
<link rel="shortcut icon" href="./_sisu/image/rb7.ico" />
</head>

<body lang="en" xml:lang="en">
<a name="top" id="top"></a>
<a name="up" id="up"></a>
<a name="start" id="start"></a>

<h1>SiSU</h1>
<p>
[<a href="http://sisudoc.org/sisu_manual/en/html/sisu/toc.html">Manual</a>]
</p>
<p>
[<a href="http://git.sisudoc.org/gitweb/?p=code/sisu.git;a=summary">Source</a>]
[<a href="http://lists.sisudoc.org/listinfo/sisu">List Info (sisu@lists.sisudoc.org)</a>]
</p>

<h1>SiSU Markup Samples</h1>
<p>
[<a href="http://git.sisudoc.org/gitweb/?p=doc/sisu-markup-samples.git;a=summary">Source</a>]
[<a href="http://sisudoc.org/sisu_markup_samples.html">Output</a>]
</p>

<hr />

<h2 class="top_band_tiny">
  Structured information, Serialized Units
  &nbsp;&nbsp;
  <a href="http://www.sisudoc.org" target="_top">
    &lt;www.sisudoc.org&gt;
  </a>
  &nbsp;&nbsp;or&nbsp;&nbsp;
  <a href="http://www.jus.uio.no/sisu/" target="_top">
    &lt;www.jus.uio.no/sisu/&gt;
  </a>
software for electronic texts, document collections, books, digital libraries &amp; search, with "atomic search" &amp; text locating system (shared object citation numbering: "<i>ocn</i>").
Outputs include: plaintext, HTML, EPUB, ODT (OpenDocumentText), (XHTML, XML,) LaTeX, PDF, SQL (PostgreSQL and SQLite).
</h2>
<p class="small">
<a href="mailto:sisu@lists.sisudoc.org">
&lt;sisu@lists.sisudoc.org&gt;
</a>
<a href="http://lists.sisudoc.org/listinfo/sisu">
&lt;http://lists.sisudoc.org/listinfo/sisu&gt;
</a>
</p>
<p class="small">
<a href="mailto:ralph@amissah.com">
&lt;ralph@amissah.com&gt;
</a>
<a href="mailto:ralph.amissah@gmail.com">
&lt;ralph.amissah@gmail.com&gt;
</a>
</p>
<p class="tiny">
#{@v.project} #{@v.version} of #{@v.date_stamp} (#{@v.date}) (n*x and Ruby!), #{@date.year_static}.
</p>
<p class="tiny">
w3 since October 3 1993.
</p>
</body>
</html>
WOK
    end
    def home_toc
      ' '
    end
  end
end
__END__
#+END_SRC

*** html_tune.rb

#+HEADER: :tangle "../lib/sisu/html_tune.rb"
#+BEGIN_SRC ruby
#<<sisu_document_header>>
require_relative 'dp'                                   # dp.rb
module SiSU_HTML_Tune
  require_relative 'se'                                 # se.rb
    include SiSU_Env; include SiSU_Screen
  require_relative 'html_parts'                         # html_parts.rb
  require_relative 'html_format'                        # html_format.rb #watch
  @@line_mode=''
  @@endnote_array=[]
  @@endnote_call_counter=1
  @@table_align='<table summary='' width="96%" border="0" cellpadding="0" col="3">
<tr ...><td width="2%" align="right">
&nbsp\;</td>
<td width="94%" valign="top" align="justify">'
  @@table_align_close='</td>
<td width="4%" align="right" valign="top">
<font size="1" color="#777777">
&nbsp;&nbsp;&nbsp;</font> </td></tr></table>'
  @@counter,@@column,@columns=0,0,0
  class Output
    def initialize(data,md)
      @data,@md=data,md
      @file=SiSU_Env::InfoFile.new(@md.fns)
      @cX=SiSU_Screen::Ansi.new(@md.opt.act[:color_state][:set]).cX
    end
    def hard_output
      @filename_tune=@file.write_file_processing.html_tune
      data=[]
      @data.each do |x|
        unless x.obj.empty?
          x.obj=x.obj.strip
          data << x
        end
      end
      data.each do |dob|
        @filename_tune.puts dob, "\n"
      end
    end
    def marshal
      File.open(@file.marshal.html_tune,'w') {|f| Marshal.dump(@data.to_a,f)}
    end
  end
  class CleanHTML
    def initialize(html='')
      @html=html
    end
    def clean_for_html
      html=@html
      str=if html.is_a?(String)
        html
      else html.obj
      end
      str=str.gsub(/#{Mx[:gl_o]}(#[0-9]{3})#{Mx[:gl_c]}/u,'&\1;').
        gsub(/#{Mx[:gl_o]}#([a-z]{2,4})#{Mx[:gl_c]}/u,'&\1;').
        gsub(/[<]/m,'&lt;').gsub(/[>]/m,'&gt;')
    end
    def clean
      html=@html
      str=if html.is_a?(String)
        html
      else html.obj
      end
      str=str.gsub(/#{Mx[:gl_o]}(#[0-9]{3})#{Mx[:gl_c]}/u,'&\1;').
        gsub(/#{Mx[:gl_o]}#([a-z]{2,4})#{Mx[:gl_c]}/u,'&\1;').
        gsub(/[\\]{2}/m,'<br>')
    end
  end
  class Tune
    include SiSU_Parts_HTML
    def initialize(data,md)
      @data,@md=data,md
      @sys=SiSU_Env::SystemCall.new
      @env=SiSU_Env::InfoEnv.new(@md.fns,@md)
    end
    def songsheet
      begin
        @cX=SiSU_Screen::Ansi.new(@md.opt.act[:color_state][:set]).cX
        if (@md.opt.act[:verbose][:set]==:on \
        || @md.opt.act[:verbose_plus][:set]==:on \
        || @md.opt.act[:maintenance][:set]==:on)
          SiSU_Screen::Ansi.new(@md.opt.act[:color_state][:set],'Tune').txt_grey
        end
        songsheet_array(@data)
        #data=songsheet_array(@data)
        if @md.opt.act[:maintenance][:set]==:on #Hard Output Tune Optional on/off here
          SiSU_HTML_Tune::Output.new(@data,@md).hard_output
          SiSU_HTML_Tune::Output.new(@data,@md).marshal
        end
        SiSU_HTML_Tune::Tune.new(@data,@md).output
      rescue
        SiSU_Errors::Rescued.new($!,$@,@md.opt.selections.str,@md.fns).location do
          __LINE__.to_s + ':' + __FILE__
        end
      ensure
      end
    end
    def songsheet_array(data)
      data_tuned=[]
      data.each do |dob|
        dob=amp_angle_brackets(dob)
        dob=endnotes_html(dob)
        dob=url_markup(dob)
        dob=markup(dob)
        data_tuned << dob
      end
      data_tuned
    end
    def urls(data)
      @words=data.each.map do |word|
        if word=~/#{Mx[:lnk_o]}(.+?)#{Mx[:lnk_c]}(?:#{Mx[:url_o]}\S+?#{Mx[:url_c]}|#{Mx[:rel_o]}\S+?#{Mx[:rel_c]}|image)/
          http_=true
          if word =~/#{Mx[:lnk_o]}.+?#{Mx[:lnk_c]}#{Mx[:url_o]}\S+?#{Mx[:url_c]}/
            m,u=/#{Mx[:lnk_o]}(.+?)#{Mx[:lnk_c]}#{Mx[:url_o]}(\S+?)#{Mx[:url_c]}/.match(word).captures
          elsif word =~/#{Mx[:lnk_o]}.+?#{Mx[:lnk_c]}#{Mx[:rel_o]}:\S+?#{Mx[:rel_c]}/
            #http_=false
            m,u=/#{Mx[:lnk_o]}(.+?)#{Mx[:lnk_c]}#{Mx[:rel_o]}:(\S+?)#{Mx[:rel_c]}/.match(word).captures
            u="#{Xx[:html_relative2]}/" + u
          elsif word =~/#{Mx[:lnk_o]}.+?#{Mx[:lnk_c]}#{Mx[:rel_o]}\S+?#{Mx[:rel_c]}/
            http_=false
            m,u=/#{Mx[:lnk_o]}(.+?)#{Mx[:lnk_c]}#{Mx[:rel_o]}(\S+?)#{Mx[:rel_c]}/.match(word).captures
          elsif word =~/#{Mx[:lnk_o]}.+?#{Mx[:lnk_c]}image/
            m,u=/#{Mx[:lnk_o]}(.+?)#{Mx[:lnk_c]}(image)/.match(word).captures
          end
          case m
          when /\.png|\.jpg|\.gif|c=|\s\d+x\d+/
            w,h=/\s(\d+)x(\d+)/.match(m).captures if m =~/\s\d+x\d+/
            w=%{width="#{w}"} if w
            h=%{height="#{h}"} if h
            c=m[/"(.+?)"/m,1]
            caption=%{<br><p class="caption">#{c}</p>} if c
            png=m.scan(/\S+/)[0]
            image_path=@md.file.output_path.html_seg.rel_image
            #image_path=(@md.fns =~/\.-ss[tm]$/) \
            #? @env.url.images_external
            #: @env.url.images_local
            ins=if u \
            and u.strip !~/^image$/
              %{<a href="#{u}"><img src="#{image_path}/#{png}" #{w} #{h} naturalsizeflag="0" align="bottom" border="0"></a>#{caption}}
            else %{<img src="#{image_path}/#{png}" #{w} #{h} naturalsizeflag="0" align="bottom" border="0">#{caption}}
            end
            word=word.gsub(/#{Mx[:lnk_o]}.+?#{Mx[:lnk_c]}(?:#{Mx[:url_o]}\S+?#{Mx[:url_c]}|image)/,ins)
          else
            link=m[/(.+)/m]
            png=m.scan(/\S+/)[0].strip
            link=link.strip
            u=u.gsub(/(\S+)/,"#{Xx[:segment]}#\\1") if u !~/\// unless http_ #marker: in scroll remove; in seg replace
            ins=%{<a href="#{u}">#{link}</a>}
            word=word.gsub(/#{Mx[:lnk_o]}.+?#{Mx[:lnk_c]}#{Mx[:url_o]}\S+?#{Mx[:url_c]}/,ins).
              gsub(/#{Mx[:lnk_o]}.+?#{Mx[:lnk_c]}#{Mx[:rel_o]}\S+?#{Mx[:rel_c]}/,ins)
          end
          word
        else word
        end
      end.join(' ')
    end
    def url_markup(dob)
      unless dob.is==:code
        if dob.obj =~/#{Mx[:lnk_o]}.+?#{Mx[:lnk_c]}(?:#{Mx[:url_o]}\S+?#{Mx[:url_c]}|#{Mx[:rel_o]}\S+?#{Mx[:rel_c]}|image)/
          @word_mode=dob.obj.scan(/#{Mx[:lnk_o]}.+?#{Mx[:lnk_c]}(?:#{Mx[:url_o]}\S+?#{Mx[:url_c]}|#{Mx[:rel_o]}\S+?#{Mx[:rel_c]}|image)[()\[\]]*[,.;:!?'"]{0,2}|(?:#{Mx[:gl_o]}\S+?#{Mx[:gl_c]})+|[^#{Mx[:lnk_o]}#{Mx[:lnk_c]}]+/mu)
          words=urls(@word_mode)
          dob.obj=dob.obj.gsub(/.+/m,words)
        end #consider change, do a while loop
        dob.obj=dob.obj.gsub(/\\copyright/i,%{<sup>&copy;</sup>})
        if (dob.obj !~/\<:ad\s+\.\.\//)
          dob.obj=dob.obj.gsub(/\<:ad\s+(\S+)?\s+(\S+\.png)\s+(.+)?\;\s+(.+)?\;\s*!\>/,
            %{\n<center><a href="http:\/\/\\1" target="external"><img src="#{@env.url.images_local}/\\2" alt="\\3"></a></center>\n})
        else
          dob.obj=dob.obj.gsub(/\<:ad\s+(\S+)?\s+(\S+\.png)\s+(.+)?\;\s+(.+)?\;\s*\>/,
            %{\n<center><a href="\\1" target="_top"><img src="#{@env.url.images_local}/\\2" alt="\\3"></a></center>\n})
        end
        dob.obj=dob.obj.gsub(/!pick/,%{<img border="0" height="15" width="15" src="#{@env.url.images}/#{the_icon.i_choice}" alt="stellar">}).
          gsub(/!new/,%{&nbsp;<img border="0" height="15" width="15" src="#{@env.url.images}/#{the_icon.i_new}" alt="new">}).
          gsub(/<:h(.{1,7}?)>/,'<a href="#h\1">\1</a>').
          gsub(/<:to(\d{1,7}?)>/,'<a href="#to\1">to&nbsp;{&nbsp;\1&nbsp;}</a> ').
          gsub(/#{Mx[:url_o]}_(\S+?)#{Mx[:url_c]}/,'<a href="\1" target="_top">\1</a>'). #http ftp matches escaped, no decoration
          gsub(/#{Mx[:url_o]}([a-zA-Z0-9._-]+\@\S+?\.[a-zA-Z0-9._-]+)#{Mx[:url_c]}/,%{#{the_url_decoration.xml_open}<a href="mailto:\\1">\\1</a>#{the_url_decoration.xml_close}}).
          gsub(/#{Mx[:url_o]}(\S+?)#{Mx[:url_c]}/,%{#{the_url_decoration.xml_open}<a href="\\1" target="_top">\\1</a>#{the_url_decoration.xml_close}}) #http ftp matches with decoration
        if dob.obj =~/#{Xx[:html_relative2]}\/\S+/ \
        and dob.obj !~/(\"#{Xx[:html_relative2]}\/\S+?\"|>\s*#{Xx[:html_relative2]}\/\S+<)/
          dob.obj=dob.obj.gsub(/(#{Xx[:html_relative2]}\/\S+)/,'<a href="\1">\1</a>')
        end
        if dob.obj =~/..\/\S+/ \
        and dob.obj !~/(\"..\/\S+?\"|>\s*..\/\S+<)/
          dob.obj=dob.obj.gsub(/\.\.(\/\S+)/,%{<a href="#{Xx[:html_relative2]}\1">\1</a>})
        end
        dob.obj=dob.obj.gsub(/<a href=":/,%{<a href="#{the_url.site}/}).
          gsub(/<a href="\.\.\//,%{<a href="#{the_url.site}/}).
          gsub(/<a href="#{Xx[:html_relative2]}\//,%{<a href="#{the_url.site}/})
      else
        dob.obj=dob.obj.gsub(/</m,'&lt;').gsub(/>/m,'&gt;')
      end
      dob
    end
    def amp_angle_brackets(dob)
      dob.obj=dob.obj.
        gsub(/&/u,'&amp;').
        gsub(/<([a-z:\/]+)>/,"#{Dx[:lt_xml]}\\1#{Dx[:gt_xml]}").
        gsub(/</u,'&lt;').gsub(/>/u,'&gt;')
      dob
    end
    def endnotes_html(dob)
      unless dob.is ==:code
        dob.obj=dob.obj.gsub(/(#{Mx[:en_a_o]}|#{Mx[:en_b_o]})(\d+)\s+(.+?)(#{Mx[:en_a_c]}|#{Mx[:en_b_c]})/,
            %{&nbsp;<a href="##{Mx[:note]}\\2"><note id="#{Mx[:note_ref]}\\2">&nbsp;<sup>\\2</sup>&nbsp;</note></a> } +
            %{\\1\\2 <a href="##{Mx[:note_ref]}\\2"><note id="#{Mx[:note]}\\2">&nbsp;<sup>\\2.</sup></note></a> \\3 \\4}).
          gsub(/(#{Mx[:en_b_o]})([*+]\d+)\s+(.+?)(#{Mx[:en_b_c]})/,
            %{&nbsp;<a href="##{Mx[:note]}\\2"><note id="#{Mx[:note_ref]}\\2">&nbsp;<sup>\\2</sup>&nbsp;</note></a> } +
            %{\\1\\2 <a href="##{Mx[:note_ref]}\\2"><note id="#{Mx[:note]}\\2">&nbsp;<sup>\\2.</sup></note></a> \\3 \\4}).
          gsub(/(#{Mx[:en_a_o]})([*+]+)\s+(.+?)(#{Mx[:en_a_c]})/,
            %{&nbsp;<a href="##{Mx[:note]}\\2"><note id="#{Mx[:note_ref]}\\2">&nbsp;<sup>\\2</sup>&nbsp;</note></a> } +
            %{\\1\\2 <a href="##{Mx[:note_ref]}\\2"><note id="#{Mx[:note]}\\2">&nbsp;<sup>\\2</sup></note></a> \\3 \\4})
      end
      dob
    end
    def markup(dob)
      dob.obj=dob.obj.gsub(/#{Mx[:mk_o]}#([a-zA-Z]+)#{Mx[:mk_c]}/,'&\1;').
        gsub(/#{Mx[:mk_o]}(#[0-9]+)#{Mx[:mk_c]}/,'&\1;')
      dob.obj=dob.obj.gsub(/#{Mx[:br_line]}|#{Mx[:br_nl]}/,'<br>') unless dob.is==:table
      dob.obj=dob.obj.gsub(/#{Mx[:fa_bold_o]}(.+?)#{Mx[:fa_bold_c]}/,'<b>\1</b>').
        gsub(/#{Mx[:fa_italics_o]}(.+?)#{Mx[:fa_italics_c]}/,'<i>\1</i>').
        gsub(/#{Mx[:fa_underscore_o]}(.+?)#{Mx[:fa_underscore_c]}/,'<u>\1</u>').
        gsub(/#{Mx[:fa_superscript_o]}(.+?)#{Mx[:fa_superscript_c]}/,'<sup>\1</sup>').
        gsub(/#{Mx[:fa_subscript_o]}(.+?)#{Mx[:fa_subscript_c]}/,'<sub>\1</sub>').
        gsub(/#{Mx[:fa_insert_o]}(.+?)#{Mx[:fa_insert_c]}/,'<ins>\1</ins>').
        gsub(/#{Mx[:fa_cite_o]}(.+?)#{Mx[:fa_cite_c]}/,'<cite>\1</cite>').
        gsub(/#{Mx[:fa_strike_o]}(.+?)#{Mx[:fa_strike_c]}/,'<del>\1</del>').
        gsub(/#{Mx[:fa_monospace_o]}(.+?)#{Mx[:fa_monospace_c]}/,'<tt>\1</tt>'). # tt, kbd
        gsub(/#{Mx[:mk_o]}:name#(\S+?)#{Mx[:mk_c]}/,'<a name="\1"></a>').
        gsub(/#{Mx[:gl_bullet]}/m,'●&nbsp;&nbsp;').
        gsub(/#{Mx[:nbsp]}/,'&nbsp;').
        gsub(/<(p|br) \/>/,'<\1>')
      dob=SiSU_HTML_Tune::CleanHTML.new(dob).clean
      dob
    end
    def output
      data=@data
      @tuned_file=data.each.map do |dob|
        dob.obj=dob.obj.strip.chomp
        dob
      end
      @tuned_file << "\n<EOF>" if (@md.fns =~/\.sst0/) #remove
      @tuned_file
    end
  end
end
__END__
#+END_SRC

*** html_scroll.rb

#+HEADER: :tangle "../lib/sisu/html_scroll.rb"
#+BEGIN_SRC ruby
#<<sisu_document_header>>
module SiSU_HTML_Scroll
  require_relative 'html_shared'                        # html_shared.rb
  require_relative 'html'                               # html.rb
  require_relative 'shared_metadata'                    # shared_metadata.rb
  require_relative 'html_promo'                         # html_promo.rb
  class Scroll
    def initialize(md='',data='',endnotes='')
      @md,@data,@endnotes=md,data,endnotes
    end
    def songsheet
      begin
        scr=SiSU_HTML_Scroll::Scroll.new(@md,@data,@endnotes).markup
        scr[:tails]=SiSU_HTML_Scroll::Scroll.new(@md).tails
        scr
      rescue
        SiSU_Errors::Rescued.new($!,$@,@md.opt.selections.str,@md.fns).location do
          __LINE__.to_s + ':' + __FILE__
        end
      ensure
      end
    end
  protected
    def markup
      data=@data
      @rcdc=false
      @scr={ body: [], metadata: [], owner_details: [] }
      data.each do |dob|
        dob.obj=dob.obj.gsub(/#{@md.file.output_path.html_seg.rel_image}/m,
          @md.file.output_path.html_scroll.rel_image)
        if defined? dob.name and dob.name =~/^meta/ \
        and dob.obj =~/Document Information/
          dob.obj=dob.obj.
            gsub(/(Document Information(?: \(metadata\))?)/,
              '\1<a name="docinfo"></a>')
        end
        if dob.obj =~/^Metadata$/ \
        and dob.lv =='B'
          dob.obj=dob.obj.gsub(/Metadata/,'') #dob.obj=''
        end
        if defined? dob.name \
        and dob.name =~/^metadata/ \
        and dob.lv =='1' \
        and dob.obj =~/SiSU Metadata, document information/
          @rcdc=true
        end
        dob.obj=dob.obj.gsub(/href="[a-z0-9._-]+(#\S+?")/m,'href="\1'). # internal document links
          gsub(/href="#{Xx[:segment]}/m,'href="')
        if dob.obj !~/(^#{Rx[:meta]}|#{Mx[:br_eof]})/
          unless dob.is ==:code
            dob.obj=dob.obj.
              gsub(/(?:#{Mx[:en_a_o]}.+?#{Mx[:en_a_c]}|#{Mx[:en_b_o]}.+?#{Mx[:en_b_c]})\s*/m,' ')
          end
          if defined? dob.ocn
            @p_num=SiSU_HTML_Format::ParagraphNumber.new(@md,dob.ocn)
          end
          sto=SiSU_HTML_Format::FormatTextObject.new(@md,dob)
          para_html=if dob.is==:heading
            x=if dob.ln==0
              sto.heading_body0
            elsif dob.ln==1
              sto.heading_body1
            elsif dob.ln==2
              sto.heading_body2
            elsif dob.ln==3
              sto.heading_body3
            elsif dob.ln==4
              sto.heading_body4
            elsif dob.ln==5
              sto.heading_body5
            elsif dob.ln==6
              sto.heading_body6
            elsif dob.ln==7
              sto.heading_body7
            end
          elsif dob.is==:break \
          and dob.from==:markup
            '<br><hr width=90% /><br>'
          elsif dob.is==:heading_insert
            x=if dob.ln==0
              unless dob.obj.empty?
                sto.heading_body0
              end
            elsif dob.ln==1
              unless dob.obj.empty?
                sto.heading_body1
              end
            elsif dob.ln==2
              unless dob.obj.empty?
                sto.heading_body2
              end
            elsif dob.ln==3
              unless dob.obj.empty?
                sto.heading_body3
              end
            elsif dob.ln==4 \
            and dob.obj !~/^(?:Endnotes|Index|Metadata|Manifest)$/
              unless dob.obj.empty?
                sto.heading_body4
              end
            elsif dob.ln==4 \
            and dob.obj=='Endnotes'
              sto.heading_body4
              @endnotes.join("\n")
            elsif dob.ln==4 \
            and dob.obj=='Index'
              sto.heading_body4
              book_idx=SiSU_Particulars::CombinedSingleton.
                instance.get_idx_html(@md.opt).html_idx
              book_idx.each do |y| #takes book index prepared for segments & strips segment identifying info
                y.gsub!(/<a href="\S+?\.html#(\d+)">(\1(?:-\d+)?)<\/a>/,
                  '<a href="#\1">\2</a>')
              end
              book_idx.join("\n")
            elsif dob.ln==5
              unless dob.obj.empty?
                sto.heading_body5
              end
            elsif dob.ln==6
              unless dob.obj.empty?
                sto.heading_body6
              end
            elsif dob.ln==7
              unless dob.obj.empty?
                sto.heading_body7
              end
            end
          elsif dob.is==:para
            if dob.indent \
            and dob.hang \
            and dob.indent =~/[0-9]/ \
            and dob.hang =~/[0-9]/
              if dob.bullet_
                (dob.indent =~/[1-9]/) \
                ? sto.format('li',"i#{dob.indent}")
                : sto.format('li','bullet')
              elsif dob.indent == dob.hang
                sto.format('p',"i#{dob.indent}")
              elsif dob.indent != dob.hang
                sto.format('p',"h#{dob.hang}i#{dob.indent}")
              else sto.para
              end
            else sto.para
            end
          elsif dob.is==:block
            sto.block
          elsif dob.is==:group
            sto.group
          elsif dob.is==:alt
            sto.alt
          elsif dob.is==:verse
            sto.verse
          elsif dob.is==:code
            sto.code
          elsif dob.is==:table
            sto.table
          elsif dob.is==:break
          end
          if dob.obj =~/<a name="n\d+">/ \
          and dob.obj =~/^(?:\^~\d+\s|<!e[:_]\d+!>)/ # hmmm re-adjusted 200507, for alt endnote which should again be matched ^~ ... not in response to problem though
            dob.obj=''
          end
          unless @rcdc
            @scr[:body] << para_html unless para_html =~/\A\s*\Z/
          end
        end
      end
      @scr
    end
    def tails
      scr_tail=[]
      format_head_scroll=SiSU_HTML_Format::HeadToc.new(@md)
      scr_tail \
      << format_head_scroll.scroll_tail \
      << format_head_scroll.html_close
      scr_tail
    end
  end
end
__END__
#+END_SRC

*** html_segments.rb

#+HEADER: :tangle "../lib/sisu/html_segments.rb"
#+BEGIN_SRC ruby
#<<sisu_document_header>>
module SiSU_HTML_Seg
  require_relative 'html_shared'                        # html_shared.rb
  require_relative 'html'                               # html.rb
  require_relative 'html_persist'                       # html_persist.rb
  require_relative 'html_promo'                         # html_promo.rb
  require_relative 'shared_metadata'                    # shared_metadata.rb
  class Output
    def initialize(md,outputfile,per,minitoc,type='')
      @md, @output_seg_file,@per,@minitoc,@type=
        md,outputfile,      per,minitoc,  type
      @title_banner_=SiSU_Env::CreateSite.new(@md.opt).html_seg_title_banner?
      @file=SiSU_Env::FileOp.new(@md)
      @make=SiSU_Env::ProcessingSettings.new(@md)
      @cl=(@make.build.html_minitoc?) \
      ? 'content'
      : 'content0'
    end
    def output
      if @per.title =~/\S/
        filename_seg=[]
        if @make.build.html_top_band?
          filename_seg \
          << @per.title \
          << @per.tocband_banner
        else
          filename_seg \
          << @per.title
        end
        if @type=='endnotes'
          @per.headings=[]
          format_head_seg=SiSU_HTML_Format::HeadSeg.new(@md)
          if @title_banner_
            @per.headings \
            << format_head_seg.
              title_banner(@md.title.main,@md.title.sub,@author)
          end
          txt_obj={ txt: 'Endnotes', ocn_display: '' }
          format_seg=SiSU_HTML_Format::FormatSeg.new(@md,txt_obj)
          @per.headings \
          << format_seg.title_heading1
          filename_seg \
          << @per.heading_endnotes \
          << @minitoc << @per.headings \
          << %{\n<div class="#{@cl}">\n} \
          << @per.endnote_all \
          << '</div>' # << '</div>'
        elsif @type=='idx'
          @per.headings=[]
          format_head_seg=SiSU_HTML_Format::HeadSeg.new(@md)
          if @title_banner_
            @per.headings \
            << format_head_seg.
              title_banner(@md.title.main,@md.title.sub,@author)
          end
          txt_obj={ txt: 'Index', ocn_display: '' }
          format_seg=SiSU_HTML_Format::FormatSeg.new(@md,txt_obj)
          @per.headings << format_seg.title_heading1
          filename_seg \
          << @per.heading_idx \
          << @minitoc << @per.headings \
          << %{\n<div class="#{@cl}">\n} \
          << @per.idx \
          << '</div>' # << '</div>'
        elsif @type=='metadata'
          metadata=SiSU_Metadata::Summary.new(@md).html_display.metadata
          @per.headings=[]
          format_head_seg=SiSU_HTML_Format::HeadSeg.new(@md)
          if @title_banner_
            @per.headings \
            << format_head_seg.
              title_banner(@md.title.main,@md.title.sub,@author)
          end
          txt_obj={ txt: 'Metadata', ocn_display: '' }
          format_seg=SiSU_HTML_Format::FormatSeg.new(@md,txt_obj)
          @per.headings \
          << format_seg.title_heading1
          filename_seg \
          << @per.heading_idx \
          << @minitoc \
          << @per.headings \
          << %{\n<div class="#{@cl}">\n} \
          << metadata \
          << '</div>' # << '</div>'
        else
          if @make.build.html_top_band?
            filename_seg \
            << @minitoc \
            << @per.headings \
            << @per.main \
            << "\n</div>\n"
          else
            filename_seg \
            << @minitoc \
            << @per.main \
            << "\n</div>\n"
          end
        end
        filename_seg <<=if @make.build.html_top_band?
          @per.tail \
          << @per.tocband_bannerless \
          << @per.credits
        else
          @per.tail \
          << @per.credits
        end
        filename_seg=filename_seg.flatten.compact #watch
        filename_seg.each do |str|
          unless str =~/\A\s*\Z/
            str=str.strip.
              gsub(Xx[:html_relative2],
                @file.path_rel_links.html_seg_2).
              gsub(Xx[:html_relative1],
                @file.path_rel_links.html_seg_1)
            @output_seg_file << str
          end
        end
        @output_seg_file.close
      end
    end
  end
  class Seg
    @@seg_url=''
    @@tracker=0
    @@seg_name=[]
    attr_reader :seg_name_x,:seg_name_x_tracker
    def initialize(md=nil,data='')
      @md,@data=md,data
      @per=SiSU_HTML_Persist::Persist.new
      @seg_name_x=@per.seg_name_x=(@@seg_name || [])
      @seg_name_x_tracker=@per.seg_name_x_tracker=(@@tracker || 0)
      @env=SiSU_Env::InfoEnv.new(@md.fns) if @md
      if @md
        @make=SiSU_Env::ProcessingSettings.new(@md)
        @cl=(@make.build.html_minitoc?) \
        ? 'content'
        : 'content0'
      else @cl='content'
      end
      if @md
        @title_banner_=SiSU_Env::CreateSite.new(@md.opt).html_seg_title_banner?
      end
    end
    def songsheet
      begin
        @minitoc=SiSU_HTML::Source::Toc.new(@md,@data).minitoc
        @per=SiSU_HTML_Persist::Persist.new
        data=get_subtoc_endnotes(@data,@per)
        data=articles(data,@per)
        cleanup(@md,@per) # (((( added ))))
        #### (((( END )))) ####
      rescue
        SiSU_Errors::Rescued.new($!,$@,@md.opt.selections.str,@md.fns).location do
          __LINE__.to_s + ':' + __FILE__
        end
      ensure
        SiSU_HTML_Persist::Persist.new.persist_init
        @@seg_name=@per.seg_name=[]
      end
    end
  protected
    def articles(data,per)
      @per=per
      tracking,newfile=0,0
      printed_endnote_seg='n'
      idx_html=nil
      if @md.book_idx
        #my_make_source_file=SiSU_Env::CreateFile.new(@md.fns)
        idx_html=SiSU_Particulars::CombinedSingleton.
          instance.get_idx_html(@md.opt).html_idx
        idx_html.each do |x|
          @per.idx << x
        end
        @per.heading_idx=''
      end
      data.each do |dob|
        if (dob.is == :heading \
        || dob.is == :heading_insert) \
        && dob.ln == 4
          @@seg_name << dob.name
          @per.seg_name = @@seg_name
          dob.name
        end
      end
      @per.seg_name_x=@per.seg_name
      @per.seg_name.length
      testforartnum=@per.seg_name_x
      if (@md.opt.act[:verbose][:set]==:on \
      || @md.opt.act[:verbose_plus][:set]==:on \
      || @md.opt.act[:maintenance][:set]==:on)
        SiSU_Screen::Ansi.new(
          @md.opt.act[:color_state][:set],
          @per.seg_name.length
        ).segmented
      end
      map_nametags=SiSU_Particulars::CombinedSingleton.
        instance.get_map_nametags(@md).nametags_map #p map_nametags
      data.each do |dob|
        if defined? dob.obj \
        and dob.obj =~/href="#{Xx[:segment]}#+\S+?"/
          while dob.obj =~/href="#{Xx[:segment]}#+(\S+?)"/
            m=$1
            if map_nametags[m] \
            and map_nametags[m][:segname]
              inf=SiSU_Env::FileOp.new(@md) if @md
              lng=(inf.output_dir_structure.by_language_code?) \
              ? ''
              : '.' + @md.opt.lng
              dob.obj.sub!(/href="#{Xx[:segment]}#+(\S+?)"/,
                %{href="#{map_nametags[m][:segname]}#{lng}#{Sfx[:html]}#\\1"})
            else
              p "NOT FOUND name_tags: #{m}"
              dob.obj.sub!(/href="#{Xx[:segment]}#+(\S+?)"/,
                %{href="#\\1"}) # not satisfactory
            end
          end
        end
        if (dob.is==:heading \
        || dob.is==:heading_insert) \
        && dob.ln==4
          @per.heading4=dob.obj
          @per.is4=newfile=1
        end
        if (dob.is==:heading \
        || dob.is==:heading_insert) \
        && dob.ln==3
          @per.heading3=dob.obj
          @per.is4,@per.is3=0,1
        end
        if (dob.is==:heading \
        || dob.is==:heading_insert) \
        && dob.ln==2
          @per.heading2=dob.obj
          @per.is4,@per.is3,@per.is2=0,0,1
        end
        if (dob.is==:heading \
        || dob.is==:heading_insert) \
        && dob.ln==1
          @per.heading1=dob.obj
          @per.is4,@per.is3,@per.is2,@per.is1=0,0,0,1
        end
        if (dob.is==:heading \
        || dob.is==:heading_insert) \
        && dob.ln==0
          @per.heading0=dob.obj
          @per.is4,@per.is3,@per.is2,@per.is1,@per.is0=0,0,0,0,1
        end
        if (@per.is1 && !@per.is2 && !@per.is3 && !@per.is4)
          if not (dob.is==:heading \
          || dob.is==:heading_insert) \
          && dob.ln==0
            $_ #; check
          end
        end
        if @per.is4==1
          if newfile==1 \
          or dob.obj =~/^#{Mx[:br_endnotes]}|^#{Mx[:br_eof]}/
            newfile=0
            if (dob.is==:heading \
            || dob.is==:heading_insert) \
            && dob.ln==4
              if tracking != 0
                @file=SiSU_Env::FileOp.new(@md)
                unless FileTest.directory?(@file.output_path.html_seg.dir)
                  FileUtils::mkdir_p(@file.output_path.html_seg.dir) \
                    if File.writable?("#{@file.output_path.base.dir}/.")
                end
                tail(@md,@per)
                #SiSU_HTML_Seg::Seg.new(@md,@per).tail
                fnh={
                  fn: @per.seg_name_x[tracking-1],
                }
                fn=@md.file.base_filename.html_seg(fnh)
                segfilename="#{@file.output_path.html_seg.dir}/#{fn}"
                output_seg_file=File.new(segfilename,'w') if @per.seg_name_x[tracking-1]
                minitoc=(@make.build.html_minitoc?) ? @minitoc : ''
                if dob.is==:heading \
                || (@per.seg_name_x[tracking-1] !~/endnotes|book_index|metadata/)
                  SiSU_HTML_Seg::Output.new(@md,output_seg_file,@per,minitoc).output
                elsif dob.is==:heading_insert
                  if @per.seg_name_x[tracking-1]=='endnotes'
                    SiSU_HTML_Seg::Output.new(@md,output_seg_file,@per,minitoc,'endnotes').output
                  elsif @per.seg_name_x[tracking-1]=='book_index'
                    SiSU_HTML_Seg::Output.new(@md,output_seg_file,@per,minitoc,'idx').output
                    @per.idx=[]
                  elsif @per.seg_name_x[tracking-1]=='metadata'
                    SiSU_HTML_Seg::Output.new(@md,output_seg_file,@per,minitoc,'metadata').output
                  else puts "#{__FILE__}::#{__LINE__}"
                  end
                else puts "#{__FILE__}::#{__LINE__}"
                end
                SiSU_HTML_Seg::Seg.new.reinitialise(per)
                #per=persist_init
                heading_art(dob)
                head(dob)
               #keep use for last segment, eg if metadata is last segment
                if @per.seg_name_x[tracking] =='metadata' # this is for metadata
                  fnh={
                    fn: @per.seg_name_x[tracking],
                  }
                  fn=@md.file.base_filename.html_seg(fnh)
                  segfilename="#{@file.output_path.html_seg.dir}/#{fn}"
                  output_seg_file=File.new(segfilename,'w')
                  SiSU_HTML_Seg::Output.new(@md,output_seg_file,@per,minitoc,'metadata').output
                  #per=persist_init
                  Seg.new.reinitialise(per)
                end
              end
              if tracking==0
                heading_art(dob)
                head(dob)
              end
            end
            tracking=tracking+1
          end
          if (dob.is==:heading \
          || dob.is==:heading_insert) \
          && dob.ln==4 \
          && dob.name
            @per.get_hash_to=dob.name
            @per.get_hash_fn=dob.name
          end
          if dob.obj.is_a?(String)
            markup(dob)
          elsif dob.obj.is_a?(Array)
            dob.obj.each do |pg|
              markup(pg)
            end
          end
          if testforartnum[tracking-1] =~/endnote/
            if printed_endnote_seg=='n'
              printed_endnote_seg='y'
            end
          end
        end
      end
      data
    end
    def heading_art(dob)
      format_head_seg=SiSU_HTML_Format::HeadSeg.new(@md)
      @per.dot_nav=if (@make.build.html_navigation?) \
      && (@make.build.html_navigation_bar?)
        x=if (dob.is==:heading \
        || dob.is==:heading_insert) \
        && (dob.ln.to_s =~/^[0-7]/)
          x=if @@tracker < @per.seg_name.length-1
            format_head_seg.dot_control_pre_next
          else
            format_head_seg.dot_control_pre
          end
        else @per.dot_nav
        end
      else @per.dot_nav=''
      end
      ads=SiSU_HTML_Promo::Ad.new(@md)
      @per.title=format_head_seg.head_seg << ads.div.major
    end
    def head(dob)
      clean=/<!.*?!>|<:.*?>/
      format_head_seg=SiSU_HTML_Format::HeadSeg.new(@md)
      if @make.build.html_navigation?
        if @@tracker < @per.seg_name.length-1
          @per.segtocband=if @@tracker==0
            format_head_seg.toc_next2
          else
            format_head_seg.toc_pre_next2
          end
        else @per.segtocband=format_head_seg.toc_pre2
        end
      else @per.segtocband=''
      end
      @p_num ||= ''
      if @per.is0==1
        @author=%{<b>#{@md.author}</b>\n} if @md.author.to_s =~/\S/
        @per.tocband_banner \
        << format_head_seg.navigation_band(@per.segtocband,@per.dot_nav)
        @per.tocband_bannerless \
        << '<br>' \
        << format_head_seg.navigation_band_bottom(@per.segtocband,@per.dot_nav)
        if @title_banner_
          @per.headings \
          << format_head_seg.title_banner(@md.title.main,@md.title.sub,@author).gsub(clean,'')
        end
        ocn=(@per.heading0[/.+?#{Mx[:id_o]}~(\d+);(?:[oh]|[0-6]:)\d+;\w\d+#{Mx[:id_c]}#{Mx[:id_o]}#{@dp}:#{@dp}#{Mx[:id_c]}$/]) \
        ? $1
        : ''
        @p_num=SiSU_HTML_Format::ParagraphNumber.new(@md,ocn)
        txt_obj={ txt: @per.heading0, ocn_display: @p_num.ocn_display }
        format_seg=SiSU_HTML_Format::FormatSeg.new(@md,txt_obj)
        @per.headings \
        << format_seg.title_heading0.gsub(clean,'')
        @per.heading0=@per.heading0.
          gsub(/&nbsp;<a name="-[\d*+]+" href="#_[\d*+]+">&nbsp;<sup>[\d*+]+<\/sup>&nbsp;<\/a>/,'')
      end
      if @per.is1==1
        heading1=@per.heading1
        ocn=(heading1[/.+?#{Mx[:id_o]}~(\d+);(?:[oh]|[0-6]:)\d+;\w\d+#{Mx[:id_c]}#{Mx[:id_o]}#{@dp}:#{@dp}#{Mx[:id_c]}$/]) \
        ? $1
        : ''
        @p_num=SiSU_HTML_Format::ParagraphNumber.new(@md,ocn)
        txt_obj={ txt: heading1, ocn_display: @p_num.ocn_display }
        format_seg=SiSU_HTML_Format::FormatSeg.new(@md,txt_obj)
        @per.headings \
        << format_seg.title_heading1.gsub(clean,'')
        @per.heading1=@per.heading1.
          gsub(/&nbsp;<a name="-[\d*+]+" href="#_[\d*+]+">&nbsp;<sup>[\d*+]+<\/sup>&nbsp;<\/a>/,'')
      end
      if @per.is2==1
        heading2=@per.heading2
        ocn=(heading2[/.+?#{Mx[:id_o]}~(\d+);(?:[oh]|[0-6]:)\d+;\w\d+#{Mx[:id_c]}#{Mx[:id_o]}#{@dp}:#{@dp}#{Mx[:id_c]}$/]) \
        ? $1
        : ''
        @p_num=SiSU_HTML_Format::ParagraphNumber.new(@md,ocn)
        txt_obj={ txt: heading2, ocn_display: @p_num.ocn_display }
        format_seg=SiSU_HTML_Format::FormatSeg.new(@md,txt_obj)
        @per.headings \
        << format_seg.title_heading2.gsub(clean,'')
        @per.heading2=@per.heading2.
          gsub(/&nbsp;<a name="-[\d*+]+" href="#_[\d*+]+">&nbsp;<sup>[\d*+]+<\/sup>&nbsp;<\/a>/,'')
      end
      if @per.is3==1
        heading3=@per.heading3
        ocn=(heading3[/.+?#{Mx[:id_o]}~(\d+);(?:[oh]|[0-6]:)\d+;\w\d+#{Mx[:id_c]}#{Mx[:id_o]}#{@dp}:#{@dp}#{Mx[:id_c]}$/]) \
        ? $1
        : ''
        @p_num=SiSU_HTML_Format::ParagraphNumber.new(@md,ocn)
        txt_obj={ txt: heading3, ocn_display: @p_num.ocn_display }
        format_seg=SiSU_HTML_Format::FormatSeg.new(@md,txt_obj)
        @per.headings \
        << format_seg.title_heading3.gsub(clean,'')
        @per.heading3=@per.heading3.
          gsub(/&nbsp;<a name="-[\d*+]+" href="#_[\d*+]+">&nbsp;<sup>[\d*+]+<\/sup>&nbsp;<\/a>/,'')
      end
      if @per.is4==1
        heading4=@per.heading4
        ocn=(heading4[/.+?#{Mx[:id_o]}~(\d+);(?:[oh]|[0-6]:)\d+;\w\d+#{Mx[:id_c]}#{Mx[:id_o]}#{@dp}:#{@dp}#{Mx[:id_c]}$/]) \
        ? $1
        : ''
        @p_num=SiSU_HTML_Format::ParagraphNumber.new(@md,ocn)
        txt_obj={ txt: heading4, ocn_display: @p_num.ocn_display }
        format_seg=SiSU_HTML_Format::FormatSeg.new(@md,txt_obj)
        @per.headings \
        << format_seg.title_heading4.gsub(clean,'')
      end
      @@tracker=@@tracker+1
    end
    def markup(dob)
      @debug=[]
      SiSU_HTML_Format::HeadSeg.new(@md)
      if dob.is !=:meta
        if dob.is==:heading \
        || dob.is==:heading_insert \
        || dob.is == :para
          @p_num=SiSU_HTML_Format::ParagraphNumber.new(@md,dob.ocn)
        end
        sto=SiSU_HTML_Format::FormatTextObject.new(@md,dob)
        dob_html=if dob.is == :heading \
        || dob.is==:heading_insert \
        || dob.is==:para
          dob_html=if dob.is==:heading \
          || dob.is==:heading_insert
            if dob.ln==4
              sto.seg_heading4
            elsif dob.ln==5
              sto.seg_heading5
            elsif dob.ln==6
              sto.seg_heading6
            elsif dob.ln==7
              sto.seg_heading6
            end
          elsif dob.is==:para
            if dob.indent \
            and dob.hang \
            and dob.indent =~/[0-9]/ \
            and dob.hang =~/[0-9]/
              if dob.bullet_
                if dob.indent =~/[1-9]/
                  sto.format('li',"i#{dob.indent}")
                else
                  sto.format('li','bullet')
                end
              elsif dob.indent == dob.hang
                sto.format('p',"i#{dob.indent}")
              elsif dob.indent != dob.hang
                sto.format('p',"h#{dob.hang}i#{dob.indent}")
              else sto.para
              end
            else sto.para
            end
          end
        elsif dob.is==:block
          sto.block
        elsif dob.is==:group
          sto.group
        elsif dob.is==:alt
          sto.alt
        elsif dob.is==:verse
          sto.verse
        elsif dob.is==:code
          sto.code
        elsif dob.is==:table
          sto.table
        elsif dob.is==:break \
        and dob.from==:markup
          '<br><hr width=90% /><br>'
        end
        if @md.flag_separate_endnotes
          dob.obj=dob.obj.gsub(/"\s+href="#(#{Mx[:note]}\d+)">/,%{" href=\"endnotes#{Sfx[:html]}#\\1">})       #endnote- twice #removed file type
        end
        if (dob.is==:heading \
        || dob.is==:heading_insert \
        || dob.is==:para) \
        && (not dob.ocn \
        || (dob.ocn.to_s.empty?))
          format_seg=SiSU_HTML_Format::FormatSeg.new(@md,dob)
        end
        dob.obj=dob.obj.gsub(/\s*(-\{{2}~\d+|<:e[:_]\d+>).*/,'')                   #potentially dagerous - removes all paragraphs with <!e_!> #?? workpoint
        if dob.obj =~/<a name="_\d+" href="#-\d+">&nbsp;<sup>/                #endnote- note-
          format_seg=SiSU_HTML_Format::FormatSeg.new(@md,dob)
          dob=format_seg.no_paranum
        end
        if (dob.is==:heading \
        || dob.is==:heading_insert) \
        && dob.ln==4
          @per.main << %{\n<div class="#{@cl}">\n}
          @per.main << dob_html
          if @make.build.segsubtoc?
            @per.main << @per.seg_subtoc[@per.get_hash_fn]                       #% insertion of sub-toc
          end
        else
          @per.main << dob_html #unless @@flag_alt==true
        end
      end
    end
    def tail(md,per)
      @md,@per=md,per
      format_head_seg=SiSU_HTML_Format::HeadSeg.new(@md)
      if @md.flag_auto_endnotes \
      and @per.seg_endnotes[@per.get_hash_fn]
        @per.tail <<  %{\n<div class="#{@cl}">\n<div class="endnote">\n}
        if @per.seg_endnotes[@per.get_hash_fn].flatten.length > 0
          @per.tail << format_head_seg.endnote_mark
          @per.tail << @per.seg_endnotes[@per.get_hash_fn].flatten #endnotes deposited at end of individual segments ||@|EXTRACTION OF ENDNOTES|
        end
        @per.tail << '</div>'
        @per.tail << '</div>' #this div closes div class content
      end
      ads=SiSU_HTML_Promo::Ad.new(@md)
      @per.credits \
      << format_head_seg.credit \
      << ads.div.close \
      << ads.display \
      << format_head_seg.html_close
    end
    def reinitialise(per)
      per.title,per.dot_nav,per.tocband_banner,per.tocband_bannerless,per.headings,per.main,per.tail,per.credits=Array.new(8){[]}
      @per.segtocband=nil
    end
    def cleanup(md,per)
      #per=persist_init
      reinitialise(per)
      @@tracker=0
      @per.seg_endnotes,@per.seg_subtoc={},{}
      @per.seg_endnotes_array,@per.seg_subtoc_array=[],[]
      per.endnote_all=[]
    end
    def get_subtoc_endnotes(data,per) #get endnotes & sub-table of contents subtoc
      @per=per
      data.each do |dob|
        dob.obj=dob.obj.gsub(/<a name=\"h\d.*?\">(.+?)<\/a>/mi,'\1')
        if @md.flag_auto_endnotes
          if (dob.is==:heading \
          || dob.is==:heading_insert) \
          && (dob.ln.to_s =~/^[0-4]/) \
          and not @per.fn.to_s.empty?
            @per.seg_endnotes[@per.fn]=[]
            @per.seg_endnotes[@per.fn] << @per.seg_endnotes_array
            @per.seg_endnotes_array=[] if dob.ln==4
          end
          if (dob.is==:heading \
          || dob.is==:heading_insert) \
          && dob.ln==4                                              #%  EXTRACTION OF SUB-TOCs & SEGMENT NAME, after EXTRACTION OF ENDNOTES & SUB-TOCs
            @per.seg_subtoc[@per.fn]=@per.seg_subtoc_array
            @per.seg_subtoc_array=[]
            if dob.name \
            and dob.obj
              @per.fn=dob.name
            else
              if dob.name =~/\S+/
                @per.fn=dob.name
              else @per.fn=''
              end
            end
          end
        end
        if dob.is==:heading \
        && (dob.ln.to_s =~/^[5-7]/)
          case dob.ln
          when 5
            txt_obj={ txt: dob.obj.strip, ocn: dob.ocn }
            format_seg=SiSU_HTML_Format::FormatSeg.new(@md,txt_obj)
            subtoc=format_seg.subtoc_lev5 #keep and make available, this is the subtoc
          when 6
            txt_obj={ txt: dob.obj.strip, ocn: dob.ocn }
            format_seg=SiSU_HTML_Format::FormatSeg.new(@md,txt_obj)
            subtoc=format_seg.subtoc_lev6 #keep and make available, this is the subtoc
          when 7
            txt_obj={ txt: dob.obj.strip, ocn: dob.ocn }
            format_seg=SiSU_HTML_Format::FormatSeg.new(@md,txt_obj)
            subtoc=format_seg.subtoc_lev7 #keep and make available, this is the subtoc
          end
          @per.seg_subtoc_array << subtoc
        end
        if @md.flag_auto_endnotes
          if (dob.obj =~/(?:#{Mx[:en_a_o]}|#{Mx[:en_b_o]})[\d*+]+\s*<a href="##{Mx[:note_ref]}[\d*+]+"/) \
          && dob.is !=:code # endnote-
            endnote_array=[]
            if dob.obj=~/#{Mx[:en_a_o]}.+?#{Mx[:en_a_c]}/m
              endnote_array << dob.obj.scan(/#{Mx[:en_a_o]}.+?#{Mx[:en_a_c]}/m)
            end
            if dob.obj=~/#{Mx[:en_b_o]}[*]\d+\s.+?#{Mx[:en_b_c]}/m
              endnote_array \
              << dob.obj.scan(/#{Mx[:en_b_o]}[*]\d+\s.+?#{Mx[:en_b_c]}/m)
            end
            if dob.obj=~/#{Mx[:en_b_o]}[+]\d+\s.+?#{Mx[:en_b_c]}/m
              endnote_array \
              << dob.obj.scan(/#{Mx[:en_b_o]}[+]\d+\s.+?#{Mx[:en_b_c]}/m)
            end
            endnote_array=endnote_array.flatten.compact #watch, check compacting
            endnote_array.each do |note|
              note_match=note.dup
              note_match_seg=note.dup
              e_n=note_match_seg[/(?:#{Mx[:en_a_o]}[\d*+]+|#{Mx[:en_b_o]}[*+]\d+)\s+(.+?)(?:#{Mx[:en_a_c]}|#{Mx[:en_b_c]})/m,1]
              try=e_n.split(/<br(?: \/)?>/)
              try.each do |e|
                txt_obj={ txt: e }
                format_seg=SiSU_HTML_Format::FormatSeg.new(@md,txt_obj)
                note_match=if e =~/#{Mx[:pa_o]}i[1-9]#{Mx[:pa_c]}/
                  format_seg.endnote_body_indent
                else format_seg.endnote_body
                end
                @per.seg_endnotes_array << note_match
              end
              try.join('<br>')
              #% creation of separate end segment/page of all endnotes referenced back to reference segment
              m=/(?:#{Mx[:en_a_o]}[\d*+]+|#{Mx[:en_b_o]}[*+]\d+)\s+(.+?href=")(##{Mx[:note_ref]}[\d*+]+".+)(?:#{Mx[:en_a_c]}|#{Mx[:en_b_c]})/mi
              endnote_part_a=note_match_seg[m,1]
              endnote_part_b=note_match_seg[m,2]
              txt_obj={ endnote_part_a: endnote_part_a, endnote_part_b: endnote_part_b }
              format_seg=SiSU_HTML_Format::FormatSeg.new(@md,txt_obj)
              note_match_all_seg=format_seg.endnote_seg_body(@per.fn) #BUG WATCH 200408
              @per.endnote_all << note_match_all_seg
            end
            dob.obj=dob.obj.gsub(/(?:#{Mx[:en_a_o]}.+?#{Mx[:en_a_c]}|#{Mx[:en_b_o]}.+?#{Mx[:en_b_c]})\s*/m,' ')
          end
        end
      end
    end
  end
end
__END__
#+END_SRC

*** html_format.rb

#+HEADER: :tangle "../lib/sisu/html_format.rb"
#+BEGIN_SRC ruby
#<<sisu_document_header>>
module SiSU_HTML_Format
  require_relative 'html_parts'                         # html_parts.rb
  class ParagraphNumber
    def initialize(md,ocn)
      @md,@ocn=md,ocn.to_s
      @ocn ||=''
      @make=SiSU_Env::ProcessingSettings.new(@md)
    end
    def ocn_display
      if @make.build.ocn?
        if @ocn.to_i==0 \
        or @ocn.empty?
          ''
        else
          %{<label class="ocn"><a href="##{@ocn}" class="lnkocn">#{@ocn}</a></label>}
        end
      else
        ''
      end
    end
    def name
      if @make.build.html_strict? \
      or @ocn==(nil || @ocn.empty?)
        ''
      else
        %{<a name="#{@ocn}"></a>}
      end
    end
    def id #w3c? "tidy" complains about numbers as identifiers ! annoying
      (@ocn==nil || @ocn.empty?) \
      ? '' : %{id="#{Mx[:ocn_id_char]}#{@ocn}"}
    end
    def goto
      (@ocn==nil || @ocn.empty?) \
      ? '' : %{<a href="##{@ocn}">}
    end
  end
  class HeadInformation
    require_relative 'css'                              # css.rb
    include SiSU_Parts_HTML
    require_relative 'xml_shared'                       # xml_shared.rb
    attr_reader :md,:rdf
    def initialize(md)
      @md=md
      # DublinCore 1 - title
      @bits=SiSU_Proj_HTML::Bits.new
      @per=SiSU_HTML_Persist::Persist.new
      @per.seg_name_x=SiSU_HTML::Seg.new.seg_name_x
      @per.seg_name_x_tracker=SiSU_HTML::Seg.new.seg_name_x_tracker
      @tocband_scroll,@tocband_segtoc=nil,nil
      @stylesheet=SiSU_Style::CSS_HeadInfo.new(md).stylesheet
      @o_str ||=SiSU_Env::ProcessingSettings.new(md).output_dir_structure
      @index,@metalink='index','#metadata'
      @toc=@md.file.base_filename.html_segtoc
    end
    def url_path_image_sys
      (@o_str.dump_or_redirect?) \
      ? './image'
      : "#{Xx[:html_relative2]}_sisu/image_sys"
    end
    def icon
      def up
        'arrow_up_red.png'
      end
      def next
        'arrow_next_red.png'
      end
      def previous
        'arrow_prev_red.png'
      end
      def dot_clear
        'dot_clear.png'
      end
      def dot_white
        'dot_white.png'
      end
      def dot
        dot_white
      end
      self
    end
    def png_nav
      def toc
        %{<img border="0" width="22" height="22" src="#{url_path_image_sys}/#{icon.up}" alt="toc" />}
      end
      def pre
        %{<img border="0" width="22" height="22" src="#{url_path_image_sys}/#{icon.previous}" alt="&lt;&lt;&nbsp;previous" />}
      end
      def nxt
        %{<img border="0" width="22" height="22" src="#{url_path_image_sys}/#{icon.next}" alt="next&nbsp;&gt;&gt;" />}
      end
      def dot_toc
        %{<img border="0" width="100%" height="20" src="#{url_path_image_sys}/#{icon.dot}" alt="&#094;" />}
      end
      def dot_pre
        %{<img border="0" width="100%" height="20" src="#{url_path_image_sys}/#{icon.dot}" alt="&lt;" />}
      end
      def dot_nxt
        %{<img border="0" width="100%" height="20" src="#{url_path_image_sys}/#{icon.dot}" alt="&gt;" />}
      end
      self
    end
    def doc_types(page=:seg) #used in toc & seg_nav_band
      wgt=SiSU_HTML_Format::Widget.new(@md)
      %{
<table summary="segment navigation available documents types: toc,doc,pdf,concordance" border="0" cellpadding="3" cellspacing="0">
<tr>
<td align="center" bgcolor=#{the_color.band2}>
  #{wgt.manifest(page)}
  #{wgt.search}
</tr></table>}
    end
    def rdf
      SiSU_XML_Tags::RDF.new(md)
    end
    def button_home(page=:seg)
      button=%{ <table summary="home button / home information" border="0" cellpadding="3" cellspacing="0">\n <tr><td align="left" bgcolor="#ffffff">\n}
      if @md.make.home_button_image.is_a?(Hash)
        image_path=if page==:manifest
          @md.file.output_path.manifest.rel_image
        elsif  page==:scroll
          @md.file.output_path.html_scroll.rel_image
        else
          @md.file.output_path.html_seg.rel_image
        end
        SiSU_Env::FileOp.new(@md)
        button +=%{   <p class="tiny_left"><a href="#{@md.make.home_button_image[:link]}" target="_top"><img border="0" src="#{image_path}/#{@md.make.home_button_image[:home_button]}"  width="#{@md.make.home_button_image[:w]}" height="#{@md.make.home_button_image[:h]}" alt="home icon --&gt;" /></a></p>\n}
      elsif @md.home_button_links.is_a?(Array)
        @md.home_button_links.each do |links|
          button +=%{  <p class="tiny_left"><a href="#{links[:url]}" target="_top">\n    #{links[:say]}\n  </a></p>\n}
        end
      end
      button +=%{ </td></tr>\n </table>}
      button
    end
    def html_close #moved
    %{</body>
</html>}
    end
  end
  class Widget < HeadInformation
    include SiSU_Parts_HTML
    def initialize(md)
      super(md)
      @md=md
      @cf_defaults=SiSU_Env::InfoProcessingFlag.new
      @env=SiSU_Env::InfoEnv.new(md.fns)
      @file=SiSU_Env::FileOp.new(md)
      @o_str ||=SiSU_Env::ProcessingSettings.new(md).output_dir_structure
      @make=SiSU_Env::ProcessingSettings.new(md)
    end
    def home
      %{<td align="center" bgcolor=#{the_color.band2}>
  <a href="../index.html" target="_top">
  #{the_nav.txt_homepage}</a>
</td>
}
    end
    def scroll(text)
      if @md.fns =~ /\.(?:-|ssm\.)?sst$/
        %{<td align="center" bgcolor=#{the_color.band2}>
  <a href="#{Xx[:html_relative1]}html/#{@file.base_filename.html_scroll}" target="_top">
    #{text}
  </a>
</td>
}
      end
    end
    def seg(text)
      %{<td align="center" bgcolor="#99CC66">
  <a href="#{@md.file.base_filename.html_segtoc}" target="_top">
    #{text}
  </a>
</td>
}
    end
    def search
      if @make.build.html_search_form?
        env=SiSU_Env::InfoEnv.new(@md.fns,@md)
        env.widget.search_form('sisusearch',nil,nil,true)
      else ''
      end
    end
    def manifest(page=:seg)
      if @make.build.links_to_manifest? \
      and not @o_str.dump_or_redirect?
        manifest_lnk=if @file.output_dir_structure.by_language_code? \
        or @file.output_dir_structure.by_filetype?
          "#{Xx[:html_relative1]}manifest/#{@file.base_filename.manifest}"
        else @file.base_filename.manifest
        end
        if page==:manifest
          manifest_lnk="#{@md.file.output_path.manifest.url}/#{@file.base_filename.manifest}"
          %{<td align="center" bgcolor=#{the_color.band2}>
  <font face="#{the_font.set_fonts}" size="2">
  #{the_url_decoration.xml_open}<a href="#{manifest_lnk}" target="_top">#{@md.file.output_path.manifest.url}/#{@file.base_filename.manifest}</a>#{the_url_decoration.xml_close}
  </font>
</td>}
        else
          %{<td align="center" bgcolor=#{the_color.band2}>
  <a href="#{manifest_lnk}" target="_top">
    #{the_nav.txt_manifest}
  </a>
</td>}
        end
      else ''
      end
    end
  end
  class XML
  end
  class HeadToc < HeadInformation
    def initialize(md)
      super(md)
      @md=md
      @o_str ||=SiSU_Env::ProcessingSettings.new(md).output_dir_structure
      @make=SiSU_Env::ProcessingSettings.new(@md)
      @file=SiSU_Env::FileOp.new(@md)
    end
    def scroll_head_navigation_band
      if @make.build.html_top_band?
        <<WOK
<td align="center" width="60%">
  #{make_scroll_search_form_and_manifest_link}
</td>
WOK
        %{<table summary="table of contents scroll navigation band" id="toc" width="100%" bgcolor=#{the_color.band1}>
<tr><td width="20%">
  #{button_home(:scroll)}
</td>
<td width="75%" align="center">
  #{doc_types}
</td>
<td width="20%">
  &nbsp;
#{the_table_close}
<p>}
      else ''
      end
    end
    def concordance_navigation_band
      up_button=if @make.build.html_navigation?
        %{</td>
<td width="5%" align="right">
  &nbsp;<a href="toc.html" target="_top" alt="-&gt;">
      #{png_nav.toc}
    </a>&nbsp;
}
      else ''
      end
      if @make.build.html_top_band?
        %{<table summary="concordance navigation band" id="toc" width="100%" bgcolor=#{the_color.band1}>
<tr><td width="20%">
  #{button_home}
</td>
<td width="75%" align="center">
  #{doc_types}
#{up_button}
#{the_table_close}
<p>}
      else ''
      end
    end
    def seg_head_navigation_band(page=:seg)
      if @make.build.html_navigation?
        if page==:manifest
          nxt=(@file.output_dir_structure.by_language_code? \
          || @file.output_dir_structure.by_filetype?) \
          ? "../html/#{@md.fnb}/toc#{@md.lang_code_insert}#{Sfx[:html]}"
          : "toc#{@md.lang_code_insert}#{Sfx[:html]}"
          firstseg=%{<a href="#{nxt}" target="_top" alt="-&gt;">
          #{png_nav.nxt}</a>}
        elsif @md.firstseg =~/\S+/
          firstseg=%{<a href="#{@md.firstseg}#{@md.lang_code_insert}#{Sfx[:html]}" target="_top" alt="-&gt;">
        #{png_nav.nxt}</a>}
        end
      else ''
      end
      if @make.build.html_top_band?
        %{<table summary="table of contents segment navigation band" id="toc" width="100%" bgcolor=#{the_color.band1}>
<tr><td width="20%">
#{button_home(page)}
</td>
<td width="75%" align="center">
  #{doc_types(page)}
</td>
<td width="5%" align="right">
  &nbsp;#{firstseg}&nbsp;
#{the_table_close}
<p>}
      else ''
      end
    end
    def manifest_link(text)
#     @file=SiSU_Env::FileOp.new(@md) if @md
  %{<font size=2>
    <a href="#{@md.file.base_filename.manifest}" target="_top">#{text}</a>
  </font>}
    end
    def concordance_link(text)
      if @md.concord_make
  %{<font size=2>
    <a href="#{@md.file.base_filename.html_concordance}" target="_top">
      #{text}
    </a>
  </font>}
      else ''
      end
    end
    def make_scroll_search_form_and_manifest_link
      wgt=SiSU_HTML_Format::Widget.new(@md)
      %{<td align="center" bgcolor=#{the_color.band2}>
  #{the_nav.txt_doc_link}
</td>
}
      %{<table summary="toc segment and scroll with pdf" border="0" cellpadding="3" cellspacing="0">
<tr>
  #{wgt.manifest}
  #{wgt.search}
</tr></table>}
    end
    def make_scroll_seg_pdf
      seg=''
      wgt=SiSU_HTML_Format::Widget.new(@md)
      seg=%{<td align="center" bgcolor=#{the_color.band2}>
  #{the_nav.txt_toc_link}
</td>
}
      %{<table summary="toc scroll and segment with pdf" border="0" cellpadding="3" cellspacing="0">
<tr>
<td align="center" bgcolor=#{the_color.band2}>
  #{wgt.manifest}
  #{wgt.search}
</tr></table>}
    end
    def make_concordance
      wgt=SiSU_HTML_Format::Widget.new(@md)
      %{<table summary="toc scroll and segment with pdf" border="0" cellpadding="3" cellspacing="0">
<tr>
<td align="center" bgcolor=#{the_color.band2}>
  #{wgt.manifest}
  #{wgt.search}
</tr></table>}
    end
    def head
      rdf=SiSU_XML_Tags::RDF.new(@md)
      %{<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>
    #{@md.title.full}
  </title>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
#{rdf.metatag_html}
#{@stylesheet.css_head}
</head>
<body lang="#{@md.opt.lng}">
<a name="top" id="top"></a>}
    end
    def concordance
      if @md.concord_make
      %{#{the_margin.css}
  <h4 class="toc">
    <a href="./#{@md.file.base_filename.html_concordance}">
      <i>Concordance</i>
    </a>
  </h4>
#{table_close}}
      else
      %{#{the_margin.css}
#{table_close}}
      end
    end
    def links_guide_vertical_open
#     @file=SiSU_Env::FileOp.new(@md) if @md
      %{
<div id="vertical_links">
  <ul id="vertical">
  <li class="refbold">
    <a href="#{the_url.home}">
      #{the_text.txt_hp}
    </a>
  </li>
  <li class="ref">
     Quick Ref.:
  </li>
  <li class="ref">
    <a href="#{@md.file.base_filename.manifest}" alt="Document Manifest" target="_top">
      Manifest
    </a>
  </li>
<!- quick ref -!>}
    end
    def links_guide_horizontal_open
#     @file=SiSU_Env::FileOp.new(@md) if @md
      %{
<div id="horizontal_links">
  <ul id="horizontal">
  <li class="refbold">
    <a href="#{the_url.home}">
      #{the_text.txt_hp}
    </a>
  </li>
  <li class="ref">
     Quick Ref.:
  </li>
  <li class="ref">
    <a href="#{@md.file.base_filename.manifest}" alt="Document Manifest" target="_top">
      Manifest
    </a>
  </li>
<!- quick ref -!>}
    end
    def links_guide_open(type='horizontal')
      (type=='vertical') \
      ? links_guide_vertical_open
      : links_guide_horizontal_open
    end
    def links_guide_close
      insert=''
      insert=if @md.sfx_src =~/s?/
        link='http://sisudoc.org'                          #get from defaults
        url='sisudoc.org'
        name='SiSU electronic documents'                   #get from defaults
        insert= %{
  <li class="ref">
    <a href="#{link}" alt="#{name}" target="_top">
      #{url}
    </a>
  </li>
  </ul>
</div>
}
      end
      %{ #{insert}
<!- quick ref -!>}
    end
    def prefix_a
    end
    def rights
      def all
        rights=SiSU_HTML_Tune::CleanHTML.new(@md.rights.all).clean_for_html
        rights=rights.gsub(/^\s*Copyright\s+\(C\)/,'Copyright <sup>&copy;</sup>&nbsp;')
        %{<p class="small_left">Rights: #{rights}</p>
<p>}
      end
      self
    end
    def prefix_b
      %{<p class="small_left">Prefix: #{@md.prefix_b}<p />}
    end
    def scroll_head_title_banner_open
      icon=@md.icon ? %{<center>\n#{@md.icon}\n</center>} : ''
      %{#{icon}
#{the_banner.instrument_cover_band_scr}}
    end
    def seg_head_title_banner_open
      icon=@md.icon ? %{<center>\n#{@md.icon}\n</center>} : ''
      %{#{icon}
#{the_banner.instrument_cover_band_seg}}
    end
    def make_scroll
      concord=concordance_link(the_nav.txt_concordance)
      %{<table summary="toc scroll" border="0" cellpadding="3" cellspacing="0">
<tr><td align="center" bgcolor="white" border="0">
  #{the_nav.txt_doc_link}
</td>
<td align="center" bgcolor="white">
   #{concord}
#{the_table_close}}
    end
    def make_seg
      concord=concordance_link(the_nav.txt_concordance)
      %{<table summary="toc segment" border="0" cellpadding="3" cellspacing="0">
<tr><td align="center" bgcolor="white">
  #{the_nav.txt_toc_link}
</td>
<td align="center" bgcolor="white">
  <font size=2>
   #{concord}
#{the_table_close}}
    end
    def manifest #check structure
      if not @o_str.dump_or_redirect?
        manifest=manifest_link(the_nav.txt_manifest)
        %{#{the_margin.txt_3}
  #{the_font.paragraph_font_small}
   #{manifest}
    </font>
#{the_table_close}}
      else ''
      end
    end
    def concordance #check structure
      concord=concordance_link(the_nav.txt_concordance)
      %{#{the_margin.txt_3}
  #{the_font.paragraph_font_small}
   #{concord}
    </font>
#{the_table_close}}
    end
    def metadata
      %{#{the_margin.css}
  <h4 class="toc">
    <a href="#{@metalink}">
      <i>MetaData</i>
    </a>
  </h4>
#{the_table_close}}
    end
    def seg_tail
      %{
<div class="main_column">
<p>&nbsp;<p>
<table summary="toc segment tail" bgcolor=#{the_color.band1}>
<tr><td width="20%">
  #{the_banner.banner_band}
</td>
<td width="60%">
  <center>
    #{@tocband_segtoc}
  </center>
</td></tr>
</table>
<p>&nbsp;</p>
#{@bits.credits_sisu}
<a name="bottom" id="bottom"></a>
<a name="end" id="end"></a>
</div>
</div>
</div>
}
    end
    def scroll_tail #debug
      nav=scroll_head_navigation_band
      %{
<div class="main_column">
#{nav}
#{@bits.credits_sisu}
<a name="bottom" id="bottom"></a>
<a name="end" id="end"></a>
</div>
}
    end
    def seg_navigation_tail #this is a bug area, look up and "tidy"
      %{
<div class="main_column">
<p>&nbsp;</p>
#{@bits.credits_sisu}
<a name="bottom" id="bottom"></a>
<a name="end" id="end"></a>
</div>
</div>
</div>
}
    end
  end
  class HeadSeg < HeadInformation
    def initialize(md)
      super(md)
    end
    def dot_control_pre_next
      pre="#{@per.seg_name_x[@per.seg_name_x_tracker-1]}#{@md.lang_code_insert}#{Sfx[:html]}"
      up=@toc
      nxt="#{@per.seg_name_x[@per.seg_name_x_tracker+1]}#{@md.lang_code_insert}#{Sfx[:html]}"
      if nxt=~/sisu_manifest\.html/
        @file=SiSU_Env::FileOp.new(@md) if @md
        if @file.output_dir_structure.by_language_code? \
        or @file.output_dir_structure.by_filetype?
          nxt=nxt.gsub(/sisu_manifest\.html/,"../../manifest/#{@file.base_filename.manifest}")
        end
      end
      %{<table summary="segment hidden control pre and next" width="100%" border="0" cellpadding="0" bgcolor=#{the_color.grey_pale} align="center">
<tr><td align="left">
  <a href="#{pre}" target="_top">
    #{png_nav.dot_pre}
  </a>
</td>
<td align="center">
  <a href="#{up}" target="_top">
    #{png_nav.dot_toc}
  </a>
</td>
<td align="right">
  <a href="#{nxt}" target="_top">
    #{png_nav.dot_nxt}
  </a>
#{the_table_close}}
    end
    def dot_control_pre
      pre="#{@per.seg_name_x[@per.seg_name_x_tracker-2]}#{@md.lang_code_insert}#{Sfx[:html]}"
      up=@toc
      nxt="#{@md.file.base_filename.html_segtoc}"
      %{<table summary="segment hidden control pre" width="100%" border="0" cellpadding="0" bgcolor=#{the_color.grey_pale} align="center">
<tr><td align="left">
  <a href="#{pre}" target="_top">
    #{png_nav.dot_pre}
  </a>
</td>
<td align="center">
  <a href="#{up}" target="_top">
    #{png_nav.dot_toc}
  </a>
</td>
<td align="right">
  <a href="#{nxt}" target="_top">
    #{png_nav.dot_nxt}
  </a>
#{the_table_close}}
    end
    def toc_nav(f_pre=false,f_nxt=false,use=1)
      pre=nxt=''
      toc=%{<td align="center" bgcolor=#{the_color.band1}>
  <a href="#{@toc}" target="_top">
    #{png_nav.toc}
  </a>
</td>}
      pre=%{<td align="center" bgcolor=#{the_color.band1}>
  <a href="#{@per.seg_name_x[@per.seg_name_x_tracker-use]}#{@md.lang_code_insert}#{Sfx[:html]}" target="_top">
    #{png_nav.pre}
  </a>
</td>} if f_pre==true
      nxt=%{<td align="center" bgcolor=#{the_color.band1}>
  <a href="#{@per.seg_name_x[@per.seg_name_x_tracker+1]}#{@md.lang_code_insert}#{Sfx[:html]}" target="_top">
    #{png_nav.nxt}
  </a>
</td>} if f_nxt==true
      if nxt =~/sisu_manifest.html/
        @file=SiSU_Env::FileOp.new(@md) if @md
        if @file.output_dir_structure.by_language_code? \
        or @file.output_dir_structure.by_filetype?
          nxt=nxt.gsub(/sisu_manifest\.html/,"../../manifest/#{@file.base_filename.manifest}")
        end
      end
      %{<table summary="segment navigation pre/next" border="0" cellpadding="3" cellspacing="0">
<tr>
#{pre}
#{toc}
#{nxt}
<td>
#{the_table_close}}
    end
    def toc_next2
      toc_nav(false,true).dup
    end
    def toc_pre_next2
      toc_nav(true,true).dup
    end
    def toc_pre2
      toc_nav(true,false,2).dup
    end
    def manifest_link(text)
  %{<font size=2>
    <a href="#{@md.file.base_filename.manifest}" target="_top">
      #{text}
    </a>
  </font>}
    end
    def concordance_link(text)
      if @md.concord_make
  %{<font size=2>
    <a href="#{@md.file.base_filename.html_concordance}" target="_top">
      #{text}
    </a>
  </font>}
      else ''
      end
    end
    def credit
      %{
<div class="main_column">
#{@bits.credits_sisu}
<a name="bottom" id="bottom"></a>
<a name="end" id="end"></a>
</div></div>
}
    end
    def navigation_band(segtocband,seg_table_top_control) #change name to navigation_band_banner
      %{<table summary="segment navigation band with banner" bgcolor=#{the_color.band1} width="100%"><tr>
<td width="20%" align="left">
#{button_home}
</td>
<td width="75%" align="center">
  #{doc_types}
</td>
<td width="5%" align="right">
  #{segtocband}
</td></tr>
</table>
#{seg_table_top_control}}
    end
    def navigation_band_bottom(segtocband,seg_table_top_control) #change name to navigation_band_bannerless
      %{
<div class="main_column">
  <table summary="segment navigation band" bgcolor=#{the_color.band1} width="100%"><tr>
  <td width="70%" align="center">
    #{doc_types}
  </td>
  <td width="5%" align="right">
    #{segtocband}
  </td></tr>
  </table>
  #{seg_table_top_control}
</div>
}
    end
    def endnote_mark
%{
<p class="center" id="endnotes">
  <hr class="endnote" />
</p>}
    end
    def endnote_section_open
%{
<div class="endnote">
}
    end
    def endnote_section_close
%{
</div>
} #revisit
    end
    def head_seg
      rdf=SiSU_XML_Tags::RDF.new(@md)
      %{<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>
    #{@per.seg_name_x[@per.seg_name_x_tracker]} -
    #{@md.title.main}
  </title>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
#{rdf.metatag_html}
#{@stylesheet.css_head_seg}
</head>
<body lang="#{@md.opt.lng}">
<a name="top" id="top"></a>}
    end
    def title_banner(title,subtitle,creator)
      %{
<div class="summary">
  <p class="tiny">
    #{title}
  </p>
  <p class="tiny">
    #{subtitle}
  </p>
  <p class="tiny">
    #{creator}
  </p>
  <p class="tiny">
    copy @
    <a href="#{the_url.home}">
      #{the_text.txt_home}
    </a>
  </p>
</div>
}
    end
  end
  class HeadScroll < HeadToc
    def initialize(md)
      super(md)
    end
    def toc_owner_details
      %{#{the_margin.txt_3}
#{the_font.paragraph_font_small}
  <a href="#owner.details">
    Owner Details
    <font size="1" color="#777777">
      &nbsp;&nbsp;&nbsp;
    </font>
  </a>
  </font>
#{the_table_close}}
    end
  end
  class FormatTextObject
    include SiSU_Parts_HTML
    attr_accessor :md,:t_o,:txt,:ocn,:format,:table,:link,:linkname,:paranum,:p_num,:headname,:banner,:url
    def initialize(md,t_o)
      @md,@t_o=md,t_o
      @make=SiSU_Env::ProcessingSettings.new(@md)
      if t_o.is_a?(Hash)
        @txt            =t_o[:txt]            || nil
        @ocn            =t_o[:ocn]            || nil
        @ocn_display    =t_o[:ocn_display]    || nil
        @headname       =t_o[:headname]       || nil
        @trailer        =t_o[:trailer]        || nil
        @endnote_part_a =t_o[:endnote_part_a] || nil
        @endnote_part_b =t_o[:endnote_part_b] || nil
        @lnk_url        =t_o[:lnk_url]        || nil
        @lnk_txt        =t_o[:lnk_txt]        || nil
        @format         =t_o[:format]         || nil
      elsif t_o.class.inspect =~/^(?:#<)?SiSU_AO_DocumentStructure/
        @dob=t_o if defined? t_o.is
        @named=nametags_seg(@dob)
        @txt=((defined? t_o.obj) ? t_o.obj : nil)
        @ocn=((defined? t_o.ocn) ? t_o.ocn.to_s : nil)
        @headname=((t_o.is==:heading and defined? t_o.name) ? t_o.name : nil)
      else
        if @md.opt.act[:maintenance][:set]==:on
          p t_o.class
          p caller
        end
      end
      @headnamed=(@headname ? %{<a id="h#{@headname}"></a>} : nil)
      if @txt and not @txt.empty?
        @txt=@txt.gsub(/#{Mx[:mk_o]}[-~]##{Mx[:mk_c]}/,'')
      end
      @p_num=ParagraphNumber.new(@md,@ocn)
    end
    def nametags_scroll(dob)
      tags=''
      if defined? dob.tags \
      and dob.tags.length > 0 # insert tags "hypertargets"
        dob.tags.each do |t|
          t=t.gsub(/[^a-z0-9._-]/,'') #use for all html tags? consider limiting to strict? or implementing earlier
          tags=tags << %{<named id="#{t}" />}
        end
      end
      tags
    end
    def nametags_seg(dob) #FIX
      tags=''
      if defined? dob.tags \
      and dob.tags.length > 0 # insert tags "hypertargets"
        dob.tags.compact.each do |t| # .compact hides a problem, nil should not occur fix (upstream)
          t=t.gsub(/[^a-z0-9._-]/,'') #use for all html tags? consider limiting to strict? or implementing earlier
          tags=(t =~/^[0-9.]+$/) \
          ? tags             #check what can be sorted in ao
          : (tags << %{<a name="#{t}" ></a>})
        end
      end
      tags
    end
    def headname #check whether used
      hn=if @t_o.is ==:heading \
      and not @t_o.name.empty? #determine use
        hn=(@t_o.is ==:heading) \
        ? (%{<a id="h#{@t_o.name}"></a>})
        : (%{<a id="#{@t_o.name}"></a>})
      else nil
      end
      hn
    end
    def endnote_body
      %{
<p class="endnote">
  #{@txt}
</p>
}
    end
    def endnote_body_indent
      %{
  <p class="endnote_indent">
    #{@txt}
  </p>
}
    end
    def no_paranum
      %{
<div class="substance">
  <label class="ocn">&nbsp;</label>
  <p class="norm">
    #{@txt}
  </p>
</div>
}
    end
    def para_form_css(tag,attrib)                                                    # regular paragraphs shaped here
      ul=ulc=''
      if tag =~/li/
        ul,ulc="<ul>\n  ","\n  </ul>"
      end
      %{
<div class="substance">
  #{@p_num.ocn_display}
  #{ul}<#{tag} class="#{attrib}" #{@p_num.id}>
    #{@named}#{@txt}
  </#{tag}>#{ulc}
</div>
}
    end
    def para
      para_form_css('p','norm')
    end
    def block
      para_form_css('p','block')
    end
    def group
      para_form_css('p','group')
    end
    def alt
      para_form_css('p','alt')
    end
    def verse
      para_form_css('p','verse')
    end
    def code
      para_form_css('p','code')
    end
    def center
      para_form_css('p','center')
    end
    def bold
      para_form_css('p','bold')
    end
    def bullet
      para_form_css('li','bullet')
    end
    def table
      @txt=if @t_o.obj !~/^<table\s/
        table=SiSU_HTML_Shared::TableHTML.new(@t_o) #move, make happen earlier
        @txt=table.table.obj
      else @txt
      end
      para_form_css('p','norm')
    end
    def format(tag,attrib)
      para_form_css(tag,attrib)
    end
    def heading_normal(tag,attrib)
      section_break=(tag=~/h[1-5]/) \
      ? '<br><hr width=90% /><br>'
      : ''
      %{#{section_break}
<div class="substance">
  #{@p_num.ocn_display}
  <#{tag} class="#{attrib}" #{@p_num.id}>#{@p_num.name}
    #{@named}#{@txt}
  </#{tag}>
</div>
}
    end
    def heading_body
      heading_normal('p','norm')
    end
    def heading_body0
      heading_normal('h1','norm')
    end
    def heading_body1
      heading_normal('h1','norm')
    end
    def heading_body2
      heading_normal('h2','norm')
    end
    def heading_body3
      heading_normal('h3','norm')
    end
    def heading_body4
      heading_normal('h4','norm')
    end
    def heading_body5
      heading_normal('h5','norm')
    end
    def heading_body6
      heading_normal('h6','norm')
    end
    def heading_body7
      heading_normal('h7','norm')
    end
    def title_heading(tag,attrib)
      cl=(@make.build.html_minitoc?) \
      ? 'content'
      : 'content0'
      %{
<div class="#{cl}">
<#{tag} class="#{attrib}">
    #{@named}#{@txt}
  </#{tag}>
</div>
}
    end
    def title_heading0
      title_heading('h1','tiny')
    end
    def title_heading1
      title_heading('h1','tiny')
    end
    def title_heading2
      title_heading('h2','tiny')
    end
    def title_heading3
      title_heading('h3','tiny')
    end
    def title_heading4
      ''
    end
    def seg_heading_sub(tag,attrib)
      @txt=@txt.gsub(/(?:#{Mx[:en_a_o]}.+?#{Mx[:en_a_c]}|#{Mx[:en_b_o]}.+?#{Mx[:en_b_c]})\s*/m,' ')
      %{
<div class="substance">
  #{@p_num.ocn_display}
  <#{tag} class="#{attrib}" #{@p_num.id}>#{@p_num.name} #{@headnamed}
    #{@named}#{@txt}
  </#{tag}>
</div>
}
    end
    def seg_heading4
      %{
<div class="substance">
  #{@p_num.ocn_display}
  <h1 class="norm" #{@p_num.id}>#{@p_num.name}
    #{@txt}
  </h1>
</div>
}
    end
    def seg_heading5
      seg_heading_sub('p','bold')
    end
    def seg_heading6
      seg_heading_sub('p','bold')
    end
    def dl #check :trailer
      "<dl><b>#{@txt}</b> #{@trailer}</dl>"
    end
    def table_css_end
      '</table>
    </p>
  </div>'
    end
    def gsub_body #fix
      @txt=case @txt
      when /^\((i+|iv|v|vi+|ix|x|xi+)\)/
        @txt.gsub(/^\((i+|iv|v|vi+|ix|x|xi+)\)/,'<b>(\1)</b>')
      when /^\(?(\d|[a-z])+\)/
        @txt.gsub(/^\((\d+|[a-z])+\)/,'<b>(\1)</b>')
      when /^\s*\d{1,3}\.\s/
        @txt.gsub(/^\s*(\d+\.)/,'<b>\1</b>')
      when /^\s*[A-Z]\.\s/
        @txt.gsub(/^\s*([A-Z]\.)/,'<b>\1</b>')
      else @txt
      end
    end
    def bold_para
      %{#{the_margin.txt_0}
  <p class="bold">
    #{@txt}
  </p>
#{the_margin.num_css}
  &nbsp;&nbsp;&nbsp;
#{the_table_close}}
    end
    def bold_heading
      %{<p class="bold">
    #{@txt}
  </p>
#{the_margin.num_css}
  &nbsp;&nbsp;&nbsp;
#{the_table_close}}
    end
    def toc_head_copy_at
      %{<p class="center">#{@txt}</p>\n}
    end
    def center
      %{<p class="center">#{@txt}</p>\n}
    end
    def bold
      %{<p class="bold">#{@txt}</p>\n}
    end
    def center_bold
      %{<p class="centerbold">#{@txt}</p>\n}
    end
  end
  class FormatScroll < FormatTextObject
    def initialize(md,txt)
      super(md,txt)
    end
  end
  class FormatSeg < FormatTextObject
    def initialize(md,txt)
      super(md,txt)
    end
    def endnote_seg_body(fn='')
      fn="../#{@md.fnb}" if fn.to_s.empty?
      %{
  <p class="endnote">
    #{@endnote_part_a}#{fn}#{@md.lang_code_insert}#{Sfx[:html]}#{@endnote_part_b}
  </p>
}
    end
    def clean(txt)
      txt=txt.gsub(/#{Mx[:en_a_o]}.+?#{Mx[:en_a_c]}/,'').
        gsub(/#{Mx[:en_b_o]}.+?#{Mx[:en_b_c]}/,'')
    end
    def subtoc_lev(tag,attrib)
      @txt=clean(@txt)
      txt=if @txt \
      and @txt =~/<\/?i>|<a\s+name="\S+?">/mi
        @txt.gsub(/<\/?i>|<a\s+name="\S+?">/mi,'') #removes name markers from subtoc, go directly to substantive text
      else @txt
      end
      note=''
      if txt =~/(#{Mx[:en_a_o]}.+?#{Mx[:en_a_c]}|#{Mx[:en_b_o]}.+?#{Mx[:en_b_c]})/m # had \s* at end
        note=$1
        note=note.gsub(/[\s]+/m,' ')
        txt=txt.gsub(/(?:#{Mx[:en_a_o]}.+?#{Mx[:en_a_c]}|#{Mx[:en_b_o]}.+?#{Mx[:en_b_c]})\s*/m,' ').
          gsub(/<a[\s]+name="-\d+"[\s]+href="#_\d+">&nbsp;<sup>\d+<\/sup>&nbsp;/m,'')
      end
      %{<#{tag} class="#{attrib}">
    <a href="##{@ocn}"><i>#{txt}</i></a> #{note}
  </#{tag}>}
    end
    def subtoc_lev5
      subtoc_lev('h5','subtoc') if @txt
    end
    def subtoc_lev6
      subtoc_lev('h6','subtoc') if @txt
    end
    def subtoc_lev7
      subtoc_lev('h7','subtoc') if @txt
    end
    def heading_sub(tag,attrib)
      @txt=@txt.gsub(/(?:#{Mx[:en_a_o]}.+?#{Mx[:en_a_c]}|#{Mx[:en_b_o]}.+?#{Mx[:en_b_c]})\s*/m,' ')
      %{
<div class="substance">
  #{@p_num.ocn_display}
  <#{tag} class="#{attrib}" #{@p_num.id}>#{@p_num.name} #{@headnamed}
    #{@txt}
  </#{tag}>
</div>
}
    end
    def heading5
      heading_sub('p','bold')
    end
    def heading6
      heading_sub('p','bold')
    end
    def heading4
      %{
<div class="substance">
  #{@p_num.ocn_display}
  <h1 class="norm" #{@p_num.id}>#{@p_num.name}
    #{@t_o[:format]}
    #{@txt}
  </h1>
</div>
}
    end
    def navigation_heading4
      %{<table summary="navigation segment heading 4" width=100% bgcolor="#08163f" border="0">
<tr><td align="center">
<p class="bold">
  #{@txt}
</p>
#{the_table_close}}
    end
    def navigation_heading5
      %{<p class="bold">
  #{@txt}
</p>}
    end
    def navigation_heading6
      %{<p class="bold">
  #{@txt}
</p>}
    end
    def navigation_center
      "<center>#{@txt}</center>"
    end
  end
  class FormatToc < FormatTextObject
    def initialize(md,txt)
      super(md,txt)
    end
    def links_guide
      %{  <li class="doc">
    <a href="#{@lnk_url}" target="_top">
      #{@lnk_txt}
    </a>
  </li>
}
    end
    def lev(tag,attrib)
      if @txt
        %{<#{tag} class="#{attrib}">
    #{@txt}
  </#{tag}>
}
      else ''
      end
    end
    def lev0 #docinfo
      lev('h1','toc')
    end
    def lev1
      lev('h1','toc')
    end
    def lev2
      lev('h2','toc')
    end
    def lev3
      lev('h3','toc')
    end
    def lev4
      lev('h4','toc')
    end
    def lev5
      lev('h5','toc')
    end
    def lev6
      lev('h6','toc')
    end
    def lev7
      lev('h7','toc')
    end
    def strip_endnotes(txt)
      txt=txt.gsub(/(?:#{Mx[:en_a_o]}.+?#{Mx[:en_a_c]}|#{Mx[:en_b_o]}.+?#{Mx[:en_b_c]})\s*/m,' ')
      txt
    end
    def mini_lev0
      @txt=strip_endnotes(@txt)
      lev('h1','minitoc')
    end
    def mini_lev1
      @txt=strip_endnotes(@txt)
      lev('h1','minitoc')
    end
    def mini_lev2
      @txt=strip_endnotes(@txt)
      lev('h2','minitoc')
    end
    def mini_lev3
      @txt=strip_endnotes(@txt)
      lev('h3','minitoc')
    end
    def mini_lev4
      @txt=strip_endnotes(@txt)
      lev('h4','minitoc')
    end
    def mini_lev5
      @txt=strip_endnotes(@txt)
      lev('h5','minitoc')
    end
    def mini_lev6
      @txt=strip_endnotes(@txt)
      lev('h6','minitoc')
    end
    def mini_lev7
      @txt=strip_endnotes(@txt)
      lev('h7','minitoc')
    end
    def mini_lev0 #docinfo
      lev('h1','minitoc')
    end
    def mini_tail
  %{
  <h4 class="minitoc">
    <a href="sisu_manifest.html">Manifest (alternative outputs)</a>
  </h4>
}
    end
    def mini_concord_tail
  %{
  <h4 class="minitoc">
    <a href="concordance.html">Concordance (wordlist)</a>
  </h4>
  <h4 class="minitoc">
    <a href="sisu_manifest.html">Manifest (alternative outputs)</a>
  </h4>
}
    end
  end
  class FormatStr
    def initialize(md,str)
      @str=str
    end
    def center
      %{<p class="center">#{@str}</p>\n}
    end
    def bold
      %{<p class="bold">#{@str}</p>\n}
    end
    def center_bold
      %{<p class="centerbold">#{@str}</p>\n}
    end
    def endnote_body
      %{
<p class="endnote">
  #{@str}
</p>
}
    end
  end
end
__END__
#+END_SRC

** shared
*** html_shared.rb

#+HEADER: :tangle "../lib/sisu/html_shared.rb"
#+BEGIN_SRC ruby
#<<sisu_document_header>>
module SiSU_HTML_Shared
  require_relative 'html_table'                         # html_table.rb
  class TableHTML < SiSU_HTML_Table::TableHTML
  end
end
__END__
#+END_SRC

*** html_lite_shared.rb

#+HEADER: :tangle "../lib/sisu/html_lite_shared.rb"
#+BEGIN_SRC ruby
#<<sisu_document_header>>
module SiSU_FormatShared
  require_relative 'html_parts'                         # html_parts.rb
  class CSS_Format
    require_relative 'se_hub_particulars'               # se_hub_particulars.rb
    include SiSU_Parts_HTML
    @@fns=nil
    def initialize(md,t_o)
      @md,@t_o=md,t_o
      @txt=@t_o.obj
      @id=@ocn=@t_o.ocn if defined? @t_o.ocn
      @lv=@t_o.lv.to_s if @t_o.is==:heading
      if @md.fns != @@fns
        @@fns,@@hname=@md.fns,''
      end
      @hname=if defined? @t_o.name \
      and not @t_o.name.to_s.empty?
        @@hname=@t_o.name
      else @@hname
      end
      @tab="\t"
      @@tablehead,@@tablefoot=[],[]
      @env=SiSU_Env::InfoEnv.new(@md.fns)
      @base_url="#{@env.url.root}/#{@md.fnb}/#{@hname}.html"
    end
    def urls(data)
      @words=[]
      map_nametags=SiSU_Particulars::CombinedSingleton.instance.get_map_nametags(@md).nametags_map
      data.each do |word|
        @words << if word=~/#{Mx[:lnk_o]}(.+?)#{Mx[:lnk_c]}(#{Mx[:url_o]}\S+?#{Mx[:url_c]}|#{Mx[:rel_o]}\S+?#{Mx[:rel_c]}|image)/
          if word =~/#{Mx[:lnk_o]}.+?#{Mx[:lnk_c]}#{Mx[:url_o]}\S+?#{Mx[:url_c]}/
            m,u=/#{Mx[:lnk_o]}(.+?)#{Mx[:lnk_c]}#{Mx[:url_o]}(\S+?)#{Mx[:url_c]}/.match(word).captures
          elsif word =~/#{Mx[:lnk_o]}.+?#{Mx[:lnk_c]}#{Mx[:rel_o]}\S+?#{Mx[:rel_c]}/
            m,u=/#{Mx[:lnk_o]}(.+?)#{Mx[:lnk_c]}#{Mx[:rel_o]}(\S+?)#{Mx[:rel_c]}/.match(word).captures
          elsif word =~/#{Mx[:lnk_o]}.+?#{Mx[:lnk_c]}image/
            m,u=/#{Mx[:lnk_o]}(.+?)#{Mx[:lnk_c]}(image)/.match(word).captures
          end
          word=case m
          when /\.png|\.jpg|\.gif|c=|\d+x\d+/
            w,h=/(\d+)x(\d+)/.match(m).captures if m =~/\d+x\d+/
            w=%{width="#{w}"} if w
            h=%{height="#{h}"} if h
            c=m[/"(.+?)"/m,1]
            caption=%{<br><p class="caption">#{c}</p>} if c
            png=m.scan(/\S+/)[0]
            ins=if u \
            and u.strip !~/^image$/
              %{<a href="#{u}">[#{png}]</a>#{caption}}
            else %{[#{png}] #{caption}}
            end
            word=word.gsub(/#{Mx[:lnk_o]}.+?#{Mx[:lnk_c]}(#{Mx[:url_o]}\S+?#{Mx[:url_c]}|image)/,ins)
          else
            u=case u
            when /^https?:\/\//
              u
            when /^:/
              u=u.gsub(/^:/,'')
              "#{@env.url.root}/#{u}"
            when /^\.\.\// # can remove
              u=u.gsub(/^\.\.\//,'')
              "#{@env.url.root}/#{u}"
            else
              if not map_nametags[u].nil?
                @env.url.root + '/' \
                + @md.fnb + '/' \
                + map_nametags[u][:segname] \
                + Sfx[:html] \
                + '#' + u
              else ''
              end
            end
            link=m[/(.+)/m]
            png=m.scan(/\S+/)[0].strip
            link=link.strip
            ins=%{<a href="#{u}">#{link}</a>}
            word=word.gsub(/#{Mx[:lnk_o]}.+?#{Mx[:lnk_c]}#{Mx[:url_o]}\S+?#{Mx[:url_c]}/,ins).
              gsub(/#{Mx[:lnk_o]}.+?#{Mx[:lnk_c]}#{Mx[:rel_o]}\S+?#{Mx[:rel_c]}/,ins)
            word
          end
          word
        else word
        end
        word
      end
      @words=@words.join(' ')
    end
    def markup_generic(s)
      s=s.gsub(/#{Mx[:fa_bold_o]}(.+?)#{Mx[:fa_bold_c]}/,'<b>\1</b>').
        gsub(/#{Mx[:fa_italics_o]}(.+?)#{Mx[:fa_italics_c]}/,'<i>\1</i>').
        gsub(/#{Mx[:fa_underscore_o]}(.+?)#{Mx[:fa_underscore_c]}/,'<u>\1</u>').
        gsub(/#{Mx[:fa_cite_o]}(.+?)#{Mx[:fa_cite_c]}/,'"\1"').
        gsub(/#{Mx[:fa_insert_o]}(.+?)#{Mx[:fa_insert_c]}/,'+{\1}+').
        gsub(/#{Mx[:fa_strike_o]}(.+?)#{Mx[:fa_strke_c]}/,'-{\1}-').
        gsub(/#{Mx[:fa_superscript_o]}(.+?)#{Mx[:fa_superscript_c]}/,'<sup>\1</sup>').
        gsub(/#{Mx[:fa_subscript_o]}(.+?)#{Mx[:fa_subscript_c]}/,'<sub>\1</sub>').
        gsub(/#{Mx[:fa_monospace_o]}(.+?)#{Mx[:fa_monospace_c]}/,'<tt>\1</tt>'). # tt, kbd
        gsub(/#{Mx[:gl_o]}#(?:126|152)#{Mx[:gl_c]}/i,'~')
    end
    def markup_object(t_o)
      s=t_o.obj
      s=if t_o.is !=:code
        s=markup_generic(s)
        if s =~/#{Mx[:lnk_o]}.+?#{Mx[:lnk_c]}(?:#{Mx[:url_o]}\S+?#{Mx[:url_c]}|#{Mx[:rel_o]}\S+?#{Mx[:rel_c]}|image)/
          wm=s.scan(/#{Mx[:lnk_o]}.+?#{Mx[:lnk_c]}(?:#{Mx[:url_o]}\S+?#{Mx[:url_c]}|#{Mx[:rel_o]}\S+?#{Mx[:rel_c]}|image)|\S+/)
          words=urls(wm)
          s=s.gsub(/.+/m,words)
        end
        s.gsub(/#{Mx[:gl_o]}(#[0-9]{3})#{Mx[:gl_c]}/u,'&\1;').
          gsub(/#{Mx[:gl_o]}#([a-z]{2,4})#{Mx[:gl_c]}/u,'&\1;').
          gsub(/#{Mx[:url_o]}[_\\](\S+?)#{Mx[:url_c]}/,'<a href="\1" target="_top">\1</a>'). #http ftp matches escaped, no decoration
          gsub(/(#{Mx[:lnk_c]})#{Mx[:url_o]}(\S+?)#{Mx[:url_c]}/,'\1<a href="\2" target="_top">\2</a>'). #special case \{ e.g. \}http://url
          gsub(/(^|#{Mx[:gl_c]}|\s)#{Mx[:url_o]}(\S+?)#{Mx[:url_c]}/,%{\\1#{the_url_decoration.xml_open}<a href="\\2" target="_top">\\2</a>#{the_url_decoration.xml_close}\\3}) #http ftp matches with decoration
      else
        s.gsub(/</m,'&lt;').
          gsub(/>/m,'&gt;')
      end
      s
    end
    def markup_note(s)
      s=markup_generic(s)
      if s =~/#{Mx[:lnk_o]}.+?#{Mx[:lnk_c]}(#{Mx[:url_o]}\S+?#{Mx[:url_c]}|#{Mx[:rel_o]}\S+?#{Mx[:rel_c]}|image)/
        wm=s.scan(/#{Mx[:lnk_o]}.+?#{Mx[:lnk_c]}(?:#{Mx[:url_o]}\S+?#{Mx[:url_c]}|#{Mx[:rel_o]}\S+?#{Mx[:rel_c]}|image)|\S+/)
        words=urls(wm)
        s=s.gsub(/.+/m,words)
      end
      s=s.gsub(/#{Mx[:gl_o]}(#[0-9]{3})#{Mx[:gl_c]}/u,'&\1;').
        gsub(/#{Mx[:gl_o]}#([a-z]{2,4})#{Mx[:gl_c]}/u,'&\1;').
        gsub(/#{Mx[:url_o]}_(\S+?)#{Mx[:url_c]}/,'<a href="\1" target="_top">\1</a>\2'). #http ftp matches escaped, no decoration
        gsub(/(#{Mx[:lnk_c]})#{Mx[:url_o]}(\S+?)#{Mx[:url_c]}/,'\1<a href="\2" target="_top">\2</a>'). #special case \{ e.g. \}http://url
        gsub(/#{Mx[:url_o]}(\S+?)#{Mx[:url_c]}/,%{#{the_url_decoration.xml_open}<a href="\\1" target="_top">\\1</a>#{the_url_decoration.xml_close}}) #http ftp matches with decoration
    end
    def paragraph
      %{<p class="h#{@lv}" type="substantive" header="#{@hname}">#{@txt}</p>\n} # << "\n"
    end
    def endnote(nr,en) #used only by db
      txt=markup_note(en)
      <<GSUB
<p class="endnote" name="note_#{nr}" from="#{@t_o.ocn}">
<a href="#{@base_url}#-#{nr}" name="_#{nr}">#{nr}.</a> <note>#{txt}</note>
</p>
GSUB
    end
    def tag_header(h)
      %{<p class="#{h[:class]}" type="#{h[:type]}" header="#{h[:header]}">#{h[:txt]}</a></p>\n} # << "\n"
    end
    def tag_para(h)
      %{<p class="#{h[:class]}" type="#{h[:type]}">#{h[:txt]}</a></p>\n}  << "\n"
    end
    def lev_toc_hname
      %{<p class="toc#{@lv}" header="#{@hname}"><a href="##{@ocn}">#{@txt}</a></p>\n}  #<< "\n"
    end
    def lev_toc
      h={ txt: txt, class: "toc#{@lv}", type: 'toc' }
      tag_para(h)
    end
    def lev4_plus
      txt=markup_object(@t_o)
      h={ txt: txt, class: "h#{@lv}", type: 'substantive', id: @ocn, header: @hname }
      tag_header(h)
    end
    def lev4_minus
      txt=markup_object(@t_o)
      h={ txt: txt, class: "h#{@t_o.ln}", type: 'substantive', id: @ocn }
      tag_para(h)
    end
    def norm_comment
      h={ txt: @t_o.obj, class: 'norm', type: 'comment' }
      tag_para(h)
    end
    def norm
      txt=markup_object(@t_o)
      h={ txt: txt, class: 'norm', type: 'substantive', id: @ocn }
      tag_para(h)
    end
    def code
      txt=markup_object(@t_o)
      h={ txt: "<tt>#{txt}</tt>", class: 'code', type: 'substantive', id: @ocn }
      tag_para(h)
    end
    def indent(t)
      txt=markup_object(@t_o)
      h={ txt: txt, class: "indent#{t}", type: 'substantive', id: @ocn }
      tag_para(h)
    end
    def hang_indent(f,t)
      txt=markup_object(@t_o)
      h={ txt: txt, class: "hang#{f}indent#{t}", type: 'substantive', id: @ocn }
      #h={ txt: txt, class: "h#{f}i#{t}", type: 'substantive', id: @ocn }
      tag_para(h)
    end
    def para_table
      %{<p class="norm" align="left"><font #{the_font.set_small} #{the_font.set_color} #{the_font.set_face}>}
    end
    def ocn
      %{<label class="ocn">#{@ocn}</label>} << "\n"
    end
    def html_table # get rid of use html_table
      @new_content=[]
      @txt.split(/\n/).each do |parablock|
        m=parablock[/<!f(.+?)!>/,1]
        @@tablefoot << m if m
        parablock=parablock.gsub(/<!f.+?!>/,'')
        @@tablehead=1 if parablock =~/#{Mx[:gr_o]}Th#{Mx[:tc_p]}/u
        parablock=parablock.gsub(/#{Mx[:gr_o]}Th?#{Mx[:tc_p]}.+?#{Mx[:tc_p]}~(\d+)#{Mx[:gr_c]}/,
          %{<table summary="normal text css" width="100%" border="0" cellpadding="2" align="center">})
        if parablock =~/#{Mx[:gr_o]}TZ#{Mx[:gr_c]}/
          tablefoot=[]
          @@tablefoot.each {|x| tablefoot << %{<p align="center"><font size=2><i>#{x}</i></font></p>\n}}
          @@tablefoot=[]
          parablock=parablock.gsub(/#{Mx[:gr_o]}TZ#{Mx[:gr_c]}/,
            %{#{the_table_close}\n}) # +
        end
        if @@tablehead==1
          if parablock =~/#{Mx[:tc_p]}#{Mx[:tc_p]}/u
            parablock=parablock.gsub(/#{Mx[:tc_o]}#{Mx[:tc_p]}#{Mx[:tc_p]}(\d+?)#{Mx[:tc_p]}/u,
                %{\n<tr>} +
                %{\n<td width="\\1%" valign="top">} +
                %{#{para_table}<b>}).
              gsub(/#{Mx[:tc_p]}#{Mx[:tc_p]}(\d+?)#{Mx[:tc_p]}/u,
                %{</b></td><td width="\\1%" valign="top">} +
                %{#{para_table}<b>}).
              gsub(/#{Mx[:tc_c]}/, '</b></td></tr>')
            @@tablehead=0
          end
          parablock
        else
          parablock=parablock.gsub(/#{Mx[:tc_o]}#{Mx[:tc_p]}#{Mx[:tc_p]}(\d+?)#{Mx[:tc_p]}/u,
              %{\n<tr>} +
              %{\n<td width="\\1%" valign="top">} +
              %{#{para_table}}).
            gsub(/#{Mx[:tc_p]}#{Mx[:tc_p]}(\d+?)#{Mx[:tc_p]}/u,
              %{</td><td width="\\1%" valign="top">} +
              %{#{para_table}}).
            gsub(/#{Mx[:tc_c]}/, '</td></tr>')
          parablock
        end
        @new_content << parablock
      end
      @new_content.join
    end
  end
  class CSS_FormatGeneric #does CSS_Format in one definition, needs to be told about attrib, despite brevity of generic, easier to see structure with CSS_Format
    def initialize(attrib='',txt='',id=nil,ocnd=nil,ocns=nil,lv='',hname=nil)
      @tab="\t"
      @attrib=attrib
      @txt=txt
      @lv=lv.to_s
      @hname=hname.to_s
      @id=@ocn=id
    end
    def paragraph
      attrib=%{class="#{@attrib}" }
      if @ocn
        id=%{id="#{Mx[:ocn_id_char]}#{@ocn}" }
        type=%{type="substantive" }
      else
        id=''
        type=%{type="comment" }
      end
      header=%{header="#{@hname}" } if @hname
      %{<p #{attrib}#{type}#{header}>#{@txt}</p>\n} #<< "\n"
    end
    def para
      paragraph
    end
  end
end
__END__
#+END_SRC

*** html_table.rb

#+HEADER: :tangle "../lib/sisu/html_table.rb"
#+BEGIN_SRC ruby
#<<sisu_document_header>>
module SiSU_HTML_Table
  require_relative 'xhtml_table'                         # xhtml_table.rb
  require_relative 'html_parts'                          # html_parts.rb
  class TableHTML < SiSU_XHTML_Table::TableXHTML
    include SiSU_Parts_HTML
  end
end
__END__
#+END_SRC

#+RESULTS:

** misc
*** html_minitoc.rb

#+HEADER: :tangle "../lib/sisu/html_minitoc.rb"
#+BEGIN_SRC ruby
#<<sisu_document_header>>
module SiSU_HTML_MiniToc
  require_relative 'html_tune'                        # html_tune.rb
    include SiSU_HTML_Tune
  class TocMini
    @@seg_mini=nil
    @@seg_url=''
    @@firstseg=nil
    def initialize(md,data)
      @md,@data=md,data
      @pat_strip_heading_name=/<a name="h?\d.*?">(.+?)<\/a>/
      @tell=SiSU_Screen::Ansi.new(@md.opt.act[:color_state][:set]) if @md
    end
    def songsheet
      if (@md.opt.act[:verbose][:set]==:on \
      || @md.opt.act[:verbose_plus][:set]==:on \
      || @md.opt.act[:maintenance][:set]==:on)
        SiSU_Screen::Ansi.new(@md.opt.act[:color_state][:set],'Toc').txt_grey
      end
      toc=nil
      @toc=[]
      @data.each do |txt|
        if txt.is ==:heading \
        || txt.is ==:heading_insert
          txt.obj=txt.obj.gsub(/(?:#{Mx[:en_a_o]}|#{Mx[:en_b_o]}).+?(?:#{Mx[:en_a_c]}|#{Mx[:en_b_c]})/m,''). #remove endnotes from toc
            gsub(/<a name="-\d+" href="#_\d+">&nbsp;<sup>\d+<\/sup>&nbsp;<\/a>/,'').
            gsub(@pat_strip_heading_name,'\1')
            #gsub(/(.*?)<a name="(\d+)"><\/a>(.*)/,'\1') #2002w42 altered gsub - problematic? - suspect
          toc=case txt.ln
          when 0 then SiSU_HTML_MiniToc::TocMini.new(@md,txt).level_0
          when 1 then SiSU_HTML_MiniToc::TocMini.new(@md,txt).level_1
          when 2 then SiSU_HTML_MiniToc::TocMini.new(@md,txt).level_2
          when 3 then SiSU_HTML_MiniToc::TocMini.new(@md,txt).level_3
          when 4 then SiSU_HTML_MiniToc::TocMini.new(@md,txt).level_4
          when 5 then SiSU_HTML_MiniToc::TocMini.new(@md,txt).level_5
          when 6 then SiSU_HTML_MiniToc::TocMini.new(@md,txt).level_6
          else
          end
          @toc << toc
        end
      end
      @toc
    end
  protected
    def level_concordance
      format_head_toc=SiSU_HTML_Format::HeadToc.new(@md)
      @@seg_mini << format_head_toc.mini_seg_concordance
    end
    def level_metadata
      format_head_toc=SiSU_HTML_Format::HeadToc.new(@md)
      @@seg_mini << format_head_toc.mini_seg_metadata
    end
    def level_word_index
      format_head_toc=SiSU_HTML_Format::HeadToc.new(@d0c)
      @@seg_mini << format_head_toc.mini_concordance
    end
    def level_0
      txt=@data
      if (txt.is ==:heading \
      || txt.is ==:heading_insert) \
      && txt.ocn !=0
        txt.obj=txt.obj.gsub(@pat_strip_heading_name,'\1')
      end
      txt_obj={ txt: txt.obj }
      format_toc=SiSU_HTML_Format::FormatToc.new(@md,txt_obj)
      toc_mini=format_toc.mini_lev0
      toc_mini
    end
    def level_1
      txt=@data
      if (txt.is ==:heading \
      || txt.is ==:heading_insert) \
      && txt.ocn !=0
        txt.obj=txt.obj.gsub(@pat_strip_heading_name,'\1')
      end
      title=unless txt.obj =~/Document Information/ then txt.obj
      else
        link='metadata'
        %{<b><a href="#{link}#{@md.lang_code_insert}#{Sfx[:html]}">#{txt.obj}</a></b>}
      end
      txt_obj={ txt: title }
      format_toc=SiSU_HTML_Format::FormatToc.new(@md,txt_obj)
      toc_mini=if txt.name =~/^meta/ \
      and txt.obj=~/Document Information/
        format_toc.mini_tail
      else format_toc.mini_lev1
      end
      toc_mini
    end
    def level_2
      txt=@data
      if (txt.is ==:heading \
      || txt.is ==:heading_insert) \
      && txt.ocn !=0
        txt.obj=txt.obj.gsub(@pat_strip_heading_name,'\1')
      end
      txt_obj={ txt: txt.obj }
      format_toc=SiSU_HTML_Format::FormatToc.new(@md,txt_obj)
      toc_mini=format_toc.mini_lev2
      toc_mini
    end
    def level_3
      txt=@data
      txt_obj={ txt: txt.obj }
      format_toc=SiSU_HTML_Format::FormatToc.new(@md,txt_obj)
      toc_mini=format_toc.mini_lev3
      toc_mini
    end
    def level_4
      txt=@data
      unless txt.obj =~/~metadata/
        if txt.ln ==4
          fnh={
            fn: txt.name,
          }
          f=@md.file.base_filename.html_seg(fnh)
          seg_link=%{  <a href="#{f}" target="_top">
    #{txt.obj}
  </a> }
          @@seg_url=txt.name
        elsif txt.obj =~/\d+.\d+.\d+.\d+|\d+.\d+.\d+|\d+.\d+|\d+/
          fn,hd=/^(\d+.\d+.\d+.\d+|\d+.\d+.\d+|\d+.\d+|\d+)(.*)/.match(dob.obj)[1,2]
          fnh={
            fn: fn,
          }
          f=@md.file.base_filename.html_seg(fnh)
          seg_link=%{<a href="#{f}" target="_top">#{fn} #{hd}</a> }
        end
        txt_obj={ txt: seg_link }
        format_toc=SiSU_HTML_Format::FormatToc.new(@md,txt_obj)
        toc_mini=format_toc.mini_lev4
        toc_mini
      end
    end
    def level_5
      txt=@data
      if (txt.is ==:heading \
      || txt.is ==:heading_insert) \
      && txt.ocn !=0
        txt.obj=txt.obj.gsub(@pat_strip_heading_name,'\1')
      end
      fnh={
        fn: @@seg_url,
      }
      f=@md.file.base_filename.html_seg(fnh)
      lnk_n_txt=%{  <a href="#{f}##{txt.ocn}">
    #{txt.obj}
  </a>}
        txt_obj={ txt: lnk_n_txt }
        format_toc=SiSU_HTML_Format::FormatToc.new(@md,txt_obj)
        toc_mini=format_toc.mini_lev5
      toc_mini
    end
    def level_6
      txt=@data
      if (txt.is ==:heading \
      || txt.is ==:heading_insert) \
      && txt.ocn !=0
        txt.obj=txt.obj.gsub(@pat_strip_heading_name,'\1')
      end
      fnh={
        fn: @@seg_url,
      }
      f=@md.file.base_filename.html_seg(fnh)
      lnk_n_txt=%{  <a href="#{f}##{txt.ocn}">
    #{txt.obj}
  </a>}
        txt_obj={ txt: lnk_n_txt }
        format_toc=SiSU_HTML_Format::FormatToc.new(@md,txt_obj)
        toc_mini=format_toc.mini_lev6
      toc_mini
    end
  end
end
__END__
#+END_SRC

*** html_concordance.rb

#+HEADER: :tangle "../lib/sisu/html_concordance.rb"
#+BEGIN_SRC ruby
#<<sisu_document_header>>
module SiSU_Concordance
  require_relative 'se_hub_particulars'                 # se_hub_particulars.rb
    include SiSU_Particulars
  require_relative 'se'                                 # se.rb
    include SiSU_Env
  require_relative 'html_format'                        # html_format.rb
    include SiSU_HTML_Format
  require_relative 'html_minitoc'                       # html_minitoc.rb
  class Source
    def initialize(opt)
      @opt=opt
      @particulars=SiSU_Particulars::CombinedSingleton.instance.get_all(opt)
    end
    def read
      begin
        @env,@md=@particulars.env,@particulars.md
        @env.url.output_tell
        unless @md.opt.act[:quiet][:set]==:on
          tool=(@md.opt.act[:verbose][:set]==:on \
          || @md.opt.act[:verbose_plus][:set]==:on \
          || @md.opt.act[:maintenance][:set]==:on) \
          ? "#{@env.program.web_browser} #{@md.file.output_path.html_concordance.dir}/#{@md.file.base_filename.html_concordance}"
          : "[#{@opt.f_pth[:lng_is]}] #{@opt.fno}"
          (@md.opt.act[:verbose][:set]==:on \
          || @md.opt.act[:verbose_plus][:set]==:on \
          || @md.opt.act[:maintenance][:set]==:on) \
          ? SiSU_Screen::Ansi.new(
              @opt.act[:color_state][:set],
              "Concordance",
              tool
            ).green_hi_blue
          : SiSU_Screen::Ansi.new(
              @opt.act[:color_state][:set],
              'Concordance',
              tool
            ).green_title_hi
        end
        wordmax=@env.concord_max
        unless @md.wc_words.nil?
          if @md.wc_words < wordmax
            SiSU_Concordance::Source::Words.new(@particulars).songsheet
          else
            SiSU_Screen::Ansi.new(
              @md.opt.act[:color_state][:set],
              "concordance skipped, large document has over #{wordmax} words (#{@md.wc_words})"
            ).warn unless @md.opt.act[:quiet][:set]==:on
          end
        else
          SiSU_Screen::Ansi.new(
            @md.opt.act[:color_state][:set],
            "wc (word count) is off, concordance will be processed for all files including those over the max set size of: #{wordmax} words"
          ).warn unless @md.opt.act[:quiet][:set]==:on
          SiSU_Concordance::Source::Words.new(@particulars).songsheet
        end
      rescue
        SiSU_Errors::Rescued.new($!,$@,@md.opt.selections.str,@md.fns).location do
          __LINE__.to_s + ':' + __FILE__
        end
      ensure
        SiSU_Env::CreateSite.new(@opt).cp_css
        Dir.chdir(@opt.f_pth[:pth])
      end
    end
    private
    class DocTitle
      #revisit, both requires (html & xml_shared) needed for stand alone operation (sisu -w [filename])
      require_relative 'xml_shared'                     # xml_shared.rb
      require_relative 'html'                           # html.rb
      def initialize(particulars)
        @particulars,@md=particulars,particulars.md
        @data=SiSU_HTML::Source::HTML_Environment.new(particulars).tuned_file_instructions
        @file=SiSU_Env::FileOp.new(@md)
        @fnb=@md.fnb
        @lex_button=%{<a href="http://www.jus.uio.no/sisu/" target="_top"><img border="0" height="44" width="144" valign="center" src="#{@file.path_rel_links.html_seg_2}_sisu/image/sisu.png" alt="SiSU home --&gt;"></a>}
        @doc_details =<<WOK
<table summary="links to text related to this rudimentary index" width="96%" border="0" cellpadding="0" align="center"><tr><td width="2%" align="right">&nbsp;</td><td width="94%" valign="top" align="justify"><h1 class="small"><a href="#{@md.file.base_filename.html_segtoc}"><b>#{@md.title.full}</b></a></h1><p class="bold">#{@md.author}</p></td></tr></table>
WOK
        @make=SiSU_Env::ProcessingSettings.new(@md)
      end
      def create
        head_banner=SiSU_HTML_Format::HeadToc.new(@md)
        minitoc=SiSU_HTML_MiniToc::TocMini.new(@md,@data).songsheet.join("\n")
        stylesheet=SiSU_Style::CSS_HeadInfo.new(@md).stylesheet
        if @make.build.manifest_minitoc?
          toc='<div class="toc">' + minitoc + '</div>'
          div_class='content'
        else
          toc=''
          div_class='content0'
        end
        top_band=if @make.build.html_top_band?
          head_banner.concordance_navigation_band
        else ''
        end
        <<WOK
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>
    SiSU created WordIndex for: #{@md.title.full}
  </title>
  <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
  <meta name="Description" content="&nbsp;SiSU created">
  <meta name="keywords" content="word index for #{@md.title.full}">
  <meta name="generator" content="SiSU (Linux &amp; Ruby!)">
  <link rel="generator" href="http://www.jus.uio.no/sisu" />
  <link rel="shortcut icon" href="../_sisu/image/rb7.ico" />
  #{stylesheet.css_head_seg}
</head>
<body>
  #{top_band}
  #{toc}
<div class="#{div_class}">
 #{@doc_details}
<p>Word index links are to html versions of the text the segmented version followed by the scroll (single document) version.<br>[For segmented text references [T1], [T2] or [T3] appearing without a link, indicates that the word appears in a title (or subtitle) of the text (that is identifiable by the appended object citation number).]</p>
<p>(The word listing/index is Case sensitive: Capitalized words appear before lower case)</p>
  <p>
    <b>word</b> (number of occurences)<br>linked references to word within document <br>
    [if number of occurences exceed number of references - word occurs more than once in at least one reference. Footnote/endnotes are either assigned to the paragraph from which they are referenced or ignored, so it is relevant to check the footnotes referenced from within a paragraph as well.]
  </p>
  <p>
    (After the page is fully loaded) you can jump directly to a word by appending a hash (#) and the word to the url for this text, (do not forget that words are case sensitive, and may be listed twice (starting with and without an upper case letter)), #your_word # [&nbsp;http://[web host]/#{@fnb}/concordance.html#your_word&nbsp;]
  </p>
WOK
      end
    end
    class Word
      @@word_previous=''
      def initialize(word,freq)
        @word,@freq=word,freq
      end
      def html
        w=if @word.capitalize==@@word_previous
          %{\n<p class="concordance_word">#{@word}</p><p class="concordance_count">(#{@freq})</p>\n\t<p class="concordance_object"> }
        else n=@word.strip.gsub(/\s+/,'_') #also need to convert extended character set to html
          %{\n<p class="concordance_word"><a name="#{n}">#{@word}</a></p><p class="concordance_count">(#{@freq})</p>\n\t<p class="concordance_object"> }
        end
        @@word_previous=@word.capitalize
        w
      end
    end
    class Words
      require_relative 'i18n'                           # i18n.rb
        include SiSU_i18n
      require_relative 'html_format'                    # html_format.rb
        include SiSU_HTML_Format
      require_relative 'se'                             # se.rb
        include SiSU_Screen
      @@dp=nil
      def initialize(particulars)
        @particulars=particulars
        begin
          @env,@md,@ao_array=particulars.env,particulars.md,particulars.ao_array
          @file=SiSU_Env::FileOp.new(@md)
          @freq=Hash.new(0)
          @dp=@@dp ||=SiSU_Env::InfoEnv.new.digest.pattern
          @rxp_lv1=/^#{Mx[:lv_o]}1:/ #fix @rxp_lv #  Mx[:lv_o]
          @rxp_lv2=/^#{Mx[:lv_o]}2:/ #fix @rxp_lv #  Mx[:lv_o]
          @rxp_lv3=/^#{Mx[:lv_o]}3:/ #fix @rxp_lv #  Mx[:lv_o]
          @rxp_title=Regexp.new("^#{Mx[:meta_o]}title#{Mx[:meta_c]}\s*(.+?)\s*$")
          @rxp_t1=Regexp.new('^T1')
          @rxp_t2=Regexp.new('^T2')
          @rxp_t3=Regexp.new('^T3')
          @rxp_excluded1=/#{Mx[:url_o]}\S+?#{Mx[:url_c]}|#{Mx[:rel_o]}\S+?#{Mx[:rel_c]}/
          @rxp_excluded0=/^(?:#{Mx[:fa_bold_o]}|#{Mx[:fa_italics_o]})?(?:to\d+|\d+|&nbsp;|#{Mx[:br_endnotes]}|EOF|#{Mx[:br_eof]}|thumb_\S+|snap_\S+|_+|-+|[(]?(?:ii+|iv|vi+|ix|xi+|xiv|xv|xvi+|xix|xx)[).]?|\S+?_\S+|[\d_]+\w\S+|[\w\d]{1,2}|\d{1,3}\w?|#{@dp}|[0-9a-f]{16,64}|\d{2,3}x\d{2,3}|\S{0,2}sha\d|\S{0,3}\d{4}w\d\d|\b\w\d+|\d_all\b|e\.?g\.?)(?:#{Mx[:fa_bold_c]}|#{Mx[:fa_italics_c]})?$/mi #this regex causes and cures a stack dump in ruby 1.9 !!!
          @rgx_splitlist=%r{[—.,;:#{Mx[:nbsp]}-]}mi
          @alph=SiSU_i18n::Alphabet.new(@md.opt.lng).hash_arrays
          @alphlst=SiSU_i18n::Alphabet.new(@md.opt.lng).hash_strings
          @rgx_scanlist=%r{#{Mx[:fa_italics_o]}[#{@alphlst[:l]}#{@alphlst[:u]}0-9"\s]{2,12}#{Mx[:fa_italics_c]}|#{Mx[:fa_bold_o]}[#{@alphlst[:l]}#{@alphlst[:u]}0-9"\s]{2,12}#{Mx[:fa_bold_c]}|(?:https?|file)://\S+|<\S+?>|[#{@alphlst[:l]}#{@alphlst[:u]}]+|\w+}mi
        rescue
          SiSU_Errors::Rescued.new($!,$@,@md.opt.selections.str,@md.fns).location do
            __LINE__.to_s + ':' + __FILE__
          end
        end
      end
      def songsheet
        begin
          FileUtils::mkdir_p(@file.output_path.html_concordance.dir) \
            unless FileTest.directory?(@file.output_path.html_concordance.dir)
          @file_concordance=File.open(@file.place_file.html_concordance.dir,'w')
          map_para
        rescue
          SiSU_Errors::Rescued.new($!,$@,@md.opt.selections.str,@md.fns).location do
            __LINE__.to_s + ':' + __FILE__
          end
        ensure
          @file_concordance.close
        end
      end
    protected
      def location_scroll(wordlocation,show)                    # not used
        %{<a href="doc#{@md.lang_code_insert}#{Sfx[:html]}\##{Mx[:ocn_id_char]}#{wordlocation}">#{wordlocation}</a>;  }
      end
      def location_seg(wordlocation,show)
        unless wordlocation.nil?
          wl=wordlocation.gsub(/(.+?)\#(\d+)/,
            "\\1#{@md.lang_code_insert}#{Sfx[:html]}##{Mx[:ocn_id_char]}\\2")     # id="o\d+" always available; a name="\d+" not available if html strict used
          case wordlocation
          when /#{@rxp_t1}|@rxp_t2}|#{@rxp_t3}/
            %{[<a href="doc#{@md.lang_code_insert}#{Sfx[:html]}##{show}">H</a>]#{show},  }
          when /(.+?)\#(\d+)/
             %{<a href="#{wl}">#{show}</a>,  }
          end
        end
      end
      def map_para
        @seg,ocn=nil,nil
        @word_map={}
        @ao_array.each do |line|
          if defined? line.ocn \
          and line.ocn.to_s =~/\d/
            if (line.is ==:heading \
            || line.is ==:heading_insert) \
            && line.ln==4
              @seg=line.name
            end
            ocn=line.ocn.to_s
            if ocn =~/\d+/ \
            and ocn !~/^0$/
              line.obj=line.obj.gsub(/#{@rxp_excluded1}/,' ')
              line.obj=line.obj.split(@rgx_splitlist).join(' ') #%take in word or other match
              for word in line.obj.scan(@rgx_scanlist) #%take in word or other match
                if word =~ /^([#{@alphlst[:l]}])/
                  firstletter=$1
                  flu=firstletter.tr(@alphlst[:l],@alphlst[:u])
                  word=word.gsub(/^#{firstletter}/,flu )
                end
                word=word.gsub(/#{Mx[:lnk_o]}|#{Mx[:lnk_c]}|#{Mx[:url_o]}|#{Mx[:url_c]}/,'').
                  gsub(/#{Mx[:fa_o]}\S+?#{Mx[:fa_o_c]}/,'').
                  gsub(/#{Mx[:fa_c_o]}\S+?#{Mx[:fa_c]}/,'').
                  gsub(/#{Mx[:gl_o]}#[a-z]+#{Mx[:gl_c]}/,'').
                  gsub(/#{Mx[:gl_o]}#[0-9]+#{Mx[:gl_c]}/,'')
                word=word.gsub(/[0-9a-f]{10,}/,' ') if word =~/[0-9]/
                word=word.gsub(/#{Mx[:br_line]}/,' ').
                  gsub(/^ +/,'').
                  gsub(/^\S$/,'')
                word=nil if word.empty?
                word=nil if word =~@rxp_excluded0 #watch
                word=nil if word =~/^\S$/
                if word
                  word=word.gsub(/#{Mx[:br_nl]}|#{Mx[:br_line]}/,' ').
                    gsub(/#{Mx[:fa_o]}[a-z]{1,7}#{Mx[:fa_o_c]}|#{Mx[:fa_c_o]}[a-z]{1,7}#{Mx[:fa_c]}/,'').
                    gsub(/#{Mx[:en_a_o]}(?:\d|[*+])*|#{Mx[:en_b_o]}(?:\d|[*+])*|#{Mx[:en_a_c]}|#{Mx[:en_b_c]}/mi,'').
                    gsub(/#{Mx[:fa_o]}\S+?#{Mx[:fa_o_c]}/,'').
                    gsub(/#{Mx[:fa_c_o]}\S+?#{Mx[:fa_c]}/,'').
                    gsub(/<\/?\S+?>/,'').
                    gsub(/^\@+/,'').
                    strip.
                    gsub(/#{Mx[:tc_p]}.+/,'').
                    gsub(/[\.,;:"]$/,'').
                    gsub(/["]/,'').
                    gsub(/^\s*[\(]/,'').
                    gsub(/[\(]\s*$/,'').
                    gsub(/^(?:See|e\.?g\.?).+/,'').
                    gsub(/^\s*[.,;:]\s*/,'').
                    strip.
                    gsub(/^\(?[a-zA-Z]\)$/,'').
                    gsub(/^\d+(st|nd|rd|th)$/,'').
                    gsub(/^(\d+\.?)+$/, '').
                    gsub(/#{Mx[:mk_o]}|#{Mx[:mk_c]}/,'').
                    gsub(/:name#\S+/,'').
                    gsub(/^\S$/,'')
                  word=nil if word =~/^\S$/
                  word=nil if word =~/^\s*$/ #watch
                  if word
                    unless word =~/[A-Z][A-Z]/ \
                    or word =~/\w+\s\w+/
                      word=word.capitalize
                    end
                    @freq[word] +=1
                    @word_map[word] ||= []
                    if line !~ /#{@rxp_lv1}|#{@rxp_lv2}|#{@rxp_lv3}/
                      loc_=%{#{location_seg("#{@seg}\##{ocn}",ocn).to_s}}
                      unless loc_.empty?
                        @word_map[word] << loc_
                      end
                    else
                      @word_map[word] << case line
                      when @rxp_lv1 then location_seg('T1',ocn) #fix @rxp_lv #  Mx[:lv_o]
                      when @rxp_lv2 then location_seg('T2',ocn) #fix @rxp_lv #  Mx[:lv_o]
                      when @rxp_lv3 then location_seg('T3',ocn) #fix @rxp_lv #  Mx[:lv_o]
                      end
                    end
                  end
                end
              end
            end
          end
        end
        seg=''
        head=SiSU_Concordance::Source::DocTitle.new(@particulars).create
        head=head.gsub(/#{Xx[:html_relative2]}/m,@file.path_rel_links.html_seg_2).
          gsub(/#{Xx[:html_relative1]}/m,@file.path_rel_links.html_seg_1)
        @file_concordance << head
        @file_concordance << '<p>'
        alph=@alph[:u]
        alph.each {|x| @file_concordance << %{<a href="##{x}">#{x}</a>,&nbsp;}}
        @file_concordance << '</p>'
        letter=alph.shift
        @file_concordance << %{\n<p class="letter"><a name="A">A</a></p>}
        for word in @freq.keys.sort! {|a,b| a.downcase<=>b.downcase}
          f=/^(\S)/.match(word)[1]
          if letter < f.upcase
            while letter < f.upcase
              if alph.length > 0
                letter=alph.shift
                @file_concordance << %{\n<p class="letter"><a name="#{letter}">#{letter}</a></p>}
              else break
              end
            end
          end
          keyword=SiSU_Concordance::Source::Word.new(word,@freq[word]).html
          if keyword !~ @rxp_excluded0
            if @word_map[word][0] =~ /\d+/
              @file_concordance << %{#{keyword}#{seg}#{@word_map[word].uniq.compact.join}}
            end
            @file_concordance << '</p>'
          end
          # special cases endnotes and header levels 1 - 3
        end
        @file_concordance << %{</div></body>\n</html>} # footer
        if @md.opt.act[:verbose_plus][:set]==:on \
        || @md.opt.act[:maintenance][:set]==:on
          SiSU_Screen::Ansi.new(
            @md.opt.act[:color_state][:set],
            @md.fns,
            "#{@md.file.output_path.html_concordance.dir}/#{@md.file.base_filename.html_concordance}"
          ).flow
        end
      end
    end
  end
end
__END__
#+END_SRC

*** html_manifest.rb

#+HEADER: :tangle "../lib/sisu/html_manifest.rb"
#+BEGIN_SRC ruby
#<<sisu_document_header>>
module SiSU_Manifest
  require_relative 'se'                                 # se.rb
    include SiSU_Env
  require_relative 'prog_text_translation'              # prog_text_translation.rb
  require_relative 'se_hub_particulars'                 # se_hub_particulars.rb
    include SiSU_Particulars
  require_relative 'html_parts'                         # html_parts.rb
  require_relative 'html_minitoc'                       # html_minitoc.rb
  require_relative 'html'                               # html.rb
    include SiSU_HTML_Format
  require_relative 'dp'                                 # dp.rb
    include SiSU_Param
  require_relative 'i18n'                               # i18n.rb
  class Source
    def initialize(opt)
      @opt=opt
      @particulars=SiSU_Particulars::CombinedSingleton.instance.get_all(opt)
      l=SiSU_Env::StandardiseLanguage.new(opt.lng).language
      @doc_language=l[:n]
    end
    def read
      begin
        @env=SiSU_Env::InfoEnv.new(@opt.fns)
        @md=SiSU_Param::Parameters.new(@opt).get
        xbrowser=@env.program.web_browser
        browser=@env.program.console_web_browser
#       webserv_url=@env.path.url.output_tell #fix in sysenv
        unless @opt.act[:quiet][:set]==:on
          url_html='file://' \
          + @md.file.output_path.manifest.dir + '/' \
          + @md.file.base_filename.manifest
          (@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],
              'Manifest',
              "#{xbrowser} #{url_html}"
            ).green_hi_blue
          : SiSU_Screen::Ansi.new(
              @opt.act[:color_state][:set],
              'Manifest',
              "[#{@opt.f_pth[:lng_is]}]",
              "#{url_html}"
            ).grey_title_grey_blue
          if (@md.opt.act[:verbose][:set]==:on \
          || @md.opt.act[:verbose_plus][:set]==:on)
            SiSU_Screen::Ansi.new(
              @opt.act[:color_state][:set],
              "#{browser} #{url_html}"
            ).grey_tab
          end
        end
        data=SiSU_HTML::Source::HTML_Environment.new(@particulars).tuned_file_instructions
        SiSU_Manifest::Source::Output.new(@md).check_output(data)
      rescue
        SiSU_Errors::Rescued.new($!,$@,@opt.selections.str,@opt.fns).location do
          __LINE__.to_s + ':' + __FILE__
        end
      ensure
        SiSU_Env::CreateSite.new(@opt).cp_css
        Dir.chdir(@opt.f_pth[:pth])
      end
    end
    private
    class Output <Source
      include SiSU_Parts_HTML
      def initialize(md)
        @manifest={ txt: [], html: [] }
        @md,@fns=md,md.fns
        @env=SiSU_Env::InfoEnv.new(md.fns)
        @f=SiSU_Env::FileOp.new(md)
        @fnb=md.fnb
        @base_url="#{@env.url.root}/#{@fnb}"
        @o_str=SiSU_Env::FileOp.new(md).output_dir_structure
        @image_path=(@o_str.dump_or_redirect?) \
        ? './image'
        : %{#{@f.path_rel_links.html_scroll_2}_sisu/image_sys}
        @base_path=@f.output_path.manifest.dir
        @@dg ||=SiSU_Env::InfoEnv.new(md.fns,md).digest(md.opt).type
        @dg=@@dg
        l=SiSU_Env::StandardiseLanguage.new(md.opt.lng).language
        @language=l[:n]
        @translate=SiSU_Translate::Source.new(md,@language)
        @stylesheet=SiSU_Style::CSS_HeadInfo.new(md).stylesheet
        @fn_lng=(@f.output_dir_structure.by_language_code?) \
        ? ''
        : ('.' + md.opt.lng)
      end
      def output
        manifest=@f.write_file.manifest
        @manifest[:html].each do |x|
          x=x.gsub(Xx[:html_relative2],@f.path_rel_links.html_scroll_2).
            gsub(Xx[:html_relative1],@f.path_rel_links.html_scroll_1)
          manifest << x
        end
      end
      def url_make(url,file,src=nil)
        if @o_str.dump_or_redirect?
          ''
        elsif src==:src #check
          %{<br>#{the_url_decoration.xml_open}<a href="#{url}/#{file}">#{url}/#{file}</a>#{the_url_decoration.xml_close}}
        else
          %{<p class="tiny">#{the_url_decoration.xml_open}<a href="#{url}/#{file}">#{url}/#{file}</a>#{the_url_decoration.xml_close}</p>}
        end
      end
      def summarize(desc,id,file,pth='',rel='',url='',img='● ')
        size=(File.size("#{pth}/#{file}")/1024.00).to_s
        kb=/([0-9]+\.[0-9]{0,1})/m.match(size)[1]
        @manifest[:txt] << "#{file} #{desc} #{kb}\n"
        @manifest[:html] << %{<tr><th class="left"><p class="norm"><a href="#{rel}/#{file}">#{img}#{desc}</a></p></th><td><p class="small"><a href="#{rel}/#{file}">#{file}</a></p>#{url_make(url,file)}</td><td class="right"><p class="right">#{kb}</p></td></tr>\n}
      end
      def summarize_html_seg(desc,id,file,pth='',rel='',url='',img='● ')
        size=(File.size("#{pth}/#{file}")/1024.00).to_s
        kb=/([0-9]+\.[0-9]{0,1})/m.match(size)[1]
        @manifest[:txt] << "#{file} #{desc} #{kb}\n"
        @manifest[:html] << %{<tr><th class="left"><p class="norm"><a href="#{rel}/#{file}">#{img}#{desc}</a></p></th><td><p class="small"><a href="#{rel}/#{file}">#{file}</a></p>#{url_make(url,file)}</td><td class="right"><p class="right">#{kb}</p></td></tr>\n}
      end
      def summarize_sources(desc,id,file,pth,rel,url)
        sys=SiSU_Env::SystemCall.new
        dgst=case @dg
        when :sha512
          sys.sha512("#{pth}/#{file}")
        when :sha256
          sys.sha256("#{pth}/#{file}")
        when :md5
          sys.md5("#{pth}/#{file}")
        else
        end
        dgst=dgst ? dgst : [ '', 'n/a' ]
        if (@md.opt.act[:verbose][:set]==:on \
        || @md.opt.act[:verbose_plus][:set]==:on \
        || @md.opt.act[:maintenance][:set]==:on)
          SiSU_Screen::Ansi.new(
            @md.opt.act[:color_state][:set],
            "#{dgst[1]} #{file}"
          ).warn
        end
        size=(File.size("#{pth}/#{file}")/1024.00).to_s
        kb=/([0-9]+\.[0-9]{0,1})/m.match(size)[1]
        @manifest[:txt] << "#{file} #{desc} #{kb}\n"
        @manifest[:html] << %{<tr>} \
        + %{<th class="left"><p class="norm" id="#{id}"><a href="#{rel}/#{file}">#{desc}</a></p></th>} \
        + %{<td class="right"><p class="tiny"><a href="#{rel}/#{file}">#{file}</a> &nbsp;&nbsp;#{dgst[1]}#{url_make(url,file,:src)}</p></td>} \
        + %{<td class="right"><p class="right">#{kb}</p></td>} \
        + %{</tr>\n} \
          if kb and kb =~/\d+/
      end
      def published_manifests?
        @f=SiSU_Env::FileOp.new(@md) #.base_filename
        @m=[]
        url=@f.output_path.base.url
        manifests={}
        mp,mn,mt,mr=nil,nil,nil,nil
        ln=SiSU_i18n::Languages.new.language.list
        Px[:lng_lst].each do |lc|
          lngc=SiSU_Env::FilenameLanguageCodeInsert.new(@md.opt,lc).language_code_insert
          fnh={
             fn: @md.fnb,
             lng: lngc,
          }
          mn=@f.base_filename.manifest(fnh)
          if @o_str.dump_or_redirect? #does not work for --redirect or --dump
            mp="#{@f.output_path.base.dir}"
            mt="#{mp}/#{mn}"
            mr="../../#{lc}/manifest/#{mn}"
            mu="#{url}/#{mn}"
          elsif @f.output_dir_structure.by_language_code?
            mp="#{@f.output_path.base.dir}/#{lc}/manifest"
            mt="#{mp}/#{mn}"
            mr="../../#{lc}/manifest/#{mn}"
            mu="#{url}/#{lc}/manifest/#{mn}"
          elsif @f.output_dir_structure.by_filetype?
            mp="#{@f.output_path.base.dir}/manifest"
            mt="#{mp}/#{mn}"
            mr=mn
            mu="#{url}/manifest/#{mn}"
          else
            mp="#{@f.output_path.base.dir}/#{@md.fnb}"
            mt="#{mp}/#{mn}"
            mr=mn
            mu="#{url}/#{mn}"
          end
          if FileTest.directory?(mp) \
          &&  FileTest.file?(mt)
            lng=ln[lc][:t]
            manifests[lc]={ ln: lng, fn: mn, rel: mr }
            @m << { mu: mu, l: lng, rel: mr }
          end
        end
        @m=@m.uniq
      end
      def languages(desc,file)
        @manifest[:html] << %{<tr><th class="left"><div id="horizontal_links"><ul id="horizontal">\n}
        published_manifests?.each do |l|
          SiSU_Translate::Source.new(@md,@language,l[:n]).language_list
          @manifest[:txt] << "#{l[:mu]} #{l[:l]}\n"
          @manifest[:html] << %{<li class="norm"><a href="#{l[:rel]}">#{l[:l]}</a>&nbsp;&nbsp;&nbsp;</li>}
        end
        @manifest[:html] << %{</ul></div></th></tr>\n}
      end
      def published_languages(desc)
        published_manifests?.each do |l|
          @manifest[:txt] << "#{l[:mu]} #{l[:l]}\n"
          @manifest[:html] << %{<tr><th class="left"><p class="bold"><a href="#{l[:mu]}">#{l[:l]}</a></p></th><td><p class="norm">#{l[:l]}</p><p class="tiny">#{the_url_decoration.xml_open}<a href="#{l[:mu]}">#{l[:mu]}</a>#{the_url_decoration.xml_close}</p></td><td class="right"><p class="right">&nbsp;</p></td></tr>\n}
        end
      end
      def metadata(desc,id,info)
        info=info.to_s.gsub(/(?:#{Mx[:br_line]}|\\)+/,'<br>')
        @manifest[:html] << %{<tr><th class="left"><p class="bold_left" id="#{id}">#{desc}:</p></th><td><p class="left">#{info}</p></td></tr>\n}
      end
      def links(url,lnk,target)
        static=if url =~/^\.\// then url.gsub(/^\.(\.)?/,@base_url)
        elsif url =~/^\.\.\//   then url.gsub(/^\.(\.)?/,@env.url.root)
        else                         url
        end
        @manifest[:html] << %{<tr><th class="right" width=5%><p class="norm">●</p></th><td class="left"><p class="norm"><a href="#{url}">#{lnk}</a></p><p class="tiny">&nbsp;&nbsp;#{the_url_decoration.xml_open}<a href="#{static}">#{static}</a>#{the_url_decoration.xml_close}</p></td></tr>\n}
      end
      def output_tests
        if FileTest.file?(@f.place_file.html_segtoc.dir)==true
          img=%{<img border="0" height="18" width="15" src="#{@image_path}/b_toc.png" alt="TOC linked" /> }
          pth=@f.output_path.html_seg.dir
          rel=@f.output_path.html_seg.rel_sm
          url=@f.output_path.html_seg.url
          desc,id,file='HTML, table of contents (for segmented text)','html',@f.base_filename.html_segtoc
          summarize_html_seg(desc,id,file,pth,rel,url,img)
        end
        if FileTest.file?(@f.place_file.html_scroll.dir)==true
          img=%{<img border="0" height="15" width="15" src="#{@image_path}/b_doc.png" alt="Full Text" /> }
          pth=@f.output_path.html_scroll.dir
          rel=@f.output_path.html_scroll.rel_sm
          url=@f.output_path.html_scroll.url
          desc,id,file='HTML, full length document','html_scroll',@f.base_filename.html_scroll
          summarize(desc,id,file,pth,rel,url,img)
        end
        if FileTest.file?(@f.place_file.html_book_index.dir)==true
          pth=@f.output_path.html_seg.dir
          rel=@f.output_path.html_seg.rel_sm
          url=@f.output_path.html_seg.url
          desc,id,file='HTML, (book type) index','html_book',@f.base_filename.html_book_index
          summarize(desc,id,file,pth,rel,url)
        end
        if FileTest.file?(@f.place_file.html_concordance.dir)==true
          pth=@f.output_path.html_seg.dir
          rel=@f.output_path.html_seg.rel_sm
          url=@f.output_path.html_seg.url
          desc,id,file='HTML, concordance file','concordance',@f.base_filename.html_concordance
          summarize(desc,id,file,pth,rel,url)
        end
        if FileTest.file?(@f.place_file.epub.dir)==true
          img=%{<img border="0" height="18" width="18" src="#{@image_path}/b_epub.png" alt="EPUB" /> }
          desc,id,file='EPUB (Electronic Publication, e-book standard)','epub',@f.base_filename.epub
          pth=@f.output_path.epub.dir
          rel=@f.output_path.epub.rel_sm
          url=@f.output_path.epub.url
          summarize(desc,id,file,pth,rel,url,img)
        end
        if FileTest.file?("#{@f.output_path.pdf.dir}/#{@f.base_filename.pdf_p_letter}")==true
          img=%{<img border="0" height="18" width="15" src="#{@image_path}/b_pdf.png" alt="PDF portrait" /> }
          pth=@f.output_path.pdf.dir
          rel=@f.output_path.pdf.rel_sm
          url=@f.output_path.pdf.url
          desc,id,file="PDF, U.S. letter size, portrait/vertical document (recommended for printing)",'pdf_letter',"#{@f.base_filename.pdf_p_letter}"
          summarize(desc,id,file,pth,rel,url,img)
        end
        if FileTest.file?("#{@f.output_path.pdf.dir}/#{@f.base_filename.pdf_l_letter}")==true
          img=%{<img border="0" height="15" width="18" src="#{@image_path}/b_pdf.png" alt="PDF landscape" /> }
          pth=@f.output_path.pdf.dir
          rel=@f.output_path.pdf.rel_sm
          url=@f.output_path.pdf.url
          desc,id,file="PDF, U.S. letter size, landscape/horizontal document (recommended for screen viewing)",'pdf_letter_landscape',"#{@f.base_filename.pdf_l_letter}"
          summarize(desc,id,file,pth,rel,url,img)
        end
        if FileTest.file?("#{@f.output_path.pdf.dir}/#{@f.base_filename.pdf_p_a4}")==true
          img=%{<img border="0" height="18" width="15" src="#{@image_path}/b_pdf.png" alt="PDF portrait" /> }
          pth=@f.output_path.pdf.dir
          rel=@f.output_path.pdf.rel_sm
          url=@f.output_path.pdf.url
          desc,id,file="PDF, A4 size, portrait/vertical document (recommended for printing)",'pdf_a4',"#{@f.base_filename.pdf_p_a4}"
          summarize(desc,id,file,pth,rel,url,img)
        end
        if FileTest.file?("#{@f.output_path.pdf.dir}/#{@f.base_filename.pdf_l_a4}")==true
          img=%{<img border="0" height="15" width="18" src="#{@image_path}/b_pdf.png" alt="PDF landscape" /> }
          pth=@f.output_path.pdf.dir
          rel=@f.output_path.pdf.rel_sm
          url=@f.output_path.pdf.url
          desc,id,file="PDF, A4 size, landscape/horizontal document (recommended for screen viewing)",'pdf_a4_landscape',"#{@f.base_filename.pdf_l_a4}"
          summarize(desc,id,file,pth,rel,url,img)
        end
        if FileTest.file?("#{@f.output_path.pdf.dir}/#{@f.base_filename.pdf_p_a5}")==true
          img=%{<img border="0" height="18" width="15" src="#{@image_path}/b_pdf.png" alt="PDF portrait" /> }
          pth=@f.output_path.pdf.dir
          rel=@f.output_path.pdf.rel_sm
          url=@f.output_path.pdf.url
          desc,id,file="PDF, A5 (book) size, portrait/vertical document (recommended for printing)",'pdf_a5',"#{@f.base_filename.pdf_p_a5}"
          summarize(desc,id,file,pth,rel,url,img)
        end
        if FileTest.file?("#{@f.output_path.pdf.dir}/#{@f.base_filename.pdf_l_a5}")==true
          img=%{<img border="0" height="15" width="18" src="#{@image_path}/b_pdf.png" alt="PDF landscape" /> }
          pth=@f.output_path.pdf.dir
          rel=@f.output_path.pdf.rel_sm
          url=@f.output_path.pdf.url
          desc,id,file="PDF, A5 (book) size, landscape/horizontal document (recommended for screen viewing)",'pdf_a5_landscape',"#{@f.base_filename.pdf_l_a5}"
          summarize(desc,id,file,pth,rel,url,img)
        end
        if FileTest.file?("#{@f.output_path.pdf.dir}/#{@f.base_filename.pdf_p_b5}")==true
          img=%{<img border="0" height="18" width="15" src="#{@image_path}/b_pdf.png" alt="PDF portrait" /> }
          pth=@f.output_path.pdf.dir
          rel=@f.output_path.pdf.rel_sm
          url=@f.output_path.pdf.url
          desc,id,file="PDF, B5 (book) size, portrait/vertical document (recommended for printing)",'pdf_b5',"#{@f.base_filename.pdf_p_b5}"
          summarize(desc,id,file,pth,rel,url,img)
        end
        if FileTest.file?("#{@f.output_path.pdf.dir}/#{@f.base_filename.pdf_l_b5}")==true
          img=%{<img border="0" height="15" width="18" src="#{@image_path}/b_pdf.png" alt="PDF landscape" /> }
          pth=@f.output_path.pdf.dir
          rel=@f.output_path.pdf.rel_sm
          url=@f.output_path.pdf.url
          desc,id,file="PDF, B5 (book) size, landscape/horizontal document (recommended for screen viewing)",'pdf_a5_landscape',"#{@f.base_filename.pdf_l_b5}"
          summarize(desc,id,file,pth,rel,url,img)
        end
        if FileTest.file?("#{@f.output_path.pdf.dir}/#{@f.base_filename.pdf_p_legal}")==true
          img=%{<img border="0" height="18" width="15" src="#{@image_path}/b_pdf.png" alt="PDF portrait" /> }
          pth=@f.output_path.pdf.dir
          rel=@f.output_path.pdf.rel_sm
          url=@f.output_path.pdf.url
          desc,id,file="PDF, U.S. legal size, portrait/vertical document (recommended for printing)",'pdf_legal',"#{@f.base_filename.pdf_p_legal}"
          summarize(desc,id,file,pth,rel,url,img)
        end
        if FileTest.file?("#{@f.output_path.pdf.dir}/#{@f.base_filename.pdf_l_legal}")==true
          img=%{<img border="0" height="15" width="18" src="#{@image_path}/b_pdf.png" alt="PDF landscape" /> }
          pth=@f.output_path.pdf.dir
          rel=@f.output_path.pdf.rel_sm
          url=@f.output_path.pdf.url
          desc,id,file="PDF, U.S. legal size, landscape/horizontal document (recommended for screen viewing)",'pdf_legal_landscape',"#{@f.base_filename.pdf_l_legal}"
          summarize(desc,id,file,pth,rel,url,img)
        end
        if FileTest.file?(@f.place_file.odt.dir)==true
          img=%{<img border="0" height="18" width="18" src="#{@image_path}/b_odf.png" alt="ODF/ODT" /> }
          pth=@f.output_path.odt.dir
          rel=@f.output_path.odt.rel_sm
          url=@f.output_path.odt.url
          desc,id,file='ODF:ODT (Open Document Format)','odt',@f.base_filename.odt
          summarize(desc,id,file,pth,rel,url,img)
        end
        if FileTest.file?(@f.place_file.xhtml.dir)==true
          pth=@f.output_path.xhtml.dir
          rel=@f.output_path.xhtml.rel_sm
          url=@f.output_path.xhtml.url
          desc,id,file='XHTML','xhtml',@f.base_filename.xhtml
          summarize(desc,id,file,pth,rel,url)
        end
        if FileTest.file?(@f.place_file.xml_sax.dir)==true
          pth=@f.output_path.xml_sax.dir
          rel=@f.output_path.xml_sax.rel_sm
          url=@f.output_path.xml_sax.url
          desc,id,file='XML SAX','xml_sax',@f.base_filename.xml_sax
          summarize(desc,id,file,pth,rel,url)
        end
        if FileTest.file?(@f.place_file.xml_dom.dir)==true
          pth=@f.output_path.xml_dom.dir
          rel=@f.output_path.xml_dom.rel_sm
          url=@f.output_path.xml_dom.url
          desc,id,file='XML DOM','xml_dom',@f.base_filename.xml_dom
          summarize(desc,id,file,pth,rel,url)
        end
        if FileTest.file?(@f.place_file.xml_docbook_article.dir)==true
          pth=@f.output_path.xml_docbook_article.dir
          rel=@f.output_path.xml_docbook_article.rel_sm
          url=@f.output_path.xml_docbook_article.url
          desc,id,file='XML Docbook Article','docbook_article',@f.base_filename.xml_docbook_article
          summarize(desc,id,file,pth,rel,url)
        end
        if FileTest.file?(@f.place_file.xml_docbook_book.dir)==true
          pth=@f.output_path.xml_docbook_book.dir
          rel=@f.output_path.xml_docbook_book.rel_sm
          url=@f.output_path.xml_docbook_book.url
          desc,id,file='XML Docbook Book','docbook',@f.base_filename.xml_docbook_book
          summarize(desc,id,file,pth,rel,url)
        end
        if FileTest.file?(@f.place_file.xml_fictionbook.dir)==true
          pth=@f.output_path.xml_fictionbook.dir
          rel=@f.output_path.xml_fictionbook.rel_sm
          url=@f.output_path.xml_fictionbook.url
          desc,id,file='XML Fictionbook','fictionbook',@f.base_filename.xml_fictionbook
          summarize(desc,id,file,pth,rel,url)
        end
        if FileTest.file?(@f.place_file.xml_scaffold_structure_sisu.dir)==true
          pth=@f.output_path.xml_scaffold_structure_sisu.dir
          rel=@f.output_path.xml_scaffold_structure_sisu.rel_sm
          url=@f.output_path.xml_scaffold_structure_sisu.url
          desc,id,file='XML Scaffold sisu structure','xml_scaffold',@f.base_filename.xml_scaffold_structure_sisu
          summarize(desc,id,file,pth,rel,url)
        end
        if FileTest.file?(@f.place_file.xml_scaffold_structure_collapse.dir)==true
          pth=@f.output_path.xml_scaffold_structure_collapse.dir
          rel=@f.output_path.xml_scaffold_structure_collapse.rel_sm
          url=@f.output_path.xml_scaffold_structure_collapse.url
          desc,id,file='XML Scaffold collapsed structure','xml_collapsed',@f.base_filename.xml_scaffold_structure_collapse
          summarize(desc,id,file,pth,rel,url)
        end
        if FileTest.file?(@f.place_file.info.dir)==true
          pth=@f.output_path.texinfo.dir
          rel=@f.output_path.texinfo.rel_sm
          url=@f.output_path.texinfo.url
          desc,id,file='Info file','info',@f.base_filename.info
          summarize(desc,id,file,pth,rel,url)
        end
        if FileTest.file?(@f.place_file.manpage.dir)==true
          pth=@f.output_path.manpage.dir
          rel=@f.output_path.manpage.rel_sm
          url=@f.output_path.manpage.url
          desc,id,file='Manpage','manpage',@f.base_filename.manpage
          summarize(desc,id,file,pth,rel,url)
        end
        if FileTest.file?(@f.place_file.sqlite_discrete.dir)==true
          desc,id,file='SQLite3 file','sqlite',@f.base_filename.sqlite_discrete
          pth=@f.output_path.sqlite_discrete.dir
          rel=@f.output_path.sqlite_discrete.rel_sm
          url=@f.output_path.sqlite_discrete.url
          summarize(desc,id,file,pth,rel,url)
        end
        if FileTest.file?(@f.place_file.txt.dir)==true
          desc,id='Plaintext (UTF-8)','text'
          pth=@f.output_path.txt.dir
          rel=@f.output_path.txt.rel_sm
          url=@f.output_path.txt.url
          file=@f.base_filename.txt
          summarize(desc,id,file,pth,rel,url)
        end
        if FileTest.file?(@f.place_file.textile.dir)==true
          desc,id='Textile text (UTF-8)','textile'
          pth=@f.output_path.textile.dir
          rel=@f.output_path.textile.rel_sm
          url=@f.output_path.textile.url
          file=@f.base_filename.textile
          summarize(desc,id,file,pth,rel,url)
        end
        if FileTest.file?(@f.place_file.asciidoc.dir)==true
          desc,id='AsciiDoc text (UTF-8)','asciidoc'
          pth=@f.output_path.asciidoc.dir
          rel=@f.output_path.asciidoc.rel_sm
          url=@f.output_path.asciidoc.url
          file=@f.base_filename.asciidoc
          summarize(desc,id,file,pth,rel,url)
        end
        if FileTest.file?(@f.place_file.markdown.dir)==true
          desc,id='Markdown text (UTF-8)','markdown'
          pth=@f.output_path.markdown.dir
          rel=@f.output_path.markdown.rel_sm
          url=@f.output_path.markdown.url
          file=@f.base_filename.markdown
          summarize(desc,id,file,pth,rel,url)
        end
        if FileTest.file?(@f.place_file.rst.dir)==true
          desc,id='rST text (UTF-8)','rst'
          pth=@f.output_path.rst.dir
          rel=@f.output_path.rst.rel_sm
          url=@f.output_path.rst.url
          file=@f.base_filename.rst
          summarize(desc,id,file,pth,rel,url)
        end
        if FileTest.file?(@f.place_file.orgmode.dir)==true
          desc,id='OrgMode structure text (UTF-8)','org'
          pth=@f.output_path.orgmode.dir
          rel=@f.output_path.orgmode.rel_sm
          url=@f.output_path.orgmode.url
          file=@f.base_filename.orgmode
          summarize(desc,id,file,pth,rel,url)
        end
        if FileTest.file?("#{@base_path}/#{@md.fns}.tex")==true
          desc,id,file='LaTeX (portrait)','latex',"#{@md.fns}.tex"
          pth,rel,url='','',''
          summarize(desc,id,file,pth,rel,url)
        end
        if FileTest.file?("#{@base_path}/#{@md.fns}.tex")==true
          desc,id,file='LaTeX (landscape)','latex_landscape',"#{@md.fns}.landscape.tex"
          pth,rel,url='','',''
          summarize(desc,id,file,pth,rel,url)
        end
        if FileTest.file?(@f.place_file.hash_digest.dir)==true
          pth=@f.output_path.hash_digest.dir
          rel=@f.output_path.hash_digest.rel_sm
          url=@f.output_path.hash_digest.url
          desc,id,file="Digest/DCC - Document Content Certificate (#{@dg})",'digests',@f.base_filename.hash_digest
          summarize(desc,id,file,pth,rel,url)
        end
      end
      def published_versions
        desc,file='Markup (SiSU source)','source',@md.fns
        languages(desc,file)
      end
      def language_versions
        if FileTest.file?(@f.place_file.manifest.dir)==true
          desc='Markup (SiSU source)'
          published_languages(desc)
        end
      end
      def qrc_image
        fn=(@f.output_dir_structure.by_filename?) \
        ? 'sisu_manifest'
        : @md.fnb
        pth=((@o_str.dump_or_redirect?) \
        || (@f.output_dir_structure.by_filename?)) \
        ? '.'
        : 'qrcode'
        img_md="#{pth}/#{fn}#{@fn_lng}.md.png"
        img_title="#{pth}/#{fn}#{@fn_lng}.title.png"
        if FileTest.file?(@f.place_file.qrcode_md.dir)==true
          @manifest[:html] <<<<WOK
<tr><td class="left">
  <p class="tiny">QR code SiSU document metadata:</p>
  <p class="tiny">
    <img border="0" src="#{img_md}" alt="qrcode metadata" />
  </p>
</td></tr>
WOK
        end
        if FileTest.file?(@f.place_file.qrcode_title.dir)==true
          @manifest[:html] <<<<WOK
<tr><td class="left">
  <p class="tiny">QR code document title info:</p>
  <p class="tiny">
    <img border="0" src="#{img_title}" alt="qrcode title" />
  </p>
</td></tr>
WOK
        end
      end
      def source_tests
        if @md.fno =~/\.ssm$/                                                  #% decide whether to extract and include requested/required documents
          if FileTest.file?(@f.place_file.src.dir)==true
            pth=@f.output_path.src.dir
            rel=@f.output_path.src.rel_sm
            url=@f.output_path.src.url
            desc,id,file='Markup Composite File (SiSU source)','source',@f.base_filename.src
            summarize_sources(desc,id,file,pth,rel,url)
          end
        else
          if FileTest.file?(@f.place_file.src.dir)==true
            pth=@f.output_path.src.dir
            rel=@f.output_path.src.rel_sm
            url=@f.output_path.src.url
            desc,id,file='Markup (SiSU source)','composite',@f.base_filename.src
            summarize_sources(desc,id,file,pth,rel,url)
          end
        end
        if FileTest.file?(@f.place_file.sisupod.dir)==true
          pth=@f.output_path.sisupod.dir
          rel=@f.output_path.sisupod.rel_sm
          url=@f.output_path.sisupod.url
          desc,id,file='SiSUdoc pod (tar.xz)','sisupod',@f.base_filename.sisupod
          summarize_sources(desc,id,file,pth,rel,url)
        end
        if FileTest.file?(@f.place_file.pot.dir)==true
          pth=@f.output_path.pot.dir
          rel=@f.output_path.pot.rel_sm
          url=@f.output_path.pot.url
          desc,id,file='SiSU pot','pot',@f.base_filename.pot
          summarize_sources(desc,id,file,pth,rel,url)
        end
      end
      def metadata_tests
        if defined? @md.title                                                   #%
          if defined? @md.title.full \
          and @md.title.full=~/\S+/
            desc,id,info=@translate.full_title,'title',@md.title.full
            metadata(desc,id,info)
          end
        end
        if defined? @md.creator                                                 #%
          if defined? @md.creator.author \
          and @md.creator.author=~/\S+/
            desc,id,info=@translate.author,'author',@md.creator.author
            metadata(desc,id,info)
          end
          if defined? @md.creator.editor \
          and @md.creator.editor=~/\S+/
            desc,id,info=@translate.editor,'editor',@md.creator.editor
            metadata(desc,id,info)
          end
          if defined? @md.creator.contributor \
          and @md.creator.contributor=~/\S+/
            desc,id,info=@translate.contributor,'contributor',@md.creator.contributor
            metadata(desc,id,info)
          end
          if defined? @md.creator.translator \
          and @md.creator.translator=~/\S+/
            desc,id,info=@translate.translator,'creator',@md.creator.translator
            metadata(desc,id,info)
          end
          if defined? @md.creator.illustrator \
          and @md.creator.illustrator=~/\S+/
            desc,id,info=@translate.illustrator,'illustrator',@md.creator.illustrator
            metadata(desc,id,info)
          end
          if defined? @md.creator.prepared_by \
          and @md.creator.prepared_by=~/\S+/
            desc,id,info=@translate.prepared_by,'prepared_by',@md.creator.prepared_by
            metadata(desc,id,info)
          end
          if defined? @md.creator.digitized_by \
          and @md.creator.digitized_by=~/\S+/
            desc,id,info=@translate.digitized_by,'designed_by',@md.creator.digitized_by
            metadata(desc,id,info)
          end
        end
        if defined? @md.rights
          if defined? @md.rights.all \
          and @md.rights.all=~/\S+/ #dc
            desc,id,info=@translate.rights,'rights',@md.rights.all
            metadata(desc,id,info)
          end
        end
        if defined? @md.date                                                    #%
          if defined? @md.date.published \
          and @md.date.published=~/\S+/ #dc
            desc,id,info=@translate.date,'date',@md.date.published
            metadata(desc,id,info)
          end
          if defined? @md.date.created \
          and @md.date.created=~/\S+/ #dc
            desc,id,info=@translate.date_created,'date_created',@md.date.created
            metadata(desc,id,info)
          end
          if defined? @md.date.issued \
          and @md.date.issued=~/\S+/ #dc
            desc,id,info=@translate.date_issued,'date_issued',@md.date.issued
            metadata(desc,id,info)
          end
          if defined? @md.date.available \
          and @md.date.available=~/\S+/ #dc
            desc,id,info=@translate.date_available,'date_available',@md.date.available
            metadata(desc,id,info)
          end
          if defined? @md.date.modified \
          and @md.date.modified=~/\S+/ #dc
            desc,id,info=@translate.date_modified,'date_modified',@md.date.modified
            metadata(desc,id,info)
          end
          if defined? @md.date.valid \
          and @md.date.valid=~/\S+/ #dc
            desc,id,info=@translate.date_valid,'date_valid',@md.date.valid
            metadata(desc,id,info)
          end
        end
        if defined? @md.publisher \
        and @md.publisher=~/\S+/ #dc
          desc,id,info=@translate.publisher,'publisher',@md.publisher
          metadata(desc,id,info)
        end
        if defined? @md.notes                                                   #%
          if defined? @md.notes.description \
          and @md.notes.description=~/\S+/
            desc,id,info=@translate.description,'description',@md.notes.description
            metadata(desc,id,info)
          end
          if defined? @md.notes.abstract \
          and @md.notes.abstract=~/\S+/
            desc,id,info=@translate.abstract,'abstract',@md.notes.abstract
            metadata(desc,id,info)
          end
          if defined? @md.notes.comment \
          and @md.notes.comment=~/\S+/
            desc,id,info=@translate.comments,'comment',@md.notes.comment
            metadata(desc,id,info)
          end
          if defined? @md.notes.prefix_a \
          and @md.notes.prefix_a=~/\S+/
            desc,id,info=@translate.prefix_a,'prefix',@md.notes.prefix_a
            metadata(desc,id,info)
          end
          if defined? @md.notes.prefix_b \
          and @md.notes.prefix_b=~/\S+/
            desc,id,info=@translate.prefix_b,'prefix_b',@md.notes.prefix_b
            metadata(desc,id,info)
          end
        end
        if defined? @md.title                                                   #%
          if defined? @md.title.language \
          and @md.title.language=~/\S+/
            desc,id,info=@translate.language,'language',@md.title.language
            metadata(desc,id,info)
          end
          if defined? @md.original.language \
          and @md.original.language=~/\S+/
            desc,id,info=@translate.language_original,'language_original',@md.original.language
            metadata(desc,id,info)
          end
        end
        if defined? @md.classify                                                #%
          if defined? @md.topic_register_array \
          and @md.topic_register_array.length > 0
            @manifest[:html] << %{<tr><th class="left"><p class="bold_left" id="topics">#{@translate.topic_register}:</p></th><td>\n}
            @md.topic_register_array.each do |t|
              t.each_with_index do |st,i|
                if st.is_a?(Array)
                  st.each do |v|
                    if v.is_a?(Array)
                      v.each do |w|
                        @manifest[:html] << %{<p class="it#{i}">#{w}</p>\n}
                      end
                    else
                      @manifest[:html] << %{<p class="it#{i}">#{v}</p>\n}
                    end
                  end
                else @manifest[:html] << %{<p class="it#{i}">#{st}</p>\n}
                end
              end
            end
            @manifest[:html] << %{</td></tr>\n}
          end
          if defined? @md.classify.subject \
          and @md.classify.subject=~/\S+/
            desc,id,info=@translate.subject,'subject',@md.classify.subject
            metadata(desc,id,info)
          end
          if defined? @md.classify.keywords \
          and @md.classify.keywords=~/\S+/
            desc,id,info=@translate.keywords,'keywords',@md.classify.keywords
            metadata(desc,id,info)
          end
          if defined? @md.classify.loc \
          and @md.classify.loc=~/\S+/
            desc,id,info=@translate.cls_loc,'loc',@md.classify.loc
            metadata(desc,id,info)
          end
          if defined? @md.classify.dewey \
          and @md.classify.dewey=~/\S+/
            desc,id,info=@translate.cls_dewey,'dewey',@md.classify.dewey
            metadata(desc,id,info)
          end
          if defined? @md.notes.coverage \
          and @md.notes.coverage=~/\S+/
            desc,id,info=@translate.coverage,'coverage',@md.notes.coverage
            metadata(desc,id,info)
          end
          if defined? @md.notes.relation \
          and @md.notes.relation=~/\S+/
            desc,id,info=@translate.relation,'relation',@md.notes.relation
            metadata(desc,id,info)
          end
          if defined? @md.notes.type \
          and @md.notes.type=~/\S+/ #dc
            desc,id,info=@translate.type,'type',@md.notes.type
            metadata(desc,id,info)
          end
          if defined? @md.notes.format \
          and @md.notes.format=~/\S+/
            desc,id,info=@transate.format,'format',@md.notes.format
            metadata(desc,id,info)
          end
        end
        if defined? @md.identifier                                              #%
          if defined? @md.identifier.oclc \
          and @md.identifier.oclc=~/\S+/
            desc,id,info=@translate.cls_oclc,'',@md.identifier.oclc
            @manifest[:html] << %{<tr><th class="left"><p class="bold_left">#{desc}:</p></th><td>\n}
            @manifest[:html] << %{<p class="left"><a href="http://worldcat.org/oclc/#{info}">#{info}</a></p>\n}
            @manifest[:html] << %{</td></tr>\n}
          end
          if defined? @md.identifier.pg \
          and @md.identifier.pg=~/\S+/
            desc,id,info=@translate.cls_gutenberg,'ocalc',@md.identifier.pg
            metadata(desc,id,info)
          end
          if defined? @md.identifier.isbn \
          and @md.identifier.isbn=~/\S+/
            desc,id,info=@translate.cls_isbn,'isbn',@md.identifier.isbn
            metadata(desc,id,info)
          end
        end
        if defined? @md.original.source \
        and @md.original.source=~/\S+/
          desc,id,info=@translate.source,'source_original',@md.original.source
          metadata(desc,id,info)
        end
        if @md.fns
          desc,id,info=@translate.sourcefile,'source_filename',@md.fns
          metadata(desc,id,info)
        end
        if @md.en[:mismatch] > 0
          desc,id,info='WARNING document error in endnote markup, number mismatch','',"endnotes: #{@md.en[:note]} != endnote reference marks: #{@md.en[:mark]} (difference = #{@md.en[:mismatch]})"
          metadata(desc,id,info)
        end
        if @md.wc_words
          desc,id,info=@translate.word_count,'wordcount',@md.wc_words
          metadata(desc,id,info)
        end
        if @md.dgst
          desc,id,info="#{@translate.sourcefile_digest} (#{@dg})",'digests',@md.dgst[1]
          metadata(desc,id,info)
        end
        if @md.sc_number
          desc,id,info=@translate.sc_number,'sc_number',@md.sc_number
          metadata(desc,id,info)
        end
        if @md.sc_date
          desc,id,info=@translate.sc_date,'sc_date',"#{@md.sc_date} at #{@md.sc_time}"
          metadata(desc,id,info)
        end
        if @md.generated
          desc,id,info=@translate.last_generated,'generated',@md.generated
          metadata(desc,id,info)
        end
        if @md.project_details
          desc,id,info=@translate.sisu_version,'project',"#{@md.project_details.project} #{@md.project_details.version} #{@md.project_details.date_stamp} (#{@md.project_details.date})#{@md.project_details.install_method}"
          metadata(desc,id,info)
        end
        if @md.ruby_version
          desc,id,info=@translate.ruby_version,'ruby',@md.ruby_version
          metadata(desc,id,info)
        end
      end
      def links_tests
        if defined? @md.lnk \
        and @md.lnk
          @md.lnk.each do |l|
            if defined? l[:say]
              target=(l[:url] !~/^\.(\.)?\//) \
              ? 'external'
              : '_top'
              url,lnk=l[:url],l[:say]
              unless url.nil? \
              or url.empty?
                links(url,lnk,target)
              end
            end
          end
        end
      end
      def check_output(data)
        begin
          make=SiSU_Env::ProcessingSettings.new(@md)
          minitoc=SiSU_HTML_MiniToc::TocMini.new(@md,data).songsheet.join("\n")
          format_head_toc=SiSU_HTML_Format::HeadToc.new(@md)
          @manifest[:html] <<<<WOK
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>
SiSU manifest: #{@md.title.full}
</title>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<meta name="sourcefile" content="#{@md.fns}" />
<link rel="generator" href="http://www.jus.uio.no/sisu" />
<link rel="shortcut icon" href="#{@f.path_rel_links.html_scroll_css}_sisu/image_sys/rb7.ico" />
#{@stylesheet.css_head}
</head>
<body lang="#{@md.opt.lng}">
#{format_head_toc.seg_head_navigation_band(:manifest)}
WOK
          if make.build.manifest_minitoc?
            if @o_str.dump_or_redirect?
            elsif @f.output_dir_structure.by_language_code? \
            or @f.output_dir_structure.by_filetype?
              minitoc=minitoc.gsub(/<a href="(\S+?)"/m,%{<a href="../html/#{@md.fnb}/\\1"}).
                gsub(/<a href="\.\.\/html\/#{@md.fnb}\/(?:sisu_manifest\.html|#{@f.base_filename.manifest})"/m,
              %{<a href="#{@f.base_filename.manifest}"})
            end
            @manifest[:html] <<<<WOK
<div class="toc">
#{minitoc.to_s}
</div>
<div class="content">
WOK
          else
            @manifest[:html] <<<<WOK
<div>
WOK
          end
          if @o_str.dump_or_redirect?
          elsif @f.output_dir_structure.by_language_code? \
          or @f.output_dir_structure.by_filetype?
            pth_local=@f.output_path.manifest.dir
            pth_rel='.'
          else
            pth_local=@f.output_path.base.dir
            pth_rel='..'
          end
          pth_rel_home=if @env.output_dir_structure.by? == :language
            '../..'
          elsif @env.output_dir_structure.by? == :filetype
            '..'
          elsif @env.output_dir_structure.by? == :filename
            '..'
          else '..'
          end
          output_organised_by="(output organised by #{@env.output_dir_structure.by?})"
          harvest=(FileTest.file?("#{pth_local}/authors#{@fn_lng}.html") \
          && FileTest.file?("#{pth_local}/topics#{@fn_lng}.html")) \
          ? %{<p class="small"><a href="#{pth_rel_home}/index.html">.:</a> other document manifests: [<a href="#{pth_rel}/authors#{@fn_lng}.html">authors</a>] [<a href="#{pth_rel}/topics#{@fn_lng}.html">topics</a>] #{output_organised_by}</p>}
          : %{<p class="small"><a href="#{pth_rel_home}">#{output_organised_by}</a></p>}
          manifest_title=%{<p class="bold">#{@translate.manifest_description}</p>#{harvest}}
          @manifest[:html] <<<<WOK
<div id="horizontal_links">
#{manifest_title}
</div>
<h1 class="small">#{@md.title.full}</h1>
<p class="bold">#{@md.author}</p>
<div id="horizontal_links"><p class="bold">
<p class="small">
&nbsp;&nbsp;<a href="#output">Document, Available Filetypes</a>
</p>
<p class="small">
&nbsp;&nbsp;<a href="#metadata">Document Metadata</a>
</p>
<p class="tiny">
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#links">metadata suggested links (if any)</a>
</p>
</div>
<table summary="normal text css" width="100%" border="0" cellpadding="2" align="center">
WOK
          published_versions
          @manifest[:html] << '</table>'
          @manifest[:html] <<<<WOK
<h2 class="small"><a name="output">#{@translate.manifest_description_output}</a></h2>
<table summary="available output/filetypes" width="100%" border="0" cellpadding="2" align="center">
<tr> <th class="left"><p class="bold">#{@translate.filetype_description}</p></th><th class="left"><p class="bold">#{@translate.filename}</p></th><th class="right"><p class="right"><b>#{@translate.file_size}</b></p><p class="tiny_right">(kB)</p></th></tr>

WOK
          output_tests
          @manifest[:html] << '</table>'
          @manifest[:html] <<<<WOK
<table summary="normal text css" width="100%" border="0" cellpadding="2" align="center">
WOK
          source_tests
          @manifest[:html] << '</table>'
          @manifest[:html] <<<<WOK
<h2 class="small"><a name="metadata">#{@translate.manifest_description_metadata}</a></h2>
<table summary="document metadata" width="100%" border="0" cellpadding="2" align="center">
<tr> <th class="left"><p class="bold" id="metadata">#{@translate.metadata}</p></th><th class="left"><p class="bold">#{@translate.description}</p></th></tr>
WOK
          metadata_tests
          @manifest[:html] <<<<WOK
</table>
WOK
          @manifest[:html] <<<<WOK
<p class="bold"><a name="links">#{@translate.suggested_links}:</a></p>
<table summary="suggested links" width="100%" border="0" cellpadding="2" align="center">
WOK
          links_tests
          @manifest[:html] <<<<WOK
</table>
WOK
          @manifest[:html] <<<<WOK
<h2 class="small"><a name="languages">#{@translate.language_version_list}</a></h2>
<table summary="language versions" width="100%" border="0" cellpadding="2" align="center">
<tr> <th class="left"><p class="bold">#{@translate.filename}</p></th><th class="left"><p class="bold">#{@translate.description}</p></th><th class="right"><p class="right">&nbsp;</p></th></tr>

WOK
          language_versions
          qrc_image
          @manifest[:html] <<<<WOK
</table>
</div>
<div>
<br>
#{SiSU_Proj_HTML::Bits.new.credits_sisu_manifest}
</div>
</body>
</html>
WOK
          output
        rescue
          SiSU_Errors::Rescued.new($!,$@,@md.opt.selections.str,@md.fns).location do
            __LINE__.to_s + ':' + __FILE__
          end
        ensure
        end
      end
    end
  end
end
__END__
#+END_SRC

*** html_persist.rb

#+HEADER: :tangle "../lib/sisu/html_persist.rb"
#+BEGIN_SRC ruby
#<<sisu_document_header>>
module SiSU_HTML_Persist
  class Persist
    @@persist=nil
    attr_accessor :is0,:is1,:is2,:is3,:is4,:heading0,:heading1,:heading2,:heading3,:heading4, :title, :dot_nav, :tocband_banner, :tocband_bannerless, :headings, :heading_endnotes, :main, :endnote_all, :tail, :credits, :heading_idx, :idx, :seg_endnotes, :seg_endnotes_array, :segtocband, :get_hash_fn, :get_hash_to, :seg_subtoc, :seg_subtoc_array, :fn, :seg_name ,:seg_name_x,:seg_name_x_tracker
    def initialize(args=nil)
      @@persist=args=(args ? args : (@@persist || persist_init_hash_values))
      @is0=args[:is0]
      @is1=args[:is1]
      @is2=args[:is2]
      @is3=args[:is3]
      @is4=args[:is4]
      @heading0=args[:heading0]
      @heading1=args[:heading1]
      @heading2=args[:heading2]
      @heading3=args[:heading3]
      @heading4=args[:heading4]
      @title=args[:title]
      @dot_nav=args[:dot_nav]
      @tocband_banner=args[:tocband_banner]
      @tocband_bannerless=args[:tocband_bannerless]
      @headings=args[:headings]
      @heading_endnotes=args[:heading_endnotes]
      @main=args[:main]
      @endnote_all=args[:endnote_all]
      @tail=args[:tail]
      @credits=args[:credits]
      @heading_idx=args[:heading_idx]
      @idx=args[:idx]
      @seg_endnotes=args[:seg_endnotes]
      @seg_endnotes_array=args[:seg_endnotes_array]
      @get_hash_to=args[:get_hash_to]
      @get_hash_fn=args[:get_hash_fn]
      @seg_subtoc=args[:seg_subtoc]
      @seg_subtoc_array=args[:seg_subtoc_array]
      @segtocband=args[:fn]
      @fn=args[:fn]
      @seg_name=args[:seg_name]
      @seg_name_x=args[:seg_name_x]
      @seg_name_x_tracker=args[:seg_name_x_tracker]
    end
    def is0
      @is0
    end
    def is1
      @is1
    end
    def is2
      @is2
    end
    def is3
      @is3
    end
    def is4
      @is4
    end
    def heading0
      @heading0
    end
    def heading1
      @heading1
    end
    def heading2
      @heading2
    end
    def heading3
      @heading3
    end
    def heading4
      @heading4
    end
    def title
      @title
    end
    def dot_nav
      @dot_nav
    end
    def tocband_banner
      @tocband_banner
    end
    def tocband_bannerless
      @tocband_bannerless
    end
    def headings
      @headings
    end
    def heading_endnotes
      @heading_endnotes
    end
    def main
      @main
    end
    def endnote_all
      @endnote_all
    end
    def tail
      @tail
    end
    def credits
      @credits
    end
    def heading_idx
      @heading_idx
    end
    def idx
      @idx
    end
    def seg_endnotes
      @seg_endnotes
    end
    def seg_endnotes_array
      @seg_endnotes_array
    end
    def get_hash_to
      @get_hash_to
    end
    def get_hash_fn
      @get_hash_fn
    end
    def seg_subtoc
      @seg_subtoc
    end
    def seg_subtoc_array
      @seg_subtoc_array
    end
    def segtocband
      @segtocband
    end
    def fn
      @fn
    end
    def seg_name
      @seg_name
    end
    def seg_name_x
      @seg_name_x
    end
    def seg_name_x_tracker
      @seg_name_x_tracker
    end
    def persist_init_hash_values
      {
        is0: 0,
        is1: 0,
        is2: 0,
        is3: 0,
        is4: 0,
        heading0: '',
        heading1: '',
        heading2: '',
        heading3: '',
        heading4: '',
        tocband_banner: [],
        tocband_bannerless: [],
        title: [],
        headings: [],
        main: [],
        idx: [],
        tail: [],
        credits: [],
        endnote_all: [],
        heading_endnotes: '',
        seg_endnotes: {},
        seg_endnotes_array: [],
        get_hash_fn: '',
        get_hash_to: '',
        seg_subtoc: {},
        seg_subtoc_array: [],
        segtocband: '',
        fn: '',
        seg_name: [],
        seg_name_x: [],
        seg_name_x_tracker: 0,
      }
    end
    def persist_init
      @@persist=nil
      Persist.new(persist_init_hash_values)
    end
  end
end
__END__
#+END_SRC

*** html_promo.rb

#+HEADER: :tangle "../lib/sisu/html_promo.rb"
#+BEGIN_SRC ruby
#<<sisu_document_header>>
module SiSU_HTML_Promo
  require_relative 'se'                                 # se.rb
    include SiSU_Env
  class Ad
    def initialize(md)
      @md=md
      @env=SiSU_Env::InfoEnv.new(@md.fns,@md)
      @rc=SiSU_Env::GetInit.new.sisu_yaml.rc
      @ad=SiSU_Env::GetInit.new.ads
      @flag=@env.widget.promo?
      @make=SiSU_Env::ProcessingSettings.new(@md)
    end
    def div
      def major
        (@make.build.html_right_pane? \
         && @flag[:ad]) \
        ? '<div id="pane_major">'
        : ''
      end
      def minor
        (@make.build.html_right_pane? \
         && @flag[:ad]) \
        ? '<div id="pane_minor">'
        : ''
      end
      def close
        (@make.build.html_right_pane? \
         && @flag[:ad]) \
        ? '</div>'
        : ''
      end
      self
    end
    def display
      ads_array,promo_array=[],[]
      if @make.build.html_right_pane? \
      && @flag[:ad]
        ads=if @md.promo && @md.promo.length > 0           #promo set in document
          promo_array=@md.promo
        elsif @flag[:rc]                                   #promo set in rc file
          promo_array=if @rc['html']['promo'].is_a?(String)
            @rc['html']['promo'].split(/[,;]\s*/)
          else @rc['html']['promo']
          end
        else advert_extract_all
        end
        ads=if promo_array.length > 0
          promo_array.each do |x|
            ads_array << advert_extract_subject(x)
          end
          ads_array
        end
        adverts(ads.join)
      end
    end
    def cell(prod,id)
      @prod,@id=prod,id
      def title
        @prod['title'] ? %{<b>#{@prod['title']}</b>} : ''
      end
      def subtitle
        @prod['subtitle'] ? %{ - #{@prod['subtitle']}} : ''
      end
      def author
        @prod['author'] ? %{<p class="pane">#{@prod['author']}</p>} : ''
      end
      def editor
        @prod['editor'] ? %{<p class="pane">#{@prod['editor']}</p>} : ''
      end
      def year
        @prod['year'] ? %{<p class="pane">#{@prod['year']}</p>} : ''
      end
      def date
        @prod['date'] ? %{<p class="pane">On: #{@prod['date']}</p>} : ''
      end
      def location
        @prod['at'] ? %{<p class="pane">At: #{@prod['at']}</p>} : ''
      end
      def pages
        @prod['pages'] ? %{<p class="pane">Pages: #{@prod['pages']} pages</p>} : ''
      end
      def form
        @prod['form'] ? %{<p class="pane">#{@prod['form']}</p>} : ''
      end
      def nick
        @prod['nick'] ? %{(#{@prod['nick']})<br>} : ''
      end
      def update
        @prod['update'] ? %{<p class="pane">Updated: #{@prod['update']}</p>} : ''
      end
      def issn
        @prod['issn'] ? %{<p class="pane">issn: #{@prod['issn']}</p>} : ''
      end
      def blurb
        @prod['blurb'] ? %{<p class="pane_blurb">#{@prod['blurb']}</p>} : ''
      end
      def search_form_sisu(table=true)
        db=if @prod['db']=~/\S+/
          (@prod['db']=~/^#{Db[:name_prefix]}\S+/) ? @prod['db'] : "#{Db[:name_prefix]}#{@prod['db']}"
        elsif defined? @rc['search']['sisu']['db'] \
        and @rc['search']['sisu']['db'] =~/\S+/
          (@rc['search']['sisu']['db']=~/^#{Db[:name_prefix]}\S+/) \
          ? @prod['search']['sisu']['db']
          : "#{Db[:name_prefix]}#{@prod['db']}"
        else nil
        end
        action=if @prod['action']=~/^https?:\/\//
          @prod['action']
        elsif defined? @rc['search']['sisu']['action'] \
        and @rc['search']['sisu']['action'] =~/^https?:\/\//
          @rc['search']['sisu']['action']
        else nil
        end
        if action \
        and db
          @env.widget.search_form('sisusearch',action,db,table)
        else ''
        end
      end
      def search_form_hyperestraier(table=true)
        action=if defined? @rc['search']['hyperestraier']['action'] \
        and @rc['search']['hyperestraier']['action'] =~/^https?:\/\//
          @rc['search']['hyperestraier']['action']
        else nil
        end
        form=if action
          '<br>' + @env.widget.search_form('hyperestraier',action,'',table)
        else ''
        end
        form
      end
      def links
        if @prod['links'] #and @prod['links']==Array
          links_a=[]
          @prod['links'].each do |x|
            if x \
            and x['url'] \
            and x['title']
              subtitle=x['subtitle'] ? %{ - #{x['subtitle']}} : ''
              url_=(x['url'] =~/https?:/) ? x['url'] : "../#{x['url']}"
              links_a << %{<p class="pane_link"><a href="#{url_}">#{x['title']}#{subtitle}</a></p>\n}
            end
          end
          links_a.join
        else ''
        end
      end
      def image
        @prod['image'] ? %{<img border="0" src="../_sisu/image/#{@prod['image']}" /><br>} : ''
      end
      def url_link
        @url_=if @prod['url'] =~/https?:/
          "#{@prod['url']}"
        else "../#{@prod['url']}" # "#{@env.url.root}/#{@prod['url']}"
        end
        def show
          @prod['url'] ? %{<p class="pane_link"><a href="#{@url_}">#{@url_}</a></p>} : ''
        end
        def url
          @prod['url'] ? %{<a href="#{@url_}">} : ''
        end
        def url_relative
          @prod['url'] ? %{<a href="../#{@prod['url']}/toc.html">} : ''
        end
        self
      end
      def flyer
        if @prod['flyer']
          %{<p class="pane"><a href="../man/pdf/#{@id}.pdf"><img border="0" height="18" width="15" src="../_sisu/image/b_pdf.png">&nbsp;PDF&nbsp;flyer</a></p>}
        else ''
        end
      end
      def price
        def gbp
          if defined? @prod['price']['gbp'] \
          and @prod['price']['gbp']
            " &nbsp;&pound;&nbsp;#{@prod['price']['gbp']}&nbsp;(GBP)&nbsp;"
          else ''
          end
        end
        def euro
          if defined? @prod['price']['euro'] \
          and @prod['price']['euro']
            " &nbsp;&euro;&nbsp;#{@prod['price']['euro']}&nbsp;(Euro)&nbsp;"
          else ''
          end
        end
        def usd
          if defined? @prod['price']['usd'] \
          and @prod['price']['usd']
            " &nbsp;$&nbsp;#{@prod['price']['usd']}&nbsp;(USD)&nbsp;"
          else ''
          end
        end
        %{<p class="pane">Price:#{gbp}#{euro}#{usd}</p>}
      end
      def adsense #draw content from a configuration file
        def column_right
          if defined? @ad[:promo]['ad']['adsense']['column_right']
            @ad[:promo]['ad']['adsense']['column_right'].join("\n")
          else ''
          end
        end
        def line_single
          if defined? @ad[:promo]['ad']['adsense']['line_single']
            @ad[:promo]['ad']['adsense']['line_single'].join("\n")
          else ''
          end
        end
        self
      end
      def site_link #Work area
        if url_link.url
           <<-WOK
<p class="pane">
#{url_link.url}
#{image}
#{title}
#{subtitle}
</a>#{nick}</p>
          WOK
        else
         <<-WOK
<p class="pane">
#{image}
#{title}
#{subtitle}
</p>
          WOK
        end
      end
      self
    end
    def output_form_sponsor(type,id)
      cell=cell(@ad[:promo][type][id],prod_id)
      <<-WOK
<br>
#{cell.site_link}
#{cell.blurb}
#{cell.links}
      WOK
    end
    def output_form_link(type,id)
      prod_id=id.gsub(/id_/,'')
      cell=cell(@ad[:promo][type][id],prod_id)
       <<WOK
<br>
#{cell.site_link}
#{cell.author}
#{cell.year}
#{cell.blurb}
#{cell.links}
WOK
    end
    def output_form_search_sisu(type,id)
      prod_id=id.gsub(/id_/,'')
      cell=cell(@ad[:promo][type][id],prod_id)
      cell.search_form_sisu(false)
    end
    def output_form_search_hyperestraier(type,id)
      prod_id=id.gsub(/id_/,'')
      cell=cell(@ad[:promo][type][id],prod_id)
      cell.search_form_hyperestraier(false)
    end
    def output_form_book(type,id)
      prod_id=id.gsub(/id_/,'')
      cell=cell(@ad[:promo][type][id],prod_id)
      prod_type=((id=~/id_(?:[0-9x]){10,13}/i) ? 'isbn' : 'id')
      id_detail=%{<p class="pane">#{prod_type}: #{prod_id}</p>}
       <<WOK
<br>
#{cell.site_link}
#{cell.author}
#{cell.year}
#{id_detail}
#{cell.pages}#{cell.form}
#{cell.price}
#{cell.flyer}
#{cell.blurb}
#{cell.links}
WOK
    end
    def output_form_journal(type,id)
      prod_id=id.gsub(/id_/,'')
      cell=cell(@ad[:promo][type][id],prod_id)
       <<WOK
<br>
#{cell.site_link}
#{cell.editor}
#{cell.issn}
#{cell.update}
#{cell.form}
#{cell.price.gsub(/Price:/,'Subscription:')}
#{cell.flyer}
#{cell.blurb}
#{cell.links}
WOK
    end
    def output_form_conference(type,id)
      prod_id=id.gsub(/id_/,'')
      cell=cell(@ad[:promo][type][id],prod_id)
#translate date (dd month yyyy) from 2007-03-04 and ruby conversion
       <<WOK
<br>
#{cell.site_link}
#{cell.date}
#{cell.location}
#{cell.price}
#{cell.flyer}
#{cell.blurb}
#{cell.links}
WOK
    end
    def output_form_select(type,id)
      case type
      when /site/
        output_form_link(type,id)
      when /sponsor/
        output_form_sponsor(type,id)
      when /search/
        if id=~/hyperestraier/
          output_form_search_hyperestraier(type,id)
        else output_form_search_sisu(type,id)
        end
      when /book/
        output_form_book(type,id)
      when /journal/
        output_form_journal(type,id)
      when /conference/
        output_form_conference(type,id)
      end
    end
    def advert_extract_subject(category) #extracts products from category/subject list
      adverts=[]
      if defined? @ad[:promo_list][category] \
      and @ad[:promo_list][category]
        @ad[:promo_list][category].keys.each do |type|
          @ad[:promo_list][category][type].each do |i|
            if i
              id=((i.inspect =~/^\d/) ? "id_#{i.to_s.strip}" : i.to_s.strip) #watch remove .to_s ?
              if defined? @ad[:promo][type][id] \
              and not @ad[:promo][type][id].nil?
                adverts << output_form_select(type,id)
              else
                if defined? @ad[:promo][category][type][id] \
                and @ad[:promo][category][type][id].is_a?(Array) \
                and @ad[:promo][category][type][id].length > 0
                  adverts << @ad[:promo][category][type][id].join("\n")
                end
              end
            end
          end
        end
      else
        SiSU_Screen::Ansi.new(
          @md.opt.act[:color_state][:set],
          "*WARN* category not found: #{category}"
        ).warn unless @md.opt.act[:quiet][:set]==:on
      end
      adverts.join
    end
    def advert_extract_all #extracts all products from list (which is broken down into categories)
      adverts=[]
      @ad[:promo_list].keys.each do |category|
        adverts << advert_extract_subject(category)
      end
      adverts.flatten
    end
    def adverts(ads)
      <<WOK
#{div.minor}
#{ads}
#{div.close}
WOK
    end
    def no_adverts
      <<WOK
#{div.minor}
#{div.close}
WOK
    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
    html

  - 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
