-*- mode: org -*-
#+TITLE:       sisu misc
#+DESCRIPTION: documents - structuring, various output representations & search
#+FILETAGS:    :sisu:misc:
#+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

* misc sort
** air.rb

#+HEADER: :tangle "../lib/sisu/air.rb"
#+BEGIN_SRC ruby
#<<sisu_document_header>>
module SiSU_Air
  require_relative 'se_hub_particulars'                 # se_hub_particulars.rb
  class Source
    @@ao_array=[]
    @@fns=nil
    def initialize(opt)
      @opt=opt
      @@fns||@opt.fns
      @particulars=SiSU_Particulars::Combined.new(opt)
      #@env=@particulars.env
      #@md=@particulars.md
      #@ao_array=@particulars.ao_array
    end
    def read
    end
  protected
    def print
      puts @particulars.md.inspect
      puts @particulars.env.inspect
      puts @particulars.ao_array
    end
  end
end
__END__
#+END_SRC

** embedded.rb

#+HEADER: :tangle "../lib/sisu/embedded.rb"
#+BEGIN_SRC ruby
#<<sisu_document_header>>
module SiSU_Embedded
  require_relative 'dp'                                 # dp.rb
    include SiSU_Param
  require_relative 'se'                                 # se.rb
    include SiSU_Env
  class Source
    def initialize(opt)
      @opt=opt
      @md=SiSU_Param::Parameters.new(@opt).get
      @env=SiSU_Env::InfoEnv.new(@md.fns)
      @rhost=SiSU_Env::InfoRemote.new(@opt).remote_host_base
      @base_src_dir=@opt.f_pth[:pth].sub(/\/#{@opt.f_pth[:lng]}$/,'')
      @f=SiSU_Env::FileOp.new(@md)
    end
    def read
      songsheet
    end
    def songsheet
      images
      audio
      multimedia
      begin
      rescue
        SiSU_Errors::Rescued.new($!,$@,@opt.selections.str,@opt.fns).location do
          __LINE__.to_s + ':' + __FILE__
        end
      ensure
      end
    end
    def images
      src="#{@base_src_dir}/_sisu/image"
      ldest=@env.path.output
      img_dir="#{@env.path.output}/_sisu/image"
      @rhost.each do |remote_conn|
        if (@md.opt.act[:verbose][:set]==:on \
        || @md.opt.act[:verbose_plus][:set]==:on \
        || @md.opt.act[:maintenance][:set]==:on \
        || @md.opt.act[:rsync][:set]==:on) \
        and FileTest.directory?(src)
          FileUtils::mkdir_p(img_dir) unless FileTest.directory?(img_dir)
          src_ec=@f.place_file.images.rel + '/' + @md.ec[:image].join(" #{@f.output_path.images.rel}/")
          unless @opt.fns =~/\.-sst$/
            SiSU_Env::SystemCall.new(src_ec,ldest,'q').rsync('--relative',@opt.base_path)
            #if @md.opt.selections.str.inspect =~/R/ #rsync to remote image directory
            #  SiSU_Env::SystemCall.new(src_ec,remote_rel,'q').rsync('--relative')
            #end
          end
        end
      end
    end
    def audio
      #p @md.ec[:audio]
      src="#{@base_src_dir}/_sisu/mm/audio"
      ldest="#{@env.path.webserv}/#{@env.path.base_markup_dir_stub}/_sisu/mm/audio"
      @rhost.each do |remote_conn|
        rdest="#{remote_conn[:name]}/#{@env.path.base_markup_dir_stub}/_sisu/mm/audio"
        if (@md.opt.act[:verbose][:set]==:on \
        || @md.opt.act[:verbose_plus][:set]==:on \
        || @md.opt.act[:maintenance][:set]==:on \
        || @md.opt.act[:rsync][:set]==:on) \
        and FileTest.directory?(src)
          FileUtils::mkdir_p(ldest) unless FileTest.directory?(ldest)
          src_ec="#{src}/" + @md.ec[:audio].join(" #{src}/")
          SiSU_Env::SystemCall.new(src_ec,"#{ldest}/.",'q').rsync
          if @md.opt.act[:rsync][:set]==:on #rsync to remote audio directory
            SiSU_Env::SystemCall.new(src_ec,"#{rdest}/.",'q').rsync
          end
        end
      end
    end
    def multimedia
      #p @md.ec[:multimedia]
      src="#{@base_src_dir}/_sisu/mm/video"
      ldest="#{@env.path.webserv}/#{@env.path.base_markup_dir_stub}/_sisu/mm/video"
      @rhost.each do |remote_conn|
        rdest="#{remote_conn[:name]}/#{@env.path.base_markup_dir_stub}/_sisu/mm/video"
        if (@md.opt.act[:verbose][:set]==:on \
        || @md.opt.act[:verbose_plus][:set]==:on \
        || @md.opt.act[:maintenance][:set]==:on \
        || @md.opt.act[:rsync][:set]==:on) \
        and FileTest.directory?(src)
          FileUtils::mkdir_p(ldest) unless FileTest.directory?(ldest)
          src_ec="#{src}/" + @md.ec[:multimedia].join(" #{src}/")
          SiSU_Env::SystemCall.new(src_ec,"#{ldest}/.",'q').rsync
          if @md.opt.act[:rsync][:set]==:on #rsync to remote video directory
            SiSU_Env::SystemCall.new(src_ec,"#{rdest}/.",'q').rsync
          end
        end
      end
    end
  end
end
__END__
#+END_SRC

** errors.rb

#+HEADER: :tangle "../lib/sisu/errors.rb"
#+BEGIN_SRC ruby
#<<sisu_document_header>>
module SiSU_Errors
  require_relative 'se'                                 # se.rb
    include SiSU_Env; include SiSU_Screen
  class Rescued <CreateFile
    def initialize(error,errorlist,cmd,fns='')
      @fns,@cmd,@error,@errorlist=fns,cmd,error,errorlist
      @cmd=(cmd \
      && (cmd =~/c/)) \
      ?  'Vc'
      : 'V'
    end
    def location
      file=@fns \
      ? (SiSU_Env::CreateFile.new(@fns).file_error)
      : (File.new('/tmp/errorlog.sisu','w+'))
      file << @fns << "\n" << @error << "\n" << @errorlist
      file.close
      if @cmd=~/[vVM]/
        SiSU_Screen::Ansi.new('',$!,$@).rescue do
          (block_given?) ? yield : __LINE__.to_s + ':' + __FILE__
        end
      else
        SiSU_Screen::Ansi.new('',"rescued, exception raised, silenced").puts_grey
      end
    end
  end
end
__END__
#+END_SRC

** git.rb

#+HEADER: :tangle "../lib/sisu/git.rb"
#+BEGIN_SRC ruby
#<<sisu_document_header>>
module SiSU_Git
  require_relative 'dp'                                 # dp.rb
  require_relative 'se'                                 # se.rb
  require_relative 'ao'                                 # ao.rb
  class Source
    def initialize(opt,process=:complete)
      @opt,@process=opt,process
      @env=SiSU_Env::InfoEnv.new
      @md=SiSU_Param::Parameters.new(@opt).get
      @file=SiSU_Env::FileOp.new(@md)
      l=SiSU_Env::StandardiseLanguage.new(@md.opt.lng).language
      unless @opt.lng==l[:c] # @md.i18n[0]==l[:c]
        p "using: #{@opt.lng} (@make: :language:); filename #{@md.fns} filename language: #{l[:c]}, mismatch"
      end
      if @env.output_dir_structure.multilingual?
        m=/((.+?)(?:\~\w{2,3})?)\.((?:-|ssm\.)?sst|ssm)$/ #watch added match for sss
        fnb,fnt=@opt.fns[m,2],@opt.fns[m,3]
      else m=/(.+?)\.((?:-|ssm\.)?sst|ssm)$/
        fnb=@fnn=@opt.fns[m,1]
        fnt=@opt.fns[m,2]
      end
      git_path_fnb=@env.processing_path.git + '/' + fnb
      lng=(@md.opt.lng) ? (@md.opt.lng) : (@md.i18n[0])
      @git_path={
        fnb:       git_path_fnb,
        doc:       git_path_fnb + '/' + Gt[:sisupod] + '/' + Gt[:doc] + '/' + lng,
        po:        git_path_fnb + '/' + Gt[:po] + '/' + lng,
        pot:       git_path_fnb + '/' + Gt[:pot],
        conf:      git_path_fnb + '/' + Gt[:sisupod] + '/' + Gt[:conf],
        image:     git_path_fnb + '/' + Gt[:sisupod] + '/' + Gt[:image],
        audio:     git_path_fnb + '/' + Gt[:sisupod] + '/' + Gt[:audio],
        video:     git_path_fnb + '/' + Gt[:sisupod] + '/' + Gt[:video],
        conf:      git_path_fnb + '/' + Gt[:sisupod] + '/' + Gt[:conf]
      }
      SiSU_AO::Source.new(@opt,nil,@process).read                            # -m
    end
    def create_file_structure_git
      make_dir_fnb
      if program_found?
        git_init
      end
    end
    def read
      create_file_structure_git
      populate.sisusrc_files
      #if program_found?
      #  git_commit
      #end
      unless @opt.act[:quiet][:set]==:on
        (@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],
            'Git path',
            @git_path[:fnb]
          ).green_hi_blue
        : SiSU_Screen::Ansi.new(
            @opt.act[:color_state][:set],
            'Git path',
            @git_path[:fnb]
          ).green_title_hi
        if (@opt.act[:verbose][:set]==:on \
        || @opt.act[:verbose_plus][:set]==:on \
        || @opt.act[:maintenance][:set]==:on)
          SiSU_Screen::Ansi.new(
            @opt.act[:color_state][:set],
            "Git path",
            "#{@opt.fns} -> #{@git_path[:fnb]}"
          ).warn
        end
      end
    end
    def program_found?
      found=`whereis git`
      (found =~/bin\/git\b/) ? true : false
    end
    def make_dir_fnb
      FileUtils::mkdir_p(@git_path[:fnb]) \
        unless FileTest.directory?(@git_path[:fnb])
      FileUtils::mkdir_p(@git_path[:doc]) \
        unless FileTest.directory?(@git_path[:doc])
      FileUtils::mkdir_p(@git_path[:po]) \
        unless FileTest.directory?(@git_path[:po])
      FileUtils::mkdir_p(@git_path[:pot]) \
        unless FileTest.directory?(@git_path[:pot])
      FileUtils::mkdir_p(@git_path[:conf]) \
        unless FileTest.directory?(@git_path[:conf])
      FileUtils::mkdir_p(@git_path[:image]) \
        unless FileTest.directory?(@git_path[:image])
      #FileUtils::mkdir_p(@git_path[:audio]) \
      #  unless FileTest.directory?(@git_path[:audio])
      #FileUtils::mkdir_p(@git_path[:video]) \
      #  unless FileTest.directory?(@git_path[:video])
    end
    def git_init
      unless FileTest.directory?("#{@git_path[:fnb]}/.git")
        pwd=Dir.pwd
        Dir.chdir(@git_path[:fnb])
        system("git init ")
        Dir.chdir(pwd)
      end
    end
    def git_commit
      if program_found?
        if FileTest.directory?("#{@git_path[:fnb]}")
          pwd=Dir.pwd
          Dir.chdir(@git_path[:fnb])
          system("
            git add . \
            && git commit -a
          ")
          Dir.chdir(pwd)
        end
      end
    end
    def populate
      def identify_language_versions
        print __FILE__ + ':'
        p __LINE__
      end
      def copy_src_head
        if @opt.f_pth[:lng] \
        and File.exist?("#{@env.path.pwd}/#{@opt.f_pth[:lng]}/#{@opt.fns}")
          FileUtils::cp_r(
            "#{@env.path.pwd}/#{@opt.f_pth[:lng]}/#{@opt.fns}",
            @git_path[:doc]
          )
        elsif @opt.fns =~/\.ssm\.sst/
          ssm=@opt.fns.gsub(/\.ssm\.sst/,'.ssm')
          FileUtils::cp_r(
            "#{@env.path.pwd}/#{ssm}",
            @git_path[:doc]
          )
        elsif File.exist?("#{@env.path.pwd}/#{@opt.fns}")
          FileUtils::cp_r(
            "#{@env.path.pwd}/#{@opt.fns}",
            @git_path[:doc]
          )
        end
      end
      def copy_related_sst_ssi
        doc_import=[]
        @rgx_doc_import=/^<<\s(\S+?\.ss[ti])/
        file_array=IO.readlines(@opt.fns,'')
        file_array.each do |f|
          if f =~@rgx_doc_import
            doc_import = doc_import \
            + f.scan(@rgx_doc_import).uniq.flatten
          end
        end
        doc_import.each do |f|
          if @opt.f_pth[:lng]
            FileUtils::cp_r(
              "#{@env.path.pwd}/#{@opt.f_pth[:lng]}/#{f}",
              @git_path[:doc]
            )
          else
            FileUtils::cp_r(
              "#{@env.path.pwd}/#{f}",
              @git_path[:doc]
            )
          end
        end
      end
      def locate_parse_file
        composite_src=@opt.fns=~/\.ssm$/ ? true : false
        if composite_src \
        and not @opt.act[:ao][:set]==:on
          ##SiSU_Assemble::Composite.new(@opt).read
          #SiSU_AO::Source.new(@opt).read                                         # -m
          @env.processing_path.composite_file \
          + '/' \
          + @opt.fnb \
          + '.ssm.sst'
        elsif composite_src
          @env.processing_path.composite_file \
          + '/' \
          + @opt.fnb \
          + '.ssm.sst'
        else
          @env.path.pwd
          + '/' \
          + @opt.fns
        end
      end
      def read_composite
        #print __FILE__ + ':'
        #p __LINE__
      end
      def sisuyaml_rc
        sisurc=@env.path.sisurc_path
        if FileTest.file?(sisurc)
          FileUtils::cp_r(sisurc,@git_path[:conf])
        end
      end
      def read_src
        print __FILE__ + ':'
        p __LINE__
      end
      def composite_src?
        @opt.fns=~/\.ssm$/ ? true : false
      end
      def sisusrc_files
        populate.copy_src_head
        if composite_src?
          populate.copy_related_sst_ssi
        end
        #parse_file_name=locate_parse_file
        #parse_file=IO.readlines(parse_file_name,'')
        populate.sisuyaml_rc #(parse_file)
        #populate.extract_composite_source
        #populate.read_composite # or read_each_composite
        populate.identify_language_versions
      end
      self
    end
  end
end
__END__
@file.output_path.sisugit
#+END_SRC

** qrcode.rb

#+HEADER: :tangle "../lib/sisu/qrcode.rb"
#+BEGIN_SRC ruby
#<<sisu_document_header>>
module SiSU_QRcode
  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'                               # html.rb
  require_relative 'dp'                                 # dp.rb
    include SiSU_Param
  require_relative 'generic_parts'                      # generic_parts.rb
  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,@opt)
        @md=SiSU_Param::Parameters.new(@opt).get
        xbrowser=@env.program.web_browser
        browser=@env.program.console_web_browser
        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],
              'QR code',
              "#{xbrowser} #{url_html}"
            ).green_hi_blue
          : SiSU_Screen::Ansi.new(
              @opt.act[:color_state][:set],
              'QR code',
              "[#{@opt.f_pth[:lng_is]}] #{@opt.fns}"
            ).green_title_hi
          if (@opt.act[:verbose][:set]==:on \
          || @opt.act[:verbose_plus][:set]==:on \
          || @opt.act[:maintenance][:set]==:on)
            SiSU_Screen::Ansi.new(
              @opt.act[:color_state][:set],
              "#{browser} #{url_html}"
            ).grey_tab
          end
        end
        data=SiSU_HTML::Source::HTML_Environment.new(@particulars).tuned_file_instructions
        OutputInfo.new(@md).check_output(data)
      rescue
        SiSU_Errors::Rescued.new($!,$@,@opt.selections.str,@opt.fns).location do
          __LINE__.to_s + ':' + __FILE__
        end
      ensure
      end
    end
    private
    class OutputInfo <Source
      include SiSU_Parts_Generic
      def initialize(md)
        @manifest={ txt: [], txt_title: [] }
        @md,@fns=md,md.fns
        @env=SiSU_Env::InfoEnv.new(@md.fns,@md.opt)
        @fnb=@md.fnb
        @base_url="#{@env.url.root}/#{@fnb}"
        @f=SiSU_Env::FileOp.new(@md)
        @base_path=@f.output_path.manifest.dir
        @@dg ||=SiSU_Env::InfoEnv.new.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)
        @f.make_path(@f.output_path.qrcode.dir)
      end
      def spaces
        Ax[:spaces]
      end
      def output_metadata
        fn=@f.base_filename.manifest_txt
        mn=''
        if @md.opt.act[:maintenance][:set]==:on
          fn=@f.base_filename.manifest_txt
          manifest=@f.write_file.manifest_txt
        end
        @manifest[:txt].each do |x|
          x=x.gsub(/\\\\/m,"\n")
          puts x if @md.opt.act[:verbose_plus][:set]==:on
          manifest << x if @md.opt.act[:maintenance][:set]==:on
          mn += x
        end
        manifest.close if @md.opt.act[:maintenance][:set]==:on
        cmd=SiSU_Env::SystemCall.new(mn,@f.place_file.qrcode_md.dir,@md.opt.selections.str)
        cmd.qrencode
      end
      def output_metadata_short
        mn=''
        @manifest[:txt_title].each do |x|
          mn += x
        end
        cmd=SiSU_Env::SystemCall.new(mn,@f.place_file.qrcode_title.dir,@md.opt.selections.str)
        cmd.qrencode
      end
      def summarize(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] <<<<WOK
#{id} #{kb}
  #{the_text.url_open}#{url}/#{file}#{the_text.url_close}
WOK
      end
      def summarize_html_seg(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] <<<<WOK
#{id} #{kb}
  #{the_text.url_open}#{url}/#{file}#{the_text.url_close}
WOK
      end
      def summarize_sources(id,file,pth,rel,url)
        sys=SiSU_Env::SystemCall.new
        dgst=case @dg
        when :sha512
          (sys.sha512("#{pth}/#{file}")) #check
        when :md5
          (sys.md5("#{pth}/#{file}"))
        else
          (sys.sha256("#{pth}/#{file}"))
        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.selections.str,
            "#{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] <<<<WOK
#{id} #{dgst[1]} #{kb}
  #{the_text.url_open}#{url}/#{file}#{the_text.url_close}
WOK
      end
      def published_manifests?
        @f=SiSU_Env::FileOp.new(@md) #.base_filename
        @m=[]
        url=@f.output_path.base.url
        manifests={}
        mp,mn,mt=nil,nil,nil
        ln=SiSU_i18n::Languages.new.language.list
        Px[:lng_lst].each do |lc|
          if @env.output_dir_structure.by_language_code?
            mp="#{@f.output_path.base.dir}/#{lc}/manifest"
            mn="#{@md.fnb}.html"
            mt="#{mp}/#{mn}"
            mu="#{url}/#{lc}/manifest/#{mn}"
          elsif @env.output_dir_structure.by_filetype?
            mp="#{@f.output_path.base.dir}/manifest"
            mn="#{@md.fnb}.#{lc}.html"
            mt="#{mp}/#{mn}"
            mu="#{url}/manifest/#{mn}"
          else
            mp="#{@f.output_path.base.dir}/#{@md.fnb}"
            mn="sisu_manifest.#{lc}.html"
            mt="#{mp}/#{mn}"
            mu="#{url}/#{mn}"
          end
          if FileTest.directory?(mp) \
          &&  FileTest.file?(mt)
            lng=ln[lc][:t]
            manifests[lc]={ ln: lng, fn: mn }
            @m << { mu: mu, l: lng }
          end
        end
        #manifests
        @m=@m.uniq
        @m
      end
      def languages(id,file)
        flv=published_manifests?
        flv.each do |l|
          SiSU_Translate::Source.new(@md,@language,l[:n]).language_list
          @manifest[:txt] << "#{l[:mu]} #{l[:l]}\n"
        end
      end
      def published_languages(id,file)
        flv=published_manifests?
        flv.each do |l|
          @manifest[:txt] << "#{l[:l]}  #{the_text.url_open}#{l[:mu]}#{the_text.url_close}\n"
        end
      end
      def metadata(id,info)
        info=info.to_s.gsub(/#{Mx[:br_line]}/,"\n")
        @manifest[:txt] << %{#{id}: #{info}\n}
      end
      def md_title_info(id,info)
        info=info.to_s.gsub(/#{Mx[:br_line]}/,"\n")
        @manifest[:txt_title] << %{#{info}\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[:txt] << %{#{url} #{lnk} #{the_text.url_open}#{static}#{the_text.url_close}\n}
      end
      def output_tests
        if FileTest.file?(@f.place_file.html_segtoc.dir)==true
          pth=@f.output_path.html_seg.dir
          rel=@f.output_path.html_seg.rel_sm
          url=@f.output_path.html_seg.url
          id,file='HTML, table of contents (for segmented text)',@f.base_filename.html_segtoc
          summarize_html_seg(id,file,pth,rel,url)
        end
        if FileTest.file?(@f.place_file.html_scroll.dir)==true
          pth=@f.output_path.html_scroll.dir
          rel=@f.output_path.html_scroll.rel_sm
          url=@f.output_path.html_scroll.url
          id,file='HTML, full length document',@f.base_filename.html_scroll
          summarize(id,file,pth,rel,url)
        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
          id,file='HTML, (book type) index',@f.base_filename.html_book_index
          summarize(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
          id,file='HTML, concordance file',@f.base_filename.html_concordance
          summarize(id,file,pth,rel,url)
        end
        if FileTest.file?(@f.place_file.epub.dir)==true
          id,file='EPUB (Electronic Publication, e-book standard)',@f.base_filename.epub
          pth=@f.output_path.epub.dir
          rel=@f.output_path.epub.rel_sm
          url=@f.output_path.epub.url
          summarize(id,file,pth,rel,url)
        end
        if FileTest.file?("#{@f.output_path.pdf.dir}/#{@f.base_filename.pdf_p_letter}")==true
          pth=@f.output_path.pdf.dir
          rel=@f.output_path.pdf.rel_sm
          url=@f.output_path.pdf.url
          id,file="PDF, U.S. letter size, portrait/vertical","#{@f.base_filename.pdf_p_letter}"
          summarize(id,file,pth,rel,url)
        end
        if FileTest.file?("#{@f.output_path.pdf.dir}/#{@f.base_filename.pdf_l_letter}")==true
          pth=@f.output_path.pdf.dir
          rel=@f.output_path.pdf.rel_sm
          url=@f.output_path.pdf.url
          id,file="PDF, U.S. letter size, landscape/horizontal","#{@f.base_filename.pdf_l_letter}"
          summarize(id,file,pth,rel,url)
        end
        if FileTest.file?("#{@f.output_path.pdf.dir}/#{@f.base_filename.pdf_p_a4}")==true
          pth=@f.output_path.pdf.dir
          rel=@f.output_path.pdf.rel_sm
          url=@f.output_path.pdf.url
          id,file="PDF, A4 size, portrait/vertical","#{@f.base_filename.pdf_p_a4}"
          summarize(id,file,pth,rel,url)
        end
        if FileTest.file?("#{@f.output_path.pdf.dir}/#{@f.base_filename.pdf_l_a4}")==true
          pth=@f.output_path.pdf.dir
          rel=@f.output_path.pdf.rel_sm
          url=@f.output_path.pdf.url
          id,file="PDF, A4 size, landscape/horizontal","#{@f.base_filename.pdf_l_a4}"
          summarize(id,file,pth,rel,url)
        end
        if FileTest.file?("#{@f.output_path.pdf.dir}/#{@f.base_filename.pdf_p_a5}")==true
          pth=@f.output_path.pdf.dir
          rel=@f.output_path.pdf.rel_sm
          url=@f.output_path.pdf.url
          id,file="PDF, A5 (book) size, portrait/vertical","#{@f.base_filename.pdf_p_a5}"
          summarize(id,file,pth,rel,url)
        end
        if FileTest.file?("#{@f.output_path.pdf.dir}/#{@f.base_filename.pdf_l_a5}")==true
          pth=@f.output_path.pdf.dir
          rel=@f.output_path.pdf.rel_sm
          url=@f.output_path.pdf.url
          id,file="PDF, A5 (book) size, landscape/horizontal","#{@f.base_filename.pdf_l_a5}"
          summarize(id,file,pth,rel,url)
        end
        if FileTest.file?("#{@f.output_path.pdf.dir}/#{@f.base_filename.pdf_p_b5}")==true
          pth=@f.output_path.pdf.dir
          rel=@f.output_path.pdf.rel_sm
          url=@f.output_path.pdf.url
          id,file="PDF, B5 (book) size, portrait/vertical","#{@f.base_filename.pdf_p_b5}"
          summarize(id,file,pth,rel,url)
        end
        if FileTest.file?("#{@f.output_path.pdf.dir}/#{@f.base_filename.pdf_l_b5}")==true
          pth=@f.output_path.pdf.dir
          rel=@f.output_path.pdf.rel_sm
          url=@f.output_path.pdf.url
          id,file="PDF, B5 (book) size, landscape/horizontal","#{@f.base_filename.pdf_l_b5}"
          summarize(id,file,pth,rel,url)
        end
        if FileTest.file?("#{@f.output_path.pdf.dir}/#{@f.base_filename.pdf_p_legal}")==true
          pth=@f.output_path.pdf.dir
          rel=@f.output_path.pdf.rel_sm
          url=@f.output_path.pdf.url
          id,file="PDF, U.S. legal size, portrait/vertical","#{@f.base_filename.pdf_p_legal}"
          summarize(id,file,pth,rel,url)
        end
        if FileTest.file?("#{@f.output_path.pdf.dir}/#{@f.base_filename.pdf_l_legal}")==true
          pth=@f.output_path.pdf.dir
          rel=@f.output_path.pdf.rel_sm
          url=@f.output_path.pdf.url
          id,file="PDF, U.S. legal size, landscape/horizontal","#{@f.base_filename.pdf_l_legal}"
          summarize(id,file,pth,rel,url)
        end
        if FileTest.file?(@f.place_file.odt.dir)==true
          pth=@f.output_path.odt.dir
          rel=@f.output_path.odt.rel_sm
          url=@f.output_path.odf.url
          id,file='ODF:ODT (Open Document Format)',@f.base_filename.odt
          summarize(id,file,pth,rel,url)
        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
          id,file='ODF:ODT (Open Document Format)',@f.base_filename.odt
          id,file='XHTML',@f.base_filename.xhtml
          summarize(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
          id,file='XML SAX',@f.base_filename.xml_sax
          summarize(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
          id,file='XML DOM',@f.base_filename.xml_dom
          summarize(id,file,pth,rel,url)
        end
        if FileTest.file?(@f.place_file.txt.dir)==true
          id='Plaintext (UTF-8)'
          #id=if @md.opt.selections.str =~/a/ then 'Plaintext (Unix (UTF-8) with footnotes)'
          #elsif @md.opt.selections.str =~/e/ then 'Plaintext (Unix (UTF-8) with endnotes)'
          #elsif @md.opt.selections.str =~/A/ then 'Plaintext (dos (UTF-8) with footnotes)'
          #elsif @md.opt.selections.str =~/E/ then 'Plaintext (dos (UTF-8) with endnotes)'
          #else                         'Plaintext (UTF-8)'
          #end
          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(id,file,pth,rel,url)
        end
        if FileTest.file?("#{@base_path}/#{@md.fns}.tex")==true
          id,file='LaTeX (portrait)',"#{@md.fns}.tex"
          pth,rel,url='','',''
          summarize(id,file,pth,rel,url)
        end
        if FileTest.file?("#{@base_path}/#{@md.fns}.tex")==true
          id,file='LaTeX (landscape)',"#{@md.fns}.landscape.tex"
          pth,rel,url='','',''
          summarize(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
          id,file='Manpage',@f.base_filename.manpage
          summarize(id,file,pth,rel,url)
        end
        if FileTest.file?(@f.place_file.texinfo.dir)==true
          pth=@f.output_path.texinfo.dir
          rel=@f.output_path.texinfo.rel_sm
          url=@f.output_path.texinfo.url
          id,file='Texinfo',@f.base_filename.texinfo
          summarize(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
          id,file="Digest/DCC - Document Content Certificate (#{@dg})",@f.base_filename.hash_digest
          summarize(id,file,pth,rel,url)
        end
      end
      def published_versions
        id,file='Markup (SiSU source)',@md.fns
        #languages(id,file)
        published_languages(id,file)
      end
      def language_versions
        if FileTest.file?(@f.place_file.manifest.dir)==true
          id,file='Markup (SiSU source)',@md.fns
          published_languages(id,file)
        end
      end
      def source_tests
        if @md.fns =~/\.ssm\.sst$/                                                  #% 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
            url=@f.output_path.src.url
            id,file='Markup Composite File (SiSU source)',@f.base_filename.src
            summarize_sources(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
            url=@f.output_path.src.url
            id,file='Markup (SiSU source)',@f.base_filename.src
            summarize_sources(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
          url=@f.output_path.sisupod.url
          id,file='SiSU doc (zip)',@f.base_filename.sisupod
          summarize_sources(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
          id,file='SiSU pot',@f.base_filename.pot
          summarize_sources(id,file,pth,rel,url)
        end
      end
      def metadata_tests
        if defined? @md.title.full \
        and @md.title.full=~/\S+/
          id,info=@translate.full_title,@md.title.full
          #id,info=@translate.full_title,%{"#{@md.title.full}"}
          metadata(id,info)
          md_title_info(id,info)
        end
        if defined? @md.creator.author \
        and @md.creator.author=~/\S+/
          id,info=@translate.author,@md.creator.author
          metadata(id,info)
          md_title_info(id,info)
        end
        if defined? @md.creator.editor \
        and @md.creator.editor=~/\S+/
          id,info=@translate.editor,@md.creator.editor
          metadata(id,info)
        end
        if defined? @md.creator.contributor \
        and @md.creator.contributor=~/\S+/
          id,info=@translate.contributor,@md.creator.contributor
          metadata(id,info)
        end
        if defined? @md.creator.translator \
        and @md.creator.translator=~/\S+/
          id,info=@translate.translator,%{(#{@md.creator.translator})}
          metadata(id,info)
          md_title_info(id,info)
        end
        if defined? @md.creator.illustrator \
        and @md.creator.illustrator=~/\S+/
          id,info=@translate.illustrator,@md.creator.illustrator
          metadata(id,info)
        end
        if defined? @md.publisher \
        and @md.publisher=~/\S+/ #dc
          id,info=@translate.publisher,@md.publisher
          metadata(id,info)
        end
        if defined? @md.creator.prepared_by \
        and @md.creator.prepared_by=~/\S+/
          id,info=@translate.prepared_by,@md.creator.prepared_by
          metadata(id,info)
        end
        if defined? @md.creator.digitized_by \
        and @md.creator.digitized_by=~/\S+/
          id,info=@translate.digitized_by,@md.creator.digitized_by
          metadata(id,info)
        end
        if defined? @md.rights.all \
        and @md.rights.all=~/\S+/ #dc
          id,info=@translate.rights,@md.rights.all
          metadata(id,info)
        end
        if defined? @md.date.published
          if defined? @md.date.published \
          and @md.date.published=~/\S+/ #dc
            id,info=@translate.date,@md.date.published
            metadata(id,info)
            md_title_info(id,info)
          end
          if defined? @md.date.created \
          and @md.date.created=~/\S+/ #dc
            id,info=@translate.date_created,@md.date.created
            metadata(id,info)
          end
          if defined? @md.date.issued \
          and @md.date.issued=~/\S+/ #dc
            id,info=@translate.date_issued,@md.date.issued
            metadata(id,info)
          end
          if defined? @md.date.available \
          and @md.date.available=~/\S+/ #dc
            id,info=@translate.date_available,@md.date.available
            metadata(id,info)
          end
          if defined? @md.date.modified \
          and @md.date.modified=~/\S+/ #dc
            id,info=@translate.date_modified,@md.date.modified
            metadata(id,info)
          end
          if defined? @md.date.valid \
          and @md.date.valid=~/\S+/ #dc
            id,info=@translate.date_valid,@md.date.valid
            metadata(id,info)
          end
        end
        if defined? @md.title.language \
        and @md.title.language=~/\S+/
          id,info=@translate.language,@md.title.language
          metadata(id,info)
        end
        if defined? @md.original.language \
        and @md.original.language=~/\S+/
          id,info=@translate.language_original,@md.original.language
          metadata(id,info)
        end
        if defined? @md.classify.subject \
        and @md.classify.subject=~/\S+/
          id,info=@translate.subject,@md.classify.subject
          metadata(id,info)
        end
        if defined? @md.classify.keywords \
        and @md.classify.keywords=~/\S+/
          id,info=@translate.keywords,@md.classify.keywords
          metadata(id,info)
        end
        if defined? @md.classify.loc \
        and @md.classify.loc=~/\S+/
          id,info=@translate.cls_loc,@md.classify.loc
          metadata(id,info)
        end
        if defined? @md.classify.dewey \
        and @md.classify.dewey=~/\S+/
          id,info=@translate.cls_dewey,@md.classify.dewey
          metadata(id,info)
        end
        if defined? @md.notes.description \
        and @md.notes.description=~/\S+/
          id,info=@translate.description,@md.notes.description
          metadata(id,info)
        end
        if defined? @md.notes.abstract \
        and @md.notes.abstract=~/\S+/
          id,info=@translate.abstract,@md.notes.abstract
          metadata(id,info)
        end
        if defined? @md.notes.comment \
        and @md.notes.comment=~/\S+/
          id,info=@translate.comments,@md.notes.comment
          metadata(id,info)
        end
        if defined? @md.notes.coverage \
        and @md.notes.coverage=~/\S+/
          id,info=@translate.coverage,@md.notes.coverage
          metadata(id,info)
        end
        if defined? @md.notes.relation \
        and @md.notes.relation=~/\S+/
          id,info=@translate.relation,@md.notes.relation
          metadata(id,info)
        end
        #if defined? @md.notes.source \
        #and @md.notes.source=~/\S+/
        #  id,info=@translate.source,@md.notes.source
        #  metadata(id,info)
        #end
        #if defined? @md.notes.history \
        #and @md.notes.history=~/\S+/
        #  id,info=@translate.history,@md.notes.history
        #  metadata(id,info)
        #end
        if defined? @md.notes.type \
        and @md.notes.type=~/\S+/ #dc
          id,info=@translate.type,@md.type
          metadata(id,info)
        end
        if defined? @md.notes.format \
        and @md.notes.format=~/\S+/
          id,info=@transate.format,@md.notes.format
          metadata(id,info)
        end
        if defined? @md.notes.prefix_a \
        and @md.notes.prefix_a=~/\S+/
          id,info=@translate.prefix_a,@md.notes.prefix_a
          metadata(id,info)
        end
        if defined? @md.notes.prefix_b \
        and @md.notes.prefix_b=~/\S+/
          id,info=@translate.prefix_b,@md.notes.prefix_b
          metadata(id,info)
        end
        if defined? @md.original.source \
        and @md.original.source=~/\S+/
          id,info=@translate.source,@md.original.source
          metadata(id,info)
        end
        if defined? @md.identifier.oclc \
        and @md.identifier.oclc=~/\S+/
          id,info=@translate.cls_oclc,@md.identifier.oclc
          @manifest[:txt] << %{#{id}:\n}
          @manifest[:txt] << %{#{info}\n}
        end
        if defined? @md.identifier.isbn \
        and @md.identifier.isbn=~/\S+/
          id,info=@translate.cls_isbn,@md.identifier.isbn
          metadata(id,info)
        end
        if defined? @md.topic_register_array \
        and @md.topic_register_array.length > 0
          @manifest[:txt] << %{#{@translate.topic_register}:\n}
          @md.topic_register_array.each do |t|
            t.each_with_index do |st,i|
              if st.is_a?(Array)
                st.each do |v|
                  @manifest[:txt] << %{#{spaces*i}#{v}\n}
                end
              else @manifest[:txt] << %{#{spaces*i}#{st}\n}
              end
            end
          end
        end
        if @md.fns
          id,info=@translate.sourcefile,@md.fns
          metadata(id,info)
        end
        if @md.en[:mismatch] > 0
          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(id,info)
        end
        if @md.wc_words
          id,info=@translate.word_count,@md.wc_words
          metadata(id,info)
        end
        if @md.dgst
          id,info="#{@translate.sourcefile_digest} (#{@dg})",@md.dgst[1]
          metadata(id,info)
        end
        if @md.sc_number
          id,info=@translate.sc_number,@md.sc_number
          metadata(id,info)
        end
        if @md.sc_date
          id,info=@translate.sc_date,"#{@md.sc_date} at #{@md.sc_time}"
          metadata(id,info)
        end
      end
      def check_output(data)
        begin
          @f=SiSU_Env::FileOp.new(@md) #.base_filename
          url=@f.output_path.base.url
          @en_manifest=if @env.output_dir_structure.by_language_code?
            "#{url}/en/manifest/#{@md.fnb}.html"
          elsif @env.output_dir_structure.by_filetype?
            "#{url}/manifest/#{@md.fnb}.#{@md.opt.lng}.html"
          else
            "#{url}/sisu_manifest.#{@md.opt.lng}.html"
          end
          @manifest[:txt] <<<<WOK
#{@translate.manifest_description_metadata}
  #{the_text.url_open}#{@en_manifest}#{the_text.url_close}
WOK
          metadata_tests
          @manifest[:txt_title] <<<<WOK
  #{the_text.url_open}#{@en_manifest}#{the_text.url_close}
WOK
          source_tests
          @manifest[:txt] <<<<WOK
#{@translate.language_version_list}
WOK
          language_versions
          output_metadata
          output_metadata_short
        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

** relaxng.rb

#+HEADER: :tangle "../lib/sisu/relaxng.rb"
#+BEGIN_SRC ruby
#<<sisu_document_header>>
module SiSU_Relaxng
  require_relative 'se'                                 # se.rb
  class RelaxNG
    def gpl3_or_later
      @gpl3_or_later =<<RELAXNG
=begin

 * Name: SiSU generated relaxng

 * Description: generated relaxng for SiSU
   (SiSU is a framework for document structuring, publishing and search)

 * Author: Ralph Amissah

 * Copyright: (C) 1997 - 2013 Ralph Amissah All Rights Reserved.

 * License: GPL 3 or later:

   SiSU, a framework for document structuring, publishing and search

   Copyright: (C) 1997 - 2013 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/licenses/gpl.html>
   [http://www.gnu.org/licenses/gpl.html]

 * SiSU uses:
   * Standard SiSU markup syntax,
   * Standard SiSU meta-markup syntax, and the
   * Standard SiSU object citation numbering and system

 * Homepages:
   [https://www.sisudoc.org]
   [https://git.sisudoc.org]

 * Ralph Amissah
   [ralph@amissah.com]
   [ralph.amissah@gmail.com]

=end
RELAXNG
    end
    def rnc_name
      def output_sax
        'sisu_sax.rnc'
      end
      def output_dom
        'sisu_dom.rnc'
      end
      def output_xhtml
        'sisu_xhtml.rnc'
      end
      def input_sax
        'sisu_sax.rnc'
      end
      def input_dom
        'sisu_dom.rnc'
      end
      def input_node
        'sisu_node.rnc'
      end
      self
    end
    def rng_name
      def output_sax
        'sisu_sax.rng'
      end
      def output_dom
        'sisu_dom.rng'
      end
      def output_xhtml
        'sisu_xhtml.rng'
      end
      def input_sax
        'sisu_sax.rng'
      end
      def input_dom
        'sisu_dom.rng'
      end
      def input_node
        'sisu_node.rng'
      end
      self
    end
    def xsd_name
      def output_sax
        'sisu_sax.xsd'
      end
      def output_dom
        'sisu_dom.xsd'
      end
      def output_xhtml
        'sisu_xhtml.xsd'
      end
      def input_sax
        'sisu_sax.xsd'
      end
      def input_dom
        'sisu_dom.xsd'
      end
      def input_node
        'sisu_node.xsd'
      end
      self
    end
    def rnc_sisu_object_input
      @relaxng =<<RELAXNG
#%% sisu object model: input
#{gpl3_or_later}
#%% definitions
# dublin core:
element-semantic =
  element semantic {
  # dublin core:
  element title { text }
  & element creator { text }?
  & element subject { text }?
  & element description { text }?
  & element publisher { text }?
  & element contributor { text }?
  & element date { text }?
  & element date.created { text }?
  & element date.issued { text }?
  & element date.available { text }?
  & element date.valid { text }?
  & element date.modified { text }?
  & element type { text }?
  & element format { text }?
  & element identifier { text }?
  & element source { text }?
  & element relation { text }?
  & element coverage { text }?
  & element rights { text }?
  & element keywords { text }?
  # extended semantic metadata:
  & attribute subtitle { text }?
  & attribute illustrator { text }?
  & attribute translator { text }?
  & attribute prepared_by { text }?
  & attribute digitized_by { text }?
  & attribute language { text }?
  & attribute language.original { text }?
  & attribute classify.pg { text }?
  & attribute classify.isbn { text }?
  & attribute classify.dewey { text }?
  & attribute classify.loc { text }?
  & attribute prefix.a { text }?
  & attribute prefix.b { text }?
  & attribute suffix { text }?
  & attribute comments { text }?
  & attribute abstract { text }?
  # & attribute information { text }?
  & attribute contact { text }?
  & attribute links { text }?
  }
element-processing =
  element processing {
  attribute structure { text }?
  & attribute level { text }?
  & attribute markup { text }?
  & attribute bold { text }?
  & attribute italics { text }?
  & attribute papersize { text }?
  & attribute vocabulary { text }?
  & element date_scheme { text }?
  & element date.issued.scheme { text }?
  & element date.available.scheme { text }?
  & element date.valid.scheme { text }?
  & element date.modified.scheme { text }?
  }?
element-head =
  element head {
    # processing instructions, and semantic data, distinguish?:
    element metadata {
      element title { text },
      element file { text },
      element generator { text },
      element-semantic,
      element-processing
    }+
  }
# body text/contents
# includes <b> <i> <u> <del> <ins> <indent1> <bullet> etc.
element-txt =
  element txt {
    text*
    & element b { text }*
    & element i { text }*
    & element u { text }*
    & element ins { text }*
    & element del { text }*
  }
element-endnote =
  element endnote {
    element number { text },
    element note { element-txt }+
  }+
element-para =
  element para {
    # attribute paragraph_format { text },
    element-txt+
    & element-endnote?
  }
element-external_space =
  element external_space {
    # ignored by sisu, provide program needs
    element program {
      # e.g. kdissert
      element name { text },
      element xpos { text },
      element ypos { text },
      element font { text },
      element outline_color { text },
      element text_color { text },
      element comment { text }
    }*
  }*,
#%% structure
  element document {
    # document head:
    element-head,
    # document body:
    element body {
      # object, a unit of text, usually a paragraph with any associated endnotes
      element node {
        element structure {
          # structure document using either node:heading levels or node:heading relationships:
          # (i) sisu default uses node:heading levels (1-6 or A-C,1-3) to build document structure
          element level { text }?,
          # (ii) sisu alternatively could use node:heading relationship information to build document structure
          element node.id { text },
          element node.parent { text },
          element node.child { text }*
        },
        element node.objects {
          element object.heading {
            # nametag used only in headings, especially important for segmented html
            element nametag { text },
            element-para
          },
          element object.para {
            element-para
          }*
        }+,
        element-external_space
      }+
    }
  }
RELAXNG
    end
    def rnc_sisu_object_ao
      @relaxng =<<RELAXNG
#%% sisu object model: ao
#{gpl3_or_later}
#%% definitions
# dublin core:
element-semantic =
  element semantic {
  # dublin core:
  element title { text }
  & element creator { text }?
  & element subject { text }?
  & element description { text }?
  & element publisher { text }?
  & element contributor { text }?
  & element date { text }?
  & element date.created { text }?
  & element date.issued { text }?
  & element date.available { text }?
  & element date.valid { text }?
  & element date.modified { text }?
  & element type { text }?
  & element format { text }?
  & element identifier { text }?
  & element source { text }?
  & element relation { text }?
  & element coverage { text }?
  & element rights { text }?
  & element keywords { text }?
  # extended semantic metadata:
  & attribute subtitle { text }?
  & attribute illustrator { text }?
  & attribute translator { text }?
  & attribute prepared_by { text }?
  & attribute digitized_by { text }?
  & attribute language { text }?
  & attribute language.original { text }?
  & attribute classify.pg { text }?
  & attribute classify.isbn { text }?
  & attribute classify.dewey { text }?
  & attribute classify.loc { text }?
  & attribute prefix.a { text }?
  & attribute prefix.b { text }?
  & attribute suffix { text }?
  & attribute comments { text }?
  & attribute abstract { text }?
  # & attribute information { text }?
  & attribute contact { text }?
  & attribute links { text }?
  }
element-processing =
  element processing {
  attribute structure { text }?
  & attribute level { text }?
  & attribute markup { text }?
  & attribute bold { text }?
  & attribute italics { text }?
  & attribute papersize { text }?
  & attribute vocabulary { text }?
  & element date_scheme { text }?
  & element date.issued.scheme { text }?
  & element date.available.scheme { text }?
  & element date.valid.scheme { text }?
  & element date.modified.scheme { text }?
  }?
element-head =
  element head {
    # processing instructions, and semantic data, distinguish?:
    element metadata {
      element title { text },
      element file { text },
      element generator { text },
      element-semantic,
      element-processing
    }+
  }
# body text/contents
# includes <b> <i> <u> <del> <ins> <indent1> <bullet> etc.
element-txt =
  element txt {
    text*
    & element b { text }*
    & element i { text }*
    & element u { text }*
    & element ins { text }*
    & element del { text }*
  }
element-checksum.endnote = element checksum.clean { text }
element-endnote =
  element endnote {
    element number { text },
    element note { element-txt }+,
    element-checksum.endnote
  }+
element-checksum.para =
  element checksum.para {
    element checksum.clean { text },
    element checksum.marked { text }
  }
element-para =
  element para {
    # attribute paragraph_format { text },
    element-txt+
    & element-endnote?
  }
element-object =
  element object {
    element-para,
    element-checksum.para
  }
# object citation number, unique sequential number for objects:
element-ocn = element ocn { text }
element-object_structure_summary =
  element-ocn,
  # type: heading level value 1 -6, or normal text
  element type { text },
  # type number: sequential number for designated type
  element type_number { text },
  # type category: sequential number for designated category, e.g. sequentially counting all headers
  element category_number { text }
element-external_space =
  element external_space {
    # ignored by sisu, provide program needs
    element program {
      # e.g. kdissert
      element name { text },
      element xpos { text },
      element ypos { text },
      element font { text },
      element outline_color { text },
      element text_color { text },
      element comment { text }
    }*
  }*,
#%% structure
  element document {
    # document head:
    element-head,
    # document body:
    element body {
      # object, a unit of text, usually a paragraph with any associated endnotes
      element node {
        element structure {
          # structure document using either node:heading levels or node:heading relationships:
          # (i) sisu default uses node:heading levels (1-6 or A-C,1-3) to build document structure
          element level { text }?,
          # (ii) sisu alternatively could use node:heading relationship information to build document structure
          element node.id { text },
          element node.parent { text },
          element node.child { text }*
        },
        element node.objects {
          element object.heading {
            element-object_structure_summary,
            # nametag used only in headings, especially important for segmented html
            element nametag { text },
            element-object
          },
          element object.para {
            element-object_structure_summary,
            element-object
          }*
        }+,
        element-external_space
      }+
    }
  }
RELAXNG
    end
    def rnc_model_output_sax
      @relaxng =<<RELAXNG
#% sax output model, part of SiSU and distributed under the same license
default namespace = ""
namespace xl = "http://www.w3.org/1999/xlink"
start =
  element document {
    element head {
      (br
       | meta
       | element creator {
           attribute class { xsd:NCName },
           (text
            | element link {
                attribute xl:href { xsd:anyURI },
                attribute xl:type { xsd:NCName },
                xsd:anyURI
              })+
         }
       | element date {
           attribute class { xsd:NCName },
           xsd:NMTOKEN
         }
       | element date_available {
           attribute class { xsd:NCName },
           xsd:NMTOKEN
         }
       | element date_created {
           attribute class { xsd:NCName },
           xsd:NMTOKEN
         }
       | element date_issued {
           attribute class { xsd:NCName },
           xsd:NMTOKEN
         }
       | element date_modified {
           attribute class { xsd:NCName },
           xsd:NMTOKEN
         }
       | element date_valid {
           attribute class { xsd:NCName },
           xsd:NMTOKEN
         }
       | element keywords {
           attribute class { xsd:NCName },
           text
         }
       | element language {
           attribute class { xsd:NCName },
           xsd:NCName
         }
       | element meta { xsd:NMTOKEN }
       | element rights {
           attribute class { xsd:NCName },
           (text | link)+
         }
       | element source {
           attribute class { xsd:NCName },
           text
         }
       | element structure {
           attribute class { xsd:NCName },
           text
         }
       | element subject {
           attribute class { xsd:NCName },
           text
         }
       | element title {
           attribute class { xsd:NCName },
           text
         }
       | element type {
           attribute class { xsd:NCName },
           text
         }
       | element source_control {
           (br
            | meta
            | element sc {
                attribute class { xsd:NCName },
                text
              })+
         })+
    },
    element body {
      element object {
        attribute id { text },
        element ocn {
          text
        },
        element text {
          attribute class { xsd:NCName },
          (text
           | b
           | br
           | del
           | en
           | i
           | link
           | sub
           | sup
           | u
           | element image {
               attribute alt { text }?,
               attribute height { xsd:integer }?,
               attribute width { xsd:integer }?,
               attribute xl:actuate { xsd:NCName },
               attribute xl:href { text },
               attribute xl:show { xsd:NCName },
               attribute xl:type { xsd:NCName }
             })+
        }?,
        element table {
          attribute align { xsd:NCName },
          attribute bgcolor { xsd:NCName },
          attribute border { xsd:integer },
          attribute cellpadding { xsd:integer },
          attribute summary { text },
          attribute width { text },
          element tr {
            element td {
              attribute valign { xsd:NCName },
              attribute width { text },
              (text | b | i)+
            }+
          }+
        }?,
        element endnote {
          attribute notenumber { xsd:integer }?,
          attribute symbol { text }?,
          (element number { xsd:integer }
           | element symbol { text }),
          element note {
            (text
             | b
             | br
             | del
             | i
             | link
             | sup
             | u
             | element em { xsd:NCName }
             | element sub { xsd:NCName })+
          }
        }*
      }+
    }
  }
meta = element meta { text }
br = element br { empty }
b = element b { (text | en | i | link | sup)+ }
i = element i { (text | b | br | sup)+ }
en = element en { text }
sub = element sub { xsd:NCName }
sup = element sup { xsd:NCName }
link =
  element link {
    attribute xl:href { xsd:anyURI },
    attribute xl:type { xsd:NCName },
    (xsd:anyURI | text | b | i | sup)+
  }
u = element u { (text | b | i)+ }
del = element del { (text | b | i | link)+ }
RELAXNG
    end
    def rnc_model_output_dom
      @relaxng =<<RELAXNG
#% dom output model, part of SiSU and distributed under the same license
default namespace = ""
namespace xl = "http://www.w3.org/1999/xlink"
start =
  element document {
    element head {
      element header {
        meta,
        (element creator { text }
         | element date { xsd:NMTOKEN }
         | element date_available { xsd:NMTOKEN }
         | element date_created { xsd:NMTOKEN }
         | element date_issued { xsd:NMTOKEN }
         | element date_modified { xsd:NMTOKEN }
         | element date_valid { xsd:NMTOKEN }
         | element keywords { text }
         | element language { xsd:NCName }
         | element rights { (text | link)+ }
         | element source { text }
         | element structure { text }
         | element subject { text }
         | element title { text }
         | element type { text }
         | element source_control {
             (br
              | meta
              | element sc {
                  attribute class { xsd:NCName },
                  text
                })+
           })
      }+
    },
    element body {
      element heading1 {
        heading,
        contents1*,
        element heading2 {
          heading,
          contents1*,
          element heading3 {
            heading,
            element contents1 {
              heading,
              content,
              element contents2 {
                heading,
                content,
                element contents3 { heading, content }*
              }*
            }+
          }*
        }*
      }+
    }
  }
meta = element meta { text }
br = element br { empty }
heading = element heading { object }
contents1 =
  element contents1 {
    heading,
    content,
    element contents2 {
      heading,
      content,
      element contents3 { heading, content }*
    }*
  }
content = element content { object* }
object =
  element object {
    attribute id { xsd:integer },
    element ocn { text },
    element nametag { text }?,
    (element table {
       attribute align { xsd:NCName },
       attribute bgcolor { xsd:NCName },
       attribute border { xsd:integer },
       attribute cellpadding { xsd:integer },
       attribute summary { text },
       attribute width { text },
       element tr {
         element td {
           attribute valign { xsd:NCName },
           attribute width { text },
           (text | b | i)+
         }+
       }+
     }
     | element text {
         attribute class { xsd:NCName }?,
         (text
          | b
          | del
          | endnote
          | i
          | link
          | element br { empty }
          | element endnote {
              element number { xsd:integer },
              element note { (text | i | link)+ }
            }
          | element image {
              attribute height { xsd:integer },
              attribute width { xsd:integer },
              attribute xl:actuate { xsd:NCName },
              attribute xl:href { text },
              attribute xl:show { xsd:NCName },
              attribute xl:type { xsd:NCName }
            }
          | element sub { text })+
       })
  }
i = element i { text }
b = element i { text }
u = element u { (text | b | i)+ }
sub = element sub { xsd:NCName }
sup = element sup { xsd:NCName }
del = element del { (text | b | i | link)+ }
link =
  element link {
    attribute xl:href { xsd:anyURI },
    attribute xl:type { xsd:NCName },
    xsd:anyURI
  }
endnote =
  element endnote {
    (element number { xsd:integer }
     | element symbol { text }),
    element note {
      (text
       | b
       | br
       | del
       | i
       | link
       | sub
       | sup
       | u
       | element em { xsd:NCName }
       | element sub { xsd:NCName })+
    }
  }
RELAXNG
    end
    def rnc_model_output_xhtml #not done
      @relaxng =<<RELAXNG
#% xhtml output model, part of SiSU and distributed under the same license
default namespace = ""
namespace xl = "http://www.w3.org/1999/xlink"
start =
  element document {
    element head {
      (br
       | element creator {
           attribute class { xsd:NCName },
           (text
            | element link {
                attribute xl:href { xsd:anyURI },
                attribute xl:type { xsd:NCName },
                xsd:anyURI
              })+
         }
       | element date {
           attribute class { xsd:NCName },
           xsd:NMTOKEN
         }
       | element date_available {
           attribute class { xsd:NCName },
           xsd:NMTOKEN
         }
       | element date_created {
           attribute class { xsd:NCName },
           xsd:NMTOKEN
         }
       | element date_issued {
           attribute class { xsd:NCName },
           xsd:NMTOKEN
         }
       | element date_modified {
           attribute class { xsd:NCName },
           xsd:NMTOKEN
         }
       | element date_valid {
           attribute class { xsd:NCName },
           xsd:NMTOKEN
         }
       | element language {
           attribute class { xsd:NCName },
           xsd:NCName
         }
       | element keywords {
           attribute class { xsd:NCName },
           text
         }
       | element meta {
           attribute content { text }?,
           attribute http-equiv { xsd:NCName }?,
           text
         }
       | element rights {
           attribute class { xsd:NCName },
           (text | link)+
         }
       | element source {
           attribute class { xsd:NCName },
           text
         }
       | element structure {
           attribute class { xsd:NCName },
           text
         }
       | element subject {
           attribute class { xsd:NCName },
           text
         }
       | element title {
           attribute class { xsd:NCName },
           text
         }
       | element type {
           attribute class { xsd:NCName },
           xsd:NCName
         })+
    },
    element body {
      element object {
        attribute id { xsd:integer },
        (element endnote {
           attribute notenumber { xsd:integer }?,
           attribute symbol { text }?,
           (text
            | b
            | br
            | del
            | i
            | link
            | sup
            | u
            | element em { xsd:NCName }
            | element sub { xsd:NCName })+
         }
         | element ocn { text }
         | element text {
             attribute class { xsd:NCName },
             (text
              | b
              | br
              | del
              | en
              | i
              | link
              | sup
              | u
              | element image {
                  attribute alt { text }?,
                  attribute height { xsd:integer }?,
                  attribute width { xsd:integer }?,
                  attribute xl:actuate { xsd:NCName },
                  attribute xl:href { text },
                  attribute xl:show { xsd:NCName },
                  attribute xl:type { xsd:NCName }
                }
              | element sub { text })+
           })+,
        element table {
          attribute align { xsd:NCName },
          attribute bgcolor { xsd:NCName },
          attribute border { xsd:integer },
          attribute cellpadding { xsd:integer },
          attribute summary { text },
          attribute width { text },
          element tr {
            element td {
              attribute valign { xsd:NCName },
              attribute width { text },
              (text | b | i)+
            }+
          }+
        }?
      }+
    }
  }
br = element br { empty }
en = element en { text }
sup = element sup { xsd:NCName }
i = element i { (text | b | br | sup)+ }
link =
  element link {
    attribute xl:href { xsd:anyURI },
    attribute xl:type { xsd:NCName },
    (text | b | i | sup)+
  }
b = element b { (text | en | i | link | sup)+ }
u = element u { (text | b | i)+ }
del = element del { (text | b | i | link)+ }
RELAXNG
    end
    def rnc_model_input_sax
      @relaxng =<<RELAXNG
#% sax input model, part of SiSU and distributed under the same license
default namespace = ""
start =
  element document {
    element head {
      element header {
        attribute class { xsd:NCName },
        (element creator { text }
         | element date { xsd:NMTOKEN }
         | element date.available { xsd:NMTOKEN }
         | element date.created { xsd:NMTOKEN }
         | element date.issued { xsd:NMTOKEN }
         | element date.modified { xsd:NMTOKEN }
         | element date.valid { xsd:NMTOKEN }
         | element italicize { text }
         | element language { xsd:NCName }
         | element links { text }
         | element markup { text }
         | element rights { text }
         | element subject { text }
         | element title { text }
         | element type { xsd:NCName }
         | element vocabulary { xsd:NCName })
      }+
    },
    element body {
      element object {
        element text {
          attribute class { xsd:NCName },
          (text
           | b
           | i
           | element endnote {
               attribute symbol { xsd:NCName },
               (text
                | i
                | element br { empty })+
             }
           | element u { i }
           | element image.path { text })+
        }?
      }+
    }
  }
i = element i { text }
b = element b { text }
RELAXNG
    end
    def rnc_model_input_dom
      @relaxng =<<RELAXNG
#% dom input model, part of SiSU and distributed under the same license
default namespace = ""
start =
  element document {
    element head {
      element header {
        attribute class { xsd:NCName },
        (element creator { text }
         | element date { xsd:NMTOKEN }
         | element date.available { xsd:NMTOKEN }
         | element date.created { xsd:NMTOKEN }
         | element date.issued { xsd:NMTOKEN }
         | element date.modified { xsd:NMTOKEN }
         | element date.valid { xsd:NMTOKEN }
         | element italicize { text }
         | element language { xsd:NCName }
         | element links { text }
         | element markup { text }
         | element rights { text }
         | element subject { text }
         | element title { text }
         | element type { xsd:NCName }
         | element vocabulary { xsd:NCName })
      }+
    },
    element body {
      element heading1 {
        heading,
        element heading2 {
          heading,
          contents1+,
          element heading3 { heading, contents1+ }+
        }
      }
    }
  }
heading = element heading { object }
contents1 =
  element contents1 {
    heading,
    content,
    element contents2 {
      heading,
      content,
      element contents3 { heading, content }*
    }*
  }
object =
  element object {
    element text {
      (text
       | italic
       | element bold { xsd:NMTOKEN }
       | element endnote {
           element symbol { text }?,
           element note {
             (text
              | italic
              | element br { empty })+
           }
         }
       | element underscore { italic }
       | element image.path { text }
       | element italic { text })+
    }
  }
italic = element italic { text }
content = element content { object+ }
RELAXNG
    end
    def rnc_model_input_node
      @relaxng =<<RELAXNG
#% node input model, part of SiSU and distributed under the same license
default namespace = ""
start =
  element document {
    element head {
      element header {
        attribute class { xsd:NCName },
        (element creator { text }
         | element date { xsd:NMTOKEN }
         | element date.available { xsd:NMTOKEN }
         | element date.created { xsd:NMTOKEN }
         | element date.issued { xsd:NMTOKEN }
         | element date.modified { xsd:NMTOKEN }
         | element date.valid { xsd:NMTOKEN }
         | element italicize { (text | i)+ }
         | element language { xsd:NCName }
         | element links { text }
         | element markup { text }
         | element rights { text }
         | element subject { text }
         | element title { text }
         | element type { xsd:NCName }
         | element vocabulary { xsd:NCName })
      }+
    },
    element body {
      element object {
        (element text {
           attribute class { xsd:NCName },
           (text
            | b
            | i
            | element br { empty }
            | element endnote {
                attribute symbol { xsd:NCName },
                (text | i)+
              }
            | element image.path { text }
            | element sub { text })+
         }
         | (element ocn { empty },
            element table {
              attribute align { xsd:NCName },
              attribute bgcolor { xsd:NCName },
              attribute border { xsd:integer },
              attribute cellpadding { xsd:integer },
              attribute summary { text },
              attribute width { text },
              element tr {
                element td {
                  attribute valign { xsd:NCName },
                  attribute width { text },
                  (text | b)+
                }+
              }+
            })),
        element node {
          element id { xsd:integer },
          element parent { xsd:integer },
          element offspring { text }?
        }
      }+
    }
  }
b = element b { text }
i = element i { text }
RELAXNG
    end
  end
end
__END__
needs updating
#+END_SRC

** remote.rb

#+HEADER: :tangle "../lib/sisu/remote.rb"
#+BEGIN_SRC ruby
#<<sisu_document_header>>
module SiSU_Remote
  require_relative 'se'                                 # se.rb
    include SiSU_Env
  class Put
    def initialize(opt)
      @opt=opt
      @dir=SiSU_Env::InfoEnv.new(@opt.fns)
      @put=(@opt.fns =~/\.ssm\.sst$/) \
      ? opt.fns.gsub(/(.+)?\.ssm\.sst$/,'\1.ssm')
      : opt.fns
      @remote=SiSU_Env::InfoRemote.new(opt)
    end
    def rsync
      SiSU_Screen::Ansi.new(
        @opt.act[:color_state][:set],
        'Remote placement ->',
        @put
      ).dark_grey_title_hi unless @opt.act[:quiet][:set]==:on
      @remote.rsync.document
    end
    def rsync_base
      SiSU_Screen::Ansi.new(
        @opt.act[:color_state][:set],
        'Remote placement ->',
        'rsync'
      ).dark_grey_title_hi unless @opt.act[:quiet][:set]==:on
      @remote.rsync.site_base
    end
    def rsync_base_sync
      SiSU_Screen::Ansi.new(
        @opt.act[:color_state][:set],
        'Remote placement ->',
        'rsync and sync'
      ).dark_grey_title_hi unless @opt.act[:quiet][:set]==:on
      @remote.rsync.site_base_sync
    end
    def rsync_sitemaps
      SiSU_Screen::Ansi.new(
        @opt.act[:color_state][:set],
        'Remote placement sitemaps ->',
        'rsync'
      ).dark_grey_title_hi unless @opt.act[:quiet][:set]==:on
      @remote.rsync_sitemaps
    end
    def rsync_harvest
      SiSU_Screen::Ansi.new(
        @opt.act[:color_state][:set],
        'Remote placement metadata harvest ->',
        'rsync_harvest'
      ).dark_grey_title_hi unless @opt.act[:quiet][:set]==:on
      @remote.rsync.site_harvest
    end
    def scp
      SiSU_Screen::Ansi.new(
        @opt.act[:color_state][:set],
        'Remote placement ->',
        @put
      ).dark_grey_title_hi unless @opt.act[:quiet][:set]==:on
      @remote.scp.document
    end
    def scp_base
      SiSU_Screen::Ansi.new(
        @opt.act[:color_state][:set],
        'Remote placement of base site ->',
        'excluding images'
      ).dark_grey_title_hi unless @opt.act[:quiet][:set]==:on
      @remote.scp.site_base
    end
    def scp_base_all
      SiSU_Screen::Ansi.new(
        @opt.act[:color_state][:set],
        'Remote placement ->',
        'complete'
      ).dark_grey_title_hi unless @opt.act[:quiet][:set]==:on
      @remote.scp.site_base_all
    end
  end
  class Get
    def initialize(opt,get_s)
      @opt,@get_s=opt,get_s
      @msg,@msgs='',nil
      @tell=lambda {
        SiSU_Screen::Ansi.new(@opt.act[:color_state][:set],
        @msg,
        "#{@msgs.inspect if @msgs}")
      }
    end
    def fns
      begin
        require 'open-uri'
        require 'pp'
      rescue LoadError
        SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia).
          error('open-uri or pp NOT FOUND (LoadError)')
      end
      require_relative 'ao_composite'                   # ao_composite.rb
      @rgx_image=/(?:^|[^_\\])\{\s*(\S+?\.(?:png|jpg|gif))/
      threads=[]
      for requested_page in @get_s
        re_fnb=/((?:https?|file):\/\/[^\/ ]+?\/[^\/ ]+?)\/\S+?\/([^\/]+?)\.ss(t)/ #revisit and remove DO
        threads << Thread.new(requested_page) do |url|
          open(url) do |f|
            raise "#{url} not found" unless f
            base_uri,fnb=re_fnb.match(url)[1..2] if re_fnb
            imagedir=base_uri + '/_sisu/image' #check on
            downloaded_file=File.new("#{fnb}.-sst",'w+')
            image_download_url=SiSU_Assemble::RemoteImage.new.image(imagedir)
            images=[]
            f.collect.each do |r|                            # work area
              unless r =~/^%+\s/
                if r !~/^%+\s/ \
                and r =~@rgx_image
                  images << r.scan(@rgx_image).uniq
                end
              end
              downloaded_file << r
            end
            if images \
            and images.length > 1
              images=images.flatten.uniq
              images.delete_if {|x| x =~/https?:\/\// }
              images=images.sort
              @msg,@msgs='downloading images:', [ images.join(',') ]
              @tell.call.warn unless @opt.act[:quiet][:set]==:on
              image_info=image_download_url + images
              SiSU_Assemble::RemoteImage.new.download_images(image_info)
              #SiSU_Assemble::RemoteImage.new.download_images(image_download_url,images)
              @msg,@msgs='downloading done',nil
              @tell.call.warn unless @opt.act[:quiet][:set]==:on
            end
            downloaded_file.close
          end
        end
      end
      threads.each {|thr| thr.join} if threads #and threads.length > 0
    end
    def sisupod
      get_p=@get_s
      if get_p.length > 0                                     #% remote sisupod
        begin
          require 'net/http'
        rescue LoadError
          SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia).
            error('net/http NOT FOUND (LoadError)')
        end
        for requested_pod in get_p
          pod_info=RemoteDownload.new(requested_pod)
          Net::HTTP.start(pod_info.pod.site) do |http|
            resp=http.get("#{pod_info.pod.path}/#{pod_info.pod.name_source}")
            open(pod_info.pod.name,'wb') do |file|
              file.write(resp.body)
             end
          end
        end
      end
    end
  end
  class RemoteDownload
    def initialize(requested_file)
      @requested_file=requested_file
    end
    def pod
      re_p_div=/https?:\/\/([^\/]+)(\/\S+)\/(sisupod\.(?:txz|zip)|\S+?(?:\.ss[mt]\.(?:txz|zip))?|[^\/]+?\.ssp)$/
      re_p=/(sisupod\.(?:txz|zip)|\S+?\.ss[mt]\.(?:txz|zip)?|[^\/]+?\.ssp)$/
      if @requested_file =~ re_p_div
        @site,@pth,@pod= re_p_div.match(@requested_file).captures
      elsif @requested_file =~ re_p
        @pod=re_p.match(@requested_file).captures.join
      end
      def site
        @site
      end
      def path
        @pth
      end
      def dir_stub
        re_p_stub=/.+?([^\/]+)$/
        re_p_stub.match(path).captures.join if path
      end
      def name_source
        @pod
      end
      def name
        name_source
      end
      self
    end
  end
end
__END__
#+END_SRC

** rexml.rb

#+HEADER: :tangle "../lib/sisu/rexml.rb"
#+BEGIN_SRC ruby
#<<sisu_document_header>>
module SiSU_Rexml
  # load XML file for REXML parsing
  begin
    require 'rexml/document' \
      if FileTest.directory?("#{RbConfig::CONFIG['rubylibdir']}/rexml") #RbConfig::CONFIG['sitedir']
  rescue LoadError
    SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia).
      error('rexml/document NOT FOUND (LoadError)')
  end
  require_relative 'dp'                                 # dp.rb
    include SiSU_Param
  require_relative 'se'                                 # se.rb
    include SiSU_Env
  class Rexml
    begin
      require 'rexml/document' \
        if FileTest.directory?("#{RbConfig::CONFIG['rubylibdir']}/rexml") #RbConfig::CONFIG['sitedir']
    rescue LoadError
      SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia).
        error('rexml/document NOT FOUND (LoadError)')
    end
    def initialize(md,fno)
      @md,@fno=md,fno
      @env=SiSU_Env::InfoEnv.new(@md.fns)
      @prog=SiSU_Env::InfoProgram.new #(md.fns) #if md
      if File.file?(@fno)
        @fnap=@fno #index.xml causes problems with index.html in server config
      end
      @e_head='/document/head'
      @e_title='/document/head/title'
      @e_object='/document/body/object'
      @e_ocn='/document/body/object/ocn'
      @e_text='/document/body/object/text'
      @e_endnote='/document/body/object/endnote'
    end
    def xml
      begin
        if FileTest.file?(@fnap)
          if @prog.rexml !=false \
          and FileTest.directory?('/usr/lib/ruby/1.8/rexml/') #note values can be other than true
            xmlfile=IO.readlines(@fnap,'').join
            begin
              @xmldoc=REXML::Document.new xmlfile
              SiSU_Screen::Ansi.new(
                @md.opt.act[:color_state][:set],
                'invert',
                'REXML',
                "XML document #{@fnap} loaded"
              ).colorize unless @md.opt.act[:quiet][:set]==:on
              if (@opt.act[:verbose][:set]==:on \
              || @opt.act[:verbose_plus][:set]==:on)
                @xmldoc.elements.each(@e_head) do |e|
                  SiSU_Screen::Ansi.new(
                    @md.opt.act[:color_state][:set],
                    'brown',
                    e
                  ).colorize unless @md.opt.act[:quiet][:set]==:on
                end
              end
            rescue REXML::ParseException
              puts 'broken XML'
            end
          end
        else
          SiSU_Screen::Ansi.new(
            @md.opt.act[:color_state][:set],
            'fuchsia',
            "File Not Found #{xmlfile}",
            'requested XML processing skipped'
          ).colorize unless @md.opt.act[:quiet][:set]==:on
          exit
        end
      rescue
        SiSU_Errors::Rescued.new($!,$@,@md.opt.selections.str,@md.fns).location do
          __LINE__.to_s + ':' + __FILE__
        end
      ensure
      end
    end
  end
end
__END__
 misc
e.each do |element|
  element.each do |child|
    if child.is_a?(REXML::Text)
      puts "Text: #{child.to_s.inspect}"
    else
      puts "SubElement: #{child.name}"
    end
  end
end
#+END_SRC

** sitemaps.rb

#+HEADER: :tangle "../lib/sisu/sitemaps.rb"
#+BEGIN_SRC ruby
#<<sisu_document_header>>
module SiSU_Sitemaps
  require_relative 'dp'                                 # dp.rb
    include SiSU_Param
  require_relative 'se'                                 # se.rb
    include SiSU_Env
  require_relative 'xml_shared'                         # xml_shared.rb
    include SiSU_XML_Munge
  class Source
    def initialize(opt)
      @opt=opt
    end
    def read
      songsheet
    end
    def songsheet
      begin
        @sys=SiSU_Env::SystemCall.new
        fn_set_lang=SiSU_Env::StandardiseLanguage.new(@opt.lng).language
        @fn=SiSU_Env::EnvCall.new(@opt.fns).lang(fn_set_lang[:c])
        if @opt.act[:sitemap][:set]==:on
          @md=SiSU_Param::Parameters.new(@opt).get
          @trans=SiSU_XML_Munge::Trans.new(@md) #check @md is required
          @env=SiSU_Env::InfoEnv.new(@md.fns)
#         @file=SiSU_Env::FileOp.new(@md)
          @rdf=SiSU_XML_Tags::RDF.new(@md)
          @fnb_utf8_xml=@md.fnb.dup
          @trans.char_enc.utf8(@fnb_utf8_xml) \
            if @sys.locale =~/utf-?8/i
          output_map(sitemap)
        elsif @opt.selections.str =~/--sitemaps/
          @sitemap_idx_fn='sitemapindex.xml'
          @env=SiSU_Env::InfoEnv.new
          output_idx(sitemap_index)
          SiSU_Screen::Ansi.new(
            @opt.act[:color_state][:set],
            'sitemap index:',
            "#{@env.path.output}/#{@sitemap_idx_fn}"
          ).result unless @opt.act[:quiet][:set]==:on
        end
      rescue
        SiSU_Errors::Rescued.new($!,$@,@opt.cmd,@opt.fns).location do
          __LINE__.to_s + ':' + __FILE__
        end
      ensure
      end
    end
    def make_file(path,filename)
      (File.writable?("#{path}/.")) \
      ? (File.new("#{path}/#{filename}",'w+'))
      : (SiSU_Screen::Ansi.new(
           '',
           "is the file or directory writable?, could not create #{filename}"
         ).warn)
    end
    def output_map(sitemap)
      path=@md.file.output_path.sitemaps.dir
      filename=@fn[:sitemap]
      touch_path=@md.file.output_path.sitemaps.dir
      touch_filename=@fn[:sitemap_touch]
      SiSU_Env::FileOp.new(@md).make_path(path)
      file=SiSU_Env::FileOp.new(@md).make_file(path,filename)
      file << sitemap
      if FileTest.file?("#{touch_path}/#{touch_filename}")
        FileUtils::rm("#{touch_path}/#{touch_filename}")
      end
    end
    def output_idx(sitemap)
      path=@env.path.output
      filename=@sitemap_idx_fn
      make_path(path)
      file=make_file(path,filename)
      file << sitemap
    end
    def sitemap_index
      sitemap_files=Dir.glob("#{@env.path.sitemaps}/sitemap_*.xml")
      sitemap_idx=[]
      sitemap_idx << <<WOK
<?xml version="1.0" encoding="UTF-8"?>
<sitemapindex xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemaps/0.9
   http://www.sitemaps.org/schemas/sitemaps/sitemap.xsd"
     xmlns="http://www.sitemaps.org/schemas/sitemapindex/0.9">
WOK
      sitemap_files.each do |s|
        f=s.gsub(/.+?\/sitemap_([^\/]+?)\.xml$/,'\1')
        @trans.char_enc.utf8(f) \
          if @sys.locale =~/utf-?8/i
sitemap_idx << <<WOK
  <sitemap>
    <loc>#{@env.path.url.remote}/#{f}/sitemap.xml</loc>
  </sitemap>
WOK
      end
      sitemap_idx << <<WOK
</sitemapindex>
WOK
      sitemap_idx.join
    end
    def sitemap
      if defined? @md.date.modified \
      and @md.date.modified=~/\d{4}-\d{2}-\d{2}/
        sitemap_date_modified
      else sitemap_no_date
      end
    end
    def sitemap_date_modified
<<WOK
<?xml version='1.0' encoding='UTF-8'?>
<urlset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemaps/0.9
  http://www.sitemaps.org/schemas/sitemaps/sitemap.xsd"
  xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
#{@rdf.comment_xml}
  <url>
    <loc>#{@env.path.url.remote}/#{@fnb_utf8_xml}/#{@fn[:toc]}</loc>
    <lastmod>#{@md.date.modified}</lastmod>
    <changefreq>monthly</changefreq>
    <priority>0.7</priority>
  </url>
  <url>
    <loc>#{@env.path.url.remote}/#{@fnb_utf8_xml}/#{@fn[:doc]}</loc>
    <lastmod>#{@md.date.modified}</lastmod>
    <priority>0.5</priority>
  </url>
  <url>
    <loc>#{@env.path.url.remote}/#{@fnb_utf8_xml}/#{@fn[:manifest]}</loc>
    <lastmod>#{@md.date.modified}</lastmod>
    <priority>0.5</priority>
  </url>
</urlset>
WOK
    end
    def sitemap_no_date
<<WOK
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
#{@rdf.comment_xml}
  <url>
    <loc>#{@env.path.url.remote}/#{@fnb_utf8_xml}/#{@fn[:toc]}</loc>
    <changefreq>monthly</changefreq>
    <priority>0.7</priority>
  </url>
  <url>
    <loc>#{@env.path.url.remote}/#{@fnb_utf8_xml}/#{@fn[:doc]}</loc>
    <priority>0.5</priority>
  </url>
  <url>
    <loc>#{@env.path.url.remote}/#{@fnb_utf8_xml}/#{@fn[:manifest]}</loc>
    <priority>0.5</priority>
  </url>
</urlset>
WOK
    end
  end
end
__END__
,* sanitize xml, pass through filter to ensure is valid - done but needs testing
,* remote placement of sitemaps --sitemaps -R (probably makes more sense than doing against -Y [filename/wildcard]) - done but needs testing
,* gzip sitemaps - not before testing / after testing
,* issue with master documnts, naming and mapping, check multilingual

<!-- Document processing information:
     * Generated by: SiSU 0.48.6 of 2006w45/6 (20061111)
     * Ruby version: ruby 1.8.5 (2006-08-25) [i486-linux]
     *
     * Last Generated on: Sat Nov 18 15:28:08 +0000 2006
     * SiSU https://git.sisudoc.org
-->
#+END_SRC

** termsheet.rb

#+HEADER: :tangle "../lib/sisu/termsheet.rb"
#+BEGIN_SRC ruby
#<<sisu_document_header>>
require_relative 'se'                                   # se.rb
require_relative 'dp'                                   # dp.rb
  include SiSU_Param
@do,@done,@used,@html_output,@txt_input,@txt_output,@@report=Array.new(7){[]}
@@info=nil
@c=0
@cX=SiSU_Screen::Ansi.new('yes').cX
@done << "\n#{@cX.blue_hi}#{@cX.black}Summary#{@cX.off*2}"
def talent(termsheet,flag)
  @@info=nil
  @@info=termsheet.gsub(/(.+?)\.termsheet\.rb/,'../facility_data/\1.html')
  @env=SiSU_Env::InfoEnv.new
  @dir_fd="#{@env.path.output}/facility_data"
  FileUtils::mkdir_p(@dir_fd) unless FileTest.directory?(@dir_fd)==true
  html_output=[]
  case termsheet
  when /.+?\.(termsheet)\.rb$/
    @basename=termsheet[/(.+?)\.termsheet\.rb/, 1]
    @standard_form={}
    require termsheet
    include Termsheet
    @standard_form=Termsheet::StandardForms.new.standardforms
    puts %{\n#{@@cX.yellow_hi}#{@@cX.black}From#{@@cX.off*2}: #{@@cX.grey_hi}#{@@cX.black}#{@basename}.termsheet.rb#{@@cX.off*3}\n\n}
    @standard_form.each do |k,v|
      @c+=1
      require v
      puts %{\n#{@@cX.blue_hi}#{@@cX.black}Producing the following#{@@cX.off*2}: #{@@cX.green}#{@basename}.#{k}#{@@cX.off}\n\n}
      @done << %{\n\t#{@@cX.grey}Documents generated#{@@cX.off}: #{@@cX.cyan}#{@basename}.#{k}#{@@cX.off}\n}
      @used << %{\n\t#{@@cX.grey}Using#{@@cX.off}: #{@@cX.ruby}#{v}#{@@cX.off}\n}
      html_output=<<WOK
<br /><a href="../#{@basename}.#{k}/landscape.pdf">
<img border="0" width="18" height="15" src="../_sisu/image/b_pdf.png" alt="pdf landscape"></a>&nbsp;
<a href="../#{@basename}.#{k}/portrait.pdf">
<img border="0" width="15" height="18" src="../_sisu/image/b_pdf.png" alt="pdf portrait"></a>&nbsp;
<a href="../#{@basename}.#{k}/sisu_manifest.html">#{@basename}.#{k}.sisu_manifest.html</a>
WOK
      @html_output << html_output
      @txt_input << %{\n\tForm #{@c}: <url:#{Dir.pwd}/#{v}>\n\t        |#{Dir.pwd}/#{v}|@|^|\n}
      @txt_output << %{\n\t#{k}: |../#{@basename}.#{k}/sisu_manifest.html|@|^|\n}
      @report_file_i=File.new("#{@dir_fd}/#{@basename}.txt",'w+')
      @report_file_o=File.new("#{@dir_fd}/#{@basename}.html",'w+')
      @filename_new=File.new("#{@basename}.#{k}.sst",'w+')
      @do << %{#{k}}
      @filename_new << @document
        # "require v" pulls in the composite @document
        # "termsheet" having all the variables required to complete the standard form @document
      @filename_new.close
    end
    @do.each do |x|
      system %{sisu -Nhwpo #{@basename}.#{x}.sst\n}
    end
  else print "not processed --> ", termsheet, "\n"
  end
  @done << %{\n\t#{@@cX.green}Summary:#{@@cX.off} #{@@cX.blue}#{@env.path.output}/facility_data/#{@basename}.html#{@@cX.off}\n}
  @done << %{\n\t#{@@cX.grey}From details provided in#{@@cX.off}: #{@@cX.green}#{termsheet}#{@@cX.off}\n}
  terms=%{\nTermsheet: <url:#{Dir.pwd}/#{termsheet}>\n           |#{Dir.pwd}/#{termsheet}|@|^|\n}
  @report_file_i << "<url:all.txt>\n|all.txt|@|^|\n" << terms << "\nForms:\n" << @txt_input  << "\nOutput Files\n" << @txt_output
  @report_file_o << %{<a href="toc.html">^</a><br />\n} << @html_output
  @@report << @done << @used << "\n"
  @done,@used=[],[]
end
require_relative 'dp'                                   # dp.rb
@argv=$*
@proc="#{@argv[0].to_s}"
if @proc =~  /^-?[wft]/
  @argv.shift
  @argv.each do |termsheet|
    talent(termsheet,@proc)
  end
end
@env=SiSU_Env::InfoEnv.new
@dir_fd="#{@env.path.output}/facility_data"
@url="#{@env.url.webserv}/facility_data"
@@report << %{\n#{@@cX.grey}See#{@@cX.off}: #{@@cX.blue}#{@dir_fd}/all.txt\t#{@dir_fd}/toc.html\t#{@dir_fd}/#{@@cX.off}\n\n#{@@cX.grey}See#{@@cX.off}: #{@@cX.blue}#{@url}/all.txt\t#{@url}/toc.html\t#{@url}/#{@@cX.off}\n\n}
puts @@report
File.unlink("#{@dir_fd}/all.txt") if FileTest.file?("#{@dir_fd}/all.txt")
File.unlink("#{@dir_fd}/toc.html") if FileTest.file?("#{@dir_fd}/toc.html")
summary_file=File.new("#{@dir_fd}/all.txt",'w+')
summary_html=File.new("#{@dir_fd}/toc.html",'w+')
ls_txt=%x{ls #{@dir_fd}/*.txt}
report_thlnk=[]
ls_txt.scan(/.+/)
ls_txt.each {|x| report_thlnk << x.gsub!(/#{@dir_fd}\/(.+)/,"<url:\\1>\n|\\1|@|^|")}
report_thlnk.join("\n")
ls_html=%x{ls #{@dir_fd}/*.html}
report_html=[]
ls_html.split(/.+/)
ls_html.each {|x| report_html << x.gsub!(/#{@dir_fd}\/(.+)/,'<a href="\1">\1</a><br />')}
report_html.join("\n")
summary_file << "#{report_thlnk}"
summary_html << "#{report_html}"
__END__
,** NOTE wrapper makes little sense without additional components, additional
   sample files must be provided - (saved till later as may confuse)
,*** bits
sisu -t x_bank.and.*
e.g. sisu -t x_bank.and.*.termsheet.rb
e.g. sisu_termsheet.rb -t x_bank.and.c*.termsheet.rb
program calls upon termsheet file with extension termsheet.rb
termsheet.rb calls upon relevant standard form files (to be used) with extension .sForm.rb
there is also a standard_terms.rb file - with terms/details that are  constant
the file produced is named after the termsheet.rb with that extension replaced with .er30
from there scribbler.rb is called upon its usual metaVerse html and pdf  creation
! :-)
to test run
termsheet.rb -f dev.export.import.trade.facility.termsheet.rb
the term sheet calls the standard form or template that is to be run against it.
#+END_SRC

** update.rb

#+HEADER: :tangle "../lib/sisu/update.rb"
#+BEGIN_SRC ruby
#<<sisu_document_header>>
module SiSU_UpdateControlFlag
  require_relative 'se'                                 # se.rb
    include SiSU_Env
  include SiSU_Param
  class Check
    def initialize(opt)
      @opt=opt
      @md=SiSU_Param::Parameters.new(@opt).get
    end
    def read
      begin
        @env=SiSU_Env::InfoEnv.new(@md.fns)
        out=@env.path.output
        base_path="#{out}/#{@md.fnb}"
        SiSU_Screen::Ansi.new(
          @md.opt.act[:color_state][:set],
          'Checking previous output',
          base_path
        ).green_hi_blue unless @md.opt.act[:quiet][:set]==:on
        SetCF.new(@md).set_flags
      rescue
        SiSU_Errors::Rescued.new($!,$@,@md.opt.selections.str,@md.fns).location do
          __LINE__.to_s + ':' + __FILE__
        end
      ensure
      end
    end
    private
    class SetCF
      def initialize(md)
        @md=md
        @env=SiSU_Env::InfoEnv.new(@md.fns)
        out=@env.path.output
        @base_path="#{out}/#{@md.fnb}"
        @pdf_fn=SiSU_Env::FileOp.new(@md).base_filename
      end
      def set_flags #-mNhwpoabxXyv
        flag='-v'
        if FileTest.file?("#{@md.file.output_path.txt.dir}/#{@md.file.base_filename.txt}")==true
          flag=flag + 'a'
        end
        if FileTest.file?("#{@md.file.output_path.html_seg.dir}/#{@md.file.base_filename.html_seg}")==true \
        or FileTest.file?("#{@md.file.output_path.html_scroll.dir}/#{@md.file.base_filename.html_scroll}")==true
          flag=flag + 'h'
        end
        if FileTest.file?("#{@md.file.output_path.xhtml.dir}/#{@md.file.base_filename.xhtml}")==true
          flag=flag + 'b'
        end
        if FileTest.file?("#{@md.file.output_path.xml_sax.dir}/#{@md.file.base_filename.xml_sax}")==true
          flag=flag + 'x'
        end
        if FileTest.file?("#{@md.file.output_path.xml_dom.dir}/#{@md.file.base_filename.xml_dom}")==true
          flag=flag + 'X'
        end
        if FileTest.file?("#{@md.file.output_path.epub.dir}/#{@md.file.base_filename.epub}")==true
          flag=flag + 'e'
        end
        if FileTest.file?("#{@md.file.output_path.odt.dir}/#{@md.file.base_filename.odt}")==true
          flag=flag + 'o'
        end
        if FileTest.file?("#{@md.file.output_path.pdf.dir}/#{@pdf_fn.pdf_p_a4}")==true \
        or FileTest.file?("#{@md.file.output_path.pdf.dir}/#{@pdf_fn.pdf_l_a4}")==true \
        or FileTest.file?("#{@md.file.output_path.pdf.dir}/#{@pdf_fn.pdf_p_letter}")==true \
        or FileTest.file?("#{@md.file.output_path.pdf.dir}/#{@pdf_fn.pdf_l_letter}")==true
          flag=flag + 'p'
        end
        if FileTest.file?("#{@md.file.output_path.html_concordance.dir}/#{@md.file.base_filename.html_concordance}")==true
          flag=flag + 'w'
        end
        if FileTest.file?("#{@md.file.output_path.digest.dir}/#{@md.file.base_filename.digest}")==true
          flag=flag + 'N'
        end
        if FileTest.file?("#{@md.file.output_path.src.dir}/#{@md.file.base_filename.src}")==true
          flag=flag + 's'
        end
        if FileTest.file?("#{@md.file.output_path.sisupod.dir}/#{@md.file.base_filename.sisupod}")==true
          flag=flag + 'S'
        end
        puts flag
        flag
      end
    end
  end
end
__END__
#+END_SRC

** urls.rb

#+HEADER: :tangle "../lib/sisu/urls.rb"
#+BEGIN_SRC ruby
#<<sisu_document_header>>
module SiSU_Urls
  require_relative 'se_hub_particulars'                 # se_hub_particulars.rb
    include SiSU_Particulars
  require_relative 'se'                                 # se.rb
    include SiSU_Env; include SiSU_Screen
  class Source
    attr_reader :opt
    def initialize(opt)
      @opt=opt
    end
    def read
      begin
        SiSU_Urls::OutputUrls.new(@opt).songsheet if @opt.fnb
      rescue
        SiSU_Errors::Rescued.new($!,$@,@opt.selections.str).location do
          __LINE__.to_s + ':' + __FILE__
        end
      ensure
      end
    end
  end
  class OutputUrls
    attr_reader :fns,:fnb,:act,:dir,:m_regular,:u
    def initialize(opt)
      @opt=opt
      @particulars=SiSU_Particulars::CombinedSingleton.instance.get_env_md(opt)
      if @particulars.is_a?(NilClass)
        if @opt.act[:verbose_plus][:set]==:on \
        or @opt.act[:maintenance][:set]==:on
          SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia).
            mark("@particulars is NilClass, acceptable e.g. for --harvest")
        end
        exit
      end
      @selections=@opt.selections.str
      @act=@opt.act
      @md=@particulars.md
      @env=@particulars.env
      @fnb=@env.fnb
      fn_set_lang=SiSU_Env::StandardiseLanguage.new(@opt.lng).language
      @fnl=@env.i18n.lang_filename(fn_set_lang[:c])
      @fn=SiSU_Env::EnvCall.new(@opt.fns).lang(fn_set_lang[:c])
      @m_regular=/(.+?)\.(?:(?:-|ssm\.)?sst|ssm)$/
      @prog=@env.program
    end
    def songsheet
      begin
        (@opt.act[:urls_all][:set]==:on) \
        ? urls_all \
        : (urls_select unless @opt.act[:quiet][:set]==:on)
      rescue
        SiSU_Errors::Rescued.new($!,$@,@opt.selections.str,@opt.fns).location do
          __LINE__.to_s + ':' + __FILE__
        end
      ensure
      end
    end
    def show
      def report(x)
        SiSU_Screen::Ansi.new(
          @opt.act[:color_state][:set],
          "[#{@opt.f_pth[:lng_is]}]",
          x[:cmd],
          x[:viewer] + ' ' \
          + x[:f_pth]
        ).result
      end
      def maintenance(x)
        if @opt.act[:maintenance][:set]==:on
          SiSU_Screen::Ansi.new(
            @opt.act[:color_state][:set],
            "[#{@opt.f_pth[:lng_is]}]",
            x[:cmd],
            x[:p_pth]
          ).maintenance
        end
      end
      self
    end
    def report_info
      def dal
        {
          cmd: '--ao',
          p_pth: @env.processing_path.ao + '/' \
          + @opt.fns + '.meta',
          fn: 'ao',
         }
      end
      def hash_digests
        {
          cmd: '--hash-digests (sha512/sha256/md5)',
          viewer: @prog.web_browser,
          f_pth: @md.file.output_path.hash_digest.dir + '/' \
          + @md.file.base_filename.hash_digest,
          fn: @fn[:digest],
         }
      end
      def text
        def txt
          {
            cmd: '--txt',
            viewer: @prog.web_browser,
            f_pth: @md.file.output_path.txt.dir + '/' \
            + @md.file.base_filename.txt,
            fn: @fn[:plain],
           }
        end
        def asciidoc
          {
            cmd: '--asciidoc',
            viewer: @prog.web_browser,
            f_pth: @md.file.output_path.asciidoc.dir + '/' \
            + @md.file.base_filename.asciidoc,
            fn: @fn[:txt_asciidoc],
           }
        end
        def markdown
          {
            cmd: '--markdown',
            viewer: @prog.web_browser,
            f_pth: @md.file.output_path.markdown.dir + '/' \
            + @md.file.base_filename.markdown,
            fn: @fn[:txt_markdown],
           }
        end
        def rst
          {
            cmd: '--rst',
            viewer: @prog.web_browser,
            f_pth: @md.file.output_path.rst.dir + '/' \
            + @md.file.base_filename.rst,
            fn: @fn[:txt_rst],
           }
        end
        def textile
          {
            cmd: '--textile',
            viewer: @prog.web_browser,
            f_pth: @md.file.output_path.textile.dir + '/' \
            + @md.file.base_filename.textile,
            fn: @fn[:txt_textile],
           }
        end
        def orgmode
          {
            cmd: '--orgmode',
            viewer: @prog.web_browser,
            f_pth: @md.file.output_path.orgmode.dir + '/' \
            + @md.file.base_filename.orgmode,
            fn: @fn[:txt_orgmode],
           }
        end
        self
      end
      def html
        def seg
          {
            cmd: '--html-seg',
            viewer: @prog.web_browser,
            f_pth: @md.file.output_path.html_seg.dir + '/' \
            + @md.file.base_filename.html_segtoc,
            p_pth: @env.processing_path.tune + '/' \
            + @md.fns + '.tune',
            fn: @fn[:toc],
           }
        end
        def scroll
          {
            cmd: '--html-scroll',
            viewer: @prog.web_browser,
            f_pth: @md.file.output_path.html_scroll.dir + '/' \
            + @md.file.base_filename.html_scroll,
            p_pth: @env.processing_path.tune + '/' \
            + @md.fns + '.tune',
            fn: @fn[:doc],
           }
        end
        def concordance
          {
            cmd: '--concordance',
            viewer: @prog.web_browser,
            f_pth: @md.file.output_path.html_concordance.dir + '/' \
            + @md.file.base_filename.html_concordance,
            fn: @fn[:concordance],
           }
        end
        self
      end
      def xhtml
        def xhtml
          {
            cmd: '--xhtml',
            viewer: @prog.web_browser,
            f_pth: @md.file.output_path.xhtml.dir + '/' \
            + @md.file.base_filename.xhtml,
            p_pth: @env.processing_path.tune + '/' \
            + @md.fns + '.tune',
            fn: @fn[:xhtml],
           }
        end
        def epub
          {
            cmd: '--epub',
            viewer: @prog.epub_viewer,
            f_pth: @md.file.output_path.epub.dir + '/' \
            + @md.file.base_filename.epub,
            p_pth: @env.processing_path.epub + '/' \
            + Ep[:d_oebps] + '/' \
            + 'index.xhtml',
            fn: @fn[:epub],
           }
        end
        self
      end
      def xml
        def odt
          {
            cmd: '--odt (ODF:ODT)',
            viewer: @prog.odf_viewer,
            f_pth: @md.file.output_path.odt.dir + '/' \
            + @md.file.base_filename.odt,
            p_pth: @env.processing_path.odf + '/' \
            + @opt.fns + '/' \
            + 'odt/content.xml',
            fn: @fn[:odf],
           }
        end
        def docbook
          {
            cmd: '--docbook',
            viewer: @prog.web_browser,
            f_pth: @md.file.output_path.xml_docbook_book.dir + '/' \
            + @md.file.base_filename.xml_docbook_book,
            fn: @fn[:xml_docbook_book],
           }
        end
        def fictionbook
          {
            cmd: '--fictionbook',
            viewer: @prog.web_browser,
            f_pth: @md.file.output_path.xml_fictionbook.dir + '/' \
            + @md.file.base_filename.xml_fictionbook,
            fn: @fn[:xml_fictionbook],
           }
        end
        def sax
          {
            cmd: '--xml-sax',
            viewer: @prog.web_browser,
            f_pth: @md.file.output_path.xml_sax.dir + '/' \
            + @md.file.base_filename.xml_sax,
            fn: @fn[:sax],
           }
        end
        def dom
          {
            cmd: '--xml-dom',
            viewer: @prog.web_browser,
            f_pth: @md.file.output_path.xml_dom.dir + '/' \
            + @md.file.base_filename.xml_dom,
            fn: @fn[:dom],
           }
        end
        def scaffold_sisu
          {
            cmd: '--xml-scaffold-sisu',
            viewer: @prog.web_browser,
            f_pth: @md.file.output_path.xml_scaffold_structure_sisu.dir + '/' \
            + @md.file.base_filename.xml_scaffold_structure_sisu,
            fn: @fn[:xml_scaffold_structure_sisu],
           }
        end
        def scaffold_collapse
          {
            cmd: '--xml-scaffold-collapse',
            viewer: @prog.web_browser,
            f_pth: @md.file.output_path.xml_scaffold_structure_collapse.dir + '/' \
            + @md.file.base_filename.xml_scaffold_structure_collapse,
            fn: @fn[:xml_scaffold_structure_collapse],
           }
        end
        self
      end
      def json
        {
          cmd: '--js (json)',
          viewer: @prog.web_browser,
          f_pth: @md.file.output_path.json.dir + '/' \
          + @md.file.base_filename.json,
          fn: @fn[:json],
        }
      end
      def pdf
        def landscape
          {
            cmd: '--pdf (landscape)',
            viewer: @prog.pdf_viewer,
            f_pth: @md.file.output_path.pdf.dir + '/' \
            + @md.file.base_filename.pdf_l \
            + @md.papersize_array[0] + '.pdf',
            p_pth: @env.processing_path.tex + '/' \
            + @opt.fns.gsub(/~/,'-') + '.' \
            + @md.papersize_array[0] \
            + '.landscape.tex',
            fn: @fn[:pdf_l],
           }
        end
        def portrait
          {
            cmd: '--pdf (portrait)',
            viewer: @prog.pdf_viewer,
            f_pth: @md.file.output_path.pdf.dir + '/' \
            + @md.file.base_filename.pdf_p \
            + @md.papersize_array[0] + '.pdf',
            p_pth: @env.processing_path.tex + '/' \
            + @opt.fns.gsub(/~/,'-') + '.' \
            + @md.papersize_array[0] \
            + '.tex',
            fn: @fn[:pdf_p],
           }
        end
        self
      end
      def manpage
        {
          cmd: '--manpage',
          viewer: @prog.manpage_viewer,
          f_pth: @md.file.output_path.manpage.dir + '/' \
          + @md.file.base_filename.manpage,
          fn: 'manpage',
         }
      end
      def texinfo
        {
          cmd: '--texinfo',
          viewer: '',
          f_pth: 'cd ' \
          + @md.file.output_path.texinfo.dir + ' && ' \
          + @env.program.texinfo + ' ' \
          + @md.file.base_filename.info \
          + '; cd -',
          fn: 'info',
         }
      end
      def db
        def psql
          {
            cmd: '--psql --update/--import',
            viewer: '',
            f_pth: @pwd_stub + '::' \
            + @opt.fns \
            + 'dbi psql',
            p_pth: @env.processing_path.postgresql + '/' \
            + @md.fns \
            + '.sql',
            fn: 'dbi psql',
           }
        end
        def sqlite
          {
            cmd: '--sqlite --update/--import',
            viewer: 'sqlite3 ',
            f_pth: @env.path.webserv + '/' \
            + @md.opt.f_pth[:pth_stub] + '/' \
            + 'sisu_sqlite.db',
            p_pth: @env.processing_path.sqlite + '/' \
            + @md.fns \
            + '.sql',
            fn: 'dbi sqlite3',
           }
        end
        def sqlite_discrete
          {
            cmd: '--sqlite',
            viewer: 'sqlite3 ',
            f_pth: @md.file.output_path.sqlite_discrete.dir + '/' \
            + @md.file.base_filename.sqlite_discrete,
            p_pth: @env.processing_path.sqlite + '/' \
            + @md.fns \
            + '.sql',
            fn: 'dbi sqlite3',
           }
        end
        self
      end
      def po4a
        def po
          {
            cmd: '--po4a/--pot',
            viewer: @prog.web_browser,
            f_pth: @prog.text_editor + ' ' \
            + @md.file.output_path.po.dir \
            + '/' + y,
            fn: @fn[:pot],
           }
        end
        def pot
          {
            cmd: '--po4a/--pot',
            viewer: @prog.web_browser,
            f_pth: @prog.text_editor + ' ' \
            + @md.file.output_path.pot.dir \
            + '/' + y,
            fn: @fn[:pot],
           }
        end
        self
      end
      def source
        {
          cmd: '--source (sisu markup)',
          viewer: @prog.text_editor,
          f_pth: @md.file.output_path.src.dir + '/' \
          + @opt.fno,
          p_pth: @md.file.output_path.src.dir + '/' \
          + @opt.fno,
          fn: @opt.fno,
         }
      end
      def sisupod
        {
          cmd: '--sisupod',
          viewer: '',
          f_pth: @md.file.output_path.sisupod.dir + '/' \
          + @opt.fno \
          + '.txz',
          p_pth: @md.file.output_path.sisupod.dir + '/' \
          + @opt.fno + '/' \
          + 'sisupod/',
          fn: @fn[:sisupod],
         }
      end
      def ruby_profile
        {
          cmd: '--profile (ruby profiler)',
          fn: 'profile',
         }
      end
      def qrcode
        {
          cmd: '--qrcode',
          viewer: @prog.web_browser,
          f_pth: @md.file.output_path.manifest.dir + '/' \
          + @md.file.base_filename.manifest,
          fn: @fn[:qrcode],
         }
      end
      def manifest
        {
          cmd: '--manifest',
          viewer: @prog.web_browser,
          f_pth: @md.file.output_path.manifest.dir + '/' \
          + @md.file.base_filename.manifest,
          fn: @fn[:manifest],
         }
      end
      def sitemap
        {
          cmd: '--sitemap',
          viewer: @prog.web_browser,
          f_pth: @md.file.output_path.sitemaps.dir + '/' \
          + @md.file.base_filename.sitemap,
          fn: @fn[:sitemap],
         }
      end
      self
    end
    def urls_select
      unless @opt.act[:quiet][:set]==:on
        i1='[' + @opt.f_pth[:lng_is] + ']'
        i2='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],
            'URLs'
          ).green_title_hi
        : SiSU_Screen::Ansi.new(
            @opt.act[:color_state][:set],
            'URL (output manifest)',
            i1, i2
          ).grey_title_grey_blue
        if (@opt.act[:verbose][:set]==:on \
        || @opt.act[:verbose_plus][:set]==:on \
        || @opt.act[:maintenance][:set]==:on)
          SiSU_Screen::Ansi.new(
            @opt.act[:color_state][:set],
            i1, i2,
          ).flow
        end
      end
      m=/.+\/(?:src\/)?(\S+)/im
      @pwd_stub="#{@env.url.output_tell}"[m,1]
      unless @opt.act[:quiet][:set]==:on
        if @opt.fns =~ @m_regular
          if (@opt.act[:verbose][:set]==:on \
          || @opt.act[:verbose_plus][:set]==:on \
          || @opt.act[:maintenance][:set]==:on)
            if @opt.act[:txt][:set]==:on
              show.report(report_info.text.txt)
              #show.maintenance(report_info.text.txt)
            end
            if @opt.act[:txt_textile][:set]==:on
              show.report(report_info.text.textile)
              #show.maintenance(report_info.text.textile)
            end
            if @opt.act[:txt_asciidoc][:set]==:on
              show.report(report_info.text.asciidoc)
              #show.maintenance(report_info.text.asciidoc)
            end
            if @opt.act[:txt_markdown][:set]==:on
              show.report(report_info.text.markdown)
              #show.maintenance(report_info.text.markdown)
            end
            if @opt.act[:txt_rst][:set]==:on
              show.report(report_info.text.rst)
              #show.maintenance(report_info.text.rst)
            end
            if @opt.act[:txt_orgmode][:set]==:on
              show.report(report_info.text.orgmode)
              #show.maintenance(report_info.text.orgmode)
            end
            if (@opt.act[:html][:set]==:on \
            or @opt.act[:html_scroll][:set]==:on \
            or @opt.act[:html_seg][:set]==:on)
              if @opt.act[:html_scroll][:set]==:on
                show.report(report_info.html.scroll)
                show.maintenance(report_info.html.scroll)
              end
              if @opt.act[:html_seg][:set]==:on
                show.report(report_info.html.seg)
                show.maintenance(report_info.html.seg)
              end
            end
            if @opt.act[:concordance][:set]==:on
              show.report(report_info.html.concordance)
              #show.maintenance(report_info.html.concordance)
            end
            if @opt.act[:xhtml][:set]==:on
              show.report(report_info.xhtml.xhtml)
              show.maintenance(report_info.xhtml.xhtml)
            end
            if @opt.act[:epub][:set]==:on
              show.report(report_info.xhtml.epub)
              show.maintenance(report_info.xhtml.epub)
            end
            if @opt.act[:odt][:set]==:on
              show.report(report_info.xml.odt)
              show.maintenance(report_info.xml.odt)
            end
            if @opt.act[:xml_dom][:set]==:on
              show.report(report_info.xml.dom)
              #show.maintenance(report_info.xml.dom)
            end
            if @opt.act[:xml_sax][:set]==:on
              show.report(report_info.xml.sax)
              #show.maintenance(report_info.xml.sax)
            end
            if @opt.act[:xml_docbook_book][:set]==:on
              show.report(report_info.xml.docbook)
              #show.maintenance(report_info.xml.docbook)
            end
            if @opt.act[:xml_fictionbook][:set]==:on
              show.report(report_info.xml.fictionbook)
              #show.maintenance(report_info.xml.fictionbook)
            end
            if @opt.act[:xml_scaffold_structure_sisu][:set]==:on
              show.report(report_info.xml.scaffold_structure_sisu)
              #show.maintenance(report_info.xml.scaffold_structure_sisu)
            end
            if @opt.act[:xml_scaffold_structure_collapse][:set]==:on
              show.report(report_info.xml.scaffold_collapse)
              #show.maintenance(report_info.xml.scaffold_collapse)
            end
            if @opt.act[:json][:set]==:on
              show.report(report_info.json)
              #show.maintenance(report_info.json)
            end
            if (@opt.act[:pdf][:set]==:on \
            or @opt.act[:pdf_p][:set]==:on \
            or @opt.act[:pdf_l][:set]==:on)
              if @opt.act[:pdf_p][:set]==:on
                show.report(report_info.pdf.portrait)
                show.maintenance(report_info.pdf.portrait)
              end
              if @opt.act[:pdf_l][:set]==:on
                show.report(report_info.pdf.landscape)
                show.maintenance(report_info.pdf.landscape)
              end
            end
            if @opt.act[:psql][:set]==:on
              show.report(report_info.db.psql)
              show.maintenance(report_info.db.psql)
            end
            if @opt.act[:sqlite_discrete][:set]==:on
              show.report(report_info.db.sqlite_discrete)
              show.maintenance(report_info.db.sqlite_discrete)
            end
            if @opt.act[:sqlite][:set]==:on
              show.report(report_info.db.sqlite)
              show.maintenance(report_info.db.sqlite)
            end
            if @opt.act[:texinfo][:set]==:on
              show.report(report_info.texinfo)
              #show.maintenance(report_info.texinfo)
            end
            if @opt.act[:manpage][:set]==:on
              show.report(report_info.manpage)
              #show.maintenance(report_info.manpage)
            end
            if @opt.act[:hash_digests][:set]==:on
              show.report(report_info.hash_digests)
              #show.maintenance(report_info.hash_digests)
            end
            if @opt.act[:po4a_shelf][:set]==:on
              #if @opt.fns =~/\S+?~\S{2}(?:_\S{2})?\.ss[mt]/
              #else
              #end
            end
            if @opt.act[:share_source][:set]==:on
              show.report(report_info.source)
              show.maintenance(report_info.source)
            end
            if @opt.act[:sisupod][:set]==:on
              show.report(report_info.sisupod)
              show.maintenance(report_info.sisupod)
            end
            if @opt.act[:qrcode][:set]==:on
              show.report(report_info.qrcode)
              #show.maintenance(report_info.qrcode)
            end
            if @opt.act[:manifest][:set]==:on
              show.report(report_info.manifest)
              show.maintenance(report_info.manifest)
            end
          end
        end
      end
    end
    def urls_all
      i="(output manifest) [#{@opt.f_pth[:lng_is]}] #{@env.url.output_tell}/#{@fnb}/sisu_manifest.html"
      SiSU_Screen::Ansi.new(
        @opt.act[:color_state][:set],
        'URLs',
        i
      ).grey_title_hi
    end
  end
end
__END__
#+END_SRC

** webrick.rb

#+HEADER: :tangle "../lib/sisu/webrick.rb"
#+BEGIN_SRC ruby
#<<sisu_document_header>>
module SiSU_Webserv
  class WebrickStart
    begin
      require 'time'
      require 'webrick'
        include WEBrick
    rescue LoadError
      SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia).
        error('time or webrick NOT FOUND (LoadError)')
    end
    require_relative 'se'                                 # se.rb
      include SiSU_Env
      include SiSU_Screen
    def initialize
      @cX=SiSU_Screen::Ansi.new('yes').cX
      @env=SiSU_Env::InfoEnv.new
      port=SiSU_Env::InfoPort.new
      @host=@env.url.webrick
      @port=port.webrick
      @serve=[]
      Dir.foreach(@env.path.webserv) do |x|
        if x !~/^\./ \
        and FileTest.directory?("#{@env.path.webserv}/#{x}")
          @serve << x
        end
      end
      @mount=[]
      @serve.each {|x| @mount << ["/#{x}", "#{@env.path.webserv}/#{x}"]}
      @pwd=Dir.pwd
      @week=Time.now.strftime(%{%Yw%W})
      puts "\n"
      @mount.each { |x,y|
        puts "  * #{@cX.blue}#{@host}:#{@port}#{x}/#{@cX.off}"
      }
      get=Dir.pwd
      brick(@port,get)
    end
    def brick(port,get='')
      cgidir=if get=~/pwd/ then Dir.pwd
      else                      '/usr/lib/cgi-bin'
      end
      port=SiSU_Env::InfoPort.new.webrick
      begin
        s=HTTPServer.new(
          Port:         port,
          DocumentRoot: Dir::pwd + '/htdocs',
          CGIPathEnv:   ENV['PATH']
        )
        cgi_dir=File.expand_path(cgidir)
        @mount.each { |x,y|                                                        # mount subdirectories
          s.mount(x, HTTPServlet::FileHandler, y, true)
        }
        s.mount('/cgi-bin', HTTPServlet::FileHandler, cgi_dir, { FancyIndexing: true })
        trap("INT"){ s.shutdown }
        s.start
      rescue
        SiSU_Errors::Rescued.new($!,$@,'-W',nil).location do #fix
          __LINE__.to_s + ':' + __FILE__
        end
      ensure
      end
    end
    def wb_cgi
      begin                                                                          #%
        wb_s2=''
                                                                 #% writes file wb.cgi to shared directories ...
                                                                 #% wb_top
        wb_top=%q(#!/usr/bin/env ruby
        # * arch-tag: webrick info on environment, mounted directories, and contents of pwd
        begin
          require 'time'
          require 'cgi'
          require 'fcgi'
        rescue LoadError
          puts 'time, cgi or fcgi NOT FOUND (LoadError)'
        end
        ls=Dir.entries('./')
        dir_contents=[]
        ls.each { |x| dir_contents << "<a href=\"./#{x}/\">#{x}</a><br>" unless x =~/^(\.)+$/ }
        dir_contents=dir_contents.sort.join(' ')
        #host=ENV['HOSTNAME']
        #host=%x{echo $HOSTNAME}
        )
        wb_s1=<<-WOK

  page=CGI.new "html3"
  page.out {
    page.html {
      page.head { page.title {"#{@host} Webrick Report"} } +
      page.body {
        page.h1 {"Webrick #{@host}"} +
        page.p {"Webrick is Ruby's built in webserver."} +
        page.center {"Host name: " + page.b{"#{@host} "} + "(#{@host})  port: " + page.b{"#{@port}"}} +
        page.center {"#{Time.now}"} +
        page.center {"#{Time.now.strftime(%{%Yw%W})}"} +
        page.p {''} +
        page.p {''} +
        page.p {page.b{"Webrick Served Directories: "}} +
        WOK
                                                               #% wb_s2 (mounts)
        @mount.each do |x,y| wb_s2 += <<-WOK
          page.p {%{<a href="#{@host}:#{@port}#{x}/">#{x}</a> } +
            %{<a href="#{@host}:#{@port}#{x}/">#{@host}:#{@port}#{x}</a> (mounts: #{y}/)   <a href="#{@host}:#{@port}#{x}/wb.cgi">info (wb.cgi)</a>}} +
          WOK
        end
                                                               #% wb_end
        wb_end=<<-WOK
        page.p {page.b{"Contents of PWD (see URL): "}} +
        page.p {"#\{dir_contents}"}
      }
    }
  }
        WOK
        @mount.each { |x,y|                                      #% wb puts
          puts y
            filename=File.new("#{y}/wb.cgi",'w')
            filename << wb_top
            filename << wb_s1
            filename << wb_s2
            filename << wb_end
            filename.close
            FileUtils::chmod(0755,"#{y}/wb.cgi &") if FileTest.file?("#{y}/wb.cgi &")
        }
      rescue
        SiSU_Errors::Rescued.new($!,$@,'-W',nil).location do #fix
          __LINE__.to_s + ':' + __FILE__
        end
      ensure
      end
    end
  end
ensure
end
__END__
#+END_SRC

** wikispeak.rb

#+HEADER: :tangle "../lib/sisu/wikispeak.rb"
#+BEGIN_SRC ruby
#<<sisu_document_header>>
module SiSU_Wikispeak
  require_relative 'ao'                                 # ao.rb
  require_relative 'se'                                 # se.rb
    include SiSU_Env
  include SiSU_Param
  require_relative 'plaintext_format'                   # plaintext_format.rb
    include Format
  require_relative 'html_parts'                         # html_parts.rb
  require_relative 'txt_shared'
  @@alt_id_count,@@alt_id_count=0,0
  @@tablefoot=''
  class Source
    def initialize(opt)
      @opt=opt
      @@dostype='msdos footnotes'
    end
    def read
      begin
        @md=SiSU_Param::Parameters.new(@opt).get
        @env=SiSU_Env::InfoEnv.new(@opt.fns)
        path=@env.path.output_tell
        tool=(@opt.act[:verbose][:set]==:on \
        || @opt.act[:verbose_plus][:set]==:on \
        || @opt.act[:maintenance][:set]==:on) \
        ? "#{@env.program.text_editor} #{path}/#{@md.fnb}/#{@md.fn[:wiki]}"
        : ''
        SiSU_Screen::Ansi.new(
          @opt.act[:color_state][:set],
          'Wikispeak',
          tool
        ).green_hi_blue unless @opt.act[:quiet][:set]==:on
        if (@opt.act[:verbose_plus][:set]==:on \
        || @opt.act[:maintenance][:set]==:on)
          SiSU_Screen::Ansi.new(
            @opt.act[:color_state][:set],
            @opt.fns,
            "#{@env.path.output_tell}/#{@md.fnb}/#{@md.fn[:wiki]}"
          ).flow
        end
        @ao_array=SiSU_AO::Source.new(@opt).get # ao file drawn here
        SiSU_Wikispeak::Source::Scroll.new(@ao_array,@md).songsheet
      rescue
        SiSU_Errors::Rescued.new($!,$@,@opt.selections.str,@opt.fns).location do
          __LINE__.to_s + ':' + __FILE__
        end
      ensure
      end
    end
    private
    class SplitTextObject <Source
      require_relative 'plaintext_format'               # plaintext_format.rb
        include Format
      @@alt_id_count=0
      @@dp=nil
      attr_reader :format,:lev,:text,:ocn,:lev_para_ocn
      def initialize(para)
        @para=para
        @format,@ocn='ordinary','ordinary'
        @dp=@@dp ||=SiSU_Env::InfoEnv.new.digest.pattern
      end
      def lev_segname_para_ocn
        @text=nil
        if @para =~/^(\d~|<:.+?>).+?#{Mx[:id_o]}~(\d+);(?:\w|[0-6]:)\d+;\w\d+#{Mx[:id_c]}#{Mx[:id_o]}#{@dp}:#{@dp}#{Mx[:id_c]}$/
          if /^(([1-6])~(\S+))\s+(\S.+?)#{Mx[:id_o]}~(\d+);(?:\w|[0-6]:)\d+;\w\d+#{Mx[:id_c]}#{Mx[:id_o]}#{@dp}:#{@dp}#{Mx[:id_c]}$/m.match(@para)
            @format,@lev,segname,@text,@ocn=$1,$2,$3,$4,$5
          elsif  /^(([1-6])~)\s+(\S.+?)#{Mx[:id_o]}~(\d+);(?:\w|[0-6]:)\d+;\w\d+#{Mx[:id_c]}#{Mx[:id_o]}#{@dp}:#{@dp}#{Mx[:id_c]}$/m.match(@para)
            @format,@lev,@text,@ocn=$1,$2,$3,$4
          elsif /<:(.+?)>\s*(\S.+?)#{Mx[:id_o]}~(\d+);(?:\w|[0-6]:)\d+;\w\d+#{Mx[:id_c]}#{Mx[:id_o]}#{@dp}:#{@dp}#{Mx[:id_c]}$/m.match(@para)
            @format,@text,@ocn=$1,$2,$3
          elsif /^(([1-6])~(\S+))\s+(\S.+?)#{Mx[:id_o]}~(\d+);(?:\w|[0-6]:)\d+;[um]\d+#{Mx[:id_c]}#{Mx[:id_o]}#{@dp}:#{@dp}#{Mx[:id_c]}$/m.match(@para)
            @@alt_id_count+=1
            @format,@lev,segname,@text,@ocn=$1,$2,$3,$4,"x#{@@alt_id_count}"
          elsif  /^(([1-6])~)\s+(\S.+?)#{Mx[:id_o]}~(\d+);[um]\d+;\w\d+#{Mx[:id_c]}#{Mx[:id_o]}#{@dp}:#{@dp}#{Mx[:id_c]}$/m.match(@para)
            @@alt_id_count+=1
            @format,@lev,@text,@ocn=$1,$2,$3,"x#{@@alt_id_count}"
          end
        else
          if /(.+?)#{Mx[:id_o]}~(\d+);(?:\w|[0-6]:)\d+;\w\d+#{Mx[:id_c]}#{Mx[:id_o]}#{@dp}:#{@dp}#{Mx[:id_c]}$/m.match(@para)
            @text,@ocn=$1,$2
          end
          if @para !~/#{Mx[:id_o]}~(\d+);(?:\w|[0-6]:)\d+;\w\d+#{Mx[:id_c]}#{Mx[:id_o]}#{@dp}:#{@dp}#{Mx[:id_c]}$|^$/ #added 2002w06
            @text=/(.+?)/m.match(@para)[1]
          end
          if /^((\d)~(?:~\S+)?)\s+(.+)/m.match(@para)
            @format,@lev,@text=$1,$2,$3
          end
        end
        format=@format.dup
        @lev_para_ocn=if @para =~/.+#{Mx[:id_o]}~\d+;(?:\w|[0-6]:)\d+;\w\d+#{Mx[:id_c]}#{Mx[:id_o]}#{@dp}:#{@dp}#{Mx[:id_c]}$/
          Format::FormatTextObject.new(format,@text,@ocn)
        else
          Format::FormatTextObject.new(format,@text,"#{Mx[:id_o]}~(\d+);[um]\d+;\w\d+#{Mx[:id_c]}#{Mx[:id_o]}#{@dp}:#{@dp}#{Mx[:id_c]}")
        end
        self
      end
    end
    class Scroll <Source
      include SiSU_TextUtils
      include SiSU_Parts_HTML
      @@endnotes_para=[]
      @@wiki={ body: [], open: [], close: [], head: [], metadata: [], tail: [], endnotes: [] }
      @@dp=nil
      def initialize(data,md)
        @data,@md=data,md
        @dp=@@dp ||=SiSU_Env::InfoEnv.new.digest.pattern
        @regx=/^(?:(?:#{Mx[:br_line]}\s*|#{Mx[:br_nl]}\s*)?#{Mx[:lv_o]}\d:(\S*?)#{Mx[:lv_c]}\s*)?(.+)/ #fix Mx[:lv_o] #m # 2004w18 pb pn removal added
        @tab="\t"
        @@dostype='unix footnotes'
        @br="\n"
      end
      def songsheet
        markup
        publish
      end
      # Used for extraction of endnotes from paragraphs
      def extract_endnotes(para='') #check
        para.scan(/(?:#{Mx[:en_a_o]}|#{Mx[:en_b_o]})([\d*+]+\s+.+?)\s*#{Mx[:id_o]}#{@dp}#{Mx[:id_c]}(?:#{Mx[:en_a_c]}|#{Mx[:en_b_c]})/)
      end
      def wiki_metadata(meta)
        util=SiSU_TextUtils::Wrap.new(meta.text,70,15,1)
        txt=util.line_wrap
        @@wiki[:metadata] <<= if meta.type=='meta'
          <<WOK

#{@tab}#{meta.el}: #{txt}
WOK
        else ''
        end
      end
      def wiki_tail
        generator="Generated by: #{@md.project_details.project} #{@md.project_details.version} of #{@md.project_details.date_stamp} (#{@md.project_details.date})"  if @md.project_details.version
        lastdone="Last Generated on: #{Time.now}"
        rubyv="Ruby version: #{@md.ruby_version}"
        sc=if @md.sc_info
          "Source file:    #{@md.sc_filename}#{@br}Version number: #{@md.sc_number}#{@br}Version date:   #{@md.sc_date}#{@br}"
        else ''
        end
        @@wiki[:tail] <<<<WOK
#{@br}
Other versions of this document: #{@br}
manifest:
   #{vz.url_root_http}/#{@md.fnb}/#{@md.fn[:manifest]}#{@br}
html:
   #{vz.url_root_http}/#{@md.fnb}/#{@md.fn[:toc]}#{@br}
pdf:
   #{vz.url_root_http}/#{@md.fnb}/#{@md.fn[:pdf_p]}
   #{vz.url_root_http}/#{@md.fnb}/#{@md.fn[:pdf_l]}#{@br}
plaintext (plain text):
   #{vz.url_root_http}/#{@md.fnb}/#{@md.fn[:plain]}#{@br}
at:
   #{vz.url_site}#{@br}

#{sc}
,* #{generator}
,* #{rubyv}
,* #{lastdone}
,* SiSU #{vz.url_sisu}
WOK
      end
      def wiki_structure(para='',lv='',ocn='',hname='') #% Used to extract the structure of a document
        lv=lv.to_i
        lv=nil if lv==0
        extract_endnotes(para)
        para.gsub!(/(?:#{Mx[:en_a_o]}|#{Mx[:en_b_o]})(?:[\d*+]+)\s+(.+?)#{Mx[:id_o]}#{@dp}#{Mx[:id_c]}(?:#{Mx[:en_a_c]}|#{Mx[:en_b_c]})/,'<ref>\1</ref>') # endnote marker marked up
        para.gsub!(/^#{Rx[:lv]}\S*\s+/,'') # endnote marker marked up
        para.gsub!(/<\S+?>#{Mx[:id_o]}#{@dp}:#{@dp}#{Mx[:id_c]}/,'') # endnote marker marked up
        if lv
          @@wiki[:body] << case lv
          when 1    then '='*2 << para.strip << @br*2
          when 2..3 then '='*2 << para.strip << @br*2
          when 4    then '='*4 << para.strip << @br*2
          when 5..6 then '='*4 << para.strip << @br*2
          end
        else @@wiki[:body] << para << @br*2 # main text, contents, body KEEP
        end
      end
      def markup                                                               # Used for major markup instructions
        data=@data
        SiSU_Env::InfoEnv.new(@md.fns)
        @data_mod,@endnotes,@level,@cont,@copen,@wiki_contents_close=Array.new(6){[]}
        (0..6).each { |x| @cont[x]=@level[x]=false }
        (4..6).each { |x| @wiki_contents_close[x]='' }
        wiki_tail
        table_message='[table omitted, see other document formats]'
        data.each do |para|
          para.gsub!(/#{Mx[:gr_o]}Th?#{Mx[:tc_p]}.+/um,"#{@br}#{table_message}") #fix
          para.gsub!(/.+?<-#>/,'')                                           # remove dummy headings (used by html) #check
          para.gsub!(/_\*\s+/,'* ')                                           # bullet markup, marked down
          para.gsub!(/&#169;/,'©')                                           # bullet markup, marked down
          para.gsub!(/&amp;/,'&')                                           # bullet markup, marked down
          para.gsub!(/<sup>(.+?)<\/sup>/,'^\1^')
          para.gsub!(/<sub>(.+?)<\/sub>/,'[\1]')
          para.gsub!(/<i>(.+?)<\/i>/,"''\\1''")
          para.gsub!(/<b>(.+?)<\/b>/,"'''\\1'''")
          para.gsub!(/<u>(.+?)<\/u>/,'_\1_')
          para.gsub!(/#{Mx[:lnk_o]}(.+?)#{Mx[:lnk_c]}#{Mx[:url_o]}(\S+?)#{Mx[:url_c]}/,'[\2 \1]')
          para.gsub!(/#{Mx[:url_o]}(\S+?)#{Mx[:url_c]}/,'[\1]')
          para.gsub!(/<:(?:block|group|verse|alt|code)(?:-end)?>(?:\s+#{Mx[:id_o]}~(\d+);(?:\w|[0-6]:)\d+;\w\d+#{Mx[:id_c]}#{Mx[:id_o]}#{@dp}:#{@dp}#{Mx[:id_c]})?/,'')
          para.gsub!(/<:p[bn]>/,'')                                         # remove page breaks
          para.gsub!(/^\s*#{Mx[:id_o]}~\d+;(?:\w|[0-6]:)\d+;\w\d+#{Mx[:id_c]}#{Mx[:id_o]}#{@dp}:#{@dp}#{Mx[:id_c]}$/,'') # remove empty lines - check
          para.gsub!(/<a href=".+?">(.+?)<\/a>/m,'\1')
          para.gsub!(/<:name#\S+?>/,'')                                       # remove name links
          para.gsub!(/&nbsp;|#{Mx[:nbsp]}/,' ')                               # decide on
          para.gsub!(/(?:^|[^_\\])#{Mx[:lnk_o]}(\S+?\.(?:png|jpg|gif)) .+?#{Mx[:lnk_c]}(?:#{Mx[:url_o]}\S+?#{Mx[:url_c]}|image)/,'    [ \1 ]') #"[ #{dir.url.images_local}\/\\1 ]")
          para.gsub!(/(?:^|[^_\\])#{Mx[:lnk_o]}\s*\S+?\.(?:png|jpg|gif)\s+.+?"(.*?)"\s*#{Mx[:lnk_c]}\S+/,'[image: "\1"]')
          if para =~/^@(\S+?):\s+(.+?)\Z/m # for headers
            d_meta=SiSU_TextUtils::HeaderScan.new(@md,para).meta
            if d_meta; wiki_metadata(d_meta)
            end
          end
          if para !~/(^@\S+?:|#{Mx[:br_endnotes]}|#{Mx[:br_eof]})/
            if para =~@regx #/.+?<~\d+;\w\d+;\w\d+>.*/ #watch change
              paranum=para[@regx,3]
              @p_num=Format::ParagraphNumber.new(paranum)
            end
            @sto=SplitTextObject.new(para).lev_segname_para_ocn
            ### problem in scroll, it appears tables are getting paragraph numbers
            m=/#{Mx[:id_o]}~(\d+);(?:\w|[0-6]:)\d+;\w\d+#{Mx[:id_c]}#{Mx[:id_o]}#{@dp}:#{@dp}#{Mx[:id_c]}$/
            if para =~m \
            and para=~/\S+/
              para=case @sto.format
              when /^(1)~(?:(\S+))?/
                wiki_structure(para,$1,@sto.ocn,$2)
                @sto.lev_para_ocn.heading_body1
              when /^(2)~(?:(\S+))?/
                wiki_structure(para,$1,@sto.ocn,$2)
                @sto.lev_para_ocn.heading_body2
              when /^(3)~(?:(\S+))?/
                wiki_structure(para,$1,@sto.ocn,$2)
                @sto.lev_para_ocn.heading_body3
              when /^(4)~(\S+)/ # work on see SiSU_text_parts::SplitTextObject
                wiki_structure(para,$1,@sto.ocn,$2)
                @sto.lev_para_ocn.heading_body4
              when /^(5)~(?:(\S+))?/
                wiki_structure(para,$1,@sto.ocn,$2)
                @sto.lev_para_ocn.heading_body5
              when /^(6)~(?:(\S+))?/
                wiki_structure(para,$1,@sto.ocn,$2)
                @sto.lev_para_ocn.heading_body6
              else
                wiki_structure(para,nil,nil,nil) #watch may be problematic
                para
              end
            elsif para =~/#{table_message}/
              @@wiki[:body] << para << @br
            elsif para =~/(Note|Endnotes?)/ \
            and para !~/#{Mx[:id_o]}~\d+;(?:\w|[0-6]:)\d+;\w\d+#{Mx[:id_c]}#{Mx[:id_o]}#{@dp}:#{@dp}#{Mx[:id_c]}$/
            elsif para =~/(MetaData)/ \
            and para =~/#{Mx[:id_o]}~(\d+);[um]\d+;\w\d+#{Mx[:id_c]}#{Mx[:id_o]}#{@dp}:#{@dp}#{Mx[:id_c]}$/ #debug 2003w46 add rc info ####suspect visit
            elsif para.include? 'Owner Details' \
            and para !~/#{Mx[:id_o]}~(\d+);(?:[oh]|[0-6]:)\d+;\w\d+#{Mx[:id_c]}#{Mx[:id_o]}#{@dp}:#{@dp}#{Mx[:id_c]}$/
            elsif para =~/(#{Mx[:tc_p]}|#{Mx[:gr_o]}Th?)/u #tables ! #fix
            elsif para =~/(.*)<!#!>(.*)/
              one,two=$1,$2
              format_text=FormatTextObject.new(one,two)
              para=format_text.seg_no_paranum
            end
            if (para =~/<a name="n\d+">/ \
            and para =~/^(-\{{2}~\d+|<!e[:_]\d+!>)/) # -endnote
              para=''
            end
            case para
            when /<:i1>/
              if para =~/.*<:#>.*$/
                format_text=FormatTextObject.new(para,'')
                para=format_text.scr_indent_one_no_paranum
              end
            when /<:i2>/
              if para =~/.*<:#>.*$/
                format_text=FormatTextObject.new(para,'')
                para=format_text.scr_indent_one_no_paranum
              end
            end
            if para !~/#{the_margin.txt_0}|#{the_margin.txt_1}|#{the_margin.txt_2}/
              # i don't get the condition for no paranum
            end
            if para =~/<:center>/
              one,two=/(.*)<:center>(.*)/.match(para)[1,2]
              format_text=FormatTextObject.new(one,two)
              para=format_text.center
            end
            para.gsub!(/<!.+!>/,' ') if para ## Clean Prepared Text
            para.gsub!(/<:\S+>/,' ') if para ## Clean Prepared Text
          end
        end
      end
      def publish
        content=[]
        content << @@wiki[:open]
        content << @@wiki[:head]
        content << @@wiki[:body]
        Output.new(content.join,@md).wiki
        @@wiki[:head],@@wiki[:body],@@wiki[:tail],@@wiki[:metadata]=[],[],[],[]
      end
    end
    class Output <Source
      include SiSU_Param
      include SiSU_Env
      def initialize(content,md)
        @content,@md=content,md
      end
      def wiki                                                            #%wiki output
        SiSU_Env::FileOp.new(@md).mkdir
        filename_wiki=SiSU_Env::FileOp.new(@md,@md.fn[:wiki]).mkfile
        @sisu=[]
        @content.each do |para|                                                # this is a hack
          if para =~/^\S/
            if para !~/^([*=-]|\.){5}/; filename_wiki.puts para           #unix wiki
            else                        filename_wiki.puts para           #unix wiki
            end
          else filename_wiki.puts para # if para =~/^\s/
          end
        end
      end
    end
  end
end
__END__
#+END_SRC

** zap.rb

#+HEADER: :tangle "../lib/sisu/zap.rb"
#+BEGIN_SRC ruby
#<<sisu_document_header>>
module SiSU_Zap
  require_relative 'se'                                 # se.rb
    include SiSU_Env
  class Source
    def initialize(opt)
      @opt=opt
      @env=SiSU_Env::InfoEnv.new(opt.fns)
    end
    def read
      zap_path="#{@env.path.output}/#{@env.fnb}"
      z=SiSU_Env::CleanOutput.new(@opt)
      if SiSU_Env::InfoSettings.new.permission?('zap')
        unless @opt.act[:quiet][:set]==:on
          tell=SiSU_Screen::Ansi.new(
            @opt.act[:color_state][:set],
            "Clean files related to processing #{@opt.selections.str} ->",
            "#{@opt.fns} -> #{zap_path}"
          )
          tell.warn
        end
        z.zap.remove_output
      else
        unless @opt.act[:quiet][:set]==:on
          tell=SiSU_Screen::Ansi.new(
            @opt.act[:color_state][:set],
            'use of -Z (zap) has not enabled in sisurc.yml'
          )
          tell.warn
        end
      end
    end
  end
end
__END__
#+END_SRC

* document header

#+NAME: sisu_document_header
#+BEGIN_SRC text
encoding: utf-8
- Name: SiSU

  - Description: documents, structuring, processing, publishing, search
    misc

  - 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/sisu>
    <https://git.sisudoc.org/projects/sisu-markup>
#+END_SRC