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

* digests.rb

#+HEADER: :tangle "../lib/sisu/digests.rb"
#+BEGIN_SRC ruby
#<<sisu_document_header>>
module SiSU_DigestView
  require_relative 'se_hub_particulars'                 # se_hub_particulars.rb
  require_relative 'prog_text_translation'              # prog_text_translation.rb
  require_relative 'shared_markup_alt.rb'               # shared_markup_alt.rb
  class Source
    @@dg=nil
    def initialize(opt)
      @opt=opt
      @fnb=@opt.fnb
      @@endnotes_para=[]
      @@dg=nil
      @dg=@@dg ||=SiSU_Env::InfoEnv.new.digest(opt).type
      @particulars=SiSU_Particulars::CombinedSingleton.instance.get_all(opt)
    end
    def read
      begin
        @env,@md,@ao_array=@particulars.env,@particulars.md,@particulars.ao_array
        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} file://#{@md.file.output_path.hash_digest.dir}/#{@md.file.base_filename.hash_digest}"
          : "[#{@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],
              "Document #{@dg} Digests",
              tool
            ).green_hi_blue
          : SiSU_Screen::Ansi.new(
              @opt.act[:color_state][:set],
              "Document #{@dg} Digests",
              tool
            ).green_title_hi
          if @opt.act[:verbose_plus][:set]==:on \
          or @opt.act[:maintenance][:set]==:on
            SiSU_Screen::Ansi.new(
              @opt.act[:color_state][:set],
              @opt.fns,
              "file://#{@md.file.output_path.hash_digest.dir}/#{@md.file.base_filename.hash_digest}"
            ).flow
          end
        end
        if SiSU_Env::SystemCall.new.openssl
          SiSU_DigestView::Source::Scroll.new(@particulars).songsheet
        else
          SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia).error('*EXITED* hash digests will not run without openssl')
        end
      rescue
        SiSU_Errors::Rescued.new($!,$@,@opt.selections.str,@opt.fns).location do
          __LINE__.to_s + ':' + __FILE__
        end
      ensure
      end
    end
    private
    class Scroll <Source
      @@dl=nil
      @@ds={
        digests_clean: [],
        digests_with_markup: [],
        tree: [],
        summary: [],
      }
      @@description,@@sc_info=[],[]
      def initialize(particulars)
        @particulars=particulars
        @data,@env,@md=@particulars.ao_array,@particulars.env,@particulars.md
        SiSU_Env::FileOp.new(@md).mkdir
        @@dg ||=@env.digest(@md.opt).type
        @@dl ||=@env.digest(@md.opt).length
        @dg,@dl=@@dg,@@dl
        l=SiSU_Env::StandardiseLanguage.new(@md.opt.lng).language
        @language=l[:n]
        @tr=SiSU_Translate::Source.new(@md,@language)
        @sp=' '
      end
      def songsheet
        @@description,@@ds[:digests_clean],@@ds[:digests_with_markup],@@ds[:tree],@@ds[:summary],@@sc_info=[],[],[],[],[],[]
        message_digest
        ao_structure
        supplementary
        output
      end
      def spaces
        Ax[:spaces]
      end
      def description(f,e='')
        puts f + e.to_s if @md.opt.act[:verbose_plus][:set]==:on
        @@description << f << e
      end
      def digests_clean(f,e='')
        puts f if @md.opt.act[:verbose_plus][:set]==:on
        @@ds[:digests_clean] << f + "\n"
      end
      def digests_with_markup(f)
        puts f if @md.opt.act[:verbose_plus][:set]==:on
        @@ds[:digests_with_markup] << f + "\n"
      end
      def ao_structure_tree(f,e='')
        puts f + e.to_s if @md.opt.act[:verbose_plus][:set]==:on
        @@ds[:tree] << f << e
      end
      def ao_structure_summary(f,e='')
        puts f + e.to_s if @md.opt.act[:verbose_plus][:set]==:on
        @@ds[:summary] << f << e
      end
      def rcinfo(f,e='')
        puts f + e.to_s if @md.opt.act[:verbose_plus][:set]==:on
        @@sc_info << f << e
      end
      def output
        file=SiSU_Env::FileOp.new(@md)
        filename_digest=file.write_file.hash_digest
        filename_digest << @@description.join << @@ds[:digests_clean].join << @@ds[:digests_with_markup].join << @@ds[:tree].join << @@ds[:summary].join << @@sc_info.join
      end
      def rgx_txt(txt)
        txt=txt.gsub(/([()])/,"\\\\\\1")
      end
      def message_digest
        @p=[]
        @g,@v,@r='','',''
        manifest="#{@env.url.root}/#{@md.fnb}/sisu_manifest.html"
        description("#{@md.title.full}\n")
        description("#{@md.author}\n")
        description("#{@md.fns}\n")
        description("----------------------------------------------\n")
        description("SiSU Document Content Certificate (Digest/DCC)\n")
        description("----------------------------------------------\n")
        description("                               #{@dg} digests\n")
        description("------------\n")
        description("Sourcefile digest:             #{@md.dgst[1]}\n")
        description("  source filename:             #{@md.fns}\n")
        description("available outputs:             #{manifest}\n")
        description("------------\n")
        description("Document Digests\n")
      end
      def ao_structure
        a=%{\nocn     digests (#{@dg}) clean text (stripped markup)}
        digests_clean(a)
        data=@data
        endnotes=nil
        data.each do |t_o|
          dgst=SiSU_TextRepresentation::ModifiedTextPlusHashDigest.new(@md,t_o).composite.dgst
          if dgst
            if t_o.is==:heading
              digests_clean("#{@sp*0}#{dgst[:ocn]}#{@sp*(8-dgst[:ocn].to_s.length)}#{dgst[:dgst_stripped_txt]} #{dgst[:is]} #{t_o.lv}")
            elsif t_o.is==:heading_insert
              digests_clean("#{@sp*0}[#{dgst[:ocn]}]#{@sp*(6-dgst[:ocn].to_s.length)}#{dgst[:dgst_stripped_txt]} #{dgst[:is]} #{t_o.lv}")
            else
              digests_clean("#{@sp*0}#{dgst[:ocn]}#{@sp*(8-dgst[:ocn].to_s.length)}#{dgst[:dgst_stripped_txt]} #{dgst[:is]}")
              if dgst[:images]
                dgst[:images].each do |img|
                  digests_clean("#{@sp*8}#{img[:img_dgst]}#{@sp*66}#{img[:img_type]} #{img[:img_name]}")
                end
              end
            end
            if dgst[:endnotes]
              dgst[:endnotes].each do |en|
                digests_clean("#{@sp*8}#{en[:note_dgst]} note [#{en[:note_number]}]")
                endnotes=en[:note_number]
              end
            end
          end
        end
        b=%{\nocn     object (#{@dg}) digests (object includes its markup & endnotes (if any))}
        digests_with_markup(b)
        data.each do |t_o|
          dgst=SiSU_TextRepresentation::ModifiedTextPlusHashDigest.new(@md,t_o).composite.dgst
          if dgst
            if t_o.is==:heading
              digests_with_markup("#{@sp*0}#{dgst[:ocn]}#{@sp*(8-dgst[:ocn].to_s.length)}#{dgst[:dgst_markedup_txt]} #{dgst[:is]} #{t_o.lv}")
            elsif t_o.is==:heading_insert
              digests_with_markup("#{@sp*0}[#{dgst[:ocn]}]#{@sp*(6-dgst[:ocn].to_s.length)}#{dgst[:dgst_markedup_txt]} #{dgst[:is]} #{t_o.lv}")
            else
              digests_with_markup("#{@sp*0}#{dgst[:ocn]}#{@sp*(8-dgst[:ocn].to_s.length)}#{dgst[:dgst_markedup_txt]} #{dgst[:is]}")
            end
          end
        end
        l=Hash.new(0)
        ocn=nil
        ao_structure_tree("------------\n")
        ao_structure_tree("document structure[*]\n")
        data.each do |t_o|
          if t_o.is==:heading
            x=case t_o.ln
            when 0 then l[0] +=1
              spaces*0 << ':A'
            when 1 then l[1] +=1
              spaces*1 << ':B'
            when 2 then l[2] +=1
              spaces*2 << ':C'
            when 3 then l[3] +=1
              spaces*3 << ':D'
            when 4 then l[4] +=1
              spaces*4 << '1'
            when 5 then l[5] +=1
              spaces*5 << '2'
            when 6 then l[6] +=1
              spaces*6 << '3'
            else nil
            end
          end
          ocn=t_o.ocn if defined? t_o.ocn and t_o.is !=:heading_insert
          ao_structure_tree("#{x}\n") if x and not x.empty?
        end
        ao_structure_tree("  [*] heading levels\n")
        ao_structure_summary("------------\n")
        ao_structure_summary("document structure[*]\n")
        [0,1,2,3,4,5,6].each do |y|
          v=case y
          when 0 then ':A'
          when 1 then ':B'
          when 2 then ':C'
          when 3 then ':D'
          when 4 then '1 '
          when 5 then '2 '
          when 6 then '3 '
          end
          ao_structure_summary("#{v}            = #{l[y]}\n") if l[y] > 0
        end
        ao_structure_summary("objects (ocn) = #{ocn}\n")
        ao_structure_summary("endnotes      = #{endnotes}\n")
        ao_structure_summary("  [*] number of headers (@) and of each heading level (:A to :D and 1 to 3)\n")
      end
      def supplementary
        if defined? @md.sc_number \
        and @md.sc_number
          rcinfo("------------\n")
          rcinfo("source control information\n")
          rcinfo("  (the following information while not important for document content certification\n   may help the publisher in locating the version referred to)\n")
          rcinfo("  rcs version number:            #{@md.sc_number}\n")
          if defined? @md.sc_date \
          and @md.sc_date
            rcinfo("  rcs date:                      #{@md.sc_date}\n")
          end
          if defined? @md.sc_time \
          and @md.sc_time
            rcinfo("  rcs time:                      #{@md.sc_time}\n")
          end
        end
        rcinfo("------------\n")
        rcinfo("Note: the time generated related fields (text and digests) will vary between otherwise identical document outputs\n")
      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
    digests

  - 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