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

* types
** asciidoc
*** txt_asciidoc.rb

#+HEADER: :tangle "../lib/sisu/txt_asciidoc.rb"
#+BEGIN_SRC ruby
#<<sisu_document_header>>
module SiSU_Txt_AsciiDoc
  require_relative 'ao'                                 # ao.rb
  require_relative 'se'                                 # se.rb
    include SiSU_Env
  require_relative 'shared_metadata'                    # shared_metadata.rb
  require_relative 'generic_parts'                      # generic_parts.rb
  require_relative 'txt_read'                           # txt_read.rb
  require_relative 'txt_shared'                         # txt_shared.rb
  require_relative 'txt_asciidoc_decorate'              # txt_decorate.rb
  require_relative 'txt_output'                         # txt_output.rb
  include SiSU_Param
  @@alt_id_count,@@alt_id_count=0,0
  @@tablefoot=''
  class Source
    include SiSU_Txt_Read
    def initialize(opt)
      @opt=opt
      unless @opt.fns =~/(.+?)\.(?:-|ssm\.)?sst$/
        puts "#{sf} not a processed file type"
      end
    end
    def read
      begin
        md=SiSU_Param::Parameters.new(@opt).get
        specific={
          description:     'AsciiDoc (plaintext utf-8)',
          output_path:     md.file.output_path.asciidoc.dir,
          output_file:     md.file.base_filename.asciidoc,
        }
        read_generic(@opt,specific)
        SiSU_Txt_AsciiDoc::Source::Scroll.new(md,@ao_array,@wrap_width).songsheet
      rescue
        SiSU_Errors::Rescued.new($!,$@,@opt.selections.str,@opt.fns).location do
          __LINE__.to_s + ':' + __FILE__
        end
      ensure
      end
    end
    private
    class Scroll <Source
      include SiSU_Parts_Generic
      include SiSU_TextUtils
      include SiSU_Decorate_Txt_AsciiDoc
      @@endnotes={ para: [], end: [] }
      def initialize(md,data,wrap_width)
        @md,@data,@wrap_width=md,data,wrap_width
        @env=SiSU_Env::InfoEnv.new(@md.fns)
        @tab="\t"
        @@endnotes_=case md.opt.selections.str
        when /--footnote/ then false
        when /--endnote/  then true
        else                   true
        end
        @plaintext={ body: [], open: [], close: [], head: [], metadata: [], tail: [] }
      end
      def songsheet
        plaintext=markup(@data)
        publish(plaintext)
      end
      def break_line
        "\n"
      end
      # Used for extraction of endnotes from paragraphs
      def plaintext_metadata
        array=SiSU_Metadata::Summary.new(@md).plaintext.metadata
        array.each do |meta|
          tag,inf=meta.scan(/^.+?:\s|.+/)
          if tag and inf
            util=SiSU_TextUtils::Wrap.new(inf,@wrap_width,15,1)
            txt=util.line_wrap
            @plaintext[:metadata] <<<<WOK

#{@tab}#{tag}#{txt}
WOK
          end
        end
      end
      def plaintext_tail
#       env=SiSU_Env::InfoEnv.new(@md.fns)
        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}#{break_line}Version number: #{@md.sc_number}#{break_line}Version date:   #{@md.sc_date}#{break_line}"
        else ''
        end
        @plaintext[:tail] <<<<WOK
#{break_line}
plaintext (plain text):
   #{@md.file.output_path.asciidoc.url}/#{@md.file.base_filename.asciidoc}#{break_line}
Other versions of this document: #{break_line}
manifest:
   #{@md.file.output_path.manifest.url}/#{@md.file.base_filename.manifest}#{break_line}
at:
   #{@md.file.output_path.base.url}#{break_line}

#{sc}
,* #{generator}
,* #{rubyv}
,* #{lastdone}
,* SiSU #{the_url.sisu_txt}
WOK
      end
      def heading_decorated_inline(dob)
        if dob.is==:heading
          heading_inline = case dob.lc
          when 0 then decorate.heading.inline.l0
          when 1 then decorate.heading.inline.l1
          when 2 then decorate.heading.inline.l2
          when 3 then decorate.heading.inline.l3
          when 4 then decorate.heading.inline.l4
          when 5 then decorate.heading.inline.l5
          when 6 then decorate.heading.inline.l6
          end
          heading_inline + ' ' +  dob.obj + ' ' + heading_inline
        end
      end
      def heading_decorated_underscore(dob,times,p_num)
        if dob.is==:heading
          #times=@wrap_width if times > @wrap_width
          case dob.lc
          when 0 then decorate.heading.underscore.l0*times + p_num << break_line*2
          when 1 then decorate.heading.underscore.l1*times + p_num << break_line*2
          when 2 then decorate.heading.underscore.l2*times + p_num << break_line*2
          when 3 then decorate.heading.underscore.l3*times + p_num << break_line*2
          when 4 then decorate.heading.underscore.l4*times + p_num << break_line*2
          when 5 then decorate.heading.underscore.l5*times + p_num << break_line*2
          when 6 then decorate.heading.underscore.l6*times + p_num << break_line*2
          end
        end
      end
      def plaintext_structure(dob='',p_num='') #% Used to extract the structure of a document
        heading_decoration=:inline #(:inline|:underscore) #switch heading decoration between inline & underscore options
        util=nil
        wrapped=if dob.is==:para \
        || dob.is==:heading
          if dob.is==:heading
            util=(heading_decoration== :inline) \
            ? (SiSU_TextUtils::Wrap.new(heading_decorated_inline(dob),@wrap_width,0))
            : (SiSU_TextUtils::Wrap.new(dob.obj,@wrap_width,0))
          elsif dob.is==:para
            if dob.hang \
            and dob.hang =~/[0-9]/ \
            and dob.indent != dob.hang
              util=SiSU_TextUtils::Wrap.new(dob.obj,@wrap_width,dob.indent.to_i*2,dob.hang.to_i*2)
              #util=SiSU_TextUtils::Wrap.new(dob.obj,@wrap_width,dob.hang.to_i*2,0)
            elsif dob.indent =~/[1-9]/
              util=if dob.bullet_
                SiSU_TextUtils::Wrap.new("* #{dob.obj}",@wrap_width,dob.indent.to_i*2)
              else SiSU_TextUtils::Wrap.new(dob.obj,@wrap_width,dob.indent.to_i*2)
              end
            else
              util=if dob.bullet_
                SiSU_TextUtils::Wrap.new("* #{dob.obj}",@wrap_width,0)
              else SiSU_TextUtils::Wrap.new(dob.obj,@wrap_width,0)
              end
            end
          else util=SiSU_TextUtils::Wrap.new(dob.obj,@wrap_width,0)
          end
          dob.is==:heading ? util.no_wrap_no_breaks : util.line_wrap
        end
        if heading_decoration== :underscore \
        and dob.is==:heading
          @plaintext[:body] << wrapped + p_num # main text, contents, body KEEP
          @plaintext[:body] << heading_decorated_underscore(dob,wrapped.length,p_num)
        else
          @plaintext[:body] << wrapped + p_num << break_line # main text, contents, body KEEP
        end
        if @@endnotes[:para] \
        and not @@endnotes_
          @@endnotes[:para].each {|e| @plaintext[:body] << e << break_line}
        elsif @@endnotes[:para] \
        and @@endnotes_
        end
        @@endnotes[:para]=[]
      end
      def markup(data)                                                       # Used for major markup instructions
        SiSU_Env::InfoEnv.new(@md.fns)
        @data_mod,@endnotes,@level,@cont,@copen,@plaintext_contents_close=Array.new(6){[]}
        (0..6).each { |x| @cont[x]=@level[x]=false }
        (4..6).each { |x| @plaintext_contents_close[x]='' }
        plaintext_tail #($1,$2)
        plaintext_metadata
        table_message='[table conversion awaited, see other document formats]'
        data.each do |dob|
          dob.obj=dob.obj.gsub(/#{Mx[:gr_o]}Th?#{Mx[:tc_p]}.+/um,"#{break_line}#{table_message}"). #fix
            gsub(/.+?#{Mx[:gl_o]}-##{Mx[:gl_c]}/,'').                              # remove dummy headings (used by html) #check also [~-]#
            gsub(/#{Mx[:fa_bold_o]}(.+?)#{Mx[:fa_bold_c]}/,
              "#{decorate.bold.open}\\1#{decorate.bold.close}").
            gsub(/#{Mx[:fa_italics_o]}(.+?)#{Mx[:fa_italics_c]}/,
              "#{decorate.italics.open}\\1#{decorate.italics.close}").
            gsub(/#{Mx[:fa_underscore_o]}(.+?)#{Mx[:fa_underscore_c]}/,
              "#{decorate.underscore.open}\\1#{decorate.underscore.close}").
            gsub(/#{Mx[:fa_subscript_o]}(.+?)#{Mx[:fa_subscript_c]}/,
              "#{decorate.subscript.open}\\1#{decorate.subscript.close}").
            gsub(/#{Mx[:fa_superscript_o]}(.+?)#{Mx[:fa_superscript_c]}/,
              "#{decorate.superscript.open}\\1#{decorate.superscript.close}").
            gsub(/#{Mx[:fa_insert_o]}(.+?)#{Mx[:fa_insert_c]}/,
              "#{decorate.insert.open}\\1#{decorate.insert.close}").
            gsub(/#{Mx[:fa_cite_o]}(.+?)#{Mx[:fa_cite_c]}/,
              "#{decorate.cite.open}\\1#{decorate.cite.close}").
            gsub(/#{Mx[:fa_strike_o]}(.+?)#{Mx[:fa_strike_c]}/,
              "#{decorate.strike.open}\\1#{decorate.strike.close}").
            gsub(/#{Mx[:fa_monospace_o]}(.+?)#{Mx[:fa_monospace_c]}/,
              "#{decorate.monospace.open}\\1#{decorate.monospace.close}")
          unless dob.is==:code
            dob.obj=dob.obj.gsub(/#{Mx[:lnk_o]}(.+?)#{Mx[:lnk_c]}#{Mx[:rel_o]}\S+?#{Mx[:rel_c]}/,'\1').
              gsub(/#{Mx[:url_o]}_(\S+?)#{Mx[:url_c]}/,'\1').
              gsub(/#{Mx[:lnk_o]}(.+?)#{Mx[:lnk_c]}#{Mx[:url_o]}(\S+?)#{Mx[:url_c]}/,'\1 [link: <\2>]').
              gsub(/#{Mx[:lnk_o]}(.+?)#{Mx[:lnk_c]}image/,'\1 [link: local image]').
              gsub(/#{Mx[:url_o]}(\S+?)#{Mx[:url_c]}/,"#{the_text.url_open}\\1#{the_text.url_close}")
            dob.obj=dob.obj.gsub(/\s*#{Mx[:en_a_o]}([\d*+]+)\s+(.+?)#{Mx[:en_a_c]}/,' footnote:[note\1,\2]').
              gsub(/\s*#{Mx[:en_b_o]}([\d*+]+\s+.+?)#{Mx[:en_b_c]}/,' footnote:[\1]')
            dob.obj=dob.obj.gsub(/#{Mx[:en_a_o]}([\d*+]+)\s+(?:.+?)#{Mx[:en_a_c]}/,'[^\1]'). # endnote marker marked up
              gsub(/#{Mx[:en_b_o]}([\d*+]+)\s+(?:.+?)#{Mx[:en_b_c]}/,'[^\1]'). # endnote marker marked up
              gsub(/#{Mx[:gl_o]}(?:#lt|#060)#{Mx[:gl_c]}/,'<').
              gsub(/#{Mx[:gl_o]}(?:#gt|#062)#{Mx[:gl_c]}/,'>').
              gsub(/#{Mx[:gl_o]}#(?:038|amp)#{Mx[:gl_c]}/,'&').
              gsub(/#{Mx[:gl_o]}#033#{Mx[:gl_c]}/,'!').
              gsub(/#{Mx[:gl_o]}#035#{Mx[:gl_c]}/,'#').
              gsub(/#{Mx[:gl_o]}#042#{Mx[:gl_c]}/,'*').
              gsub(/#{Mx[:gl_o]}#045#{Mx[:gl_c]}/,'-').
              gsub(/#{Mx[:gl_o]}#047#{Mx[:gl_c]}/,'/').
              gsub(/#{Mx[:gl_o]}#095#{Mx[:gl_c]}/,'_').
              gsub(/#{Mx[:gl_o]}#123#{Mx[:gl_c]}/,'{').
              gsub(/#{Mx[:gl_o]}#125#{Mx[:gl_c]}/,'}').
              gsub(/#{Mx[:gl_o]}#126#{Mx[:gl_c]}/,'~').
              gsub(/#{Mx[:gl_o]}#169#{Mx[:gl_c]}/,'©').
              gsub(/#{Mx[:gl_o]}#092#{Mx[:gl_c]}/,'\\')
          end
          dob.obj=if dob.of==:block                                   # watch
            dob.obj.gsub(/#{Mx[:gl_o]}●#{Mx[:gl_c]}/m,"* ").
              gsub(/\n?#{Mx[:br_line]}\n?|\n?#{Mx[:br_nl]}\n?/m,break_line)
          else dob.obj.gsub(/\n?#{Mx[:br_line]}\n?|\n?#{Mx[:br_nl]}\n?/m,break_line*2)
          end
          if dob.is==:code
            dob.obj=dob.obj.gsub(/(^|[^}])_([<>])/m,'\1\2'). # _> _<
              gsub(/(^|[^}])_([<>])/m,'\1\2') # _<_<
          end
          dob.obj=dob.obj.gsub(/#{Mx[:url_o]}_(\S+?)#{Mx[:url_c]}/,'\1').
            gsub(/<a href=".+?">(.+?)<\/a>/m,'\1').
            gsub(/#{Mx[:mk_o]}:name#(\S+?)#{Mx[:mk_c]}/,'').                       # remove name links
            gsub(/&nbsp;|#{Mx[:nbsp]}/,' ').                                       # decide on
            gsub(/(?:^|[^_\\])#{Mx[:lnk_o]}(\S+?\.(?:png|jpg|gif)) .+?#{Mx[:lnk_c]}#{Mx[:url_o]}\S+?#{Mx[:url_c]}/,'    [ \1 ]'). #"[ #{dir.url.images_local}\/\\1 ]")
            gsub(/(?:^|[^_\\])#{Mx[:lnk_o]}(\S+?\.(?:png|jpg|gif)) .+?#{Mx[:lnk_c]}image/,'    [ \1 ]').
            gsub(/(?:^|[^_\\])\{\s*\S+?\.(?:png|jpg|gif)\s+.+?"(.*?)"\s*\}\S+/,'[image: "\1"]')
          if dob.obj !~/(^#{Rx[:meta]}|#{Mx[:br_eof]}|#{Mx[:br_endnotes]})/
            p_num=''
            #ocn
            if dob.is==:heading \
            or dob.is==:para
              plaintext_structure(dob,p_num)
            elsif dob.is==:group \
            or dob.is==:block \
            or dob.is==:verse \
            or dob.is==:code \
            or dob.is==:table
              @plaintext[:body] << dob.obj + p_num << break_line
            elsif dob.is==:break
              sp=' '
              ln='<' #ln='-'
              @plaintext[:body] <<=if dob.obj==Mx[:br_page] \
              or dob.obj==Mx[:br_page_new] \
              or dob.obj==Mx[:br_page_line]
                "#{break_line}#{ln*40}#{break_line*2}"
              elsif dob.obj ==Mx[:br_obj]
                "#{break_line}#{sp*20}*  *  *#{break_line*2}"
              end # following empty line (break_line) missing, fix
            end
            dob='' if (dob.obj =~/<a name="n\d+">/ \
              and dob.obj =~/^(-\{{2}~\d+|<!e[:_]\d+!>)/) # -endnote
            if dob ## Clean Prepared Text
              dob.obj=dob.obj.gsub(/<!.+!>/,' ').
                gsub(/<:\S+>/,' ')
            end
          end
        end
        @plaintext
      end
      def publish(plaintext)
        divider='='
        content=[]
        content << plaintext[:open]
        content << plaintext[:head]
        content << plaintext[:body]
        content << @@endnotes[:end] if @@endnotes_
        content << "#{break_line}#{divider*@wrap_width}#{break_line}"
        content << plaintext[:metadata]
        content << "#{break_line}#{divider*@wrap_width}#{break_line}" if @md.stmp =~/\w+/ #not used?
        content << plaintext[:tail]
        outputfile=SiSU_Env::FileOp.new(@md).write_file.asciidoc
        Txt_Output::Output.new.document(content,outputfile)
        @@endnotes={ para: [], end: [] }
      end
    end
  end
end
__END__
#+END_SRC

*** txt_asciidoc_decorate.rb

#+HEADER: :tangle "../lib/sisu/txt_asciidoc_decorate.rb"
#+BEGIN_SRC ruby
#<<sisu_document_header>>
module SiSU_Decorate_Txt_AsciiDoc
  def decorate
    def heading
      def inline
        def l0
          '='
        end
        def l1
          '=='
        end
        def l2
          '==='
        end
        def l3
          '===='
        end
        def l4
          '====='
        end
        def l5
          '' #'======' #logical
        end
        self
      end
      def underscore
        def l0
          '='
        end
        def l1
          '-'
        end
        def l2
          '~'
        end
        def l3
          '^'
        end
        def l4
          '+'
        end
        def l5
          '.' #'.' #proposed
        end
        self
      end
      self
    end
    def bold
      def open
        '*'
      end
      def close
        '*'
      end
      self
    end
    def italics
      def open
        '_'
      end
      def close
        '_'
      end
      self
    end
    def underscore
      def open
        ''
      end
      def close
        ''
      end
      self
    end
   #def emphasis
   #  def open
   #    ''
   #  end
   #  def close
   #    ''
   #  end
   #  self
   #end
    def cite
      def open
        '"'
      end
      def close
        '"'
      end
      self
    end
    def insert
      def open
        ''
      end
      def close
        ''
      end
      self
    end
    def strike
      def open
        '-'
      end
      def close
        '-'
      end
      self
    end
    def superscript
      def open
        '^'
      end
      def close
        '^'
      end
      self
    end
    def subscript
      def open
        '~'
      end
      def close
        '~'
      end
      self
    end
    def hilite #bold
      def open
        '*'
      end
      def close
        '*'
      end
      self
    end
    def monospace
      def open
        '+'
      end
      def close
        '+'
      end
      self
    end
    self
  end
end
__END__
#+END_SRC

** markdown
*** txt_markdown.rb

#+HEADER: :tangle "../lib/sisu/txt_markdown.rb"
#+BEGIN_SRC ruby
#<<sisu_document_header>>
module SiSU_Txt_Markdown
  require_relative 'ao'                                 # ao.rb
  require_relative 'se'                                 # se.rb
    include SiSU_Env
  require_relative 'shared_metadata'                    # shared_metadata.rb
  require_relative 'generic_parts'                      # generic_parts.rb
  require_relative 'txt_read'                           # txt_read.rb
  require_relative 'txt_shared'                         # txt_shared.rb
  require_relative 'txt_markdown_decorate'              # txt_markdown_decorate.rb
  require_relative 'txt_output'                         # txt_output.rb
  include SiSU_Param
  @@alt_id_count,@@alt_id_count=0,0
  @@tablefoot=''
  class Source
    include SiSU_Txt_Read
    def initialize(opt)
      @opt=opt
      unless @opt.fns =~/(.+?)\.(?:-|ssm\.)?sst$/
        puts "#{sf} not a processed file type"
      end
    end
    def read
      begin
        md=SiSU_Param::Parameters.new(@opt).get
        specific={
          description:     'Markdown (plaintext utf-8)',
          output_path:     md.file.output_path.markdown.dir,
          output_file:     md.file.base_filename.markdown,
        }
        read_generic(@opt,specific)
        SiSU_Txt_Markdown::Source::Scroll.new(md,@ao_array,@wrap_width).songsheet
      rescue
        SiSU_Errors::Rescued.new($!,$@,@opt.selections.str,@opt.fns).location do
          __LINE__.to_s + ':' + __FILE__
        end
      ensure
      end
    end
    private
    class Scroll <Source
      include SiSU_Parts_Generic
      include SiSU_TextUtils
      include SiSU_Decorate_Txt_Markdown
      @@endnotes={ para: [], end: [] }
      def initialize(md,data,wrap_width)
        @md,@data,@wrap_width=md,data,wrap_width
        @env=SiSU_Env::InfoEnv.new(@md.fns)
        @tab="\t"
        @@endnotes_=case md.opt.selections.str
        when /--footnote/ then false
        when /--endnote/  then true
        else                   true
        end
        @plaintext={ body: [], open: [], close: [], head: [], metadata: [], tail: [] }
      end
      def songsheet
        plaintext=markup(@data)
        publish(plaintext)
      end
      def break_line
        "\n"
      end
      # Used for extraction of endnotes from paragraphs
      def extract_endnotes(dob='')
        notes=dob.obj.scan(/(?:#{Mx[:en_a_o]}|#{Mx[:en_b_o]})([\d*+]+\s+.+?)(?:#{Mx[:en_a_c]}|#{Mx[:en_b_c]})/)
        @n=[]
        notes.flatten.each do |n| #high cost to deal with <br> appropriately within plaintext, consider
          n=n.dup.to_s
          if n =~/#{Mx[:br_line]}|#{Mx[:br_nl]}/
            fix = n.split(/#{Mx[:br_line]}|#{Mx[:br_nl]}/) #watch #added
            fix.each do |x|
              unless x.empty? then @n << x
              end
            end
          else                     @n << n
          end
        end
        notes=@n.flatten
        notes.each do |e|
          util=(e.to_s =~/^\[[\d*+]+\]:/) \
          ? (SiSU_TextUtils::Wrap.new(e.to_s,@wrap_width,4,1))
          : (SiSU_TextUtils::Wrap.new(e.to_s,@wrap_width,1,1))
          wrap=util.line_wrap
          wrap=if wrap =~ /^\s*[\d*+]+\s+.+?\s*\Z/m
            wrap.gsub(/^(\s*)([\d*+]+)\s+(.+?)\s*\Z/m, <<-GSUB
\\1[\\2]: \\3
              GSUB
            )
          else
            wrap.gsub(/^(.+)\Z/m, <<-GSUB
\\1
              GSUB
            )
          end
          @@endnotes[:para] << "-#{wrap}"
          @@endnotes[:end] << '' << wrap
        end
        @@endnotes
      end
      def plaintext_metadata
        array=SiSU_Metadata::Summary.new(@md).plaintext.metadata
        array.each do |meta|
          tag,inf=meta.scan(/^.+?:\s|.+/)
          if tag and inf
            util=SiSU_TextUtils::Wrap.new(inf,@wrap_width,15,1)
            txt=util.line_wrap
            @plaintext[:metadata] <<<<WOK

#{@tab}#{tag}#{txt}
WOK
          end
        end
      end
      def plaintext_tail
#       env=SiSU_Env::InfoEnv.new(@md.fns)
        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}#{break_line}Version number: #{@md.sc_number}#{break_line}Version date:   #{@md.sc_date}#{break_line}"
        else ''
        end
        @plaintext[:tail] <<<<WOK
#{break_line}
plaintext (plain text):
   #{@md.file.output_path.markdown.url}/#{@md.file.base_filename.markdown}#{break_line}
Other versions of this document: #{break_line}
manifest:
   #{@md.file.output_path.manifest.url}/#{@md.file.base_filename.manifest}#{break_line}
at:
   #{@md.file.output_path.base.url}#{break_line}

#{sc}
,* #{generator}
,* #{rubyv}
,* #{lastdone}
,* SiSU #{the_url.sisu_txt}
WOK
      end
      def heading_decorated_inline(dob)
        if dob.is==:heading
          heading_inline = case dob.lc
          when 0 then decorate.heading.inline.l0
          when 1 then decorate.heading.inline.l1
          when 2 then decorate.heading.inline.l2
          when 3 then decorate.heading.inline.l3
          when 4 then decorate.heading.inline.l4
          when 5 then decorate.heading.inline.l5
          when 6 then decorate.heading.inline.l6
          end
          heading_inline + ' ' +  dob.obj + ' ' + heading_inline
        end
      end
      def heading_decorated_underscore(dob,times,p_num)
        if dob.is==:heading
          #times=@wrap_width if times > @wrap_width
          case dob.lc
          when 0 then decorate.heading.underscore.l0*times + p_num << break_line*2
          when 1 then decorate.heading.underscore.l1*times + p_num << break_line*2
          when 2 then decorate.heading.underscore.l2*times + p_num << break_line*2
          when 3 then decorate.heading.underscore.l3*times + p_num << break_line*2
          when 4 then decorate.heading.underscore.l4*times + p_num << break_line*2
          when 5 then decorate.heading.underscore.l5*times + p_num << break_line*2
          when 6 then decorate.heading.underscore.l6*times + p_num << break_line*2
          end
        end
      end
      def plaintext_structure(dob='',p_num='') #% Used to extract the structure of a document
        heading_decoration=:inline #(:inline|:underscore) #switch heading decoration between inline & underscore options
        util=nil
        wrapped=if dob.is==:para \
        || dob.is==:heading
          if dob.is==:heading
            util=(heading_decoration== :inline) \
            ? (SiSU_TextUtils::Wrap.new(heading_decorated_inline(dob),@wrap_width,0))
            : (SiSU_TextUtils::Wrap.new(dob.obj,@wrap_width,0))
          elsif dob.is==:para
            if dob.hang \
            and dob.hang =~/[0-9]/ \
            and dob.indent != dob.hang
              util=SiSU_TextUtils::Wrap.new(dob.obj,@wrap_width,dob.indent.to_i*2,dob.hang.to_i*2)
              #util=SiSU_TextUtils::Wrap.new(dob.obj,@wrap_width,dob.hang.to_i*2,0)
            elsif dob.indent =~/[1-9]/
              util=if dob.bullet_
                SiSU_TextUtils::Wrap.new("* #{dob.obj}",@wrap_width,dob.indent.to_i*2)
              else SiSU_TextUtils::Wrap.new(dob.obj,@wrap_width,dob.indent.to_i*2)
              end
            else
              util=if dob.bullet_
                SiSU_TextUtils::Wrap.new("* #{dob.obj}",@wrap_width,0)
              else SiSU_TextUtils::Wrap.new(dob.obj,@wrap_width,0)
              end
            end
          else util=SiSU_TextUtils::Wrap.new(dob.obj,@wrap_width,0)
          end
          dob.is==:heading ? util.no_wrap_no_breaks : util.line_wrap
        end
        if heading_decoration== :underscore \
        and dob.is==:heading
          @plaintext[:body] << wrapped + p_num # main text, contents, body KEEP
          @plaintext[:body] << heading_decorated_underscore(dob,wrapped.length,p_num)
        else
          @plaintext[:body] << wrapped + p_num << break_line # main text, contents, body KEEP
        end
        if @@endnotes[:para] \
        and not @@endnotes_
          @@endnotes[:para].each {|e| @plaintext[:body] << e << break_line}
        elsif @@endnotes[:para] \
        and @@endnotes_
        end
        @@endnotes[:para]=[]
      end
      def markup(data)                                                       # Used for major markup instructions
        SiSU_Env::InfoEnv.new(@md.fns)
        @data_mod,@endnotes,@level,@cont,@copen,@plaintext_contents_close=Array.new(6){[]}
        (0..6).each { |x| @cont[x]=@level[x]=false }
        (4..6).each { |x| @plaintext_contents_close[x]='' }
        plaintext_tail #($1,$2)
        plaintext_metadata
        table_message='[table conversion awaited, see other document formats]'
        data.each do |dob|
          dob.obj=dob.obj.gsub(/#{Mx[:gr_o]}Th?#{Mx[:tc_p]}.+/um,"#{break_line}#{table_message}"). #fix
            gsub(/.+?#{Mx[:gl_o]}-##{Mx[:gl_c]}/,'').                              # remove dummy headings (used by html) #check also [~-]#
            gsub(/#{Mx[:fa_bold_o]}(.+?)#{Mx[:fa_bold_c]}/,
              "#{decorate.bold.open}\\1#{decorate.bold.close}").
            gsub(/#{Mx[:fa_italics_o]}(.+?)#{Mx[:fa_italics_c]}/,
              "#{decorate.italics.open}\\1#{decorate.italics.close}").
            gsub(/#{Mx[:fa_underscore_o]}(.+?)#{Mx[:fa_underscore_c]}/,
              "#{decorate.underscore.open}\\1#{decorate.underscore.close}").
            gsub(/#{Mx[:fa_subscript_o]}(.+?)#{Mx[:fa_subscript_c]}/,
              "#{decorate.subscript.open}\\1#{decorate.subscript.close}").
            gsub(/#{Mx[:fa_superscript_o]}(.+?)#{Mx[:fa_superscript_c]}/,
              "#{decorate.superscript.open}\\1#{decorate.superscript.close}").
            gsub(/#{Mx[:fa_insert_o]}(.+?)#{Mx[:fa_insert_c]}/,
              "#{decorate.insert.open}\\1#{decorate.insert.close}").
            gsub(/#{Mx[:fa_cite_o]}(.+?)#{Mx[:fa_cite_c]}/,
              "#{decorate.cite.open}\\1#{decorate.cite.close}").
            gsub(/#{Mx[:fa_strike_o]}(.+?)#{Mx[:fa_strike_c]}/,
              "#{decorate.strike.open}\\1#{decorate.strike.close}").
            gsub(/#{Mx[:fa_monospace_o]}(.+?)#{Mx[:fa_monospace_c]}/,
              "#{decorate.monospace.open}\\1#{decorate.monospace.close}")
          unless dob.is==:code
            dob.obj=dob.obj.gsub(/#{Mx[:lnk_o]}(.+?)#{Mx[:lnk_c]}#{Mx[:rel_o]}\S+?#{Mx[:rel_c]}/,'\1').
              gsub(/#{Mx[:url_o]}_(\S+?)#{Mx[:url_c]}/,'\1').
              gsub(/#{Mx[:lnk_o]}(.+?)#{Mx[:lnk_c]}#{Mx[:url_o]}(\S+?)#{Mx[:url_c]}/,'\1 [link: <\2>]').
              gsub(/#{Mx[:lnk_o]}(.+?)#{Mx[:lnk_c]}image/,'\1 [link: local image]').
              gsub(/#{Mx[:url_o]}(\S+?)#{Mx[:url_c]}/,"#{the_text.url_open}\\1#{the_text.url_close}")
            extract_endnotes(dob)
            dob.obj=dob.obj.gsub(/#{Mx[:en_a_o]}([\d*+]+)\s+(?:.+?)#{Mx[:en_a_c]}/,'[^\1]'). # endnote marker marked up
              gsub(/#{Mx[:en_b_o]}([\d*+]+)\s+(?:.+?)#{Mx[:en_b_c]}/,'[^\1]'). # endnote marker marked up
              gsub(/#{Mx[:gl_o]}(?:#lt|#060)#{Mx[:gl_c]}/,'<').
              gsub(/#{Mx[:gl_o]}(?:#gt|#062)#{Mx[:gl_c]}/,'>').
              gsub(/#{Mx[:gl_o]}#(?:038|amp)#{Mx[:gl_c]}/,'&').
              gsub(/#{Mx[:gl_o]}#033#{Mx[:gl_c]}/,'!').
              gsub(/#{Mx[:gl_o]}#035#{Mx[:gl_c]}/,'#').
              gsub(/#{Mx[:gl_o]}#042#{Mx[:gl_c]}/,'*').
              gsub(/#{Mx[:gl_o]}#045#{Mx[:gl_c]}/,'-').
              gsub(/#{Mx[:gl_o]}#047#{Mx[:gl_c]}/,'/').
              gsub(/#{Mx[:gl_o]}#095#{Mx[:gl_c]}/,'_').
              gsub(/#{Mx[:gl_o]}#123#{Mx[:gl_c]}/,'{').
              gsub(/#{Mx[:gl_o]}#125#{Mx[:gl_c]}/,'}').
              gsub(/#{Mx[:gl_o]}#126#{Mx[:gl_c]}/,'~').
              gsub(/#{Mx[:gl_o]}#169#{Mx[:gl_c]}/,'©').
              gsub(/#{Mx[:gl_o]}#092#{Mx[:gl_c]}/,'\\')
          end
          dob.obj=if dob.of==:block                                   # watch
            dob.obj.gsub(/#{Mx[:gl_o]}●#{Mx[:gl_c]}/m,"* ").
              gsub(/\n?#{Mx[:br_line]}\n?|\n?#{Mx[:br_nl]}\n?/m,break_line)
          else dob.obj.gsub(/\n?#{Mx[:br_line]}\n?|\n?#{Mx[:br_nl]}\n?/m,break_line*2)
          end
          if dob.is==:code
            dob.obj=dob.obj.gsub(/(^|[^}])_([<>])/m,'\1\2'). # _> _<
              gsub(/(^|[^}])_([<>])/m,'\1\2') # _<_<
          end
          dob.obj=dob.obj.gsub(/#{Mx[:url_o]}_(\S+?)#{Mx[:url_c]}/,'\1').
            gsub(/<a href=".+?">(.+?)<\/a>/m,'\1').
            gsub(/#{Mx[:mk_o]}:name#(\S+?)#{Mx[:mk_c]}/,'').                       # remove name links
            gsub(/&nbsp;|#{Mx[:nbsp]}/,' ').                                       # decide on
            gsub(/(?:^|[^_\\])#{Mx[:lnk_o]}(\S+?\.(?:png|jpg|gif)) .+?#{Mx[:lnk_c]}#{Mx[:url_o]}\S+?#{Mx[:url_c]}/,'    [ \1 ]'). #"[ #{dir.url.images_local}\/\\1 ]")
            gsub(/(?:^|[^_\\])#{Mx[:lnk_o]}(\S+?\.(?:png|jpg|gif)) .+?#{Mx[:lnk_c]}image/,'    [ \1 ]').
            gsub(/(?:^|[^_\\])\{\s*\S+?\.(?:png|jpg|gif)\s+.+?"(.*?)"\s*\}\S+/,'[image: "\1"]')
          if dob.obj !~/(^#{Rx[:meta]}|#{Mx[:br_eof]}|#{Mx[:br_endnotes]})/
            p_num=''
            #ocn
            if dob.is==:heading \
            or dob.is==:para
              plaintext_structure(dob,p_num)
            elsif dob.is==:group \
            or dob.is==:block \
            or dob.is==:verse \
            or dob.is==:code \
            or dob.is==:table
              @plaintext[:body] << dob.obj + p_num << break_line
            elsif dob.is==:break
              sp=' '
              ln='-'
              @plaintext[:body] <<=if dob.obj==Mx[:br_page] \
              or dob.obj==Mx[:br_page_new] \
              or dob.obj==Mx[:br_page_line]
                "#{break_line}#{ln*40}#{break_line*2}"
              elsif dob.obj ==Mx[:br_obj]
                "#{break_line}#{sp*20}*  *  *#{break_line*2}"
              end # following empty line (break_line) missing, fix
            end
            dob='' if (dob.obj =~/<a name="n\d+">/ \
              and dob.obj =~/^(-\{{2}~\d+|<!e[:_]\d+!>)/) # -endnote
            if dob ## Clean Prepared Text
              dob.obj=dob.obj.gsub(/<!.+!>/,' ').
                gsub(/<:\S+>/,' ')
            end
          end
        end
        @plaintext
      end
      def publish(plaintext)
        divider='='
        content=[]
        content << plaintext[:open]
        content << plaintext[:head]
        content << plaintext[:body]
        content << @@endnotes[:end] if @@endnotes_
        content << "#{break_line}#{divider*@wrap_width}#{break_line}"
        content << plaintext[:metadata]
        content << "#{break_line}#{divider*@wrap_width}#{break_line}" if @md.stmp =~/\w+/ #not used?
        content << plaintext[:tail]
        outputfile=SiSU_Env::FileOp.new(@md).write_file.markdown
        Txt_Output::Output.new.document(content,outputfile)
        @@endnotes={ para: [], end: [] }
      end
    end
  end
end
__END__
#+END_SRC

*** txt_markdown_decorate.rb

#+HEADER: :tangle "../lib/sisu/txt_markdown_decorate.rb"
#+BEGIN_SRC ruby
#<<sisu_document_header>>
module SiSU_Decorate_Txt_Markdown
  def decorate
    def heading
      def inline                   #atx
        def l0
          '#'
        end
        def l1
          '##'
        end
        def l2
          '###'
        end
        def l3
          '####'
        end
        def l4
          '#####'
        end
        def l5
          '######'
        end
        self
      end
      def underscore               #Setext
        def l1
          '='
        end
        def l2
          '-'
        end
        def l3
          ''
        end
        def l4
          ''
        end
        def l5
          ''
        end
        def l6
          ''
        end
        self
      end
      self
    end
    def bold
      def open
        '**'
      end
      def close
        '**'
      end
      self
    end
    def italics
      def open
        '*'
      end
      def close
        '*'
      end
      self
    end
    def underscore
      def open
        '_'
      end
      def close
        '_'
      end
      self
    end
   #def emphasis
   #  def open
   #    ''
   #  end
   #  def close
   #    ''
   #  end
   #  self
   #end
    def cite
      def open
        '"'
      end
      def close
        '"'
      end
      self
    end
    def insert
      def open
        '+'
      end
      def close
        '+'
      end
      self
    end
    def strike
      def open
        '-'
      end
      def close
        '-'
      end
      self
    end
    def superscript
      def open
        '^'
      end
      def close
        '^'
      end
      self
    end
    def subscript
      def open
        '['
      end
      def close
        ']'
      end
      self
    end
    def hilite
      def open
        '**'
      end
      def close
        '**'
      end
      self
    end
    def monospace
      def open
        '`'
      end
      def close
        '`'
      end
      self
    end
    self
  end
end
__END__
#+END_SRC

** orgmode
*** txt_orgmode.rb

#+HEADER: :tangle "../lib/sisu/txt_orgmode.rb"
#+BEGIN_SRC ruby
#<<sisu_document_header>>
module SiSU_Txt_OrgMode
  require_relative 'ao'                                 # ao.rb
  require_relative 'se'                                 # se.rb
    include SiSU_Env
  require_relative 'shared_metadata'                    # shared_metadata.rb
  require_relative 'generic_parts'                      # generic_parts.rb
  require_relative 'txt_read'                           # txt_read.rb
  require_relative 'txt_shared'                         # txt_shared.rb
  require_relative 'txt_orgmode_decorate'               # txt_orgmode_decorate.rb
  require_relative 'txt_output'                         # txt_output.rb
  include SiSU_Param
  @@alt_id_count,@@alt_id_count=0,0
  @@tablefoot=''
  class Source
    include SiSU_Txt_Read
    def initialize(opt)
      @opt=opt
      unless @opt.fns =~/(.+?)\.(?:-|ssm\.)?sst$/
        puts "#{sf} not a processed file type"
      end
    end
    def read
      begin
        md=SiSU_Param::Parameters.new(@opt).get
        specific={
          description:     'OrgMode (plaintext utf-8)',
          output_path:     md.file.output_path.orgmode.dir,
          output_file:     md.file.base_filename.orgmode,
        }
        read_generic(@opt,specific)
        SiSU_Txt_OrgMode::Source::Scroll.new(md,@ao_array,@wrap_width).songsheet
      rescue
        SiSU_Errors::Rescued.new($!,$@,@opt.selections.str,@opt.fns).location do
          __LINE__.to_s + ':' + __FILE__
        end
      ensure
      end
    end
    private
    class Scroll <Source
      include SiSU_Parts_Generic
      include SiSU_TextUtils
      include SiSU_Decorate_Txt_OrgMode
      @@endnotes={ para: [], end: [] }
      def initialize(md,data,wrap_width)
        @md,@data,@wrap_width=md,data,wrap_width
        @env=SiSU_Env::InfoEnv.new(@md.fns)
        @tab="\t"
        @@endnotes_=case md.opt.selections.str
        when /--footnote/ then false
        when /--endnote/  then true
        else                   true
        end
        @plaintext={ body: [], open: [], close: [], head: [], endnotes: [], metadata: [], tail: [] }
        @plaintext[:head]= <<-WOK
#+TITLE: #{@md.title.short}
#+AUTHOR: #{@md.creator.author}
#+EMAIL: #{@md.creator.email}
#+STARTUP: indent content
#+LANGUAGE: #{@md.opt.lng}
#+OPTIONS: H:3 num:nil toc:t \\n:nil @:t ::t |:t ^:nil _:nil -:t f:t *:t <:t
#+OPTIONS: TeX:t LaTeX:t skip:nil d:nil todo:t pri:nil tags:not-in-toc
#+OPTIONS: author:nil email:nil creator:nil timestamp:nil
#+EXPORT_SELECT_TAGS: export
#+EXPORT_EXCLUDE_TAGS: noexport

        WOK
      end
      def songsheet
        plaintext=markup(@data)
        publish(plaintext)
      end
      def break_line
        "\n"
      end
      def extract_endnotes(dob='')
        notes=dob.obj.
          scan(/(?:#{Mx[:en_a_o]}|#{Mx[:en_b_o]})([\d*+]+\s+.+?)(?:#{Mx[:en_a_c]}|#{Mx[:en_b_c]})/)
        @n=[]
        notes.flatten.each do |n| #high cost to deal with <br> appropriately within plaintext, consider
          n=n.dup.to_s
          if n =~/#{Mx[:br_line]}|#{Mx[:br_nl]}/
            fix = n.split(/#{Mx[:br_line]}|#{Mx[:br_nl]}/) #watch #added
            fix.each do |x|
              unless x.empty? then @n << x
              end
            end
          else                     @n << n
          end
        end
        notes=@n.flatten
        notes.each do |e|
          util=(e.to_s =~/^\[[\d*+]+\]:/) \
          ? (SiSU_TextUtils::Wrap.new(e.to_s,@wrap_width,4,1))
          : (SiSU_TextUtils::Wrap.new(e.to_s,@wrap_width,1,1))
          wrap=util.line_wrap
          wrap=if wrap =~ /^\s*[\d*+]+\s+.+?\s*\Z/m
            wrap.gsub(/^(\s*)([\d*+]+)\s+(.+?)\s*\Z/m, <<-GSUB
\\1[fn:\\2] \\3
              GSUB
            )
          else
            wrap.gsub(/^(.+)\Z/m, <<-GSUB
\\1
              GSUB
            )
          end
          @@endnotes[:para] << "-#{wrap}"
          @@endnotes[:end] << '' << wrap.strip
        end
        @@endnotes
      end
      # Used for extraction of endnotes from paragraphs
      def plaintext_metadata
        array=SiSU_Metadata::Summary.new(@md).plaintext.metadata
        array.each do |meta|
          tag,inf=meta.scan(/^.+?:\s|.+/)
          if tag and inf
            util=SiSU_TextUtils::Wrap.new(inf,@wrap_width,15,1)
            txt=util.line_wrap
            @plaintext[:metadata] <<<<WOK

#{@tab}#{tag}#{txt}
WOK
          end
        end
      end
      def plaintext_tail
#       env=SiSU_Env::InfoEnv.new(@md.fns)
        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}#{break_line}Version number: #{@md.sc_number}#{break_line}Version date:   #{@md.sc_date}#{break_line}"
        else ''
        end
        @plaintext[:tail] <<<<WOK
,** Metadata
#{break_line}
plaintext (plain text):
   #{@md.file.output_path.orgmode.url}/#{@md.file.base_filename.orgmode}#{break_line}
Other versions of this document: #{break_line}
manifest:
   #{@md.file.output_path.manifest.url}/#{@md.file.base_filename.manifest}#{break_line}
at:
   #{@md.file.output_path.base.url}#{break_line}

  #{sc}
  * #{generator}
  * #{rubyv}
  * #{lastdone}
  * SiSU #{the_url.sisu_txt}
WOK
      end
      def heading_decorated_inline(dob)
        if dob.is==:heading
          heading_inline = case dob.lc
          when 0 then decorate.heading.inline.l0
          when 1 then decorate.heading.inline.l1
          when 2 then decorate.heading.inline.l2
          when 3 then decorate.heading.inline.l3
          when 4 then decorate.heading.inline.l4
          when 5 then decorate.heading.inline.l5
          when 6 then decorate.heading.inline.l6
          end
          heading_inline + ' ' +  dob.obj
        end
      end
      def plaintext_structure(dob='',p_num='') #% Used to extract the structure of a document
        heading_decoration=:inline #(:inline|:underscore) #switch heading decoration between inline & underscore options
        util=nil
        wrapped=if dob.is==:para \
        || dob.is==:heading
          if dob.is==:heading
            util=(heading_decoration== :inline) \
            ? (SiSU_TextUtils::Wrap.new(heading_decorated_inline(dob),@wrap_width,0))
            : (SiSU_TextUtils::Wrap.new(dob.obj,@wrap_width,0))
          elsif dob.is==:para
            if dob.hang \
            and dob.hang =~/[0-9]/ \
            and dob.indent != dob.hang
              util=SiSU_TextUtils::Wrap.new(dob.obj,@wrap_width,dob.indent.to_i*2,dob.hang.to_i*2)
              #util=SiSU_TextUtils::Wrap.new(dob.obj,@wrap_width,dob.hang.to_i*2,0)
            elsif dob.indent =~/[1-9]/
              util=if dob.bullet_
                SiSU_TextUtils::Wrap.new("* #{dob.obj}",@wrap_width,dob.indent.to_i*2)
              else SiSU_TextUtils::Wrap.new(dob.obj,@wrap_width,dob.indent.to_i*2)
              end
            else
              util=if dob.bullet_
                SiSU_TextUtils::Wrap.new("* #{dob.obj}",@wrap_width,0)
              else SiSU_TextUtils::Wrap.new(dob.obj,@wrap_width,0)
              end
            end
          else util=SiSU_TextUtils::Wrap.new(dob.obj,@wrap_width,0)
          end
          dob.is==:heading ? util.no_wrap_no_breaks : util.line_wrap
        end
        if dob.is==:para \
        || dob.is==:heading
          @plaintext[:body] << wrapped + p_num << break_line # main text, contents, body KEEP
        end
# remove ...
        if @@endnotes[:para] \
        and not @@endnotes_
          @@endnotes[:para].each {|e| @plaintext[:body] << e << break_line}
        elsif @@endnotes[:para] \
        and @@endnotes_
          @@endnotes[:para].each {|e| @plaintext[:endnotes] << e << break_line}
        end
        @@endnotes[:para]=[]
      end
      def markup(data)                                                       # Used for major markup instructions
        SiSU_Env::InfoEnv.new(@md.fns)
        @data_mod,@endnotes,@level,@cont,@copen,@plaintext_contents_close=Array.new(6){[]}
        (0..6).each { |x| @cont[x]=@level[x]=false }
        (4..6).each { |x| @plaintext_contents_close[x]='' }
        plaintext_tail #($1,$2)
        plaintext_metadata
        table_message='[table conversion awaited, see other document formats]'
        data.each do |dob|
          dob.obj=dob.obj.gsub(/#{Mx[:gr_o]}Th?#{Mx[:tc_p]}.+/um,"#{break_line}#{table_message}"). #fix
            gsub(/.+?#{Mx[:gl_o]}-##{Mx[:gl_c]}/,'').                              # remove dummy headings (used by html) #check also [~-]#
            gsub(/#{Mx[:fa_bold_o]}(.+?)#{Mx[:fa_bold_c]}/,
              "#{decorate.bold.open}\\1#{decorate.bold.close}").
            gsub(/#{Mx[:fa_italics_o]}(.+?)#{Mx[:fa_italics_c]}/,
              "#{decorate.italics.open}\\1#{decorate.italics.close}").
            gsub(/#{Mx[:fa_underscore_o]}(.+?)#{Mx[:fa_underscore_c]}/,
              "#{decorate.underscore.open}\\1#{decorate.underscore.close}").
            gsub(/#{Mx[:fa_subscript_o]}(.+?)#{Mx[:fa_subscript_c]}/,
              "#{decorate.subscript.open}\\1#{decorate.subscript.close}").
            gsub(/#{Mx[:fa_superscript_o]}(.+?)#{Mx[:fa_superscript_c]}/,
              "#{decorate.superscript.open}\\1#{decorate.superscript.close}").
            gsub(/#{Mx[:fa_insert_o]}(.+?)#{Mx[:fa_insert_c]}/,
              "#{decorate.insert.open}\\1#{decorate.insert.close}").
            gsub(/#{Mx[:fa_cite_o]}(.+?)#{Mx[:fa_cite_c]}/,
              "#{decorate.cite.open}\\1#{decorate.cite.close}").
            gsub(/#{Mx[:fa_strike_o]}(.+?)#{Mx[:fa_strike_c]}/,
              "#{decorate.strike.open}\\1#{decorate.strike.close}").
            gsub(/#{Mx[:fa_monospace_o]}(.+?)#{Mx[:fa_monospace_c]}/,
              "#{decorate.monospace.open}\\1#{decorate.monospace.close}")
          unless dob.is==:code
            dob.obj=dob.obj.gsub(/#{Mx[:lnk_o]}(.+?)#{Mx[:lnk_c]}#{Mx[:rel_o]}\S+?#{Mx[:rel_c]}/,'\1').
              gsub(/#{Mx[:url_o]}_(\S+?)#{Mx[:url_c]}/,'[[\1]]').
              gsub(/#{Mx[:lnk_o]}(.+?)#{Mx[:lnk_c]}#{Mx[:url_o]}(\S+?)#{Mx[:url_c]}/,'[[\2][\1]]').
              gsub(/#{Mx[:lnk_o]}(.+?)#{Mx[:lnk_c]}image/,'[[\1]] [link: local image]').
              gsub(/#{Mx[:url_o]}(\S+?)#{Mx[:url_c]}/,'[[\1]]') #urls
            extract_endnotes(dob)
            dob.obj=dob.obj.gsub(/#{Mx[:en_a_o]}([\d*+]+)\s+(?:.+?)#{Mx[:en_a_c]}/,'[fn:\1]'). # endnote marker marked up
              gsub(/#{Mx[:en_b_o]}([\d*+]+)\s+(?:.+?)#{Mx[:en_b_c]}/,'[fn:\1]'). # endnote marker marked up
              gsub(/#{Mx[:gl_o]}(?:#lt|#060)#{Mx[:gl_c]}/,'<').
              gsub(/#{Mx[:gl_o]}(?:#gt|#062)#{Mx[:gl_c]}/,'>').
              gsub(/#{Mx[:gl_o]}#(?:038|amp)#{Mx[:gl_c]}/,'&').
              gsub(/#{Mx[:gl_o]}#033#{Mx[:gl_c]}/,'!').
              gsub(/#{Mx[:gl_o]}#035#{Mx[:gl_c]}/,'#').
              gsub(/#{Mx[:gl_o]}#042#{Mx[:gl_c]}/,'*').
              gsub(/#{Mx[:gl_o]}#045#{Mx[:gl_c]}/,'-').
              gsub(/#{Mx[:gl_o]}#047#{Mx[:gl_c]}/,'/').
              gsub(/#{Mx[:gl_o]}#095#{Mx[:gl_c]}/,'_').
              gsub(/#{Mx[:gl_o]}#123#{Mx[:gl_c]}/,'{').
              gsub(/#{Mx[:gl_o]}#125#{Mx[:gl_c]}/,'}').
              gsub(/#{Mx[:gl_o]}#126#{Mx[:gl_c]}/,'~').
              gsub(/#{Mx[:gl_o]}#169#{Mx[:gl_c]}/,'©').
              gsub(/#{Mx[:gl_o]}#092#{Mx[:gl_c]}/,'\\')
          end
          dob.obj=if dob.of==:block                                   # watch
            dob.obj.gsub(/#{Mx[:gl_o]}●#{Mx[:gl_c]}/m,"* ").
              gsub(/\n?#{Mx[:br_line]}\n?|\n?#{Mx[:br_nl]}\n?/m,break_line)
          else dob.obj.gsub(/\n?#{Mx[:br_line]}\n?|\n?#{Mx[:br_nl]}\n?/m,break_line*2)
          end
          if dob.is==:code
            dob.obj=dob.obj.gsub(/(^|[^}])_([<>])/m,'\1\2'). # _> _<
              gsub(/(^|[^}])_([<>])/m,'\1\2'). # _<_<
              gsub(/^\*/m,',*')
            dob.obj = '#+BEGIN_SRC sh :tangle no :padline no :exports none   :noweb yes' + "\n" + dob.obj + '#+END_SRC'
          end
          dob.obj=dob.obj.gsub(/#{Mx[:url_o]}_(\S+?)#{Mx[:url_c]}/,'\1').
            gsub(/<a href=".+?">(.+?)<\/a>/m,'\1').
            gsub(/#{Mx[:mk_o]}:name#(\S+?)#{Mx[:mk_c]}/,'').                       # remove name links
            gsub(/&nbsp;|#{Mx[:nbsp]}/,' ').                                       # decide on
            gsub(/(?:^|[^_\\])#{Mx[:lnk_o]}(\S+?\.(?:png|jpg|gif)) .+?#{Mx[:lnk_c]}#{Mx[:url_o]}\S+?#{Mx[:url_c]}/,'    [ \1 ]'). #"[ #{dir.url.images_local}\/\\1 ]")
            gsub(/(?:^|[^_\\])#{Mx[:lnk_o]}(\S+?\.(?:png|jpg|gif)) .+?#{Mx[:lnk_c]}image/,'    [ \1 ]').
            gsub(/(?:^|[^_\\])\{\s*\S+?\.(?:png|jpg|gif)\s+.+?"(.*?)"\s*\}\S+/,'[image: "\1"]')
          if dob.obj !~/(^#{Rx[:meta]}|#{Mx[:br_eof]}|#{Mx[:br_endnotes]})/
            p_num=''
            #ocn
            if dob.is==:heading \
            or dob.is==:para
              plaintext_structure(dob,p_num)
            elsif dob.is==:group \
            or dob.is==:block \
            or dob.is==:verse \
            or dob.is==:code \
            or dob.is==:table
              @plaintext[:body] << dob.obj + p_num << break_line
            elsif dob.is==:break
              sp=' '
              ln='<' #ln='-'
              @plaintext[:body] <<=if dob.obj==Mx[:br_page] \
              or dob.obj==Mx[:br_page_new] \
              or dob.obj==Mx[:br_page_line]
                "#{break_line}#{ln*40}#{break_line*2}"
              elsif dob.obj ==Mx[:br_obj]
                "#{break_line}#{sp*20}*  *  *#{break_line*2}"
              end # following empty line (break_line) missing, fix
            end
            dob='' if (dob.obj =~/<a name="n\d+">/ \
              and dob.obj =~/^(-\{{2}~\d+|<!e[:_]\d+!>)/) # -endnote
            if dob ## Clean Prepared Text
              dob.obj=dob.obj.gsub(/<!.+!>/,' ').
                gsub(/<:\S+>/,' ')
            end
          end
        end
        @plaintext
      end
      def publish(plaintext)
        divider='='
        content=[]
        content << plaintext[:open]
        content << plaintext[:head]
        content << plaintext[:body]
        if @@endnotes_
          content << '** Endnotes' <<  @@endnotes[:end]
        end
        content << plaintext[:metadata]
        content << "#{break_line}#{divider*@wrap_width}#{break_line}" if @md.stmp =~/\w+/ #not used?
        content << plaintext[:tail]
        outputfile=SiSU_Env::FileOp.new(@md).write_file.orgmode
        Txt_Output::Output.new.document(content,outputfile)
        @@endnotes={ para: [], end: [] }
      end
    end
  end
end
__END__
#+END_SRC

*** txt_orgmode_decorate.rb

#+HEADER: :tangle "../lib/sisu/txt_orgmode_decorate.rb"
#+BEGIN_SRC ruby
#<<sisu_document_header>>
module SiSU_Decorate_Txt_OrgMode
  def decorate
    def heading
      def inline
        def l0
          '*'
        end
        def l1
          '**'
        end
        def l2
          '***'
        end
        def l3
          '****'
        end
        def l4
          '*****'
        end
        def l5
          '******'
        end
        self
      end
      self
    end
    def bold
      def open
        '*'
      end
      def close
        '*'
      end
      self
    end
    def italics
      def open
        '/'
      end
      def close
        '/'
      end
      self
    end
    def underscore
      def open
        ''
      end
      def close
        ''
      end
      self
    end
   #def emphasis
   #  def open
   #    ''
   #  end
   #  def close
   #    ''
   #  end
   #  self
   #end
    def cite
      def open
        '"'
      end
      def close
        '"'
      end
      self
    end
    def insert
      def open
        ''
      end
      def close
        ''
      end
      self
    end
    def strike
      def open
        '+'
      end
      def close
        '+'
      end
      self
    end
    def superscript
      def open
        '^'
      end
      def close
        '^'
      end
      self
    end
    def subscript
      def open
        '~'
      end
      def close
        '~'
      end
      self
    end
    def hilite #bold
      def open
        '*'
      end
      def close
        '*'
      end
      self
    end
    def monospace
      def open
        '~'
      end
      def close
        '~'
      end
      self
    end
    self
  end
end
__END__
#+END_SRC

** plain
*** txt_plain.rb

#+HEADER: :tangle "../lib/sisu/txt_plain.rb"
#+BEGIN_SRC ruby
#<<sisu_document_header>>
module SiSU_Txt_Plain
  require_relative 'ao'                                 # ao.rb
  require_relative 'se'                                 # se.rb
    include SiSU_Env
  require_relative 'shared_metadata'                    # shared_metadata.rb
  require_relative 'generic_parts'                      # generic_parts.rb
  require_relative 'txt_read'                           # txt_read.rb
  require_relative 'txt_shared'                         # txt_shared.rb
  require_relative 'txt_plain_decorate'                 # txt_plain_decorate.rb
  require_relative 'txt_output'                         # txt_output.rb
  include SiSU_Param
  @@alt_id_count,@@alt_id_count=0,0
  @@tablefoot=''
  class Source
    include SiSU_Txt_Read
    def initialize(opt)
      @opt=opt
      unless @opt.fns =~/(.+?)\.(?:-|ssm\.)?sst$/
        puts "#{sf} not a processed file type"
      end
    end
    def read
      begin
        md=SiSU_Param::Parameters.new(@opt).get
        specific={
          description:     'Plaintext (utf-8)',
          output_path:     md.file.output_path.txt.dir,
          output_file:     md.file.base_filename.txt,
        }
        read_generic(@opt,specific)
        SiSU_Txt_Plain::Source::Scroll.new(md,@ao_array,@wrap_width).songsheet
      rescue
        SiSU_Errors::Rescued.new($!,$@,@opt.selections.str,@opt.fns).location do
          __LINE__.to_s + ':' + __FILE__
        end
      ensure
      end
    end
    private
    class Scroll <Source
      include SiSU_Parts_Generic
      include SiSU_TextUtils
      include SiSU_Decorate_Txt_Plain
      @@endnotes={ para: [], end: [] }
      def initialize(md,data,wrap_width)
        @md,@data,@wrap_width=md,data,wrap_width
        @env=SiSU_Env::InfoEnv.new(@md.fns)
        @tab="\t"
        @@endnotes_=case md.opt.selections.str
        when /--footnote/ then false
        when /--endnote/  then true
        else                   true
        end
        @plaintext={ body: [], open: [], close: [], head: [], metadata: [], tail: [] }
      end
      def songsheet
        plaintext=markup(@data)
        publish(plaintext)
      end
      def break_line
        "\n"
      end
      # Used for extraction of endnotes from paragraphs
      def extract_endnotes(dob='')
        notes=dob.obj.scan(/(?:#{Mx[:en_a_o]}|#{Mx[:en_b_o]})([\d*+]+\s+.+?)(?:#{Mx[:en_a_c]}|#{Mx[:en_b_c]})/)
        @n=[]
        notes.flatten.each do |n| #high cost to deal with <br> appropriately within plaintext, consider
          n=n.dup.to_s
          if n =~/#{Mx[:br_line]}|#{Mx[:br_nl]}/
            fix = n.split(/#{Mx[:br_line]}|#{Mx[:br_nl]}/) #watch #added
            fix.each do |x|
              unless x.empty?; @n << x
              end
            end
          else                 @n << n
          end
        end
        notes=@n.flatten
        notes.each do |e|
          util=(e.to_s =~/^\[[\d*+]+\]:/) \
          ? (SiSU_TextUtils::Wrap.new(e.to_s,@wrap_width,4,1))
          : (SiSU_TextUtils::Wrap.new(e.to_s,@wrap_width,1,1))
          wrap=util.line_wrap
          wrap=if wrap =~ /^\s*[\d*+]+\s+.+?\s*\Z/m
            wrap.gsub(/^(\s*)([\d*+]+)\s+(.+?)\s*\Z/m, <<-GSUB
\\1[\\2]: \\3
              GSUB
            )
          else
            wrap.gsub(/^(.+)\Z/m, <<-GSUB
\\1
              GSUB
            )
          end
          @@endnotes[:para] << "-#{wrap}"
          @@endnotes[:end] << '' << wrap
        end
        @@endnotes
      end
      def plaintext_metadata
        array=SiSU_Metadata::Summary.new(@md).plaintext.metadata
        array.each do |meta|
          tag,inf=meta.scan(/^.+?:\s|.+/)
          if tag and inf
            util=SiSU_TextUtils::Wrap.new(inf,@wrap_width,15,1)
            txt=util.line_wrap
            @plaintext[:metadata] <<<<WOK

#{@tab}#{tag}#{txt}
WOK
          end
        end
      end
      def plaintext_tail
#       env=SiSU_Env::InfoEnv.new(@md.fns)
        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}#{break_line}Version number: #{@md.sc_number}#{break_line}Version date:   #{@md.sc_date}#{break_line}"
        else ''
        end
        @plaintext[:tail] <<<<WOK
#{break_line}
plaintext (plain text):
   #{@md.file.output_path.txt.url}/#{@md.file.base_filename.txt}#{break_line}
Other versions of this document: #{break_line}
manifest:
   #{@md.file.output_path.manifest.url}/#{@md.file.base_filename.manifest}#{break_line}
at:
   #{@md.file.output_path.base.url}#{break_line}

#{sc}
,* #{generator}
,* #{rubyv}
,* #{lastdone}
,* SiSU #{the_url.sisu_txt}
WOK
      end
      def plaintext_structure(dob='',p_num='') #% Used to extract the structure of a document
        lv=n=n3=nil
        if dob.is==:heading
          lv=dob.ln
          n=lv - 1
          n3=lv + 2
        end
        util=nil
        wrapped=if dob.is==:para \
        || dob.is==:heading
          if dob.is==:para
            if dob.hang \
            and dob.hang =~/[0-9]/ \
            and dob.indent != dob.hang
              util=SiSU_TextUtils::Wrap.new(dob.obj,@wrap_width,dob.indent.to_i*2,dob.hang.to_i*2)
              #util=SiSU_TextUtils::Wrap.new(dob.obj,@wrap_width,dob.hang.to_i*2,0)
            elsif dob.indent =~/[1-9]/
              util=if dob.bullet_
                SiSU_TextUtils::Wrap.new("* #{dob.obj}",@wrap_width,dob.indent.to_i*2)
              else SiSU_TextUtils::Wrap.new(dob.obj,@wrap_width,dob.indent.to_i*2)
              end
            else
              util=if dob.bullet_
                SiSU_TextUtils::Wrap.new("* #{dob.obj}",@wrap_width,0)
              else SiSU_TextUtils::Wrap.new(dob.obj,@wrap_width,0)
              end
            end
          else util=SiSU_TextUtils::Wrap.new(dob.obj,@wrap_width,0)
          end
          util.line_wrap
        end
        if lv
          times=wrapped.length
          times=@wrap_width if times > @wrap_width
          @plaintext[:body] << case lv
          when 0 then wrapped.upcase << break_line << decorate.heading_underscore.l0*times + p_num << break_line*2
          when 1 then wrapped.upcase << break_line << decorate.heading_underscore.l1*times + p_num << break_line*2
          when 2 then wrapped.upcase << break_line << decorate.heading_underscore.l2*times + p_num << break_line*2
          when 3 then wrapped.upcase << break_line << decorate.heading_underscore.l3*times + p_num << break_line*2
          when 4
            unless dob.use_ == :dummy
              wrapped.upcase << break_line << decorate.heading_underscore.l4*times + p_num << break_line*2
            end
          when 5 then wrapped.upcase << break_line << decorate.heading_underscore.l5*times + p_num << break_line*2
          when 6 then wrapped.upcase << break_line << decorate.heading_underscore.l6*times + p_num << break_line*2
          when 7
            wrapped.upcase << break_line << decorate.heading_underscore.l7*times + p_num << break_line*2
          #when 7 then wrapped.upcase << break_line << decorate.heading_underscore.l7*times + p_num << break_line*2
          end
        else
          @plaintext[:body] << wrapped + p_num << break_line # main text, contents, body KEEP
        end
        if @@endnotes[:para] \
        and not @@endnotes_
          @@endnotes[:para].each {|e| @plaintext[:body] << e << break_line}
        elsif @@endnotes[:para] \
        and @@endnotes_
        end
        @@endnotes[:para]=[]
      end
      def ocn_display(dob)
        make=SiSU_Env::ProcessingSettings.new(@md)
        if make.build.plaintext_ocn?
          if defined? dob.ocn \
          and dob.ocn.is_a?(Fixnum)
            (defined? dob.ocn) \
            ? "\n#{Dx[:ocn_o]}#{dob.ocn}#{Dx[:ocn_c]}" \
            : ''
          else ''
          end
        else ''
        end
      end
      def markup(data)                                                       # Used for major markup instructions
        SiSU_Env::InfoEnv.new(@md.fns)
        @data_mod,@endnotes,@level,@cont,@copen,@plaintext_contents_close=Array.new(6){[]}
        (0..7).each { |x| @cont[x]=@level[x]=false }
        (4..7).each { |x| @plaintext_contents_close[x]='' }
        plaintext_tail #($1,$2)
        plaintext_metadata
        table_message='[table omitted, see other document formats]'
        data.each do |dob|
          dob.obj=dob.obj.gsub(/#{Mx[:gr_o]}Th?#{Mx[:tc_p]}.+/um,"#{break_line}#{table_message}"). #fix
            gsub(/.+?#{Mx[:gl_o]}-##{Mx[:gl_c]}/,'').                              # remove dummy headings (used by html) #check also [~-]#
            gsub(/#{Mx[:fa_bold_o]}(.+?)#{Mx[:fa_bold_c]}/,
              "#{decorate.bold.open}\\1#{decorate.bold.close}").
            gsub(/#{Mx[:fa_italics_o]}(.+?)#{Mx[:fa_italics_c]}/,
              "#{decorate.italics.open}\\1#{decorate.italics.close}").
            gsub(/#{Mx[:fa_underscore_o]}(.+?)#{Mx[:fa_underscore_c]}/,
              "#{decorate.underscore.open}\\1#{decorate.underscore.close}").
            gsub(/#{Mx[:fa_subscript_o]}(.+?)#{Mx[:fa_subscript_c]}/,
              "#{decorate.subscript.open}\\1#{decorate.subscript.close}").
            gsub(/#{Mx[:fa_superscript_o]}(.+?)#{Mx[:fa_superscript_c]}/,
              "#{decorate.superscript.open}\\1#{decorate.superscript.close}").
            gsub(/#{Mx[:fa_insert_o]}(.+?)#{Mx[:fa_insert_c]}/,
              "#{decorate.insert.open}\\1#{decorate.insert.close}").
            gsub(/#{Mx[:fa_cite_o]}(.+?)#{Mx[:fa_cite_c]}/,
              "#{decorate.cite.open}\\1#{decorate.cite.close}").
            gsub(/#{Mx[:fa_strike_o]}(.+?)#{Mx[:fa_strike_c]}/,
              "#{decorate.strike.open}\\1#{decorate.strike.close}").
            gsub(/#{Mx[:fa_monospace_o]}(.+?)#{Mx[:fa_monospace_c]}/,
              "#{decorate.monospace.open}\\1#{decorate.monospace.close}")
          unless dob.is==:code
            dob.obj=dob.obj.gsub(/#{Mx[:lnk_o]}(.+?)#{Mx[:lnk_c]}#{Mx[:rel_o]}\S+?#{Mx[:rel_c]}/,'\1').
              gsub(/#{Mx[:url_o]}_(\S+?)#{Mx[:url_c]}/,'\1').
              gsub(/#{Mx[:lnk_o]}(.+?)#{Mx[:lnk_c]}#{Mx[:url_o]}(\S+?)#{Mx[:url_c]}/,'\1 [link: <\2>]').
              gsub(/#{Mx[:lnk_o]}(.+?)#{Mx[:lnk_c]}image/,'\1 [link: local image]').
              gsub(/#{Mx[:url_o]}(\S+?)#{Mx[:url_c]}/,"#{the_text.url_open}\\1#{the_text.url_close}")
            extract_endnotes(dob)
            dob.obj=dob.obj.gsub(/#{Mx[:en_a_o]}([\d*+]+)\s+(?:.+?)#{Mx[:en_a_c]}/,'[^\1]'). # endnote marker marked up
              gsub(/#{Mx[:en_b_o]}([\d*+]+)\s+(?:.+?)#{Mx[:en_b_c]}/,'[^\1]'). # endnote marker marked up
              gsub(/#{Mx[:gl_o]}(?:#lt|#060)#{Mx[:gl_c]}/,'<').
              gsub(/#{Mx[:gl_o]}(?:#gt|#062)#{Mx[:gl_c]}/,'>').
              gsub(/#{Mx[:gl_o]}#(?:038|amp)#{Mx[:gl_c]}/,'&').
              gsub(/#{Mx[:gl_o]}#033#{Mx[:gl_c]}/,'!').
              gsub(/#{Mx[:gl_o]}#035#{Mx[:gl_c]}/,'#').
              gsub(/#{Mx[:gl_o]}#042#{Mx[:gl_c]}/,'*').
              gsub(/#{Mx[:gl_o]}#045#{Mx[:gl_c]}/,'-').
              gsub(/#{Mx[:gl_o]}#047#{Mx[:gl_c]}/,'/').
              gsub(/#{Mx[:gl_o]}#095#{Mx[:gl_c]}/,'_').
              gsub(/#{Mx[:gl_o]}#123#{Mx[:gl_c]}/,'{').
              gsub(/#{Mx[:gl_o]}#125#{Mx[:gl_c]}/,'}').
              gsub(/#{Mx[:gl_o]}#126#{Mx[:gl_c]}/,'~').
              gsub(/#{Mx[:gl_o]}#169#{Mx[:gl_c]}/,'©').
              gsub(/#{Mx[:gl_o]}#092#{Mx[:gl_c]}/,'\\')
          end
          dob.obj=if dob.of==:block                                   # watch
            dob.obj.gsub(/#{Mx[:gl_o]}●#{Mx[:gl_c]}/m,"* ").
              gsub(/\n?#{Mx[:br_line]}\n?|\n?#{Mx[:br_nl]}\n?/m,break_line)
          else dob.obj.gsub(/\n?#{Mx[:br_line]}\n?|\n?#{Mx[:br_nl]}\n?/m,break_line*2)
          end
          if dob.is==:code
            dob.obj=dob.obj.gsub(/(^|[^}])_([<>])/m,'\1\2'). # _> _<
              gsub(/(^|[^}])_([<>])/m,'\1\2') # _<_<
          end
          dob.obj=dob.obj.gsub(/#{Mx[:url_o]}_(\S+?)#{Mx[:url_c]}/,'\1').
            gsub(/<a href=".+?">(.+?)<\/a>/m,'\1').
            gsub(/#{Mx[:mk_o]}:name#(\S+?)#{Mx[:mk_c]}/,'').                       # remove name links
            gsub(/&nbsp;|#{Mx[:nbsp]}/,' ').                                       # decide on
            gsub(/(?:^|[^_\\])#{Mx[:lnk_o]}(\S+?\.(?:png|jpg|gif)) .+?#{Mx[:lnk_c]}#{Mx[:url_o]}\S+?#{Mx[:url_c]}/,'    [ \1 ]'). #"[ #{dir.url.images_local}\/\\1 ]")
            gsub(/(?:^|[^_\\])#{Mx[:lnk_o]}(\S+?\.(?:png|jpg|gif)) .+?#{Mx[:lnk_c]}image/,'    [ \1 ]').
            gsub(/(?:^|[^_\\])\{\s*\S+?\.(?:png|jpg|gif)\s+.+?"(.*?)"\s*\}\S+/,'[image: "\1"]')
          if dob.obj !~/(^#{Rx[:meta]}|#{Mx[:br_eof]}|#{Mx[:br_endnotes]})/
            p_num=ocn_display(dob)
            if dob.is==:heading \
            or dob.is==:para
              plaintext_structure(dob,p_num)
            elsif dob.is==:group \
            or dob.is==:block \
            or dob.is==:verse \
            or dob.is==:code \
            or dob.is==:table
              @plaintext[:body] << dob.obj + p_num << break_line
            elsif dob.is==:break
              sp=' '
              ln='-'
              @plaintext[:body] <<=if dob.obj==Mx[:br_page] \
              or dob.obj==Mx[:br_page_new] \
              or dob.obj==Mx[:br_page_line]
                "#{break_line}#{ln*40}#{break_line*2}"
              elsif dob.obj ==Mx[:br_obj]
                "#{break_line}#{sp*20}*  *  *#{break_line*2}"
              end # following empty line (break_line) missing, fix
            end
            dob='' if (dob.obj =~/<a name="n\d+">/ \
              and dob.obj =~/^(-\{{2}~\d+|<!e[:_]\d+!>)/) # -endnote
            if dob ## Clean Prepared Text
              dob.obj=dob.obj.gsub(/<!.+!>/,' ').
                gsub(/<:\S+>/,' ')
            end
          end
        end
        @plaintext
      end
      def publish(plaintext)
        divider='='
        content=[]
        content << plaintext[:open]
        content << plaintext[:head]
        content << plaintext[:body]
        content << @@endnotes[:end] if @@endnotes_
        content << "#{break_line}#{divider*@wrap_width}#{break_line}"
        content << plaintext[:metadata]
        content << "#{break_line}#{divider*@wrap_width}#{break_line}" if @md.stmp =~/\w+/ #not used?
        content << plaintext[:tail]
        outputfile=SiSU_Env::FileOp.new(@md).write_file.txt
        Txt_Output::Output.new.document(content,outputfile)
        @@endnotes={ para: [], end: [] }
      end
    end
  end
end
__END__
  bold_o:                    '*',          bold_c:                   '*',
 #bold_o:                    '!',          bold_c:                   '!',
 #emphasis_o:                '*',          emphasis_c:               '*',
  italics_o:                 '/',          italics_c:                '/',
  underscore_o:              '_',          underscore_c:             '_',
  cite_o:                    '"',          cite_c:                   '"',
  insert_o:                  '+',          insert_c:                 '+',
  strike_o:                  '-',          strike_c:                 '-',
  superscript_o:             '^',          superscript_c:            '^',
  subscript_o:               '[',          subscript_c:              ']',
  hilite_o:                  '*',          hilite_c:                 '*',
  monospace_o:               '',           monospace_c:              '',
  p_bold_o:                  '!{',         p_bold_c:                 '}!',
  p_italics_o:               '/{',         p_italics_c:              '}/',
  p_underscore_o:            '_{',         p_underscore_c:           '}_',
  p_cite_o:                  '"{',         p_cite_c:                 '}"',
  p_insert_o:                '+{',         p_insert_c:               '}+',
  p_strike_o:                '-{',         p_strike_c:               '}-',
  p_superscript_o:           '^{',         p_superscript_c:          '}^',
  p_subscript_o:             ',{',         p_subscript_c:            '},',
  p_hilite_o:                '*{',         p_hilite_c:               '}*',
  p_monospace_o:             '#{',         p_monospace_c:            '}#',
#+END_SRC

*** txt_plain_decorate.rb

#+HEADER: :tangle "../lib/sisu/txt_plain_decorate.rb"
#+BEGIN_SRC ruby
#<<sisu_document_header>>
module SiSU_Decorate_Txt_Plain
  def decorate
    def heading_underscore
      def l0
        '='
      end
      def l1
        '*'
      end
      def l2
        '+'
      end
      def l3
        '~'
      end
      def l4
        '-'
      end
      def l5
        '.'
      end
      def l6
        '.'
      end
      def l7
        '.'
      end
      self
    end
    def bold
      def open
        '*'
      end
      def close
        '*'
      end
      self
    end
    def italics
      def open
        '/'
      end
      def close
        '/'
      end
      self
    end
    def underscore
      def open
        '_'
      end
      def close
        '_'
      end
      self
    end
   #def emphasis
   #  def open
   #    ''
   #  end
   #  def close
   #    ''
   #  end
   #  self
   #end
    def cite
      def open
        '"'
      end
      def close
        '"'
      end
      self
    end
    def insert
      def open
        '+'
      end
      def close
        '+'
      end
      self
    end
    def strike
      def open
        '-'
      end
      def close
        '-'
      end
      self
    end
    def superscript
      def open
        '^'
      end
      def close
        '^'
      end
      self
    end
    def subscript
      def open
        '['
      end
      def close
        ']'
      end
      self
    end
    def hilite
      def open
        '*'
      end
      def close
        '*'
      end
      self
    end
    def monospace
      def open
        '#'
      end
      def close
        '#'
      end
      self
    end
    self
  end
end
__END__
#+END_SRC

** rst
*** txt_rst.rb

#+HEADER: :tangle "../lib/sisu/txt_rst.rb"
#+BEGIN_SRC ruby
#<<sisu_document_header>>
module SiSU_Txt_rST
  require_relative 'ao'                                 # ao.rb
  require_relative 'se'                                 # se.rb
    include SiSU_Env
  require_relative 'shared_metadata'                    # shared_metadata.rb
  require_relative 'generic_parts'                      # generic_parts.rb
  require_relative 'txt_read'                           # txt_read.rb
  require_relative 'txt_shared'                         # txt_shared.rb
  require_relative 'txt_rst_decorate'                   # txt_rst_decorate.rb
  require_relative 'txt_output'                         # txt_output.rb
  include SiSU_Param
  @@alt_id_count,@@alt_id_count=0,0
  @@tablefoot=''
  class Source
    include SiSU_Txt_Read
    def initialize(opt)
      @opt=opt
      unless @opt.fns =~/(.+?)\.(?:-|ssm\.)?sst$/
        puts "#{sf} not a processed file type"
      end
    end
    def read
      begin
        md=SiSU_Param::Parameters.new(@opt).get
        specific={
          description:     'rST (plaintext utf-8)',
          output_path:     md.file.output_path.rst.dir,
          output_file:     md.file.base_filename.rst,
        }
        read_generic(@opt,specific)
        SiSU_Txt_rST::Source::Scroll.new(md,@ao_array,@wrap_width).songsheet
      rescue
        SiSU_Errors::Rescued.new($!,$@,@opt.selections.str,@opt.fns).location do
          __LINE__.to_s + ':' + __FILE__
        end
      ensure
      end
    end
    private
    class Scroll <Source
      include SiSU_Parts_Generic
      include SiSU_TextUtils
      include SiSU_Decorate_Txt_rST
      @@endnotes={ para: [], end: [] }
      def initialize(md,data,wrap_width)
        @md,@data,@wrap_width=md,data,wrap_width
        @env=SiSU_Env::InfoEnv.new(@md.fns)
        @tab="\t"
        @@endnotes_=case md.opt.selections.str
        when /--footnote/ then false
        when /--endnote/  then true
        else                   true
        end
        @plaintext={ body: [], open: [], close: [], head: [], metadata: [], tail: [] }
      end
      def songsheet
        plaintext=markup(@data)
        publish(plaintext)
      end
      def break_line
        "\n"
      end
      # Used for extraction of endnotes from paragraphs
      def extract_endnotes(dob='')
        notes=dob.obj.scan(/(?:#{Mx[:en_a_o]}|#{Mx[:en_b_o]})([\d*+]+\s+.+?)(?:#{Mx[:en_a_c]}|#{Mx[:en_b_c]})/)
        @n=[]
        notes.flatten.each do |n| #high cost to deal with <br> appropriately within plaintext, consider
          n=n.dup.to_s
          if n =~/#{Mx[:br_line]}|#{Mx[:br_nl]}/
            fix = n.split(/#{Mx[:br_line]}|#{Mx[:br_nl]}/) #watch #added
            fix.each do |x|
              unless x.empty?; @n << x
              end
            end
          else                 @n << n
          end
        end
        notes=@n.flatten
        notes.each do |e|
          util=(e.to_s =~/^\[[\d*+]+\]:/) \
          ? (SiSU_TextUtils::Wrap.new(e.to_s,@wrap_width,4,1))
          : (SiSU_TextUtils::Wrap.new(e.to_s,@wrap_width,1,1))
          wrap=util.line_wrap
          wrap=if wrap =~ /^\s*[\d*+]+\s+.+?\s*\Z/m
            wrap.gsub(/^(\s*)([\d*+]+)\s+(.+?)\s*\Z/m, <<-GSUB
\\1[\\2]: \\3
              GSUB
            )
          else
            wrap.gsub(/^(.+)\Z/m, <<-GSUB
\\1
              GSUB
            )
          end
          @@endnotes[:para] << "-#{wrap}"
          @@endnotes[:end] << '' << wrap
        end
        @@endnotes
      end
      def plaintext_metadata
        array=SiSU_Metadata::Summary.new(@md).plaintext.metadata
        array.each do |meta|
          tag,inf=meta.scan(/^.+?:\s|.+/)
          if tag and inf
            util=SiSU_TextUtils::Wrap.new(inf,@wrap_width,15,1)
            txt=util.line_wrap
            @plaintext[:metadata] <<<<WOK

#{@tab}#{tag}#{txt}
WOK
          end
        end
      end
      def plaintext_tail
#       env=SiSU_Env::InfoEnv.new(@md.fns)
        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}#{break_line}Version number: #{@md.sc_number}#{break_line}Version date:   #{@md.sc_date}#{break_line}"
        else ''
        end
        @plaintext[:tail] <<<<WOK
#{break_line}
plaintext (plain text):
   #{@md.file.output_path.rst.url}/#{@md.file.base_filename.rst}#{break_line}
Other versions of this document: #{break_line}
manifest:
   #{@md.file.output_path.manifest.url}/#{@md.file.base_filename.manifest}#{break_line}
at:
   #{@md.file.output_path.base.url}#{break_line}

#{sc}
,* #{generator}
,* #{rubyv}
,* #{lastdone}
,* SiSU #{the_url.sisu_txt}
WOK
      end
      def heading_decorated_underscore(dob,times,p_num)
        if dob.is==:heading
          #times=@wrap_width if times > @wrap_width
          case dob.lc
          when 0 then decorate.heading.underscore.l0*times + p_num << break_line*2
          when 1 then decorate.heading.underscore.l1*times + p_num << break_line*2
          when 2 then decorate.heading.underscore.l2*times + p_num << break_line*2
          when 3 then decorate.heading.underscore.l3*times + p_num << break_line*2
          when 4 then decorate.heading.underscore.l4*times + p_num << break_line*2
          when 5 then decorate.heading.underscore.l5*times + p_num << break_line*2
          when 6 then decorate.heading.underscore.l6*times + p_num << break_line*2
          end
        end
      end
      def plaintext_structure(dob='',p_num='') #% Used to extract the structure of a document
        util=nil
        wrapped=if dob.is==:para \
        || dob.is==:heading
          if dob.is==:heading
            util=SiSU_TextUtils::Wrap.new(dob.obj,@wrap_width,0)
          elsif dob.is==:para
            if dob.hang \
            and dob.hang =~/[0-9]/ \
            and dob.indent != dob.hang
              util=SiSU_TextUtils::Wrap.new(dob.obj,@wrap_width,dob.indent.to_i*2,dob.hang.to_i*2)
              #util=SiSU_TextUtils::Wrap.new(dob.obj,@wrap_width,dob.hang.to_i*2,0)
            elsif dob.indent =~/[1-9]/
              util=if dob.bullet_
                SiSU_TextUtils::Wrap.new("* #{dob.obj}",@wrap_width,dob.indent.to_i*2)
              else SiSU_TextUtils::Wrap.new(dob.obj,@wrap_width,dob.indent.to_i*2)
              end
            else
              util=if dob.bullet_
                SiSU_TextUtils::Wrap.new("* #{dob.obj}",@wrap_width,0)
              else SiSU_TextUtils::Wrap.new(dob.obj,@wrap_width,0)
              end
            end
          else util=SiSU_TextUtils::Wrap.new(dob.obj,@wrap_width,0)
          end
          dob.is==:heading ? util.no_wrap_no_breaks : util.line_wrap
        end
        if dob.is==:heading
          @plaintext[:body] << wrapped + p_num # main text, contents, body KEEP
          @plaintext[:body] << heading_decorated_underscore(dob,wrapped.length,p_num)
        else
          @plaintext[:body] << wrapped + p_num << break_line # main text, contents, body KEEP
        end
        if @@endnotes[:para] \
        and not @@endnotes_
          @@endnotes[:para].each {|e| @plaintext[:body] << e << break_line}
        elsif @@endnotes[:para] \
        and @@endnotes_
        end
        @@endnotes[:para]=[]
      end
      def markup(data)                                                       # Used for major markup instructions
        SiSU_Env::InfoEnv.new(@md.fns)
        @data_mod,@endnotes,@level,@cont,@copen,@plaintext_contents_close=Array.new(6){[]}
        (0..6).each { |x| @cont[x]=@level[x]=false }
        (4..6).each { |x| @plaintext_contents_close[x]='' }
        plaintext_tail #($1,$2)
        plaintext_metadata
        table_message='[table conversion awaited, see other document formats]'
        data.each do |dob|
          dob.obj=dob.obj.gsub(/#{Mx[:gr_o]}Th?#{Mx[:tc_p]}.+/um,"#{break_line}#{table_message}"). #fix
            gsub(/.+?#{Mx[:gl_o]}-##{Mx[:gl_c]}/,'').                              # remove dummy headings (used by html) #check also [~-]#
            gsub(/#{Mx[:fa_bold_o]}(.+?)#{Mx[:fa_bold_c]}/,
              "#{decorate.bold.open}\\1#{decorate.bold.close}").
            gsub(/#{Mx[:fa_italics_o]}(.+?)#{Mx[:fa_italics_c]}/,
              "#{decorate.italics.open}\\1#{decorate.italics.close}").
            gsub(/#{Mx[:fa_underscore_o]}(.+?)#{Mx[:fa_underscore_c]}/,
              "#{decorate.underscore.open}\\1#{decorate.underscore.close}").
            gsub(/#{Mx[:fa_subscript_o]}(.+?)#{Mx[:fa_subscript_c]}/,
              "#{decorate.subscript.open}\\1#{decorate.subscript.close}").
            gsub(/#{Mx[:fa_superscript_o]}(.+?)#{Mx[:fa_superscript_c]}/,
              "#{decorate.superscript.open}\\1#{decorate.superscript.close}").
            gsub(/#{Mx[:fa_insert_o]}(.+?)#{Mx[:fa_insert_c]}/,
              "#{decorate.insert.open}\\1#{decorate.insert.close}").
            gsub(/#{Mx[:fa_cite_o]}(.+?)#{Mx[:fa_cite_c]}/,
              "#{decorate.cite.open}\\1#{decorate.cite.close}").
            gsub(/#{Mx[:fa_strike_o]}(.+?)#{Mx[:fa_strike_c]}/,
              "#{decorate.strike.open}\\1#{decorate.strike.close}").
            gsub(/#{Mx[:fa_monospace_o]}(.+?)#{Mx[:fa_monospace_c]}/,
              "#{decorate.monospace.open}\\1#{decorate.monospace.close}")
          unless dob.is==:code
            dob.obj=dob.obj.gsub(/#{Mx[:lnk_o]}(.+?)#{Mx[:lnk_c]}#{Mx[:rel_o]}\S+?#{Mx[:rel_c]}/,'\1').
              gsub(/#{Mx[:url_o]}_(\S+?)#{Mx[:url_c]}/,'\1').
              gsub(/#{Mx[:lnk_o]}(.+?)#{Mx[:lnk_c]}#{Mx[:url_o]}(\S+?)#{Mx[:url_c]}/,'\1 [link: <\2>]').
              gsub(/#{Mx[:lnk_o]}(.+?)#{Mx[:lnk_c]}image/,'\1 [link: local image]').
              gsub(/#{Mx[:url_o]}(\S+?)#{Mx[:url_c]}/,"#{the_text.url_open}\\1#{the_text.url_close}")
            extract_endnotes(dob)
            dob.obj=dob.obj.gsub(/#{Mx[:en_a_o]}([\d*+]+)\s+(?:.+?)#{Mx[:en_a_c]}/,'[^\1]'). # endnote marker marked up
              gsub(/#{Mx[:en_b_o]}([\d*+]+)\s+(?:.+?)#{Mx[:en_b_c]}/,'[^\1]'). # endnote marker marked up
              gsub(/#{Mx[:gl_o]}(?:#lt|#060)#{Mx[:gl_c]}/,'<').
              gsub(/#{Mx[:gl_o]}(?:#gt|#062)#{Mx[:gl_c]}/,'>').
              gsub(/#{Mx[:gl_o]}#(?:038|amp)#{Mx[:gl_c]}/,'&').
              gsub(/#{Mx[:gl_o]}#033#{Mx[:gl_c]}/,'!').
              gsub(/#{Mx[:gl_o]}#035#{Mx[:gl_c]}/,'#').
              gsub(/#{Mx[:gl_o]}#042#{Mx[:gl_c]}/,'*').
              gsub(/#{Mx[:gl_o]}#045#{Mx[:gl_c]}/,'-').
              gsub(/#{Mx[:gl_o]}#047#{Mx[:gl_c]}/,'/').
              gsub(/#{Mx[:gl_o]}#095#{Mx[:gl_c]}/,'_').
              gsub(/#{Mx[:gl_o]}#123#{Mx[:gl_c]}/,'{').
              gsub(/#{Mx[:gl_o]}#125#{Mx[:gl_c]}/,'}').
              gsub(/#{Mx[:gl_o]}#126#{Mx[:gl_c]}/,'~').
              gsub(/#{Mx[:gl_o]}#169#{Mx[:gl_c]}/,'©').
              gsub(/#{Mx[:gl_o]}#092#{Mx[:gl_c]}/,'\\')
          end
          dob.obj=if dob.of==:block                                   # watch
            dob.obj.gsub(/#{Mx[:gl_o]}●#{Mx[:gl_c]}/m,"* ").
              gsub(/\n?#{Mx[:br_line]}\n?|\n?#{Mx[:br_nl]}\n?/m,break_line)
          else dob.obj.gsub(/\n?#{Mx[:br_line]}\n?|\n?#{Mx[:br_nl]}\n?/m,break_line*2)
          end
          if dob.is==:code
            dob.obj=dob.obj.gsub(/(^|[^}])_([<>])/m,'\1\2'). # _> _<
              gsub(/(^|[^}])_([<>])/m,'\1\2') # _<_<
          end
          dob.obj=dob.obj.gsub(/#{Mx[:url_o]}_(\S+?)#{Mx[:url_c]}/,'\1').
            gsub(/<a href=".+?">(.+?)<\/a>/m,'\1').
            gsub(/#{Mx[:mk_o]}:name#(\S+?)#{Mx[:mk_c]}/,'').                       # remove name links
            gsub(/&nbsp;|#{Mx[:nbsp]}/,' ').                                       # decide on
            gsub(/(?:^|[^_\\])#{Mx[:lnk_o]}(\S+?\.(?:png|jpg|gif)) .+?#{Mx[:lnk_c]}#{Mx[:url_o]}\S+?#{Mx[:url_c]}/,'    [ \1 ]'). #"[ #{dir.url.images_local}\/\\1 ]")
            gsub(/(?:^|[^_\\])#{Mx[:lnk_o]}(\S+?\.(?:png|jpg|gif)) .+?#{Mx[:lnk_c]}image/,'    [ \1 ]').
            gsub(/(?:^|[^_\\])\{\s*\S+?\.(?:png|jpg|gif)\s+.+?"(.*?)"\s*\}\S+/,'[image: "\1"]')
          if dob.obj !~/(^#{Rx[:meta]}|#{Mx[:br_eof]}|#{Mx[:br_endnotes]})/
            p_num=''
            #ocn
            if dob.is==:heading \
            or dob.is==:para
              plaintext_structure(dob,p_num)
            elsif dob.is==:group \
            or dob.is==:block \
            or dob.is==:verse \
            or dob.is==:code \
            or dob.is==:table
              @plaintext[:body] << dob.obj + p_num << break_line
            elsif dob.is==:break
              sp=' '
              ln='-'
              @plaintext[:body] <<=if dob.obj==Mx[:br_page] \
              or dob.obj==Mx[:br_page_new] \
              or dob.obj==Mx[:br_page_line]
                "#{break_line}#{ln*40}#{break_line*2}"
              elsif dob.obj ==Mx[:br_obj]
                "#{break_line}#{sp*20}*  *  *#{break_line*2}"
              end # following empty line (break_line) missing, fix
            end
            dob='' if (dob.obj =~/<a name="n\d+">/ \
              and dob.obj =~/^(-\{{2}~\d+|<!e[:_]\d+!>)/) # -endnote
            if dob ## Clean Prepared Text
              dob.obj=dob.obj.gsub(/<!.+!>/,' ').
                gsub(/<:\S+>/,' ')
            end
          end
        end
        @plaintext
      end
      def publish(plaintext)
        divider='='
        content=[]
        content << plaintext[:open]
        content << plaintext[:head]
        content << plaintext[:body]
        content << @@endnotes[:end] if @@endnotes_
        content << "#{break_line}#{divider*@wrap_width}#{break_line}"
        content << plaintext[:metadata]
        content << "#{break_line}#{divider*@wrap_width}#{break_line}" if @md.stmp =~/\w+/ #not used?
        content << plaintext[:tail]
        outputfile=SiSU_Env::FileOp.new(@md).write_file.rst
        Txt_Output::Output.new.document(content,outputfile)
        @@endnotes={ para: [], end: [] }
      end
    end
  end
end
__END__
#+END_SRC

*** txt_rst_decorate.rb

#+HEADER: :tangle "../lib/sisu/txt_rst_decorate.rb"
#+BEGIN_SRC ruby
#<<sisu_document_header>>
module SiSU_Decorate_Txt_rST
  def decorate
    def heading
      def underscore
        def l0
          '='
        end
        def l1
          '-'
        end
        def l2
          '`'
        end
        def l3
          ':'
        end
        def l4
          "'"
        end
        def l5
          '"'
        end
        self
      end
      self
    end
    def bold
      def open
        '*'
      end
      def close
        '*'
      end
      self
    end
    def italics
      def open
        '/'
      end
      def close
        '/'
      end
      self
    end
    def underscore
      def open
        '_'
      end
      def close
        '_'
      end
      self
    end
   #def emphasis
   #  def open
   #    ''
   #  end
   #  def close
   #    ''
   #  end
   #  self
   #end
    def cite
      def open
        '"'
      end
      def close
        '"'
      end
      self
    end
    def insert
      def open
        '+'
      end
      def close
        '+'
      end
      self
    end
    def strike
      def open
        '-'
      end
      def close
        '-'
      end
      self
    end
    def superscript
      def open
        '^'
      end
      def close
        '^'
      end
      self
    end
    def subscript
      def open
        '['
      end
      def close
        ']'
      end
      self
    end
    def hilite
      def open
        '*'
      end
      def close
        '*'
      end
      self
    end
    def monospace
      def open
        '#'
      end
      def close
        '#'
      end
      self
    end
    self
  end
end
__END__
#+END_SRC

** textile
*** txt_textile.rb

#+HEADER: :tangle "../lib/sisu/txt_textile.rb"
#+BEGIN_SRC ruby
#<<sisu_document_header>>
module SiSU_Txt_Textile
  require_relative 'ao'                                 # ao.rb
  require_relative 'se'                                 # se.rb
    include SiSU_Env
  require_relative 'shared_metadata'                    # shared_metadata.rb
  require_relative 'generic_parts'                      # generic_parts.rb
  require_relative 'txt_read'                           # txt_read.rb
  require_relative 'txt_shared'                         # txt_shared.rb
  require_relative 'txt_textile_decorate'               # txt_textile_decorate.rb
  require_relative 'txt_output'                         # txt_output.rb
  include SiSU_Param
  @@alt_id_count,@@alt_id_count=0,0
  @@tablefoot=''
  class Source
    include SiSU_Txt_Read
    #include SiSU_Parts_Generic
    def initialize(opt)
      @opt=opt
      unless @opt.fns =~/(.+?)\.(?:-|ssm\.)?sst$/
        puts "#{sf} not a processed file type"
      end
    end
    def read
      begin
        md=SiSU_Param::Parameters.new(@opt).get
        specific={
          description:     'Textile (plaintext utf-8)',
          output_path:     md.file.output_path.textile.dir,
          output_file:     md.file.base_filename.textile,
        }
        read_generic(@opt,specific)
        SiSU_Txt_Textile::Source::Scroll.new(md,@ao_array,@wrap_width).songsheet
      rescue
        SiSU_Errors::Rescued.new($!,$@,@opt.selections.str,@opt.fns).location do
          __LINE__.to_s + ':' + __FILE__
        end
      ensure
      end
    end
    private
    class Scroll <Source
      include SiSU_Parts_Generic
      include SiSU_TextUtils
      include SiSU_Decorate_Txt_Textile
      @@endnotes={ para: [], end: [] }
      def initialize(md,data,wrap_width)
        @md,@data,@wrap_width=md,data,wrap_width
        @env=SiSU_Env::InfoEnv.new(@md.fns)
        @tab="\t"
        @@endnotes_=case md.opt.selections.str
        when /--footnote/ then false
        when /--endnote/  then true
        else                   true
        end
        @plaintext={ body: [], open: [], close: [], head: [], metadata: [], tail: [] }
      end
      def songsheet
        plaintext=markup(@data)
        publish(plaintext)
      end
      def break_line
        "\n"
      end
      # Used for extraction of endnotes from paragraphs
      def extract_endnotes(dob='')
        notes=dob.obj.scan(/(?:#{Mx[:en_a_o]}|#{Mx[:en_b_o]})([\d*+]+\s+.+?)(?:#{Mx[:en_a_c]}|#{Mx[:en_b_c]})/)
        @n=[]
        notes.flatten.each do |n| #high cost to deal with <br> appropriately within plaintext, consider
          n=n.dup.to_s
          if n =~/#{Mx[:br_line]}|#{Mx[:br_nl]}/
            fix = n.split(/#{Mx[:br_line]}|#{Mx[:br_nl]}/) #watch #added
            fix.each do |x|
              unless x.empty?; @n << x
              end
            end
          else                 @n << n
          end
        end
        notes=@n.flatten
        notes.each do |e|
          util=(e.to_s =~/^\[[\d*+]+\]:/) \
          ? (SiSU_TextUtils::Wrap.new(e.to_s,@wrap_width,4,1))
          : (SiSU_TextUtils::Wrap.new(e.to_s,@wrap_width,1,1))
          wrap=util.line_wrap
          wrap=if wrap =~ /^\s*[\d*+]+\s+.+?\s*\Z/m
            wrap.gsub(/^(\s*)([\d*+]+)\s+(.+?)\s*\Z/m, <<-GSUB
\\1[\\2]: \\3
              GSUB
            )
          else
            wrap.gsub(/^(.+)\Z/m, <<-GSUB
\\1
              GSUB
            )
          end
          @@endnotes[:para] << "-#{wrap}"
          @@endnotes[:end] << '' << wrap
        end
        @@endnotes
      end
      def plaintext_metadata
        array=SiSU_Metadata::Summary.new(@md).plaintext.metadata
        array.each do |meta|
          tag,inf=meta.scan(/^.+?:\s|.+/)
          if tag and inf
            util=SiSU_TextUtils::Wrap.new(inf,@wrap_width,15,1)
            txt=util.line_wrap
            @plaintext[:metadata] <<<<WOK

#{@tab}#{tag}#{txt}
WOK
          end
        end
      end
      def plaintext_tail
#       env=SiSU_Env::InfoEnv.new(@md.fns)
        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}#{break_line}Version number: #{@md.sc_number}#{break_line}Version date:   #{@md.sc_date}#{break_line}"
        else ''
        end
        @plaintext[:tail] <<<<WOK
#{break_line}
plaintext (plain text):
   #{@md.file.output_path.textile.url}/#{@md.file.base_filename.textile}#{break_line}
Other versions of this document: #{break_line}
manifest:
   #{@md.file.output_path.manifest.url}/#{@md.file.base_filename.manifest}#{break_line}
at:
   #{@md.file.output_path.base.url}#{break_line}

#{sc}
,* #{generator}
,* #{rubyv}
,* #{lastdone}
,* SiSU #{the_url.sisu_txt}
WOK
      end
      def heading_decorated_inline(dob)
        if dob.is==:heading
          heading_inline = case dob.lc
          when 0 then decorate.heading.inline.l0
          when 1 then decorate.heading.inline.l1
          when 2 then decorate.heading.inline.l2
          when 3 then decorate.heading.inline.l3
          when 4 then decorate.heading.inline.l4
          when 5 then decorate.heading.inline.l5
          when 6 then decorate.heading.inline.l6
          end
          heading_inline + ' ' +  dob.obj
        end
      end
      def plaintext_structure(dob='',p_num='') #% Used to extract the structure of a document
        util=nil
        wrapped=if dob.is==:para \
        || dob.is==:heading
          if dob.is==:heading
            util=SiSU_TextUtils::Wrap.new(heading_decorated_inline(dob),@wrap_width,0,0)
          elsif dob.is==:para
            if dob.hang \
            and dob.hang =~/[0-9]/ \
            and dob.indent != dob.hang
              util=SiSU_TextUtils::Wrap.new(dob.obj,@wrap_width,dob.indent.to_i*2,dob.hang.to_i*2)
              #util=SiSU_TextUtils::Wrap.new(dob.obj,@wrap_width,dob.hang.to_i*2,0)
            elsif dob.indent =~/[1-9]/
              util=if dob.bullet_
                SiSU_TextUtils::Wrap.new("* #{dob.obj}",@wrap_width,dob.indent.to_i*2)
              else SiSU_TextUtils::Wrap.new(dob.obj,@wrap_width,dob.indent.to_i*2)
              end
            else
              util=if dob.bullet_
                SiSU_TextUtils::Wrap.new("* #{dob.obj}",@wrap_width,0)
              else SiSU_TextUtils::Wrap.new(dob.obj,@wrap_width,0)
              end
            end
          else util=SiSU_TextUtils::Wrap.new(dob.obj,@wrap_width,0)
          end
          dob.is==:heading ? util.no_wrap_no_breaks : util.line_wrap
        end
        @plaintext[:body] << wrapped + p_num << break_line # main text, contents, body KEEP
        if @@endnotes[:para] \
        and not @@endnotes_
          @@endnotes[:para].each {|e| @plaintext[:body] << e << break_line}
        elsif @@endnotes[:para] \
        and @@endnotes_
        end
        @@endnotes[:para]=[]
      end
      def markup(data)                                                       # Used for major markup instructions
        SiSU_Env::InfoEnv.new(@md.fns)
        @data_mod,@endnotes,@level,@cont,@copen,@plaintext_contents_close=Array.new(6){[]}
        (0..6).each { |x| @cont[x]=@level[x]=false }
        (4..6).each { |x| @plaintext_contents_close[x]='' }
        plaintext_tail #($1,$2)
        plaintext_metadata
        table_message='[table conversion awaited, see other document formats]'
        data.each do |dob|
          dob.obj=dob.obj.gsub(/#{Mx[:gr_o]}Th?#{Mx[:tc_p]}.+/um,"#{break_line}#{table_message}"). #fix
            gsub(/.+?#{Mx[:gl_o]}-##{Mx[:gl_c]}/,'').                              # remove dummy headings (used by html) #check also [~-]#
            gsub(/#{Mx[:fa_bold_o]}(.+?)#{Mx[:fa_bold_c]}/,
              "#{decorate.bold.open}\\1#{decorate.bold.close}").
            gsub(/#{Mx[:fa_italics_o]}(.+?)#{Mx[:fa_italics_c]}/,
              "#{decorate.italics.open}\\1#{decorate.italics.close}").
            gsub(/#{Mx[:fa_underscore_o]}(.+?)#{Mx[:fa_underscore_c]}/,
              "#{decorate.underscore.open}\\1#{decorate.underscore.close}").
            gsub(/#{Mx[:fa_subscript_o]}(.+?)#{Mx[:fa_subscript_c]}/,
              "#{decorate.subscript.open}\\1#{decorate.subscript.close}").
            gsub(/#{Mx[:fa_superscript_o]}(.+?)#{Mx[:fa_superscript_c]}/,
              "#{decorate.superscript.open}\\1#{decorate.superscript.close}").
            gsub(/#{Mx[:fa_insert_o]}(.+?)#{Mx[:fa_insert_c]}/,
              "#{decorate.insert.open}\\1#{decorate.insert.close}").
            gsub(/#{Mx[:fa_cite_o]}(.+?)#{Mx[:fa_cite_c]}/,
              "#{decorate.cite.open}\\1#{decorate.cite.close}").
            gsub(/#{Mx[:fa_strike_o]}(.+?)#{Mx[:fa_strike_c]}/,
              "#{decorate.strike.open}\\1#{decorate.strike.close}").
            gsub(/#{Mx[:fa_monospace_o]}(.+?)#{Mx[:fa_monospace_c]}/,
              "#{decorate.monospace.open}\\1#{decorate.monospace.close}")
          unless dob.is==:code
            dob.obj=dob.obj.gsub(/#{Mx[:lnk_o]}(.+?)#{Mx[:lnk_c]}#{Mx[:rel_o]}\S+?#{Mx[:rel_c]}/,'\1').
              gsub(/#{Mx[:url_o]}_(\S+?)#{Mx[:url_c]}/,'\1').
              gsub(/#{Mx[:lnk_o]}(.+?)#{Mx[:lnk_c]}#{Mx[:url_o]}(\S+?)#{Mx[:url_c]}/,'\1 [link: <\2>]').
              gsub(/#{Mx[:lnk_o]}(.+?)#{Mx[:lnk_c]}image/,'\1 [link: local image]').
              gsub(/#{Mx[:url_o]}(\S+?)#{Mx[:url_c]}/,"#{the_text.url_open}\\1#{the_text.url_close}")
            extract_endnotes(dob)
            dob.obj=dob.obj.gsub(/#{Mx[:en_a_o]}([\d*+]+)\s+(?:.+?)#{Mx[:en_a_c]}/,'[^\1]'). # endnote marker marked up
              gsub(/#{Mx[:en_b_o]}([\d*+]+)\s+(?:.+?)#{Mx[:en_b_c]}/,'[^\1]'). # endnote marker marked up
              gsub(/#{Mx[:gl_o]}(?:#lt|#060)#{Mx[:gl_c]}/,'<').
              gsub(/#{Mx[:gl_o]}(?:#gt|#062)#{Mx[:gl_c]}/,'>').
              gsub(/#{Mx[:gl_o]}#(?:038|amp)#{Mx[:gl_c]}/,'&').
              gsub(/#{Mx[:gl_o]}#033#{Mx[:gl_c]}/,'!').
              gsub(/#{Mx[:gl_o]}#035#{Mx[:gl_c]}/,'#').
              gsub(/#{Mx[:gl_o]}#042#{Mx[:gl_c]}/,'*').
              gsub(/#{Mx[:gl_o]}#045#{Mx[:gl_c]}/,'-').
              gsub(/#{Mx[:gl_o]}#047#{Mx[:gl_c]}/,'/').
              gsub(/#{Mx[:gl_o]}#095#{Mx[:gl_c]}/,'_').
              gsub(/#{Mx[:gl_o]}#123#{Mx[:gl_c]}/,'{').
              gsub(/#{Mx[:gl_o]}#125#{Mx[:gl_c]}/,'}').
              gsub(/#{Mx[:gl_o]}#126#{Mx[:gl_c]}/,'~').
              gsub(/#{Mx[:gl_o]}#169#{Mx[:gl_c]}/,'©').
              gsub(/#{Mx[:gl_o]}#092#{Mx[:gl_c]}/,'\\')
          end
          dob.obj=if dob.of==:block                                   # watch
            dob.obj.gsub(/#{Mx[:gl_o]}●#{Mx[:gl_c]}/m,"* ").
              gsub(/\n?#{Mx[:br_line]}\n?|\n?#{Mx[:br_nl]}\n?/m,break_line)
          else dob.obj.gsub(/\n?#{Mx[:br_line]}\n?|\n?#{Mx[:br_nl]}\n?/m,break_line*2)
          end
          if dob.is==:code
            dob.obj=dob.obj.gsub(/(^|[^}])_([<>])/m,'\1\2'). # _> _<
              gsub(/(^|[^}])_([<>])/m,'\1\2') # _<_<
          end
          dob.obj=dob.obj.gsub(/#{Mx[:url_o]}_(\S+?)#{Mx[:url_c]}/,'\1').
            gsub(/<a href=".+?">(.+?)<\/a>/m,'\1').
            gsub(/#{Mx[:mk_o]}:name#(\S+?)#{Mx[:mk_c]}/,'').                       # remove name links
            gsub(/&nbsp;|#{Mx[:nbsp]}/,' ').                                       # decide on
            gsub(/(?:^|[^_\\])#{Mx[:lnk_o]}(\S+?\.(?:png|jpg|gif)) .+?#{Mx[:lnk_c]}#{Mx[:url_o]}\S+?#{Mx[:url_c]}/,'    [ \1 ]'). #"[ #{dir.url.images_local}\/\\1 ]")
            gsub(/(?:^|[^_\\])#{Mx[:lnk_o]}(\S+?\.(?:png|jpg|gif)) .+?#{Mx[:lnk_c]}image/,'    [ \1 ]').
            gsub(/(?:^|[^_\\])\{\s*\S+?\.(?:png|jpg|gif)\s+.+?"(.*?)"\s*\}\S+/,'[image: "\1"]')
          if dob.obj !~/(^#{Rx[:meta]}|#{Mx[:br_eof]}|#{Mx[:br_endnotes]})/
            p_num=''
            #ocn
            if dob.is==:heading \
            or dob.is==:para
              plaintext_structure(dob,p_num)
            elsif dob.is==:group \
            or dob.is==:block \
            or dob.is==:verse \
            or dob.is==:code \
            or dob.is==:table
              @plaintext[:body] << dob.obj + p_num << break_line
            elsif dob.is==:break
              sp=' '
              ln='-'
              @plaintext[:body] <<=if dob.obj==Mx[:br_page] \
              or dob.obj==Mx[:br_page_new] \
              or dob.obj==Mx[:br_page_line]
                "#{break_line}#{ln*40}#{break_line*2}"
              elsif dob.obj ==Mx[:br_obj]
                "#{break_line}#{sp*20}*  *  *#{break_line*2}"
              end # following empty line (break_line) missing, fix
            end
            dob='' if (dob.obj =~/<a name="n\d+">/ \
              and dob.obj =~/^(-\{{2}~\d+|<!e[:_]\d+!>)/) # -endnote
            if dob ## Clean Prepared Text
              dob.obj=dob.obj.gsub(/<!.+!>/,' ').
                gsub(/<:\S+>/,' ')
            end
          end
        end
        @plaintext
      end
      def publish(plaintext)
        divider='='
        content=[]
        content << plaintext[:open]
        content << plaintext[:head]
        content << plaintext[:body]
        content << @@endnotes[:end] if @@endnotes_
        content << "#{break_line}#{divider*@wrap_width}#{break_line}"
        content << plaintext[:metadata]
        content << "#{break_line}#{divider*@wrap_width}#{break_line}" if @md.stmp =~/\w+/ #not used?
        content << plaintext[:tail]
        outputfile=SiSU_Env::FileOp.new(@md).write_file.textile
        Txt_Output::Output.new.document(content,outputfile)
        @@endnotes={ para: [], end: [] }
      end
    end
  end
end
__END__
#+END_SRC

*** txt_textile_decorate.rb

#+HEADER: :tangle "../lib/sisu/txt_textile_decorate.rb"
#+BEGIN_SRC ruby
#<<sisu_document_header>>
module SiSU_Decorate_Txt_Textile
  def decorate
    def heading
      def inline
        def l0
          'h1. '
        end
        def l1
          'h2. '
        end
        def l2
          'h3. '
        end
        def l3
          'h4. '
        end
        def l4
          'h5. '
        end
        def l5
          'h6. '
        end
        self
      end
      self
    end
    def bold
      def open
        '*'
      end
      def close
        '*'
      end
      self
    end
    def italics
      def open
        '_'
      end
      def close
        '_'
      end
      self
    end
    def underscore
      def open
        '+'
      end
      def close
        '+'
      end
      self
    end
   #def emphasis
   #  def open
   #    ''
   #  end
   #  def close
   #    ''
   #  end
   #  self
   #end
    def cite
      def open
        '"'
      end
      def close
        '"'
      end
      self
    end
    def insert
      def open
        ''
      end
      def close
        ''
      end
      self
    end
    def strike
      def open
        '-'
      end
      def close
        '-'
      end
      self
    end
    def superscript
      def open
        '^'
      end
      def close
        '^'
      end
      self
    end
    def subscript
      def open
        '~'
      end
      def close
        '~'
      end
      self
    end
    def hilite
      def open
        '*'
      end
      def close
        '*'
      end
      self
    end
    def monospace
      def open
        ''
      end
      def close
        ''
      end
      self
    end
    self
  end
end
__END__
#+END_SRC

* txt_output.rb

#+HEADER: :tangle "../lib/sisu/txt_output.rb"
#+BEGIN_SRC ruby
#<<sisu_document_header>>
module Txt_Output
  class Output
    include SiSU_Param
    include SiSU_Env
    def document(content,outputfile)
      emptyline=0
      content.each do |para|           # this is a hack
        if para.is_a?(Array) \
        and para.length > 0
          para.each do |line|
            if line
              line=line.gsub(/[ \t]+$/m,'').
                gsub(/^\A[ ]*\Z/m,'')
              (line=~/^\A\Z/) \
              ? (emptyline+=1)
              : emptyline=0
              if emptyline < 2         #remove additional empty lines
                outputfile.puts line
              end
            end
          end
        else outputfile.puts para      #unix plaintext # /^([*=-]|\.){5}/
        end
      end
      outputfile.close
    end
  end
end
__END__

#+END_SRC

* txt_read.rb

#+HEADER: :tangle "../lib/sisu/txt_read.rb"
#+BEGIN_SRC ruby
#<<sisu_document_header>>
module SiSU_Txt_Read
  require_relative 'se'                                 # se.rb
    include SiSU_Env
  def read_generic(opt,specific)
    begin
      env=SiSU_Env::InfoEnv.new(opt.fns)
      unless opt.act[:quiet][:set]==:on
        tool=(opt.act[:verbose][:set]==:on \
        || opt.act[:verbose_plus][:set]==:on \
        || opt.act[:maintenance][:set]==:on) \
        ? "#{env.program.text_editor} #{specific[:output_path]}/#{specific[:output_file]}"
        : "[#{opt.f_pth[:lng_is]}] #{opt.fno}"
        (opt.act[:verbose][:set]==:on \
        || opt.act[:verbose_plus][:set]==:on \
        || opt.act[:maintenance][:set]==:on) \
        ? SiSU_Screen::Ansi.new(
            opt.act[:color_state][:set],
            specific[:description],
            tool
          ).green_hi_blue
        : SiSU_Screen::Ansi.new(
            opt.act[:color_state][:set],
            specific[:description],
            tool
          ).green_title_hi
        if (opt.act[:verbose_plus][:set]==:on \
        || opt.act[:maintenance][:set]==:on)
          SiSU_Screen::Ansi.new(
            opt.act[:color_state][:set],
            opt.fns,
            "#{specific[:output_path]}/#{specific[:output_file]}"
          ).flow
        end
      end
      @ao_array=SiSU_AO::Source.new(opt).get # ao file drawn here
      @wrap_width=if defined? md.make.plaintext_wrap \
      and md.make.plaintext_wrap
        md.make.plaintext_wrap
      elsif defined? env.plaintext_wrap \
      and env.plaintext_wrap
        env.plaintext_wrap
      else 78
      end
      #wrap_width=(defined? md.make.plaintext_wrap) ? md.make.plaintext_wrap : 78
    rescue
      SiSU_Errors::Rescued.new($!,$@,opt.selections.str,opt.fns).location do
        __LINE__.to_s + ':' + __FILE__
      end
    ensure
    end
  end
end
__END__
#+END_SRC

* txt_shared.rb

#+HEADER: :tangle "../lib/sisu/txt_shared.rb"
#+BEGIN_SRC ruby
#<<sisu_document_header>>
module SiSU_TextUtils
  require_relative 'generic_parts'                      # generic_parts.rb
  class Wrap
    def initialize(para='',n_char_max=76,n_indent=0,n_hang=nil,post='')
      @para,@n_char_max,@n_indent,@post,=para,n_char_max,n_indent,post
      @n_char_max_extend = n_char_max
      @n_hang=n_hang ? n_hang : @n_indent
    end
    def break_line
      "\n"
    end
    def line_wrap
      space=' '
      spaces_indent,spaces_hang="#{break_line}#{space*@n_indent}",space*@n_hang
      line=0
      out=[]
      out[line]=''
      @para=@para.gsub(/<br>/,' \\ ').
        gsub(/#{Mx[:br_nl]}/,"\n\n")
      words=@para.scan(/\n\n|\s+\\\s+|<br>|\S+/m)
      while words != ''
        word=words.shift
        if not word
          out[line] unless out[line].empty? #check
          break
        elsif word =~/<br>/
          word=nil
          out[line]=out[line].gsub(/<br>/,'')
          line=line
        elsif word =~/\n\n/
          word="\n"
          @n_char_max_extend = @n_char_max
          line += 1
        elsif (out[line].length + word.length) > (@n_char_max_extend - @n_indent) \
        and out[line] =~/\S+/
          @n_char_max_extend = @n_char_max
          out[line].squeeze!(' ')
          line += 1
        end
        if word
          out[line]=if out[line] \
          and out[line] !~/\S+$/m
            "#{out[line]}#{word}"
          elsif out[line] \
          and out[line] =~/\S+/
            "#{out[line]} #{word}"
          else "#{word.strip}"
          end
        end
        @oldword=word if word =~/\S+/
      end
      post=(@post.empty?) \
      ? ''
      : "\n" + (' '*@n_indent) +@post
      spaces_hang + out.join(spaces_indent) + post
    end
    def line_wrap_indent1
      @n_indent,@n_hang=2,2
      line_wrap
    end
    def line_wrap_endnote
      @n_indent,@n_hang=4,2
      line_wrap
    end
    def array_wrap
      if @para.is_a?(Array)
        @arr=[]
        @para.each do |line|
          @arr << SiSU_TextUtils::Wrap.new(line,@n_char_max,@n_indent,@n_hang).line_wrap
        end
      end
      @arr
    end
    def no_wrap
      @para
    end
    def no_wrap_no_breaks
      @para.gsub(/\n/m,' ').gsub(/\s\s+/,' ')
    end
  end
  class HeaderScan
    def initialize(md,para)
      @md,@p=md,para
    end
    def extract(tag,tag_content,type,attrib)
      if dc_tag \
      and dc_content
        [dc_tag,dc_content,{dc_tag=>dc_content}]
      else nil
      end
    end
    def header(tag,tag_content,type='',attrib='') #this will break stuff and must be tested thoroughly 20060825
      @tag,@tag_content,@type,@attrib=tag,tag_content,type,attrib
      def label #element
        @tag
      end
      def type
        @type
      end
      def text
        @tag_content
      end
      def info  #element text
        @tag_content
      end
      def attribute
        @attrib
      end
      def element
        @tag
      end
      def attrib
        @attrib
      end
      def el
        @tag
      end
      self
    end
    def start_is_match
      case @p
      when /^#{Mx[:meta_o]}(title)#{Mx[:meta_c]}\s*(.+?)$/               then header($1,@md.title.full,'meta','dc') #dc 1
      when /^#{Mx[:meta_o]}(creator|author)#{Mx[:meta_c]}\s*(.+?)$/      then header('creator',$2,'meta','dc')    #dc 2
      when /^#{Mx[:meta_o]}(subject)#{Mx[:meta_c]}\s*(.+?)$/             then header($1,$2,'meta','dc')           #dc 3
      when /^#{Mx[:meta_o]}(description)#{Mx[:meta_c]}\s*(.+?)$/         then header($1,$2,'meta','dc')           #dc 4
      when /^#{Mx[:meta_o]}(publisher)#{Mx[:meta_c]}\s*(.+?)$/           then header($1,$2,'meta','dc')           #dc 5
      when /^#{Mx[:meta_o]}(contributor)#{Mx[:meta_c]}\s*(.+?)$/         then header($1,$2,'meta','dc')           #dc 6
      when /^#{Mx[:meta_o]}(date)#{Mx[:meta_c]}\s*(.+?)$/                then header($1,$2,'meta','dc')           #dc 7
      when /^#{Mx[:meta_o]}(date\.created)#{Mx[:meta_c]}\s*(.+?)$/       then header($1,$2,'meta','extra')
      when /^#{Mx[:meta_o]}(date\.issued)#{Mx[:meta_c]}\s*(.+?)$/        then header($1,$2,'meta','extra')
      when /^#{Mx[:meta_o]}(date\.available)#{Mx[:meta_c]}\s*(.+?)$/     then header($1,$2,'meta','extra')
      when /^#{Mx[:meta_o]}(date\.valid)#{Mx[:meta_c]}\s*(.+?)$/         then header($1,$2,'meta','extra')
      when /^#{Mx[:meta_o]}(date\.modified)#{Mx[:meta_c]}\s*(.+?)$/      then header($1,$2,'meta','extra')
      when /^#{Mx[:meta_o]}(type)#{Mx[:meta_c]}\s*(.+?)$/                then header($1,$2,'meta','dc')           #dc 8
      when /^#{Mx[:meta_o]}(format)#{Mx[:meta_c]}\s*(.+?)$/              then header($1,$2,'meta','dc')           #dc 9
      when /^#{Mx[:meta_o]}(identifier)#{Mx[:meta_c]}\s*(.+?)$/          then header($1,$2,'meta','dc')           #dc 10
      when /^#{Mx[:meta_o]}(source)#{Mx[:meta_c]}\s*(.+?)$/              then header($1,$2,'meta','dc')           #dc 11
      when /^#{Mx[:meta_o]}(language)#{Mx[:meta_c]}\s*(.+?)$/            then header($1,$2,'meta','dc')           #dc 12
      when /^#{Mx[:meta_o]}(relation)#{Mx[:meta_c]}\s*(.+?)$/            then header($1,$2,'meta','dc')           #dc 13
      when /^#{Mx[:meta_o]}(coverage)#{Mx[:meta_c]}\s*(.+?)$/            then header($1,$2,'meta','dc')           #dc 14
      when /^#{Mx[:meta_o]}(rights)#{Mx[:meta_c]}\s*(.+?)$/              then header($1,$2,'meta','dc')           #dc 15
      when /^#{Mx[:meta_o]}(keywords)#{Mx[:meta_c]}\s*(.+?)$/            then header($1,$2,'meta','extra')
      when /^#{Mx[:meta_o]}(copyright)#{Mx[:meta_c]}\s*(.+?)$/           then header($1,$2,'meta','extra')
      when /^#{Mx[:meta_o]}(translator|translated_by)#{Mx[:meta_c]}\s*(.+?)$/   then header('translator',$2)
      when /^#{Mx[:meta_o]}(illustrator|illustrated_by)#{Mx[:meta_c]}\s*(.+?)$/ then header('illustrator',$2)
      when /^#{Mx[:meta_o]}(prepared_by)#{Mx[:meta_c]}\s*(.+?)$/         then header($1,$2,'meta','extra')
      when /^#{Mx[:meta_o]}(digitized_by)#{Mx[:meta_c]}\s*(.+?)$/        then header($1,$2,'meta','extra')
      when /^#{Mx[:meta_o]}(comments?)#{Mx[:meta_c]}\s*(.+?)$/           then header($1,$2,'meta','extra')
      when /^#{Mx[:meta_o]}(abstract)#{Mx[:meta_c]}\s*(.+?)$/            then header($1,$2,'meta','extra')
      when /^#{Mx[:meta_o]}(tags?)#{Mx[:meta_c]}\s*(.+?)$/               then header($1,$2,'meta','extra')
      when /^#{Mx[:meta_o]}(catalogue)#{Mx[:meta_c]}\s*(.+?)$/           then header($1,$2,'meta','extra')
      when /^#{Mx[:meta_o]}(class(?:ify)?_loc)#{Mx[:meta_c]}\s*(.+?)$/   then header('classify_loc',$2,'meta','extra')
      when /^#{Mx[:meta_o]}(class(?:ify)?_dewey)#{Mx[:meta_c]}\s*(.+?)$/ then header('classify_dewey',$2,'meta','extra')
      when /^#{Mx[:meta_o]}(class(?:ify)?_pg)#{Mx[:meta_c]}\s*(.+?)$/    then header('classify_pg',$2,'meta','extra')
      when /^#{Mx[:meta_o]}(class(?:ify)?_isbn)#{Mx[:meta_c]}\s*(.+?)$/  then header('classify_isbn',$2,'meta','extra')
      when /^#{Mx[:meta_o]}(toc|structure)#{Mx[:meta_c]}\s*(.+?)$/       then header('structure',$2,'process','instruct')
      when /^#{Mx[:meta_o]}(level|page|markup)#{Mx[:meta_c]}\s*(.+?)$/   then header('markup',$2,'process','instruct')
      when /^#{Mx[:meta_o]}(bold)#{Mx[:meta_c]}\s*(.+?)$/                then header($1,$2,'process','instruct')
      when /^#{Mx[:meta_o]}(italics|itali[sz]e)#{Mx[:meta_c]}\s*(.+?)$/  then header('italicize',$2,'process','instruct')
      when /^#{Mx[:meta_o]}(vocabulary|wordlist)#{Mx[:meta_c]}\s*(.+?)$/ then header('vocabulary',$2,'process','instruct')
      when /^#{Mx[:meta_o]}(css|stylesheet)#{Mx[:meta_c]}\s*(.+?)$/      then header('css',$2,'process','instruct')
      when /^#{Mx[:meta_o]}(links)#{Mx[:meta_c]}\s*(.+?)$/               then header($1,$2,'process','instruct')
      when /^#{Mx[:meta_o]}(prefix)#{Mx[:meta_c]}\s*(.+?)$/              then header($1,$2,'process','instruct') #add a & b
      when /^#{Mx[:meta_o]}(suffix)#{Mx[:meta_c]}\s*(.+?)$/              then header($1,$2,'process','instruct')
      when /^#{Mx[:meta_o]}(information)#{Mx[:meta_c]}\s*(.+?)$/         then header($1,$2,'process','instruct')
      when /^#{Mx[:meta_o]}(contact)#{Mx[:meta_c]}\s*(.+?)$/             then header($1,$2,'process','instruct')
      when /^#{Mx[:meta_o]}(rcs|cvs)#{Mx[:meta_c]}\s*(.+?)$/             then header('version',$2,'process','instruct')
      else nil
      end
    end
    def dublin
      if @p =~/^#{Mx[:meta_o]}\S+?#{Mx[:meta_c]}/
        start_is_match
      else nil
      end
    end
    def meta
      if @p =~/^#{Mx[:meta_o]}\S+?#{Mx[:meta_c]}/
        start_is_match
      else nil
      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
    txt

  - Author: Ralph Amissah
    <ralph.amissah@gmail.com>

  - Copyright: (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
    2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2019,
    2020, 2021, Ralph Amissah,
    All Rights Reserved.

  - License: GPL 3 or later:

    SiSU, a framework for document structuring, publishing and search

    Copyright (C) Ralph Amissah

    This program is free software: you can redistribute it and/or modify it
    under the terms of the GNU General Public License as published by the Free
    Software Foundation, either version 3 of the License, or (at your option)
    any later version.

    This program is distributed in the hope that it will be useful, but WITHOUT
    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
    more details.

    You should have received a copy of the GNU General Public License along with
    this program. If not, see <http://www.gnu.org/licenses/>.

    If you have Internet connection, the latest version of the GPL should be
    available at these locations:
    <http://www.fsf.org/licensing/licenses/gpl.html>
    <http://www.gnu.org/licenses/gpl.html>

    <http://www.sisudoc.org/sisu/en/manifest/gpl.fsf.html>

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

  - Homepages:
    <http://www.sisudoc.org>

  - Git
    <https://git.sisudoc.org/projects/>
    <https://git.sisudoc.org/projects/?p=software/sisu.git;a=summary>
    <https://git.sisudoc.org/projects/?p=markup/sisu-markup-samples.git;a=summary>
#+END_SRC
