diff options
| author | Ralph Amissah <ralph@amissah.com> | 2017-04-12 15:23:23 -0400 | 
|---|---|---|
| committer | Ralph Amissah <ralph@amissah.com> | 2019-04-10 15:14:14 -0400 | 
| commit | da0f051e1aced4fa1fd5cd13c0548279bf04b2a0 (patch) | |
| tree | 3c74421c4ce35e28e93512eb01606219e37e0dfb | |
| parent | start work on block outputs (diff) | |
0.13.9 sisupod & epub3, zipped output
| -rw-r--r-- | dub.sdl | 3 | ||||
| -rw-r--r-- | makefile | 2 | ||||
| -rw-r--r-- | maker.org | 89 | ||||
| -rw-r--r-- | org/ao_debugs.org | 10 | ||||
| -rw-r--r-- | org/ao_doc_abstraction.org | 38 | ||||
| -rw-r--r-- | org/defaults.org | 218 | ||||
| -rw-r--r-- | org/output.org | 932 | ||||
| -rw-r--r-- | org/sdp.org | 8 | ||||
| -rwxr-xr-x | src/sdp.d | 6 | ||||
| -rw-r--r-- | src/sdp/ao_defaults.d | 3 | ||||
| -rw-r--r-- | src/sdp/ao_doc_debugs.d | 10 | ||||
| -rw-r--r-- | src/sdp/create_zip_file.d | 16 | ||||
| -rw-r--r-- | src/sdp/defaults.d | 180 | ||||
| -rw-r--r-- | src/sdp/output_epub.d | 449 | ||||
| -rw-r--r-- | src/sdp/output_epub3.d | 717 | ||||
| -rw-r--r-- | src/sdp/output_html.d | 12 | ||||
| -rw-r--r-- | src/sdp/output_hub.d | 17 | ||||
| -rw-r--r-- | src/sdp/output_xhtmls.d | 120 | ||||
| -rw-r--r-- | src/sdp/source_sisupod.d | 201 | ||||
| -rw-r--r-- | views/version.txt | 2 | 
20 files changed, 2061 insertions, 972 deletions
| @@ -137,7 +137,8 @@ configuration "sdp-debug-unittest-ldc" {    platforms            "posix"    compiler             "ldc2"    targetName           "sdp-debug-ldc" -  dflags               "-J=views" "-I=src/sdp" "-Dddocs" +  dflags               "-J=views" "-I=src/sdp" +  #dflags               "-J=views" "-I=src/sdp" "-Dddocs"    buildRequirements    "allowWarnings"    buildOptions         "verbose" "debugMode" "debugInfo" "unittests" "optimize"    debugVersions        "checkdoc" "summary" @@ -41,7 +41,7 @@ PRG_BIN=$(PRG_NAME)  PRG_BINDIR=./bin  PRG_DOCDIR=./docs  # ORG -ORG_VERSION=20160725 +ORG_VERSION=20161214  EMACSLISP=/usr/share/emacs/site-lisp  EMACSLISP_ORG=~/.emacs.d/elpa/org-$($(shell echo $(ORG_VERSION)))  EMACSLISP_ORG_CONTRIB=~/.emacs.d/elpa/org-plus-contrib-$($(shell echo $(ORG_VERSION))) @@ -15,13 +15,13 @@  [[./org/sdp.org][sdp.org]]  [[./org/][org/]]  * sdp makefile                                                     :makefile: -** TODO settings [+2]                                              :settings: -*** alternative D compilers (dmd/ldc2/gdc) [+1]                    :compiler: +** TODO settings [+2]                                             :settings: +*** alternative D compilers (dmd/ldc2/gdc) [+1]                  :compiler:  http://dlang.org/download.html  https://wiki.dlang.org/Compilers -**** dmd [#A]                                                           :dmd: +**** dmd [#A]                                                        :dmd:  http://dlang.org/ @@ -32,7 +32,7 @@ DMD_FLAGS_RELEASE=-O -inline -release  DMD_FLAG_BINOF=-of  #+END_SRC -**** ldc2 [#A]                                                          :ldc: +**** ldc2 [#A]                                                       :ldc:  https://github.com/ldc-developers/ldc @@ -43,7 +43,7 @@ LDC_FLAGS_RELEASE=-O4 -inline -release  LDC_FLAG_BINOF=-of=  #+END_SRC -**** TODO gdc                                                           :gdc: +**** TODO gdc                                                        :gdc:  #+BEGIN_SRC makefile :tangle makefile  GDC=gdc @@ -52,26 +52,26 @@ GDC_FLAGS_RELEASE=-march=native -O3 -pipe -frelease  GDC_FLAG_BINOF=-o  #+END_SRC -*** build tools (dub/rdmd) [+1]                                  :build:tool: -**** rdmd                                                              :rdmd: +*** build tools (dub/rdmd) [+1]                                :build:tool: +**** rdmd                                                           :rdmd:  #+BEGIN_SRC makefile :tangle makefile  RDMD=rdmd  RDMD_FLAGS=--build-only --compiler=  #+END_SRC -**** dub [#A]                                                           :dub: +**** dub [#A]                                                        :dub:  #+BEGIN_SRC makefile :tangle makefile  DUB=dub  DUB_FLAGS=-v --force --compiler=  #+END_SRC -*** TODO [#A] set/select: ~D compiler~ & ~debug flags~ [+1] [2/2]        :select: +*** TODO [#A] set/select: ~D compiler~ & ~debug flags~ [+1] [2/2]      :select:  - [X] Set D_COMPILER (one of DMD LDC or GDC)  - [X] Set debug flags (using DMD standard flag -debug=) -**** TODO SET compiler: "SET_D_COMPILER=":                  :compiler:select: +**** TODO SET compiler: "SET_D_COMPILER=":               :compiler:select:  [[http://wiki.dlang.org/Compilers][D Compilers wiki]]  [[http://dlang.org/download.html][D Compilers download]]  Set D_COMPILER one of DMD, LDC or GDC e.g.: SET_D_COMPILER=DMD @@ -147,8 +147,9 @@ Set debug flags using DMD standard flag -debug= e.g.:    structattrib    summary    table +  toc -*** D compiler settings [+1]                              :settings:compiler: +*** D compiler settings [+1]                            :settings:compiler:  **** compiler settings  #+BEGIN_SRC makefile :tangle makefile @@ -176,7 +177,7 @@ endif  DUB_FLAGS_DEBUG :=$(shell echo $(DC_FLAGS_DEBUG_SET)| sed -e "s/-debug/--debug/g"| sed -e "s/-unittest//g")  #+END_SRC -*** Project Details                                             :project:sdp: +*** Project Details                                           :project:sdp:  #+BEGIN_SRC makefile :tangle makefile  PRG_NAME=sdp @@ -187,11 +188,11 @@ PRG_BINDIR=./bin  PRG_DOCDIR=./docs  #+END_SRC -*** Emacs Org settings                            :settings:emacs:org:tangle: +*** Emacs Org settings                          :settings:emacs:org:tangle:  #+BEGIN_SRC makefile :tangle makefile  # ORG -ORG_VERSION=20160725 +ORG_VERSION=20161214  EMACSLISP=/usr/share/emacs/site-lisp  EMACSLISP_ORG=~/.emacs.d/elpa/org-$($(shell echo $(ORG_VERSION)))  EMACSLISP_ORG_CONTRIB=~/.emacs.d/elpa/org-plus-contrib-$($(shell echo $(ORG_VERSION))) @@ -200,7 +201,7 @@ ORGFILES=""  ORGDIR=$(shell echo `pwd`)  #+END_SRC -** "make" commands [+2]                                       :make:commands: +** "make" commands [+2]                                      :make:commands:  - build commands    - build    - debug @@ -216,8 +217,8 @@ ORGDIR=$(shell echo `pwd`)  - git snapshot    - gitsnapshot -*** build commands [+1]                                       :build:compile: -**** build rebuild                                            :build:rebuild: +*** build commands [+1]                                     :build:compile: +**** build rebuild                                         :build:rebuild:  ***** compilers  #+BEGIN_SRC makefile :tangle makefile @@ -234,7 +235,7 @@ makefile_new:  	make -k tangle_maker  #+END_SRC -***** TODO _dub_ build rebuild [#A]                                       :dub: +***** TODO _dub_ build rebuild [#A]                                   :dub:  ****** generic  #+BEGIN_SRC makefile :tangle makefile @@ -296,7 +297,7 @@ dub_release_test_dmd: tangle dub_dmd_release_test  dub_release_test_ldc: tangle dub_ldc_release_test  #+END_SRC -***** rdmd build rebuild                                               :rdmd: +***** rdmd build rebuild                                           :rdmd:  #+BEGIN_SRC makefile :tangle makefile  rdmd: $(PRG_SRCDIR)/$(PRG_SRC) @@ -305,7 +306,7 @@ rdmd: $(PRG_SRCDIR)/$(PRG_SRC)  	$(PRG_SRCDIR)/$(PRG_NAME)/$(PRG_SRC)  #+END_SRC -**** debug                                                            :debug: +**** debug                                                         :debug:  ***** debug  #+BEGIN_SRC makefile :tangle makefile @@ -354,7 +355,7 @@ debug_rdmd_gdc: $(PRG_SRCDIR)/$(PRG_SRC)  	$(PRG_SRCDIR)/$(PRG_NAME)/$(PRG_SRC)  #+END_SRC -**** release                                                        :release: +**** release                                                     :release:  ***** release @@ -374,7 +375,7 @@ release_rdmd: distclean tangle $(PRG_SRCDIR)/$(PRG_SRC)  	$(PRG_SRCDIR)/$(PRG_SRC)  #+END_SRC -*** init clean distclean etc.                                         :clean: +*** init clean distclean etc.                                       :clean:  #+BEGIN_SRC makefile :tangle makefile  skel: @@ -409,7 +410,7 @@ distclean_and_init: expunge  	mkdir -p $(PRG_BINDIR);  #+END_SRC -*** Org Babel Tangle batch process command                           :tangle: +*** Org Babel Tangle batch process command                         :tangle:  **** tangle: org babel tangle *.org  #+BEGIN_SRC makefile :tangle makefile  tangle: skel @@ -470,10 +471,10 @@ gitsnapshot: distclean tangle  #+END_SRC  * TODO configuration misc                                     :configuration: -** dub                                                                  :dub: +** dub                                                                 :dub:  Every DUB package should contain a [[http://code.dlang.org/package-format?lang=json][dub.json]] (or [[http://code.dlang.org/package-format?lang=sdl][dub.sdl]]) -*** TODO dub.sdl [#A]                                                   :sdl: +*** TODO dub.sdl [#A]                                                 :sdl:  **** header                                                       :header:  #+BEGIN_SRC sh  :tangle dub.sdl @@ -650,7 +651,8 @@ configuration "sdp-debug-unittest-ldc" {    platforms            "posix"    compiler             "ldc2"    targetName           "sdp-debug-ldc" -  dflags               "-J=views" "-I=src/sdp" "-Dddocs" +  dflags               "-J=views" "-I=src/sdp" +  #dflags               "-J=views" "-I=src/sdp" "-Dddocs"    buildRequirements    "allowWarnings"    buildOptions         "verbose" "debugMode" "debugInfo" "unittests" "optimize"    debugVersions        "checkdoc" "summary" @@ -740,7 +742,7 @@ configuration "sdp-debug-docs-gdc" {  }  #+END_SRC -*** +dub.json+                                                           :json: +*** +dub.json+                                                         :json:  **** +sdp+  #+BEGIN_SRC json  :tangle no @@ -760,7 +762,7 @@ configuration "sdp-debug-docs-gdc" {  }  #+END_SRC -** .gitignore                                                     :gitignore: +** .gitignore                                                    :gitignore:  #+BEGIN_SRC sh :tangle .gitignore  # git ls-files --others --exclude-from=.git/info/exclude @@ -793,7 +795,7 @@ configuration "sdp-debug-docs-gdc" {  #*.\#*  #+END_SRC -** sh script to batch process emacs org babel tangle    :shell_script:tangle: +** sh script to batch process emacs org babel tangle   :shell_script:tangle:    [[http://orgmode.org/manual/Batch-execution.html]]  creates a shell batch script called "tangle", that will tangle (emacs org  babel tangle) org files in ./org/ to create .d source files in ./src/sdp/ @@ -827,18 +829,18 @@ emacs --batch -Q -q \  #+END_SRC  * dub zfunc                                                           :zfunc: -** ,dubdmd                                                              :dmd: +** ,dubdmd                                                             :dmd:  #+BEGIN_SRC sh  :tangle no  time dub --compiler=dmd -v --force  #+END_SRC -** ,dubldc                                                              :ldc: +** ,dubldc                                                             :ldc:  #+BEGIN_SRC sh  :tangle no  time dub --compiler=ldc2 -v --force  #+END_SRC  * D build notes                                                       :notes: -** compilers                                                       :compiler: -*** dmd [#A]                                                            :dmd: +** compilers                                                      :compiler: +*** dmd [#A]                                                          :dmd:  #+BEGIN_SRC sh  dmd -de -w -J./views -I./src/sdp -unittest -debug=checkdoc -debug=summary -debug=dumpdoc -of./bin/sdp ./src/sdp.d @@ -846,7 +848,7 @@ dmd -de -w -J./views -I./src/sdp -of./bin/sdp ./src/sdp.d  dmd -de -w -J./views -I./src/sdp -O -release -of./bin/sdp ./src/sdp.d  #+END_SRC -*** ldc2 [#A]                                                          :ldc2: +*** ldc2 [#A]                                                        :ldc2:  #+BEGIN_SRC sh  ldc2 -de -w -J./views -I./src/sdp -unittest -d-debug=checkdoc -d-debug=summary -d-debug=dumpdoc -of=./bin/sdp ./src/sdp.d @@ -854,7 +856,7 @@ ldc2 -de -w -J./views -I./src/sdp -of=./bin/sdp ./src/sdp.d  ldc2 -de -w -J./views -I./src/sdp -O4 -release -of=./bin/sdp ./src/sdp.d  #+END_SRC -*** gdc (not done) [#F]                                                 :gdc: +*** gdc (not done) [#F]                                               :gdc:  not done @@ -867,8 +869,8 @@ not done  "gdc might be worth a shot if your code is compatible", profan  re: dmd "one can easily get 2x (and even more) speedup by simply switching to gdc -O2", ketmar -** build tools                                                   :build:tool: -*** rdmd [#C]                                                          :rdmd: +** build tools                                                  :build:tool: +*** rdmd [#C]                                                        :rdmd:  flags similar to dmd @@ -884,7 +886,7 @@ rdmd -de -w -J./views -I./src/sdp -unittest -debug=checkdoc -debug=summary -debu  rdmd -de -w -J./views -I./src/sdp -unittest -d-debug=checkdoc -d-debug=summary -d-debug=dumpdoc --compiler=ldc2 -of./bin/sdp ./src/sdp.d  #+END_SRC -*** dub [#A]                                                            :dub: +*** dub [#A]                                                          :dub:  https://github.com/dlang/dub/  http://code.dlang.org/getting_started  http://code.dlang.org/docs/commandline @@ -955,9 +957,10 @@ dub --compiler=ldc2 -v --force --config=sdp-debug-clean  # sdp-debug-clean  # time ~sdp3/bin/sdp-debug-clean -v --html --no-assert en/autonomy_markup0.sst  #+END_SRC -** TODO debug options list [#A]                                       :debug: +** TODO debug options list [#A]                                      :debug:  #+BEGIN_SRC sh  :tangle no +debugVersions "asserts"  debugVersions "biblio"  debugVersions "biblio0"  debugVersions "bibliobuild" @@ -977,6 +980,9 @@ debugVersions "configfile"  debugVersions "dumpdoc"  debugVersions "endnotes"  debugVersions "endnotes_build" +debugVersions "epubmanifest" +debugVersions "epub_archive" +debugVersions "epub_output"  debugVersions "footnotes"  debugVersions "footnotesdone"  debugVersions "glossary" @@ -1004,6 +1010,7 @@ debugVersions "parabulletindent"  debugVersions "paraindent"  debugVersions "paraindenthang"  debugVersions "parent" +debugVersions "paths"  debugVersions "poem"  debugVersions "quote"  debugVersions "raw" @@ -1022,12 +1029,16 @@ debugVersions "section_bookindex"  debugVersions "section_bookindex_seg"  debugVersions "section_bookindex_scroll"  debugVersions "section_blurb" +debugVersions "segnames" +debugVersions "sisupod" +debugVersions "sisupod_zip"  debugVersions "source"  debugVersions "srclines"  debugVersions "structattrib"  debugVersions "summary"  debugVersions "table"  debugVersions "toc" +debugVersions "toc_nav_dom"  #+END_SRC  ** make (emacs) diff --git a/org/ao_debugs.org b/org/ao_debugs.org index c35ff2e..39fdbac 100644 --- a/org/ao_debugs.org +++ b/org/ao_debugs.org @@ -301,7 +301,7 @@ debug(section_body) {  #+name: ao_output_debugs  #+BEGIN_SRC d -debug(dom) { +debug(toc_nav_dom) {    enum DomTags { none, open, close, close_and_open, open_still, }    foreach (sect; doc_matters.keys_seq_seg) {      foreach (obj; contents[sect]) { @@ -313,10 +313,10 @@ debug(dom) {              break;            case DomTags.close_and_open :              writeln(markup.indent_by_spaces_provided(k), "</", k, ">"); -            writeln(markup.indent_by_spaces_provided(k), "<", k, ">", obj.text); +            writeln(markup.indent_by_spaces_provided(k), "<", k, ">", obj.text, " file: ", obj.segment_anchor_tag, ".xhtml#", obj.ocn);              break;            case DomTags.open : -            writeln(markup.indent_by_spaces_provided(k), "<", k, ">", obj.text); +            writeln(markup.indent_by_spaces_provided(k), "<", k, ">", obj.text, " file: ", obj.segment_anchor_tag, ".xhtml#", obj.ocn);              break;            default :              break; @@ -336,10 +336,10 @@ debug(dom) {              break;            case DomTags.close_and_open :              writeln(markup.indent_by_spaces_provided(k), "</", k, ">"); -            writeln(markup.indent_by_spaces_provided(k), "<", k, ">", obj.text); +            writeln(markup.indent_by_spaces_provided(k), "<", k, ">", obj.text, " file: ", obj.segment_anchor_tag, ".xhtml#", obj.ocn);              break;            case DomTags.open : -            writeln(markup.indent_by_spaces_provided(k), "<", k, ">", obj.text); +            writeln(markup.indent_by_spaces_provided(k), "<", k, ">", obj.text, " file: ", obj.segment_anchor_tag, ".xhtml#", obj.ocn);              break;            default :              break; diff --git a/org/ao_doc_abstraction.org b/org/ao_doc_abstraction.org index 355c126..240b8df 100644 --- a/org/ao_doc_abstraction.org +++ b/org/ao_doc_abstraction.org @@ -14,6 +14,22 @@  [[./sdp.org][sdp]]  [[./][org/]]  * 0. the document notes +** abstraction +- abstract for downstream processing +  - identify document structure and objects +    - identify document structure (headings/levels/sections) +    - identify objects +  - set document, generate common abstraction for downstream parsing +    - set different document sections, toc, body, endnotes, book index, etc. +    - object numbers, heading/ chapter numbering etc, endnote numbers +  - unify object representations +    - multiple markups for same object type given single representation +  - extract object attributes +  - unify inline markup on objects +    - inline markup made easier to identify + +- simplify downstream parsing +  ** document sections  |--------------+--------------+---+---+--------------------------------------------------+---+---+---| @@ -1784,6 +1800,12 @@ this can be extracted earlier)  Build here:  - DOM structure  - ancestors and decendants +  - ancestors could be determined earlier, but convenient to have here +  - descendants could be in the form of: headings contained under current +    heading, and/or; the range of objects under the current heading +- you could decide on a sequential object list, containing all objects (both +  substantive and non-substantive objects), in addition to ocn, which are for +  substantive/ citable objects within the document  (as needed) up to document heading 1~, lev4 html: @@ -3126,6 +3148,22 @@ void _poem_block_(L,O,T,C,N,Ma)(  ***** table block                                                 :table: +there are 3 types of table markup that need to be nomalized (given a single representation) here + +- curly brace block +- tic block +- special notation block + +you need: +- identify the type for the munging to create uniform presentation +  - curly, tick, special +  - table heading row, bool +- present table header info in uniform way +  - table_number_of_columns, int (count) +  - table_column_widths, int[] column widths (as given or calculate average) +  - show table walls, bool +- table content marked up in uniform way +  #+name: abs_functions_block_table  #+BEGIN_SRC d  void _table_block_(L,O,T,Ma)( diff --git a/org/defaults.org b/org/defaults.org index cb4ee80..b83308d 100644 --- a/org/defaults.org +++ b/org/defaults.org @@ -911,103 +911,226 @@ private import  #+name: defaults_template_paths  #+BEGIN_SRC d  template SiSUpaths() { -  string _base_filename(string fn_src) { -    string _fn_base = ""; -    if (extension(fn_src) == ".sst") { -      _fn_base = baseName(fn_src, ".sst"); -    } else if (extension(fn_src) == ".ssm") { -      _fn_base = baseName(fn_src, ".ssm"); -    } -    return _fn_base; -  } +#+END_SRC + +**** base + +#+name: defaults_template_paths +#+BEGIN_SRC d    struct DirPaths {      string base_filename(string fn_src) { -      return _base_filename(fn_src); +      return baseName(stripExtension(fn_src));      }    } +#+END_SRC + +**** sisupod + +***** pod + +#+name: defaults_template_paths +#+BEGIN_SRC d    struct SiSUpodPaths {      string base_filename(string fn_src) { -      return _base_filename(fn_src); +      return baseName(stripExtension(fn_src)); +    } +    string sisupod_filename(string fn_src) { +      return "sisupod".chainPath(base_filename(fn_src) ~ ".zip").array; +    } +    string base(string fn_src) { +      return "sisupod".chainPath(base_filename(fn_src)).array; +    } +  } +#+END_SRC + +***** pod zipped + +#+name: defaults_template_paths +#+BEGIN_SRC d +  struct SiSUpodPathsZipped { +    auto spod_pths = SiSUpodPaths(); +    string base_filename(string fn_src) { +      return spod_pths.base_filename(fn_src); +    } +    string sisupod_filename(string fn_src) { +      return spod_pths.sisupod_filename(fn_src);      }      string base(string fn_src) { -      return chainPath("sisupod", _base_filename(fn_src)).array; +      return spod_pths.base(fn_src);      } -    string doc(string fn_src) { -      return chainPath(base(fn_src), "doc").array; -      // return chainPath(base(fn_src), "text").array; +    auto doc_root(string fn_src) { +      return "doc";      } -    string doc_lng(string fn_src, string lng) { -      return chainPath(doc(fn_src), lng).array; +    auto doc(string fn_src) { +      return doc_root(fn_src);      } -    string conf(string fn_src) { -      return chainPath(doc(fn_src), "_sisu").array; +    auto doc_lng(string fn_src, string lng) { +      return doc_root(fn_src).chainPath(lng).array;      } -    string image(string fn_src) { -      return chainPath(conf(fn_src), "image").array; +    auto conf(string fn_src) { +      return doc_root(fn_src).chainPath("_sisu").array;      } -    string css(string fn_src) { -      return chainPath(conf(fn_src), "css").array; +    auto image(string fn_src) { +      return conf(fn_src).chainPath("image").array;      } -    string fn_doc(string fn_src, string lng) { -      return chainPath((doc_lng(fn_src, lng)), baseName(fn_src)).array; +    auto css(string fn_src) { +      return conf(fn_src).chainPath("css").array;      } -    string fn_doc_insert(string fn_src, string fn_insert, string lng) { -      return chainPath((doc_lng(fn_src, lng)), baseName(fn_insert)).array; +    auto fn_doc(string fn_src, string lng) { +      return (doc_lng(fn_src, lng)).chainPath(baseName(fn_src)).array; +    } +    auto fn_doc_insert(string fn_src, string fn_insert, string lng) { +      return (doc_lng(fn_src, lng)).chainPath(baseName(fn_insert)).array;      }    } +#+END_SRC + +***** pod unzipped archive + +#+name: defaults_template_paths +#+BEGIN_SRC d +  struct SiSUpodPathsFilesystemArchive { +    auto spod_pths = SiSUpodPaths(); +    string base_filename(string fn_src) { +      return spod_pths.base_filename(fn_src); +    } +    string sisupod_filename(string fn_src) { +      return spod_pths.sisupod_filename(fn_src); +    } +    string base(string fn_src) { +      return spod_pths.base(fn_src); +    } +    auto doc_root(string fn_src) { +      return base(fn_src).chainPath("doc").array; +    } +    auto doc(string fn_src) { +      return doc_root(fn_src); +    } +    auto doc_lng(string fn_src, string lng) { +      return doc_root(fn_src).chainPath(lng).array; +    } +    auto conf(string fn_src) { +      return doc_root(fn_src).chainPath("_sisu").array; +    } +    auto image(string fn_src) { +      return conf(fn_src).chainPath("image").array; +    } +    auto css(string fn_src) { +      return conf(fn_src).chainPath("css").array; +    } +    auto fn_doc(string fn_src, string lng) { +      return (doc_lng(fn_src, lng)).chainPath(baseName(fn_src)).array; +    } +    auto fn_doc_insert(string fn_src, string fn_insert, string lng) { +      return (doc_lng(fn_src, lng)).chainPath(baseName(fn_insert)).array; +    } +  } +#+END_SRC + +**** html5 + +#+name: defaults_template_paths +#+BEGIN_SRC d    struct HtmlPaths {      string base_filename(string fn_src) { -      return _base_filename(fn_src); +      return baseName(stripExtension(fn_src));      }      string base() { -      return chainPath("en", "html").array; +      return "en".chainPath("html").array;      }      string seg(string fn_src) { -      return chainPath(base, _base_filename(fn_src)).array; +      return base.chainPath(base_filename(fn_src)).array;      }      string fn_scroll(string fn_src) { -      return chainPath(base, _base_filename(fn_src) ~ ".html").array; +      return base.chainPath(base_filename(fn_src) ~ ".html").array;      }      string fn_seg(string fn_src, string seg_filename) { -      return chainPath(seg(fn_src), seg_filename ~ ".html").array; +      return seg(fn_src).chainPath(seg_filename ~ ".html").array;      }    } -  struct EpubPaths { +#+END_SRC + +**** epub3 + +#+name: defaults_template_paths +#+BEGIN_SRC d +  struct Epub3paths { +    string dirtop() { +      return "".chainPath("").array; +    }      string base_filename(string fn_src) { -      return _base_filename(fn_src); +      return baseName(stripExtension(fn_src));      }      string base() { -      return chainPath("en", "epub").array; +      return "en".chainPath("epub3").array;      } -    string doc(string fn_src) { -      return chainPath(base, _base_filename(fn_src)).array; +    string epub_file(string fn_src) { +      return base.chainPath(base_filename(fn_src) ~ ".epub").array; +    } +    string docdir(string fn_src) { +      return base.chainPath(base_filename(fn_src)).array;      }      string doc_meta_inf(string fn_src) { -      return chainPath(doc(fn_src), "META-INF").array; +      return dirtop.chainPath("META-INF").array;      }      string doc_oebps(string fn_src) { -      return chainPath(doc(fn_src), "OEBPS").array; +      return dirtop.chainPath("OEBPS").array;      }      string doc_oebps_css(string fn_src) { -      return chainPath(doc_oebps(fn_src), "css").array; +      return doc_oebps(fn_src).chainPath("css").array;      }      string doc_oebps_image(string fn_src) { -      return chainPath(doc_oebps(fn_src), "image").array; +      return doc_oebps(fn_src).chainPath("image").array;      }      string fn_mimetypes(string fn_src) { -      return chainPath(doc(fn_src), "mimetypes").array; +      return dirtop.chainPath("mimetypes").array;      }      string fn_dmi_container_xml(string fn_src) { -      return chainPath(doc_meta_inf(fn_src), "container.xml").array; +      return doc_meta_inf(fn_src).chainPath("container.xml").array; +    } +    string fn_oebps_toc_nav_xhtml(string fn_src) { +      return doc_oebps(fn_src).chainPath("toc_nav.xhtml").array;      }      string fn_oebps_toc_ncx(string fn_src) { -      return chainPath(doc_oebps(fn_src), "toc.ncx").array; +      return doc_oebps(fn_src).chainPath("toc.ncx").array;      }      string fn_oebps_content_opf(string fn_src) { -      return chainPath(doc_oebps(fn_src), "content.opf").array; +      return doc_oebps(fn_src).chainPath("content.opf").array;      }      string fn_oebps_content_xhtml(string fn_src, string seg_filename) { -      return chainPath(doc_oebps(fn_src), seg_filename ~ ".xhtml").array; +      return doc_oebps(fn_src).chainPath(seg_filename ~ ".xhtml").array; +    } +    debug(epub_output) { +      string dbg_doc_meta_inf(string fn_src) { +        return docdir(fn_src).chainPath("META-INF").array; +      } +      string dbg_doc_oebps(string fn_src) { +        return docdir(fn_src).chainPath("OEBPS").array; +      } +      string dbg_doc_oebps_css(string fn_src) { +        return doc_oebps(fn_src).chainPath("css").array; +      } +      string dbg_doc_oebps_image(string fn_src) { +        return doc_oebps(fn_src).chainPath("image").array; +      } +      string dbg_fn_mimetypes(string fn_src) { +        return docdir(fn_src).chainPath("mimetypes").array; +      } +      string dbg_fn_dmi_container_xml(string fn_src) { +        return doc_meta_inf(fn_src).chainPath("container.xml").array; +      } +      string dbg_fn_oebps_toc_nav_xhtml(string fn_src) { +        return doc_oebps(fn_src).chainPath("toc_nav.xhtml").array; +      } +      string dbg_fn_oebps_toc_ncx(string fn_src) { +        return doc_oebps(fn_src).chainPath("toc.ncx").array; +      } +      string dbg_fn_oebps_content_opf(string fn_src) { +        return doc_oebps(fn_src).chainPath("content.opf").array; +      } +      string dbg_fn_oebps_content_xhtml(string fn_src, string seg_filename) { +        return doc_oebps(fn_src).chainPath(seg_filename ~ ".xhtml").array; +      }      }    }  } @@ -1072,8 +1195,7 @@ template InternalMarkup() {      auto tc_o = "┏"; //"『"; // "┏" ┓      auto tc_c = "┚"; // "』"; // "┚"  table row mark #Mx[:tc_c]="』\n"      auto tc_p = "┆";   // table col/misc mark -    string indent_by_spaces_provided(int indent) { -      auto _indent_spaces ="░░";   // auto nbsp = "░"; +    string indent_by_spaces_provided(int indent, string _indent_spaces ="░░") {        _indent_spaces = replicate(_indent_spaces, indent);        return _indent_spaces;      } diff --git a/org/output.org b/org/output.org index e84796d..a9fdc74 100644 --- a/org/output.org +++ b/org/output.org @@ -17,7 +17,7 @@  #+BEGIN_SRC d :tangle ../src/sdp/output_hub.d  /++ -  output hub<BR> +  output hub<br>    check & generate output types requested  +/  template outputHub() { @@ -38,13 +38,14 @@ template outputHub() {      std.traits,      std.typecons,      std.uni, -    std.utf, +    std.utf; +  import      defaults, -    output_epub, +    output_epub3,      output_html,      output_xhtmls, -    source_sisupod; -  import +    source_sisupod, +    create_zip_file,      output_rgx,      output_xhtmls;    void outputHub(D,I)(D doc_abstraction, I doc_matters) { @@ -83,10 +84,10 @@ template outputHub() {        if ((doc_matters.opt_action_bool["verbose"])) {writeln("html scroll done");}      }      if (doc_matters.opt_action_bool["epub"]) { -      if ((doc_matters.opt_action_bool["verbose"])) {write("epub processing... ");} -      outputEPub!()(doc_abstraction, doc_matters); +      if ((doc_matters.opt_action_bool["verbose"])) {write("epub3 processing... ");} +      outputEPub3!()(doc_abstraction, doc_matters);        // epub.css_write; -      if ((doc_matters.opt_action_bool["verbose"])) {writeln("epub done");} +      if ((doc_matters.opt_action_bool["verbose"])) {writeln("epub3 done");}      }      if (doc_matters.opt_action_bool["pdf"]) {        /+ mixin outputPDF; +/ @@ -117,27 +118,53 @@ private import    std.algorithm,    std.array,    std.container, +  std.digest.sha,    std.exception,    std.file,    std.getopt,    std.json, -  std.process, -  std.stdio, +  std.outbuffer,    std.path, +  std.process,    std.range,    std.regex, +  std.stdio,    std.string,    std.traits,    std.typecons,    std.uni,    std.utf, +  std.zip,    std.conv : to;  import +  create_zip_file,    defaults,    output_rgx,    output_xhtmls;  #+END_SRC +** _zip_ +*** template                                                     :template: + +#+BEGIN_SRC d :tangle ../src/sdp/create_zip_file.d +template createZipFile() { +  import std.file; +  import std.outbuffer; +  import std.string; +  import std.zip; +  void createZipFile( +    string zip_file_name, +    void[] compressed_zip_data, +  ) { +    try { +      write(zip_file_name, compressed_zip_data); +    } catch (ZipException ex) { +      // Handle Errors +    } +  } +} +#+END_SRC +  ** _sisupod_                                                         :sisupod:  *** template                                                     :template: @@ -162,12 +189,13 @@ template SiSUpod() {  #+name: source_sisupod_init  #+BEGIN_SRC d -debug(asserts){ +debug(asserts) {    // static assert(is(typeof(doc_matters) == tuple));  }  mixin SiSUoutputRgxInit;  mixin SiSUpaths; -auto pth_sisupod = SiSUpodPaths(); +auto pth_sisupod = SiSUpodPathsZipped(); +auto pth_sisupod_filesystem = SiSUpodPathsFilesystemArchive();  mixin SiSUlanguageCodes;  auto lang = Lang();  auto rgx = Rgx(); @@ -177,20 +205,20 @@ assert (doc_matters.source_filename.match(rgx.src_fn));  #+name: source_sisupod_mkdirs  #+BEGIN_SRC d  /+ create directory structure +/ -if (!exists(pth_sisupod.doc(doc_matters.source_filename))) { -  pth_sisupod.doc(doc_matters.source_filename).mkdirRecurse; +if (!exists(pth_sisupod_filesystem.doc(doc_matters.source_filename))) { +  pth_sisupod_filesystem.doc(doc_matters.source_filename).mkdirRecurse;  } -if (!exists(pth_sisupod.conf(doc_matters.source_filename))) { -  pth_sisupod.conf(doc_matters.source_filename).mkdirRecurse; +if (!exists(pth_sisupod_filesystem.conf(doc_matters.source_filename))) { +  pth_sisupod_filesystem.conf(doc_matters.source_filename).mkdirRecurse;  } -if (!exists(pth_sisupod.css(doc_matters.source_filename))) { -  pth_sisupod.css(doc_matters.source_filename).mkdirRecurse; +if (!exists(pth_sisupod_filesystem.css(doc_matters.source_filename))) { +  pth_sisupod_filesystem.css(doc_matters.source_filename).mkdirRecurse;  } -if (!exists(pth_sisupod.image(doc_matters.source_filename))) { -  pth_sisupod.image(doc_matters.source_filename).mkdirRecurse; +if (!exists(pth_sisupod_filesystem.image(doc_matters.source_filename))) { +  pth_sisupod_filesystem.image(doc_matters.source_filename).mkdirRecurse;  } -if (!exists(pth_sisupod.doc_lng(doc_matters.source_filename, doc_matters.language))) { -  pth_sisupod.doc_lng(doc_matters.source_filename, doc_matters.language).mkdirRecurse; +if (!exists(pth_sisupod_filesystem.doc_lng(doc_matters.source_filename, doc_matters.language))) { +  pth_sisupod_filesystem.doc_lng(doc_matters.source_filename, doc_matters.language).mkdirRecurse;  }  #+END_SRC @@ -200,54 +228,158 @@ if (!exists(pth_sisupod.doc_lng(doc_matters.source_filename, doc_matters.languag  #+BEGIN_SRC d  debug(sisupod) {    writeln(__LINE__, ": ", -    // doc_matters.environment["pwd"], "/", -      doc_matters.source_filename, " -> ", -    // doc_matters.environment["pwd"], "/", -      pth_sisupod.fn_doc( -        doc_matters.source_filename, -        doc_matters.language -  )); -} -if (exists(doc_matters.source_filename)) { -  copy( +    doc_matters.source_filename, " -> ", +    pth_sisupod_filesystem.fn_doc(      doc_matters.source_filename, -    pth_sisupod.fn_doc( -      doc_matters.source_filename, -      doc_matters.language +    doc_matters.language    ));  } -if (doc_matters.file_insert_list.length > 0) { -  foreach (insert_file; doc_matters.file_insert_list) { -    debug(sisupod) { +auto zip = new ZipArchive(); +auto fn_sisupod = pth_sisupod.sisupod_filename(doc_matters.source_filename); +{ /+ bundle images +/ +  foreach (image; doc_matters.image_list) { +    debug(sisupodimages) {        writeln( +        "_sisu/image/", image, " -> ", +        pth_sisupod.image(doc_matters.source_filename), "/", image +      ); +    } +    auto fn_src = "_sisu/image/"~ image; +    auto fn_out =  pth_sisupod.image(doc_matters.source_filename).to!string ~ "/" ~ image; +    auto fn_out_filesystem =  pth_sisupod_filesystem.image(doc_matters.source_filename).to!string ~ "/" ~ image; +    if (exists(fn_src)) { +      fn_src.copy(fn_out_filesystem); +      { +        auto zip_arc_member_file = new ArchiveMember(); +        zip_arc_member_file.name = fn_out; +        auto zip_data = new OutBuffer(); +        zip_data.write(cast(char[]) ((fn_src).read)); +        zip_arc_member_file.expandedData = zip_data.toBytes(); +        zip.addMember(zip_arc_member_file); +        createZipFile!()(pth_sisupod.sisupod_filename(fn_src), zip.build()); +      } +    } +  } +} +{ /+ bundle sisu_document_make +/ +  auto fn_src = "_sisu/sisu_document_make"; // check (_sisu/sisu_document_make) +  auto fn_out = pth_sisupod.conf(doc_matters.source_filename).to!string ~ "/" ~ "sisu_document_make"; +  auto fn_out_filesystem = pth_sisupod_filesystem.conf(doc_matters.source_filename).to!string ~ "/" ~ "sisu_document_make"; +  if (exists(fn_src)) { +    fn_src.copy(fn_out_filesystem); +    { +      auto zip_arc_member_file = new ArchiveMember(); +      zip_arc_member_file.name = fn_out; +      auto zip_data = new OutBuffer(); +      zip_data.write((fn_src).readText); +      zip_arc_member_file.expandedData = zip_data.toBytes(); +      zip.addMember(zip_arc_member_file); +      createZipFile!()(pth_sisupod.sisupod_filename(fn_src), zip.build()); +    } +  } +} +{ /+ bundle primary file +/ +  auto fn_src = doc_matters.source_filename; +  auto fn_out = pth_sisupod.fn_doc(doc_matters.source_filename, doc_matters.language).to!string; +  auto fn_out_filesystem = pth_sisupod_filesystem.fn_doc(doc_matters.source_filename, doc_matters.language).to!string; +  if (exists(fn_src)) { +    fn_src.copy(fn_out_filesystem); +    { +      auto zip_arc_member_file = new ArchiveMember(); +      zip_arc_member_file.name = fn_out; +      auto zip_data = new OutBuffer(); +      zip_data.write((fn_src).readText); +      zip_arc_member_file.expandedData = zip_data.toBytes(); +      zip.addMember(zip_arc_member_file); +      createZipFile!()(pth_sisupod.sisupod_filename(fn_src), zip.build()); +    } +  } +} +{ /+ bundle insert files +/ +  if (doc_matters.file_insert_list.length > 0) { +    foreach (insert_file; doc_matters.file_insert_list) { +      debug(sisupod) { +        writeln(            insert_file, " -> ",            pth_sisupod.fn_doc_insert(              doc_matters.source_filename,              insert_file,              doc_matters.language -      )); -    } -    if (exists(insert_file)) { -      insert_file.copy( -        pth_sisupod.fn_doc_insert( -          doc_matters.source_filename, -          insert_file, -          doc_matters.language -      )); +        )); +      } +      auto fn_src = insert_file; +      auto fn_out = pth_sisupod.fn_doc_insert( +        doc_matters.source_filename, +        insert_file, +        doc_matters.language +      ).to!string; +      auto fn_out_filesystem = pth_sisupod_filesystem.fn_doc_insert( +        doc_matters.source_filename, +        insert_file, +        doc_matters.language +      ).to!string; +      if (exists(fn_src)) { +        fn_src.copy(fn_out_filesystem); +        { +          auto zip_arc_member_file = new ArchiveMember(); +          zip_arc_member_file.name = insert_file; +          auto zip_data = new OutBuffer(); +          zip_data.write((fn_src).readText); +          zip_arc_member_file.expandedData = zip_data.toBytes(); +          zip.addMember(zip_arc_member_file); +          createZipFile!()(pth_sisupod.sisupod_filename(fn_src), zip.build()); +        } +      }      }    }  } -foreach (image; doc_matters.image_list) { -  debug(sisupod) { -    writeln( -        "_sisu/image/", image, " -> ", -        pth_sisupod.image(doc_matters.source_filename), "/", image -    ); +#+END_SRC + +*** sha256 of sisupod.zip, zip debug, read zip archive + +#+name: source_sisupod_copy +#+BEGIN_SRC d +if (exists(fn_sisupod)) { +  try { +    auto data = (cast(byte[]) (fn_sisupod).read); +    writefln("%-(%02x%) %s", data.sha256Of, fn_sisupod); +    debug(sisupod) { +      try { +        auto zipped = new ZipArchive((fn_sisupod).read); +        foreach (filename, member; zipped.directory) { +          auto data = zipped.expand(member); +          writeln("> ", filename, " length ", data.length); // filename == member.name +          // Use data +        } +      } +      catch (ZipException ex) { +        // Handle errors +      } +      if (doc_matters.source_filename == "en/the_wealth_of_networks.yochai_benkler.sst") { +        assert( +          ((data).sha256Of).toHexString +          == "DDE0013C13C6A4F06D4BE72087E2CDEF47697CA38A6A2D65BA7207DB6B144271", +          "\nsisupod: sha256 value for " +          ~ doc_matters.source_filename +          ~ " has changed, is now: " +          ~ ((data).sha256Of).toHexString +        ); +      } +      if (doc_matters.source_filename == "en/sisu_markup_stress_test.sst") { +        assert( +          ((data).sha256Of).toHexString +          == "112C0AEDD2518A1803D91A7CF5785274A3116C0779A631782D0C0813B212C68A", +          "\nsisupod: sha256 value for " +          ~ doc_matters.source_filename +          ~ " has changed, is now: " +          ~ ((data).sha256Of).toHexString +        ); +      } +    }    } -  if (exists("_sisu/image/"~ image)) { -    ("_sisu/image/"~ image).copy( -      (pth_sisupod.image(doc_matters.source_filename) ~ "/" ~ image) -    ); +    catch (ErrnoException ex) +  { +    // Handle errors    }  }  #+END_SRC @@ -279,7 +411,7 @@ string special_characters(string _txt){      .replaceAll(rgx.xhtml_ampersand,    "&")      .replaceAll(rgx.xhtml_less_than,    "<")      .replaceAll(rgx.xhtml_greater_than, ">") -    .replaceAll(rgx.xhtml_line_break,   "<br>"); +    .replaceAll(rgx.xhtml_line_break,   "<br />");    return _txt;  }  #+END_SRC @@ -329,7 +461,7 @@ string _xhtml_anchor_tags(const(string[]) anchor_tags) {  auto scroll_head(Me)(    Me dochead_meta,  ) { -  debug(asserts){ +  debug(asserts) {      static assert(is(typeof(dochead_meta) == string[string][string]));    }    string o; @@ -337,26 +469,27 @@ auto scroll_head(Me)(  <html>  <head>    <meta charset="utf-8"> -  <title> -    %s%s -  </title> -<meta http-equiv="Content-Type" content="text/html;charset=utf-8" /> -  <meta name="dc.title" content="Title" /> -  <meta name="dc.author" content="Author" /> -  <meta name="dc.publisher" content="SiSU http://www.jus.uio.no/sisu (this copy)" /> -  <meta name="dc.date" content="year" /> -  <meta name="dc.date.created" content="year" /> -  <meta name="dc.date.issued" content="year" /> -  <meta name="dc.date.available" content="year" /> -  <meta name="dc.date.valid" content="year" /> -  <meta name="dc.date.modified" content="year" /> -  <meta name="dc.language" content="US" /> -  <meta name="dc.rights" content="Copyright: Copyright (C) year holder /> -  <meta name="generator" content="sdp [SiSU 7.1.8 of 2016w08/5 (2016-02-26)] (n*x and D)" /> -    <link rel="generator" href="http://www.sisudoc.org/" /> +    <title> +      %s%s +    </title> +    <meta http-equiv="Content-Type" content="text/html;charset=utf-8" /> +    <meta name="dc.title" content="Title" /> +    <meta name="dc.author" content="Author" /> +    <meta name="dc.publisher" content="SiSU http://www.jus.uio.no/sisu (this copy)" /> +    <meta name="dc.date" content="year" /> +    <meta name="dc.date.created" content="year" /> +    <meta name="dc.date.issued" content="year" /> +    <meta name="dc.date.available" content="year" /> +    <meta name="dc.date.valid" content="year" /> +    <meta name="dc.date.modified" content="year" /> +    <meta name="dc.language" content="US" /> +    <meta name="dc.rights" content="Copyright: Copyright (C) year holder /> +    <meta name="generator" content="sdp [SiSU 7.1.8 of 2016w08/5 (2016-02-26)] (n*x and D)" /> +  </meta> +  <link rel="generator" href="http://www.sisudoc.org/" />    <link rel="shortcut icon" href="../_sisu/image/rb7.ico" /> -  <link href="../../_sisu/css/html.css" rel="stylesheet"> -  <link href="../../../_sisu/css/html.css" rel="stylesheet"> +  <link href="../../_sisu/css/html.css" rel="stylesheet" /> +  <link href="../../../_sisu/css/html.css" rel="stylesheet" />  </head>  <body lang="en">  <a name="top" id="top"></a>¶", @@ -374,7 +507,7 @@ dochead_meta["title"]["full"],  auto seg_head(Me)(    Me dochead_meta,  ) { -  debug(asserts){ +  debug(asserts) {      static assert(is(typeof(dochead_meta) == string[string][string]));    }    string o; @@ -382,26 +515,27 @@ auto seg_head(Me)(  <html>  <head>    <meta charset="utf-8"> -  <title> -    %s%s -  </title> -<meta http-equiv="Content-Type" content="text/html;charset=utf-8" /> -  <meta name="dc.title" content="Title" /> -  <meta name="dc.author" content="Author" /> -  <meta name="dc.publisher" content="SiSU http://www.jus.uio.no/sisu (this copy)" /> -  <meta name="dc.date" content="year" /> -  <meta name="dc.date.created" content="year" /> -  <meta name="dc.date.issued" content="year" /> -  <meta name="dc.date.available" content="year" /> -  <meta name="dc.date.valid" content="year" /> -  <meta name="dc.date.modified" content="year" /> -  <meta name="dc.language" content="US" /> -  <meta name="dc.rights" content="Copyright: Copyright (C) year holder /> -  <meta name="generator" content="sdp [SiSU 7.1.8 of 2016w08/5 (2016-02-26)] (n*x and D)" /> -    <link rel="generator" href="http://www.sisudoc.org/" /> +    <title> +      %s%s +    </title> +    <meta http-equiv="Content-Type" content="text/html;charset=utf-8" /> +    <meta name="dc.title" content="Title" /> +    <meta name="dc.author" content="Author" /> +    <meta name="dc.publisher" content="SiSU http://www.jus.uio.no/sisu (this copy)" /> +    <meta name="dc.date" content="year" /> +    <meta name="dc.date.created" content="year" /> +    <meta name="dc.date.issued" content="year" /> +    <meta name="dc.date.available" content="year" /> +    <meta name="dc.date.valid" content="year" /> +    <meta name="dc.date.modified" content="year" /> +    <meta name="dc.language" content="US" /> +    <meta name="dc.rights" content="Copyright: Copyright (C) year holder" /> +    <meta name="generator" content="sdp [SiSU 7.1.8 of 2016w08/5 (2016-02-26)] (n*x and D)" /> +  </meta> +  <link rel="generator" href="http://www.sisudoc.org/" />    <link rel="shortcut icon" href="../_sisu/image/rb7.ico" /> -  <link href="../../_sisu/css/html.css" rel="stylesheet"> -  <link href="../../../_sisu/css/html.css" rel="stylesheet"> +  <link href="../../_sisu/css/html.css" rel="stylesheet" /> +  <link href="../../../_sisu/css/html.css" rel="stylesheet" />  </head>  <body lang="en">  <a name="top" id="top"></a>¶", @@ -485,13 +619,13 @@ auto inline_links(O)(  #+name: xhtml_format_objects  #+BEGIN_SRC d  auto inline_notes_scroll(O)( -  auto return ref const O         obj, -  string                  _txt, +  auto return ref const O   obj, +  string                    _txt,  ) {    if (obj.inline_notes_reg) {      _txt = (_txt).replaceAll(        rgx.inline_notes_delimiter_al_regular_number_note, -      ("<a href=\"#note_$1\"><note id=\"noteref_$1\"> <sup>$1</sup> </note></a>") +      ("<a href=\"#note_$1\"><note id=\"noteref_$1\"> <sup>$1</sup> </note></a>")      );    }    debug(markup_endnotes) { @@ -535,7 +669,7 @@ auto inline_notes_seg(O)(          "\">",          "<note id=\"note_",          m.captures[1], -        "\"> <sup>", +        "\"> <sup>",          m.captures[1],          ".</sup></note></a>",          m.captures[2], @@ -544,7 +678,7 @@ auto inline_notes_seg(O)(      }      _txt = (_txt).replaceAll(        rgx.inline_notes_delimiter_al_regular_number_note, -      ("<a href=\"#note_$1\"><note id=\"noteref_$1\"> <sup>$1</sup> </note></a>") +      ("<a href=\"#note_$1\"><note id=\"noteref_$1\"> <sup>$1</sup> </note></a>")      );    } else if (_txt.match(rgx.inline_notes_delimiter_al_regular_number_note)) {      debug(markup) { @@ -625,7 +759,7 @@ auto heading(O)(    auto tags = _xhtml_anchor_tags(obj.anchor_tags);    string o;    if (obj.obj_cite_number.empty) { -    o = format(q"¶<br><hr /><br> +    o = format(q"¶<br /><hr /><br />    <div class="substance">      <h%s class="%s">%s        %s @@ -638,7 +772,7 @@ auto heading(O)(        obj.heading_lev_markup,      );    } else { -    o = format(q"¶<br><hr /><br> +    o = format(q"¶<br /><hr /><br />    <div class="substance">      <label class="ocn"><a href="#%s" class="lnkocn">%s</a></label>      <h%s class="%s" id="%s"><a name="%s"></a>%s @@ -707,7 +841,7 @@ auto para(O)(    auto tags = _xhtml_anchor_tags(obj.anchor_tags);    _txt = font_face(_txt);    string o; -  _txt = (obj.bullet) ? ("●  " ~ _txt) : _txt; +  _txt = (obj.bullet) ? ("●  " ~ _txt) : _txt;    if (obj.obj_cite_number.empty) {      o = format(q"¶  <div class="substance">    <p class="%s" indent="h%si%s">%s @@ -942,7 +1076,6 @@ auto block(O)(  </div>¶",        obj.is_a,        _txt -      // obj.text      );    } else {      o = format(q"¶  <div class="substance"> @@ -956,7 +1089,6 @@ auto block(O)(        obj.is_a,        obj.obj_cite_number,        _txt -      // obj.text      );    }    return o; @@ -1008,9 +1140,9 @@ auto verse(O)(                           // using code from code block, review  ) {    _txt = font_face(_txt);    _txt = (_txt) -    .replaceAll(rgx.newline, "<br>\n") -    .replaceAll(rgx.two_spaces, " " ~ " " ~ " " ~ " ") -    .replaceAll(rgx.nbsp_and_space, " " ~ " ") +    .replaceAll(rgx.newline, "<br />\n") +    .replaceAll(rgx.two_spaces, " " ~ " " ~ " " ~ " ") +    .replaceAll(rgx.nbsp_and_space, " " ~ " ")      .replaceAll(rgx.strip_br, "");    string o;    if (obj.obj_cite_number.empty) { @@ -1084,8 +1216,8 @@ auto verse_seg(O)(      ) {        string _txt = obj.text;        _txt = (_txt) -        .replaceAll(rgx.newline, "<br>\n") -        .replaceAll(rgx.nbsp_char, " "); +        .replaceAll(rgx.newline, "<br />\n") +        .replaceAll(rgx.nbsp_char, " ");        string o;        if (obj.obj_cite_number.empty) {            o = format(q"¶  <div class="substance"> @@ -1388,7 +1520,7 @@ void scroll_write_output(Fn,C)(    Fn fn_src,    C doc,  ) { -  debug(asserts){ +  debug(asserts) {      static assert(is(typeof(fn_src) == string));      static assert(is(typeof(doc)    == string[]));    } @@ -1636,7 +1768,7 @@ void seg_write_output(M,D,E)(    D doc_html,    E doc_html_endnotes,  ) { -  debug(asserts){ +  debug(asserts) {      static assert(is(typeof(doc_html)      == string[][string]));    }    mixin SiSUoutputRgxInit; @@ -2523,104 +2655,225 @@ auto css_write() {  #+END_SRC  *** _epub_ [#B]                                                        :epub: + +|-----------------------+--------------------------+---------------------------+----------------------------------| +| function              | filename                 | module                    | variable                         | +|-----------------------+--------------------------+---------------------------+----------------------------------| +| identify doc filetype | mimetype                 | epub3_mimetypes           | mimetypes                        | +|-----------------------+--------------------------+---------------------------+----------------------------------| +| identify doc root     | META-INF/container.xml   | epub3_container_xml       | meta_inf_container_xml           | +|-----------------------+--------------------------+---------------------------+----------------------------------| +| doc manifest          | OEBPS/content.opf        | epub3_oebps_content       | oebps_content_opf                | +|-----------------------+--------------------------+---------------------------+----------------------------------| +| doc navigation        | OEBPS/toc_nav.xhtml      | epub3_oebps_toc_nav_xhtml | oebps_toc_nav_xhtml              | +|                       | OEBPS/toc.ncx            | epub2_oebps_toc_ncx       | oebps_toc_ncx                    | +|-----------------------+--------------------------+---------------------------+----------------------------------| +| doc contents          | OEBPS/[files ... ].xhtml | outputEPub3               | doc_epub3[seg_filename]          | +|                       |                          |                           | doc_epub3_endnotes[seg_filename] | +|-----------------------+--------------------------+---------------------------+----------------------------------| +  **** template                                                   :template: -#+BEGIN_SRC d :tangle ../src/sdp/output_epub.d -template outputEPub() { +#+BEGIN_SRC d :tangle ../src/sdp/output_epub3.d +template outputEPub3() {    <<output_imports>>    mixin InternalMarkup;    mixin outputXHTMLs; -  <<output_epub_fixed>> -  <<output_epub_constructs>> -  <<output_epub_xhtml>> -  <<output_epub_xhtml_seg>> -  <<output_epub_css>> +  <<output_epub3_fixed>> +  <<output_epub3_constructs>> +  <<output_epub3_xhtml>> +  <<output_epub3_xhtml_seg>> +  <<output_epub3_css>>  }  #+END_SRC -**** epub special files                                           :format: -***** static -****** mimetype (file) +**** special (epub) files                                         :format: +***** DONE static +****** _identify doc filetype_ (mimetype) [static] + +- mimetype file indicating that zip file contains an EPUB -#+name: output_epub_fixed +#+name: output_epub3_fixed  #+BEGIN_SRC d -string epub_mimetypes() { +string epub3_mimetypes() {    string o; -  o = format(q"¶application/epub+zip¶"); +  o = format(q"¶application/epub+zip¶") ~ "\n";    return o;  }  #+END_SRC -****** META-INF/container.xml (file) +****** _identify doc root_ (META-INF/container.xml) [static] rootfile: contains document root path -#+name: output_epub_fixed +- identifies the root package document (so systems can find it), [unchanged from epub2] + +#+name: output_epub3_fixed  #+BEGIN_SRC d -string epub_container_xml() { +string epub3_container_xml() {    string o; -  o = format(q"¶<?xml version='1.0' encoding='utf-8'?> -<container version="1.0" -  xmlns="urn:oasis:names:tc:opendocument:xmlns:container"> -  <rootfiles> -    <rootfile full-path="OEBPS/content.opf" -      media-type="application/oebps-package+xml" /> -  </rootfiles> -</container>¶"); +  o = format(q"¶<?xml version='1.0' encoding='utf-8'?>¶") ~ "\n"; +  o ~= format(q"¶<container version="1.0" +xmlns="urn:oasis:names:tc:opendocument:xmlns:container"> +<rootfiles> +  <rootfile full-path="OEBPS/content.opf" +    media-type="application/oebps-package+xml" /> +</rootfiles>¶") ~ "\n</container>\n";    return o;  }  #+END_SRC -***** constructs (in OEBPS) -****** TODO OEBPS/content.opf (register content: files, images etc.) +***** constructs (in dir: OEBPS) +****** TODO _doc manifest_ (OEBPS/content.opf) manifest, register content: files, images etc. + +- manifest, listing all resources +- provides the default reading order +- identifies the navigation document -#+name: output_epub_constructs +#+name: output_epub3_constructs  #+BEGIN_SRC d -string epub_oebps_content(D,I)(D doc_abstraction, I doc_matters) { -  string uuid = "18275d951861c77f78acd05672c9906924c59f18a2e0ba06dad95959693e9bd8"; // TODO shared elsewhere -  string content = format(q"¶<?xml version='1.0' encoding='utf-8'?> -<?xml version='1.0' encoding='utf-8'?> +string epub3_oebps_content(D,I,P)(D doc_abstraction, I doc_matters, P parts) { +  string uuid = "18275d951861c77f78acd05672c9906924c59f18a2e0ba06dad95959693e9bd8"; // TODO sort uuid in doc_matters! +  string content = format(q"¶  <?xml version='1.0' encoding='utf-8'?>  <package xmlns="http://www.idpf.org/2007/opf" version="2.0" unique-identifier="EPB-UUID"> -  <opf:metadata +  <metadata      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" -    xmlns:opf="http://www.idpf.org/2007/opf"      xmlns:dcterms="http://purl.org/dc/terms/"      xmlns:dc="http://purl.org/dc/elements/1.1/"      unique-identifier="urn:uuid:%s" version="2.0"> -    <dc:title>%s</dc:title> -    <dc:creator opf:file-as="%s" opf:role="aut">%s</dc:creator> -    <dc:language>en</dc:language> -    <dc:date opf:event="published">%s</dc:date> +    <!-- <dc:title id="title">%s</dc:title> --> +    <dc:title id="title">%s</dc:title> +    <meta refines="#title" property="title-type">main</meta> +    <dc:title id="subtitle">%s</dc:title> +    <meta refines="#subtitle" property="title-type">subtitle</meta> +    <dc:creator file-as="%s" id="aut">%s</dc:creator> +    <dc:language>%s</dc:language> +    <dc:date id="published">%s</dc:date>      <dc:rights>Copyright: %s</dc:rights> -    <dc:identifier opf:scheme="URI">ox/current/en/epub/sisu_markup.epub</dc:identifier> +    <dc:identifier scheme="URI">%s</dc:identifier>      <dc:identifier id="bookid">urn:uuid:%s</dc:identifier>      <!-- <dc:identifier id="EPB-UUID">urn:uuid:%s</dc:identifier> --> -  </opf:metadata> +  </metadata>    <manifest> -    <!-- NCX --> -    <item id="ncx" href="toc.ncx" media-type="application/x-dtbncx+xml" /> +    <!-- NCX epub2 navigation --> +      <item id="ncx" href="toc.ncx" media-type="application/x-dtbncx+xml" />      <!-- CSS Style Sheets --> -    <item id="main-css" href="css/xhtml.css" media-type="text/css" />¶", +      <item id="main-css" href="css/xhtml.css" media-type="text/css" /> +    <!-- nav epub3 navigation --> +      <item id="nav" href="toc_nav.xhtml" media-type="application/xhtml+xml" properties="nav" /> +¶", +    uuid, +    doc_matters.dochead_meta["title"]["full"], +    doc_matters.dochead_meta["title"]["main"], +    (doc_matters.dochead_meta["title"]["sub"].empty) +      ? "" : doc_matters.dochead_meta["title"]["sub"], +    (doc_matters.dochead_meta["creator"]["author"].empty) +      ? "" : doc_matters.dochead_meta["creator"]["author"], +    (doc_matters.dochead_meta["creator"]["author"].empty) +      ? "" : doc_matters.dochead_meta["creator"]["author"], +    doc_matters.language, +    (doc_matters.dochead_meta["date"]["published"].empty) +      ? "" : doc_matters.dochead_meta["date"]["published"], +    (doc_matters.dochead_meta["rights"]["copyright"].empty) +      ? "" : doc_matters.dochead_meta["rights"]["copyright"],      uuid, -    doc_matters.dochead_meta["title"]["full"],                                                               // title -    (doc_matters.dochead_meta["creator"]["author"].empty) ? "" : " by " ~ doc_matters.dochead_meta["creator"]["author"], // author -    (doc_matters.dochead_meta["creator"]["author"].empty) ? "" : " by " ~ doc_matters.dochead_meta["creator"]["author"], // author -    (doc_matters.dochead_meta["date"]["published"].empty) ? "" : " by " ~ doc_matters.dochead_meta["date"]["published"],  // date -    (doc_matters.dochead_meta["rights"]["copyright"].empty) ? "" : " by " ~ doc_matters.dochead_meta["rights"]["copyright"],  // rights      uuid,      uuid,    ); +  content ~= "    " ~ "<!-- Content Documents -->" ~ "\n  "; +  content ~= parts["manifest_documents"]; +  // TODO sort jpg & png +  content ~= "    " ~ "<!-- Images -->" ~ "\n  "; +  foreach (image; doc_matters.image_list) { +    content ~= format(q"¶      <item id="%s" href="image/%s" media-type="image/png" /> +¶", +      image,                        // strip image type, remove .png .jpg suffix, use in media-type="image/" +      image, +    ); +  } +  content ~= "  " ~ "</manifest>"         ~ "\n  "; +  content ~= "  " ~ "<spine toc=\"ncx\">" ~ "\n  "; +  content ~= parts["spine"]; +  content ~= "  " ~ "</spine>"            ~ "\n  "; +  content ~= "  " ~ "<guide>"             ~ "\n  "; +  content ~= parts["guide"]; +  content ~= "  " ~ "</guide>"            ~ "\n  "; +  content ~= ""   ~ "</package>"; +  return content; +} +#+END_SRC + +****** _doc navigation epub3_ (OEBPS/toc_nav.xhtml) epub3 navigable toc using Dom structure + +- toc_nav.xhtml declared as nav file in content.opf (epub3 navigation document) + +#+name: output_epub3_constructs +#+BEGIN_SRC d +string epub3_oebps_toc_nav_xhtml(D,I)(D doc_abstraction, I doc_matters) { +  enum DomTags { none, open, close, close_and_open, open_still, } +  auto markup = InlineMarkup(); +  string toc ="<nav epub:type=\"toc\" id=\"toc\">\n";    foreach (sect; doc_matters.keys_seq_seg) {      foreach (obj; doc_abstraction[sect]) { +      if (obj.is_a == "heading") { +        foreach_reverse (n; 0 .. 7) { +          string k = n.to!string; +          switch (obj.dom_collapsed[n]) { +          case DomTags.close : +            toc ~= markup.indent_by_spaces_provided((n + 1), "  ") ~ "</li>" ~ "\n"; +            toc ~= markup.indent_by_spaces_provided(n, "  ") ~ "</ol>" ~ "\n"; +            break; +          case DomTags.close_and_open : +            toc ~= markup.indent_by_spaces_provided((n + 1), "  ") ~ "</li>" ~ "\n"; +            if  (obj.dom_markedup[n] < 4) { +              toc ~= markup.indent_by_spaces_provided((n + 1), "  ") ~ "<li>" ~ "\n" +              ~ markup.indent_by_spaces_provided((n + 2), "  ") +              ~ "<span class=\"navhd\">" ~ obj.text ~ "</span>" ~ "\n"; +            } else { +              string hashtag =(obj.heading_lev_markup == 4) +              ? "" +              : ("#" ~ obj.ocn.to!string); +              toc ~= markup.indent_by_spaces_provided((n + 1), "  ") ~ "<li>" ~ "\n" +              ~ markup.indent_by_spaces_provided((n + 2), "  ") +              ~ "<a href=\"" ~ obj.segment_anchor_tag ~ ".xhtml" ~ hashtag ~ "\">" +              ~ obj.text +              ~ "</a>" ~ "\n"; +            } +            break; +          case DomTags.open : +            toc ~= markup.indent_by_spaces_provided(n, "  ") ~ "<ol>" ~ "\n"; +            if  (obj.dom_markedup[n] < 4) { +              toc ~= markup.indent_by_spaces_provided(n, "  ") +              ~ "<li><span class=\"navhd\">" ~ obj.text ~ "</span>" ~ "\n"; +            } else { +              string hashtag =(obj.heading_lev_markup == 4) +              ? "" +              : ("#" ~ obj.ocn.to!string); +              toc ~= markup.indent_by_spaces_provided((n + 1), "  ") ~ "<li>" ~ "\n" +              ~ markup.indent_by_spaces_provided((n + 2), "  ") +              ~ "<a href=\"" ~ obj.segment_anchor_tag ~ ".xhtml" ~ hashtag ~ "\">" +              ~ obj.text +              ~ "</a>" ~ "\n"; +            } +            break; +          default : +            break; +          } +        } +      }      }    } -  return content; +  toc ~="</nav>\n"; +  return toc;  }  #+END_SRC -****** TODO OEBPS/toc.ncx (navigable toc using Dom structure) +****** TODO _doc navigation epub2_ (OEBPS/toc.ncx) navigable toc using Dom structure -#+name: output_epub_constructs +- toc.ncx (epub2 navigation document) +  - (replaced in epub3 by a declared xhtml nav file, in our case toc_nav.xhtml) + +#+name: output_epub3_constructs  #+BEGIN_SRC d -string epub_oebps_toc(D,I)(D doc_abstraction, I doc_matters) { +string epub2_oebps_toc_ncx(D,I)(D doc_abstraction, I doc_matters) {    int counter = 0;    string uuid = "18275d951861c77f78acd05672c9906924c59f18a2e0ba06dad95959693e9bd8"; // TODO shared elsewhere    auto markup = InlineMarkup(); @@ -2698,27 +2951,24 @@ obj.segment_anchor_tag,   // lev < 4 [no link]; lev == 4 [filename] markup.xhtml  }  #+END_SRC -**** seg                                                             :seg: -***** switch (sections & objects) format epub xhtml output +**** the document contents                                           :seg: +***** switch (sections & objects) format epub3 xhtml output -#+name: output_epub_xhtml_seg +#+name: output_epub3_xhtml_seg  #+BEGIN_SRC d -void outputEPub(D,I)( +void outputEPub3(D,I)(    auto return ref const D    doc_abstraction,    auto return ref I          doc_matters,  ) {    mixin SiSUoutputRgxInit;    auto xhtml_format = outputXHTMLs();    auto rgx = Rgx(); -  string[][string] doc_epub; -  string[][string] doc_epub_endnotes; +  string[][string] doc_epub3; +  string[][string] doc_epub3_endnotes;    string[] doc;    string segment_filename;    string[] top_level_headings = ["","","",""]; -  auto mimetypes = epub_mimetypes; -  auto meta_inf_container_xml = epub_container_xml; -  auto oebps_toc_ncx = epub_oebps_toc(doc_abstraction, doc_matters); -  auto oebps_content_opf = epub_oebps_content(doc_abstraction, doc_matters); +  string[string] oepbs_content_parts;    string suffix = ".xhtml";    foreach (part; doc_matters.keys_seq_seg) {      foreach (obj; doc_abstraction[part]) { @@ -2753,18 +3003,18 @@ void outputEPub(D,I)(            break;          case 4:            segment_filename = obj.segment_anchor_tag; -          doc_epub[segment_filename] ~= xhtml_format.seg_head(doc_matters.dochead_meta); +          doc_epub3[segment_filename] ~= xhtml_format.seg_head(doc_matters.dochead_meta);            foreach (top_level_heading; top_level_headings) { -            doc_epub[segment_filename] ~= top_level_heading; +            doc_epub3[segment_filename] ~= top_level_heading;            }            auto t = xhtml_format.heading_seg(obj, suffix); -          doc_epub[segment_filename] ~= t[0]; -          doc_epub_endnotes[segment_filename] ~= t[1]; +          doc_epub3[segment_filename] ~= t[0]; +          doc_epub3_endnotes[segment_filename] ~= t[1];            break;          case 5: .. case 7:            auto t = xhtml_format.heading_seg(obj, suffix); -          doc_epub[segment_filename] ~= t[0]; -          doc_epub_endnotes[segment_filename] ~= t[1]; +          doc_epub3[segment_filename] ~= t[0]; +          doc_epub3_endnotes[segment_filename] ~= t[1];            break;          case 8: .. case 9: // unused numbers, if remain check            if ((doc_matters.opt_action_bool["debug"])) { @@ -2785,7 +3035,7 @@ void outputEPub(D,I)(            case "para":              switch (obj.is_a) {              case "toc": -              doc_epub[segment_filename] ~= xhtml_format.toc(obj); +              doc_epub3[segment_filename] ~= xhtml_format.toc(obj);                break;              default:                if ((doc_matters.opt_action_bool["debug"])) { @@ -2807,8 +3057,8 @@ void outputEPub(D,I)(              switch (obj.is_a) {              case "para":                auto t = xhtml_format.para_seg(obj, suffix); -              doc_epub[segment_filename] ~= t[0]; -              doc_epub_endnotes[segment_filename] ~= t[1]; +              doc_epub3[segment_filename] ~= t[0]; +              doc_epub3_endnotes[segment_filename] ~= t[1];                break;              default:                if ((doc_matters.opt_action_bool["debug"])) { @@ -2821,33 +3071,33 @@ void outputEPub(D,I)(              switch (obj.is_a) {              case "quote":                auto t = xhtml_format.quote_seg(obj, suffix); -              doc_epub[segment_filename] ~= to!string(t[0]); -              doc_epub_endnotes[segment_filename] ~= t[1]; +              doc_epub3[segment_filename] ~= to!string(t[0]); +              doc_epub3_endnotes[segment_filename] ~= t[1];                break;              case "group":                auto t = xhtml_format.group_seg(obj, suffix); -              doc_epub[segment_filename] ~= to!string(t[0]); -              doc_epub_endnotes[segment_filename] ~= t[1]; +              doc_epub3[segment_filename] ~= to!string(t[0]); +              doc_epub3_endnotes[segment_filename] ~= t[1];                break;              case "block":                auto t = xhtml_format.block_seg(obj, suffix); -              doc_epub[segment_filename] ~= to!string(t[0]); -              doc_epub_endnotes[segment_filename] ~= t[1]; +              doc_epub3[segment_filename] ~= to!string(t[0]); +              doc_epub3_endnotes[segment_filename] ~= t[1];                break;              case "poem":                break;              case "verse":                auto t = xhtml_format.verse_seg(obj, suffix); -              doc_epub[segment_filename] ~= to!string(t[0]); -              doc_epub_endnotes[segment_filename] ~= t[1]; +              doc_epub3[segment_filename] ~= to!string(t[0]); +              doc_epub3_endnotes[segment_filename] ~= t[1];                break;              case "code": -              doc_epub[segment_filename] ~= xhtml_format.code(obj); +              doc_epub3[segment_filename] ~= xhtml_format.code(obj);                break;              case "table":                auto t = xhtml_format.para_seg(obj, suffix); -              doc_epub[segment_filename] ~= t[0]; -              doc_epub_endnotes[segment_filename] ~= t[1]; +              doc_epub3[segment_filename] ~= t[0]; +              doc_epub3_endnotes[segment_filename] ~= t[1];                break;              default:                if ((doc_matters.opt_action_bool["debug"])) { @@ -2869,27 +3119,27 @@ void outputEPub(D,I)(              switch (obj.is_a) {              case "endnote":                auto t = xhtml_format.para_seg(obj, suffix); -              doc_epub[segment_filename] ~= t[0]; +              doc_epub3[segment_filename] ~= t[0];                break;              case "glossary":                auto t = xhtml_format.para_seg(obj, suffix); -              doc_epub[segment_filename] ~= t[0]; -              doc_epub_endnotes[segment_filename] ~= t[1]; +              doc_epub3[segment_filename] ~= t[0]; +              doc_epub3_endnotes[segment_filename] ~= t[1];                break;              case "bibliography":                auto t = xhtml_format.para_seg(obj, suffix); -              doc_epub[segment_filename] ~= t[0]; -              doc_epub_endnotes[segment_filename] ~= t[1]; +              doc_epub3[segment_filename] ~= t[0]; +              doc_epub3_endnotes[segment_filename] ~= t[1];                break;              case "bookindex":                auto t = xhtml_format.para_seg(obj, suffix); -              doc_epub[segment_filename] ~= t[0]; -              doc_epub_endnotes[segment_filename] ~= t[1]; +              doc_epub3[segment_filename] ~= t[0]; +              doc_epub3_endnotes[segment_filename] ~= t[1];                break;              case "blurb":                auto t = xhtml_format.para_seg(obj, suffix); -              doc_epub[segment_filename] ~= t[0]; -              doc_epub_endnotes[segment_filename] ~= t[1]; +              doc_epub3[segment_filename] ~= t[0]; +              doc_epub3_endnotes[segment_filename] ~= t[1];                break;              default:                if ((doc_matters.opt_action_bool["debug"])) { @@ -2914,14 +3164,59 @@ void outputEPub(D,I)(            break;          }        } +      if (obj.is_a == "heading") { +        if (obj.heading_lev_markup == 4) { +          oepbs_content_parts["manifest_documents"] ~= format(q"¶      <item id="%s.xhtml" href="%s.xhtml" media-type="application/xhtml+xml" /> +¶", +            obj.segment_anchor_tag, +            obj.segment_anchor_tag, +          ); +          oepbs_content_parts["spine"] ~= format(q"¶    <itemref idref="%s.xhtml" linear="yes" /> +¶", +            obj.segment_anchor_tag, +          ); +          oepbs_content_parts["guide"] ~= format(q"¶      <reference type="%s" href="%s" /> +¶", +            obj.segment_anchor_tag, +            obj.segment_anchor_tag, +          ); +        } else if (obj.heading_lev_markup > 4) { +          oepbs_content_parts["manifest_documents"] ~= format(q"¶      <item id="%s.xhtml#%s" href="%s.xhtml#%s" media-type="application/xhtml+xml" /> +¶", +            obj.segment_anchor_tag, +            obj.obj_cite_number, +            obj.segment_anchor_tag, +            obj.obj_cite_number, +          ); +          oepbs_content_parts["spine"] ~= format(q"¶    <itemref idref="%s.xhtml#%s" linear="yes" /> +¶", +            obj.segment_anchor_tag, +            obj.obj_cite_number, +          ); +          oepbs_content_parts["guide"] ~= format(q"¶      <reference type="%s#%s" href="%s#%s" /> +¶", +            obj.segment_anchor_tag, +            obj.obj_cite_number, +            obj.segment_anchor_tag, +            obj.obj_cite_number, +          ); +        } +      }      }    } -  epub_write_output_files( +  /+ epub specific documents +/ +  auto mimetypes = epub3_mimetypes; +  auto meta_inf_container_xml = epub3_container_xml; +  auto oebps_toc_ncx = epub2_oebps_toc_ncx(doc_abstraction, doc_matters); +  auto oebps_toc_nav_xhtml = epub3_oebps_toc_nav_xhtml(doc_abstraction, doc_matters); +  auto oebps_content_opf = epub3_oebps_content(doc_abstraction, doc_matters, oepbs_content_parts); +  epub3_write_output_files(      doc_matters, -    doc_epub, -    doc_epub_endnotes, +    doc_epub3, +    doc_epub3_endnotes,      mimetypes,      meta_inf_container_xml, +    oebps_toc_nav_xhtml,      oebps_toc_ncx,      oebps_content_opf,    ); @@ -2930,71 +3225,214 @@ void outputEPub(D,I)(  **** write output files -#+name: output_epub_xhtml_seg +#+name: output_epub3_xhtml_seg  #+BEGIN_SRC d -void epub_write_output_files(M,D,E,Mt,Mic,Ot,Oc)( +void epub3_write_output_files(M,D,E,Mt,Mic,Otnx,Otn,Oc)(    M    doc_matters, -  D    doc_epub, -  E    doc_epub_endnotes, +  D    doc_epub3, +  E    doc_epub3_endnotes,    Mt   mimetypes,    Mic  meta_inf_container_xml, -  Ot   oebps_toc_ncx, +  Otnx oebps_toc_nav_xhtml, +  Otn  oebps_toc_ncx,    Oc   oebps_content_opf,  ) { -  debug(asserts){ -    static assert(is(typeof(doc_epub)               == string[][string])); +  debug(asserts) { +    static assert(is(typeof(doc_epub3)              == string[][string]));      static assert(is(typeof(mimetypes)              == string));      static assert(is(typeof(meta_inf_container_xml) == string)); +    static assert(is(typeof(oebps_toc_nav_xhtml)    == string));      static assert(is(typeof(oebps_toc_ncx)          == string));      static assert(is(typeof(oebps_content_opf)      == string));    }    mixin SiSUpaths; -  auto pth_epub = EpubPaths(); +  auto pth_epub3 = Epub3paths();    auto xhtml_format = outputXHTMLs(); +  /+ zip file +/ +  auto fn_epub = pth_epub3.epub_file(doc_matters.source_filename); +  auto zip = new ZipArchive(); // ZipArchive zip = new ZipArchive(); +  /+ zip archive member files +/    try { -    if (!exists(pth_epub.doc_meta_inf(doc_matters.source_filename))) { -      pth_epub.doc_meta_inf(doc_matters.source_filename).mkdirRecurse; +    if (!exists(pth_epub3.doc_meta_inf(doc_matters.source_filename))) { +      pth_epub3.doc_meta_inf(doc_matters.source_filename).mkdirRecurse;      } -    if (!exists(pth_epub.doc_oebps_css(doc_matters.source_filename))) { -      pth_epub.doc_oebps_css(doc_matters.source_filename).mkdirRecurse; +    if (!exists(pth_epub3.doc_oebps_css(doc_matters.source_filename))) { +      pth_epub3.doc_oebps_css(doc_matters.source_filename).mkdirRecurse;      } -    if (!exists(pth_epub.doc_oebps_image(doc_matters.source_filename))) { -      pth_epub.doc_oebps_image(doc_matters.source_filename).mkdirRecurse; +    if (!exists(pth_epub3.doc_oebps_image(doc_matters.source_filename))) { +      pth_epub3.doc_oebps_image(doc_matters.source_filename).mkdirRecurse;      } -    /+ OEBPS/[segments].xhtml +/ -    foreach (seg_filename; doc_matters.segnames) { -      auto f = File(pth_epub.fn_oebps_content_xhtml(doc_matters.source_filename, seg_filename), "w"); -      /+ // f.writeln(seg_head); // not needed built and inserted earlier +/ -      foreach (docseg; doc_epub[seg_filename]) { -        f.writeln(docseg); +    { /+ OEBPS/[segments].xhtml (the document contents) +/ +      foreach (seg_filename; doc_matters.segnames) { +        string fn = pth_epub3.fn_oebps_content_xhtml(doc_matters.source_filename, seg_filename); +        /+ add zip archive file members (with their content) +/ +        auto zip_arc_member_file = new ArchiveMember(); +        // add seg fn to zip archive +        zip_arc_member_file.name = fn; +        auto zip_data = new OutBuffer(); +        debug(epub_output) { +          string fn_dbg = pth_epub3.dbg_fn_oebps_content_xhtml(doc_matters.source_filename, seg_filename); +          auto f = File(fn_dbg, "w"); +        } +        /+ // f.writeln(seg_head); // not needed built and inserted earlier +/ +        foreach (docseg; doc_epub3[seg_filename]) { +          debug(epub_output) { f.writeln(docseg); } +          zip_data.write(docseg.dup); // cast as: char[] +        } +        foreach (docseg; doc_epub3_endnotes[seg_filename]) { +          debug(epub_output) { f.writeln(docseg); } +          zip_data.write(docseg.dup); // cast as: char[] +        } +        debug(epub_output) { f.writeln(xhtml_format.tail); } // needed for each lev4 +        zip_data.write(xhtml_format.tail.dup); // cast as: char[] +        zip_arc_member_file.expandedData = zip_data.toBytes(); +        zip.addMember(zip_arc_member_file); +        /+ create the zip file +/ +        createZipFile!()(fn_epub, zip.build());        } -      foreach (docseg; doc_epub_endnotes[seg_filename]) { -        f.writeln(docseg); +    } +    string fn; +    debug(epub_output) { string fn_dbg; } +    File f; +    { /+ mimetypes (identify zip file type) +/ +      debug(epub_output) { +        fn_dbg = pth_epub3.dbg_fn_mimetypes(doc_matters.source_filename); +        File(fn_dbg, "w").writeln(mimetypes);        } -      f.writeln(xhtml_format.tail); // needed for each lev4 +      fn = pth_epub3.fn_mimetypes(doc_matters.source_filename); +      /+ add zip archive file members (with their content) +/ +      auto zip_arc_member_file = new ArchiveMember(); +      // add mimetypes to zip archive +      zip_arc_member_file.name = fn; +      auto zip_data = new OutBuffer(); +      zip_data.write(mimetypes.dup); // cast as: char[] +      zip_arc_member_file.expandedData = zip_data.toBytes(); +      zip.addMember(zip_arc_member_file); +      /+ create the zip file +/ +      createZipFile!()(fn_epub, zip.build()); +    } +    { /+  META-INF/container.xml (identify doc root) +/ +      debug(epub_output) { +        fn_dbg = pth_epub3.dbg_fn_dmi_container_xml(doc_matters.source_filename); +        File(fn_dbg, "w").writeln(meta_inf_container_xml); +      } +      fn = pth_epub3.fn_dmi_container_xml(doc_matters.source_filename); +      /+ add zip archive file members (with their content) +/ +      auto zip_arc_member_file = new ArchiveMember(); +      // add META-INF/container.xml to zip archive +      zip_arc_member_file.name = fn; +      auto zip_data = new OutBuffer(); +      zip_data.write(meta_inf_container_xml.dup); // cast as: char[] +      zip_arc_member_file.expandedData = zip_data.toBytes(); +      zip.addMember(zip_arc_member_file); +      /+ create the zip file +/ +      createZipFile!()(fn_epub, zip.build()); +    } +    { /+ OEBPS/toc_nav.xhtml (navigation toc epub3) +/ +      debug(epub_output) { +        fn_dbg = pth_epub3.dbg_fn_oebps_toc_nav_xhtml(doc_matters.source_filename); +        File(fn_dbg, "w").writeln(oebps_toc_nav_xhtml); +      } +      fn = pth_epub3.fn_oebps_toc_nav_xhtml(doc_matters.source_filename); +      /+ add zip archive file members (with their content) +/ +      auto zip_arc_member_file = new ArchiveMember(); +      // add OEBPS/toc_nav.xhtml to zip archive +      zip_arc_member_file.name = fn; +      auto zip_data = new OutBuffer(); +      zip_data.write(oebps_toc_nav_xhtml.dup); // cast as: char[] +      zip_arc_member_file.expandedData = zip_data.toBytes(); +      zip.addMember(zip_arc_member_file); +      /+ create the zip file +/ +      createZipFile!()(fn_epub, zip.build()); +    } +    { /+ TODO OEBPS/toc.ncx (navigation toc epub2) +/ +      debug(epub_output) { +        fn_dbg = pth_epub3.dbg_fn_oebps_toc_ncx(doc_matters.source_filename); +        File(fn_dbg, "w").writeln(oebps_toc_ncx); +      } +      fn = pth_epub3.fn_oebps_toc_ncx(doc_matters.source_filename); +      /+ add zip archive file members (with their content) +/ +      auto zip_arc_member_file = new ArchiveMember(); +      // add OEBPS/toc.ncx to zip archive +      zip_arc_member_file.name = fn; +      auto zip_data = new OutBuffer(); +      zip_data.write(oebps_toc_ncx.dup); // cast as: char[] +      zip_arc_member_file.expandedData = zip_data.toBytes(); +      zip.addMember(zip_arc_member_file); +      /+ create the zip file +/ +      createZipFile!()(fn_epub, zip.build());      } -    /+ mimetypes +/ -    auto f = File(pth_epub.fn_mimetypes(doc_matters.source_filename), "w"); -    f.writeln(mimetypes); -    /+  META-INF/container.xml +/ -    f = File(pth_epub.fn_dmi_container_xml(doc_matters.source_filename), "w"); -    f.writeln(meta_inf_container_xml); -    /+ OEBPS/toc.ncx +/ -    f = File(pth_epub.fn_oebps_toc_ncx(doc_matters.source_filename), "w"); -    f.writeln(oebps_toc_ncx); -    /+ OEBPS/content.opf +/ -    f = File(pth_epub.fn_oebps_content_opf(doc_matters.source_filename), "w"); -    f.writeln(oebps_content_opf); -    foreach (image; doc_matters.image_list) { -      if (exists("_sisu/image/"~ image)) { -        ("_sisu/image/"~ image) -        .copy((pth_epub.doc_oebps_image(doc_matters.source_filename)) ~ "/" ~ image); +    { /+ TODO OEBPS/content.opf (doc manifest) +/ +      debug(epub_output) { +        fn_dbg = pth_epub3.dbg_fn_oebps_content_opf(doc_matters.source_filename); +        File(fn_dbg, "w").writeln(oebps_content_opf); +      } +      fn = pth_epub3.fn_oebps_content_opf(doc_matters.source_filename); +      /+ add zip archive file members (with their content) +/ +      auto zip_arc_member_file = new ArchiveMember(); +      // add OEBPS/content.opf to zip archive +      zip_arc_member_file.name = fn; +      auto zip_data = new OutBuffer(); +      zip_data.write(oebps_content_opf.dup); // cast as: char[] +      zip_arc_member_file.expandedData = zip_data.toBytes(); +      zip.addMember(zip_arc_member_file); +      /+ create the zip file +/ +      createZipFile!()(fn_epub, zip.build()); +    } +    { /+ OEBPS/_sisu/image (images) +/ +      foreach (image; doc_matters.image_list) { +        if (exists("_sisu/image/"~ image)) { +          ("_sisu/image/"~ image) +          .copy((pth_epub3.doc_oebps_image(doc_matters.source_filename)) ~ "/" ~ image); +        } +      } +      foreach (image; doc_matters.image_list) { +        debug(epub_images) { +          writeln( +            "_sisu/image/", image, " -> ", +            pth_epub3.doc_oebps_image(doc_matters.source_filename), "/", image +          ); +        } +        auto fn_src = "_sisu/image/"~ image; +        auto fn_out =  pth_epub3.doc_oebps_image(doc_matters.source_filename).to!string ~ "/" ~ image; +        if (exists(fn_src)) { +          { +            auto zip_arc_member_file = new ArchiveMember(); +            zip_arc_member_file.name = fn_out; +            auto zip_data = new OutBuffer(); +            zip_data.write(cast(char[]) ((fn_src).read)); +            zip_arc_member_file.expandedData = zip_data.toBytes(); +            zip.addMember(zip_arc_member_file); +            createZipFile!()(fn_epub, zip.build()); +          } +        }        }      }    }    catch (ErrnoException ex) {      // Handle error    } +#+END_SRC + +*** zip debug, read zip  archive + +#+name: output_epub3_xhtml_seg +#+BEGIN_SRC d +  debug(epub_archive) { +    if (exists(fn_epub)) { +      try { +        auto zipped = new ZipArchive((fn_epub).read); +        foreach (filename, member; zipped.directory) { +          auto data = zipped.expand(member); +          writeln(filename, " length ", data.length); // member.name +          // Use data +        } +      } +      catch (ZipException ex) { +        // Handle errors +      } +    } +  }  }  #+END_SRC diff --git a/org/sdp.org b/org/sdp.org index ff989c9..6ef3d06 100644 --- a/org/sdp.org +++ b/org/sdp.org @@ -23,7 +23,7 @@ struct Version {    int minor;    int patch;  } -enum ver = Version(0, 13, 8); +enum ver = Version(0, 13, 9);  #+END_SRC  * 1. sdp (sisu document parser)                                         :sdp: @@ -72,9 +72,9 @@ void main(string[] args) {  }  unittest {    /++ -	name        "sdp" -	description "A SiSU document parser writen in D." -	homepage    "http://sisudoc.org" +  name        "sdp" +  description "A SiSU document parser writen in D." +  homepage    "http://sisudoc.org"    +/  }  #+END_SRC @@ -222,8 +222,8 @@ void main(string[] args) {  }  unittest {    /++ -	name        "sdp" -	description "A SiSU document parser writen in D." -	homepage    "http://sisudoc.org" +  name        "sdp" +  description "A SiSU document parser writen in D." +  homepage    "http://sisudoc.org"    +/  } diff --git a/src/sdp/ao_defaults.d b/src/sdp/ao_defaults.d index 846a7d2..21352e2 100644 --- a/src/sdp/ao_defaults.d +++ b/src/sdp/ao_defaults.d @@ -394,8 +394,7 @@ template InternalMarkup() {      auto tc_o = "┏"; //"『"; // "┏" ┓      auto tc_c = "┚"; // "』"; // "┚"  table row mark #Mx[:tc_c]="』\n"      auto tc_p = "┆";   // table col/misc mark -    string indent_by_spaces_provided(int indent) { -      auto _indent_spaces ="░░";   // auto nbsp = "░"; +    string indent_by_spaces_provided(int indent, string _indent_spaces ="░░") {        _indent_spaces = replicate(_indent_spaces, indent);        return _indent_spaces;      } diff --git a/src/sdp/ao_doc_debugs.d b/src/sdp/ao_doc_debugs.d index 989a826..05e3739 100644 --- a/src/sdp/ao_doc_debugs.d +++ b/src/sdp/ao_doc_debugs.d @@ -113,7 +113,7 @@ template SiSUdebugs() {          }        }      } -    debug(dom) { +    debug(toc_nav_dom) {        enum DomTags { none, open, close, close_and_open, open_still, }        foreach (sect; doc_matters.keys_seq_seg) {          foreach (obj; contents[sect]) { @@ -125,10 +125,10 @@ template SiSUdebugs() {                  break;                case DomTags.close_and_open :                  writeln(markup.indent_by_spaces_provided(k), "</", k, ">"); -                writeln(markup.indent_by_spaces_provided(k), "<", k, ">", obj.text); +                writeln(markup.indent_by_spaces_provided(k), "<", k, ">", obj.text, " file: ", obj.segment_anchor_tag, ".xhtml#", obj.ocn);                  break;                case DomTags.open : -                writeln(markup.indent_by_spaces_provided(k), "<", k, ">", obj.text); +                writeln(markup.indent_by_spaces_provided(k), "<", k, ">", obj.text, " file: ", obj.segment_anchor_tag, ".xhtml#", obj.ocn);                  break;                default :                  break; @@ -148,10 +148,10 @@ template SiSUdebugs() {                  break;                case DomTags.close_and_open :                  writeln(markup.indent_by_spaces_provided(k), "</", k, ">"); -                writeln(markup.indent_by_spaces_provided(k), "<", k, ">", obj.text); +                writeln(markup.indent_by_spaces_provided(k), "<", k, ">", obj.text, " file: ", obj.segment_anchor_tag, ".xhtml#", obj.ocn);                  break;                case DomTags.open : -                writeln(markup.indent_by_spaces_provided(k), "<", k, ">", obj.text); +                writeln(markup.indent_by_spaces_provided(k), "<", k, ">", obj.text, " file: ", obj.segment_anchor_tag, ".xhtml#", obj.ocn);                  break;                default :                  break; diff --git a/src/sdp/create_zip_file.d b/src/sdp/create_zip_file.d new file mode 100644 index 0000000..6ea55f4 --- /dev/null +++ b/src/sdp/create_zip_file.d @@ -0,0 +1,16 @@ +template createZipFile() { +  import std.file; +  import std.outbuffer; +  import std.string; +  import std.zip; +  void createZipFile( +    string zip_file_name, +    void[] compressed_zip_data, +  ) { +    try { +      write(zip_file_name, compressed_zip_data); +    } catch (ZipException ex) { +      // Handle Errors +    } +  } +} diff --git a/src/sdp/defaults.d b/src/sdp/defaults.d index a6520a3..537b4ba 100644 --- a/src/sdp/defaults.d +++ b/src/sdp/defaults.d @@ -3,103 +3,188 @@  +/  template SiSUpaths() { -  string _base_filename(string fn_src) { -    string _fn_base = ""; -    if (extension(fn_src) == ".sst") { -      _fn_base = baseName(fn_src, ".sst"); -    } else if (extension(fn_src) == ".ssm") { -      _fn_base = baseName(fn_src, ".ssm"); -    } -    return _fn_base; -  }    struct DirPaths {      string base_filename(string fn_src) { -      return _base_filename(fn_src); +      return baseName(stripExtension(fn_src));      }    }    struct SiSUpodPaths {      string base_filename(string fn_src) { -      return _base_filename(fn_src); +      return baseName(stripExtension(fn_src)); +    } +    string sisupod_filename(string fn_src) { +      return "sisupod".chainPath(base_filename(fn_src) ~ ".zip").array; +    } +    string base(string fn_src) { +      return "sisupod".chainPath(base_filename(fn_src)).array; +    } +  } +  struct SiSUpodPathsZipped { +    auto spod_pths = SiSUpodPaths(); +    string base_filename(string fn_src) { +      return spod_pths.base_filename(fn_src); +    } +    string sisupod_filename(string fn_src) { +      return spod_pths.sisupod_filename(fn_src); +    } +    string base(string fn_src) { +      return spod_pths.base(fn_src); +    } +    auto doc_root(string fn_src) { +      return "doc"; +    } +    auto doc(string fn_src) { +      return doc_root(fn_src); +    } +    auto doc_lng(string fn_src, string lng) { +      return doc_root(fn_src).chainPath(lng).array; +    } +    auto conf(string fn_src) { +      return doc_root(fn_src).chainPath("_sisu").array; +    } +    auto image(string fn_src) { +      return conf(fn_src).chainPath("image").array; +    } +    auto css(string fn_src) { +      return conf(fn_src).chainPath("css").array; +    } +    auto fn_doc(string fn_src, string lng) { +      return (doc_lng(fn_src, lng)).chainPath(baseName(fn_src)).array; +    } +    auto fn_doc_insert(string fn_src, string fn_insert, string lng) { +      return (doc_lng(fn_src, lng)).chainPath(baseName(fn_insert)).array; +    } +  } +  struct SiSUpodPathsFilesystemArchive { +    auto spod_pths = SiSUpodPaths(); +    string base_filename(string fn_src) { +      return spod_pths.base_filename(fn_src); +    } +    string sisupod_filename(string fn_src) { +      return spod_pths.sisupod_filename(fn_src);      }      string base(string fn_src) { -      return chainPath("sisupod", _base_filename(fn_src)).array; +      return spod_pths.base(fn_src); +    } +    auto doc_root(string fn_src) { +      return base(fn_src).chainPath("doc").array;      } -    string doc(string fn_src) { -      return chainPath(base(fn_src), "doc").array; -      // return chainPath(base(fn_src), "text").array; +    auto doc(string fn_src) { +      return doc_root(fn_src);      } -    string doc_lng(string fn_src, string lng) { -      return chainPath(doc(fn_src), lng).array; +    auto doc_lng(string fn_src, string lng) { +      return doc_root(fn_src).chainPath(lng).array;      } -    string conf(string fn_src) { -      return chainPath(doc(fn_src), "_sisu").array; +    auto conf(string fn_src) { +      return doc_root(fn_src).chainPath("_sisu").array;      } -    string image(string fn_src) { -      return chainPath(conf(fn_src), "image").array; +    auto image(string fn_src) { +      return conf(fn_src).chainPath("image").array;      } -    string css(string fn_src) { -      return chainPath(conf(fn_src), "css").array; +    auto css(string fn_src) { +      return conf(fn_src).chainPath("css").array;      } -    string fn_doc(string fn_src, string lng) { -      return chainPath((doc_lng(fn_src, lng)), baseName(fn_src)).array; +    auto fn_doc(string fn_src, string lng) { +      return (doc_lng(fn_src, lng)).chainPath(baseName(fn_src)).array;      } -    string fn_doc_insert(string fn_src, string fn_insert, string lng) { -      return chainPath((doc_lng(fn_src, lng)), baseName(fn_insert)).array; +    auto fn_doc_insert(string fn_src, string fn_insert, string lng) { +      return (doc_lng(fn_src, lng)).chainPath(baseName(fn_insert)).array;      }    }    struct HtmlPaths {      string base_filename(string fn_src) { -      return _base_filename(fn_src); +      return baseName(stripExtension(fn_src));      }      string base() { -      return chainPath("en", "html").array; +      return "en".chainPath("html").array;      }      string seg(string fn_src) { -      return chainPath(base, _base_filename(fn_src)).array; +      return base.chainPath(base_filename(fn_src)).array;      }      string fn_scroll(string fn_src) { -      return chainPath(base, _base_filename(fn_src) ~ ".html").array; +      return base.chainPath(base_filename(fn_src) ~ ".html").array;      }      string fn_seg(string fn_src, string seg_filename) { -      return chainPath(seg(fn_src), seg_filename ~ ".html").array; +      return seg(fn_src).chainPath(seg_filename ~ ".html").array;      }    } -  struct EpubPaths { +  struct Epub3paths { +    string dirtop() { +      return "".chainPath("").array; +    }      string base_filename(string fn_src) { -      return _base_filename(fn_src); +      return baseName(stripExtension(fn_src));      }      string base() { -      return chainPath("en", "epub").array; +      return "en".chainPath("epub3").array; +    } +    string epub_file(string fn_src) { +      return base.chainPath(base_filename(fn_src) ~ ".epub").array;      } -    string doc(string fn_src) { -      return chainPath(base, _base_filename(fn_src)).array; +    string docdir(string fn_src) { +      return base.chainPath(base_filename(fn_src)).array;      }      string doc_meta_inf(string fn_src) { -      return chainPath(doc(fn_src), "META-INF").array; +      return dirtop.chainPath("META-INF").array;      }      string doc_oebps(string fn_src) { -      return chainPath(doc(fn_src), "OEBPS").array; +      return dirtop.chainPath("OEBPS").array;      }      string doc_oebps_css(string fn_src) { -      return chainPath(doc_oebps(fn_src), "css").array; +      return doc_oebps(fn_src).chainPath("css").array;      }      string doc_oebps_image(string fn_src) { -      return chainPath(doc_oebps(fn_src), "image").array; +      return doc_oebps(fn_src).chainPath("image").array;      }      string fn_mimetypes(string fn_src) { -      return chainPath(doc(fn_src), "mimetypes").array; +      return dirtop.chainPath("mimetypes").array;      }      string fn_dmi_container_xml(string fn_src) { -      return chainPath(doc_meta_inf(fn_src), "container.xml").array; +      return doc_meta_inf(fn_src).chainPath("container.xml").array; +    } +    string fn_oebps_toc_nav_xhtml(string fn_src) { +      return doc_oebps(fn_src).chainPath("toc_nav.xhtml").array;      }      string fn_oebps_toc_ncx(string fn_src) { -      return chainPath(doc_oebps(fn_src), "toc.ncx").array; +      return doc_oebps(fn_src).chainPath("toc.ncx").array;      }      string fn_oebps_content_opf(string fn_src) { -      return chainPath(doc_oebps(fn_src), "content.opf").array; +      return doc_oebps(fn_src).chainPath("content.opf").array;      }      string fn_oebps_content_xhtml(string fn_src, string seg_filename) { -      return chainPath(doc_oebps(fn_src), seg_filename ~ ".xhtml").array; +      return doc_oebps(fn_src).chainPath(seg_filename ~ ".xhtml").array; +    } +    debug(epub_output) { +      string dbg_doc_meta_inf(string fn_src) { +        return docdir(fn_src).chainPath("META-INF").array; +      } +      string dbg_doc_oebps(string fn_src) { +        return docdir(fn_src).chainPath("OEBPS").array; +      } +      string dbg_doc_oebps_css(string fn_src) { +        return doc_oebps(fn_src).chainPath("css").array; +      } +      string dbg_doc_oebps_image(string fn_src) { +        return doc_oebps(fn_src).chainPath("image").array; +      } +      string dbg_fn_mimetypes(string fn_src) { +        return docdir(fn_src).chainPath("mimetypes").array; +      } +      string dbg_fn_dmi_container_xml(string fn_src) { +        return doc_meta_inf(fn_src).chainPath("container.xml").array; +      } +      string dbg_fn_oebps_toc_nav_xhtml(string fn_src) { +        return doc_oebps(fn_src).chainPath("toc_nav.xhtml").array; +      } +      string dbg_fn_oebps_toc_ncx(string fn_src) { +        return doc_oebps(fn_src).chainPath("toc.ncx").array; +      } +      string dbg_fn_oebps_content_opf(string fn_src) { +        return doc_oebps(fn_src).chainPath("content.opf").array; +      } +      string dbg_fn_oebps_content_xhtml(string fn_src, string seg_filename) { +        return doc_oebps(fn_src).chainPath(seg_filename ~ ".xhtml").array; +      }      }    }  } @@ -122,8 +207,7 @@ template InternalMarkup() {      auto tc_o = "┏"; //"『"; // "┏" ┓      auto tc_c = "┚"; // "』"; // "┚"  table row mark #Mx[:tc_c]="』\n"      auto tc_p = "┆";   // table col/misc mark -    string indent_by_spaces_provided(int indent) { -      auto _indent_spaces ="░░";   // auto nbsp = "░"; +    string indent_by_spaces_provided(int indent, string _indent_spaces ="░░") {        _indent_spaces = replicate(_indent_spaces, indent);        return _indent_spaces;      } diff --git a/src/sdp/output_epub.d b/src/sdp/output_epub.d deleted file mode 100644 index 0cc3a31..0000000 --- a/src/sdp/output_epub.d +++ /dev/null @@ -1,449 +0,0 @@ -template outputEPub() { -  private import -    std.algorithm, -    std.array, -    std.container, -    std.exception, -    std.file, -    std.getopt, -    std.json, -    std.process, -    std.stdio, -    std.path, -    std.range, -    std.regex, -    std.string, -    std.traits, -    std.typecons, -    std.uni, -    std.utf, -    std.conv : to; -  import -    defaults, -    output_rgx, -    output_xhtmls; -  mixin InternalMarkup; -  mixin outputXHTMLs; -  string epub_mimetypes() { -    string o; -    o = format(q"¶application/epub+zip¶"); -    return o; -  } -  string epub_container_xml() { -    string o; -    o = format(q"¶<?xml version='1.0' encoding='utf-8'?> -  <container version="1.0" -    xmlns="urn:oasis:names:tc:opendocument:xmlns:container"> -    <rootfiles> -      <rootfile full-path="OEBPS/content.opf" -        media-type="application/oebps-package+xml" /> -    </rootfiles> -  </container>¶"); -    return o; -  } -  string epub_oebps_content(D,I)(D doc_abstraction, I doc_matters) { -    string uuid = "18275d951861c77f78acd05672c9906924c59f18a2e0ba06dad95959693e9bd8"; // TODO shared elsewhere -    string content = format(q"¶<?xml version='1.0' encoding='utf-8'?> -  <?xml version='1.0' encoding='utf-8'?> -  <package xmlns="http://www.idpf.org/2007/opf" version="2.0" unique-identifier="EPB-UUID"> -    <opf:metadata -      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" -      xmlns:opf="http://www.idpf.org/2007/opf" -      xmlns:dcterms="http://purl.org/dc/terms/" -      xmlns:dc="http://purl.org/dc/elements/1.1/" -      unique-identifier="urn:uuid:%s" version="2.0"> -      <dc:title>%s</dc:title> -      <dc:creator opf:file-as="%s" opf:role="aut">%s</dc:creator> -      <dc:language>en</dc:language> -      <dc:date opf:event="published">%s</dc:date> -      <dc:rights>Copyright: %s</dc:rights> -      <dc:identifier opf:scheme="URI">ox/current/en/epub/sisu_markup.epub</dc:identifier> -      <dc:identifier id="bookid">urn:uuid:%s</dc:identifier> -      <!-- <dc:identifier id="EPB-UUID">urn:uuid:%s</dc:identifier> --> -    </opf:metadata> -    <manifest> -      <!-- NCX --> -      <item id="ncx" href="toc.ncx" media-type="application/x-dtbncx+xml" /> -      <!-- CSS Style Sheets --> -      <item id="main-css" href="css/xhtml.css" media-type="text/css" />¶", -      uuid, -      doc_matters.dochead_meta["title"]["full"],                                                               // title -      (doc_matters.dochead_meta["creator"]["author"].empty) ? "" : " by " ~ doc_matters.dochead_meta["creator"]["author"], // author -      (doc_matters.dochead_meta["creator"]["author"].empty) ? "" : " by " ~ doc_matters.dochead_meta["creator"]["author"], // author -      (doc_matters.dochead_meta["date"]["published"].empty) ? "" : " by " ~ doc_matters.dochead_meta["date"]["published"],  // date -      (doc_matters.dochead_meta["rights"]["copyright"].empty) ? "" : " by " ~ doc_matters.dochead_meta["rights"]["copyright"],  // rights -      uuid, -      uuid, -    ); -    foreach (sect; doc_matters.keys_seq_seg) { -      foreach (obj; doc_abstraction[sect]) { -      } -    } -    return content; -  } -  string epub_oebps_toc(D,I)(D doc_abstraction, I doc_matters) { -    int counter = 0; -    string uuid = "18275d951861c77f78acd05672c9906924c59f18a2e0ba06dad95959693e9bd8"; // TODO shared elsewhere -    auto markup = InlineMarkup(); -    enum DomTags { none, open, close, close_and_open, open_still, } -    string toc = format(q"¶<?xml version='1.0' encoding='utf-8'?> -  <ncx xmlns="http://www.daisy.org/z3986/2005/ncx/" version="2005-1"> -    <head> -      <!-- four required metadata items (for all NCX documents, -        (including the relaxed constraints of OPS 2.0) --> -      <title>%s%s</title> -      <link href="css/xhtml.css" rel="stylesheet" type="text/css" id="main-css" /> -      <meta name="dtb:uid" content="urn:uuid:%s" /> -      <!-- <meta name="epub-creator" content="SiSU http://www.jus.uio.no/sisu (this copy)" /> --> -      <meta name="dtb:depth" content="%s" /> -      <meta name="dtb:totalPageCount" content="0" /> -      <meta name="dtb:maxPageNumber" content="0" /> -    </head> -    <docTitle> -      <text>%s</text> -    </docTitle> -    <docAuthor> -      <text>%s</text> -    </docAuthor> -    <navMap>¶", -      doc_matters.dochead_meta["title"]["full"],                                                               // title -      (doc_matters.dochead_meta["creator"]["author"].empty) ? "" : " by " ~ doc_matters.dochead_meta["creator"]["author"], // author -      uuid,                                                                                        // uuid -      "3",                                                                                         // content depth -      doc_matters.dochead_meta["title"]["full"],                                                               // title -      (doc_matters.dochead_meta["creator"]["author"].empty) ? "" : doc_matters.dochead_meta["creator"]["author"],          // author -    ); -    foreach (sect; doc_matters.keys_seq_seg) { -      foreach (obj; doc_abstraction[sect]) { -        if (obj.is_a == "heading") { -          foreach_reverse (k; 0 .. 7) { -            switch (obj.dom_markedup[k]) { -            case DomTags.close : -  toc ~= "</navPoint>"; -              break; -            case DomTags.close_and_open : -              ++counter; -  toc ~= "</navPoint>"; -  toc ~= format(q"¶<navPoint class="chapter" id="navpoint" playOrder="%s"> -  <navLabel> -    <text>%s</text> -  </navLabel> -  <content src="%s" />¶", -  counter, -  obj.text, -  obj.segment_anchor_tag,   // lev < 4 [no link]; lev == 4 [filename] markup.xhtml; lev > 4 [filename#ocn] (links done in segment_anchor_tag) -  ); -              break; -            case DomTags.open : -              ++counter; -  toc ~= format(q"¶<navPoint class="chapter" id="navpoint" playOrder="%s"> -  <navLabel> -    <text>%s</text> -  </navLabel> -  <content src="%s" />¶", -  counter, -  obj.text, -  obj.segment_anchor_tag,   // lev < 4 [no link]; lev == 4 [filename] markup.xhtml; lev > 4 [filename#ocn] (fix links in segment_anchor_tag) -  ); -              break; -            default : -              break; -            } -          } -        } -      } -    } -    toc ~= format(q"¶  </navMap> -  </ncx>¶"); -    return toc; -  } -   -  void outputEPub(D,I)( -    auto return ref const D    doc_abstraction, -    auto return ref I          doc_matters, -  ) { -    mixin SiSUoutputRgxInit; -    auto xhtml_format = outputXHTMLs(); -    auto rgx = Rgx(); -    string[][string] doc_epub; -    string[][string] doc_epub_endnotes; -    string[] doc; -    string segment_filename; -    string[] top_level_headings = ["","","",""]; -    auto mimetypes = epub_mimetypes; -    auto meta_inf_container_xml = epub_container_xml; -    auto oebps_toc_ncx = epub_oebps_toc(doc_abstraction, doc_matters); -    auto oebps_content_opf = epub_oebps_content(doc_abstraction, doc_matters); -    string suffix = ".xhtml"; -    foreach (part; doc_matters.keys_seq_seg) { -      foreach (obj; doc_abstraction[part]) { -        if (obj.is_a == "heading") { -          switch (obj.heading_lev_markup) { -          case 0: .. case 3: -            /+ fill buffer, and replace with new levels from 1 to 3 +/ -            switch (obj.heading_lev_markup) { -            case 0: -              top_level_headings[0] = ""; -              top_level_headings[1] = ""; -              top_level_headings[2] = ""; -              top_level_headings[3] = ""; -              goto default; -            case 1: -              top_level_headings[1] = ""; -              top_level_headings[2] = ""; -              top_level_headings[3] = ""; -              goto default; -            case 2: -              top_level_headings[2] = ""; -              top_level_headings[3] = ""; -              goto default; -            case 3: -              top_level_headings[3] = ""; -              goto default; -            default: -              auto t = xhtml_format.heading_seg(obj, suffix); -              top_level_headings[obj.heading_lev_markup] = t[0]; -              break; -            } -            break; -          case 4: -            segment_filename = obj.segment_anchor_tag; -            doc_epub[segment_filename] ~= xhtml_format.seg_head(doc_matters.dochead_meta); -            foreach (top_level_heading; top_level_headings) { -              doc_epub[segment_filename] ~= top_level_heading; -            } -            auto t = xhtml_format.heading_seg(obj, suffix); -            doc_epub[segment_filename] ~= t[0]; -            doc_epub_endnotes[segment_filename] ~= t[1]; -            break; -          case 5: .. case 7: -            auto t = xhtml_format.heading_seg(obj, suffix); -            doc_epub[segment_filename] ~= t[0]; -            doc_epub_endnotes[segment_filename] ~= t[1]; -            break; -          case 8: .. case 9: // unused numbers, if remain check -            if ((doc_matters.opt_action_bool["debug"])) { -              writeln(__FILE__, ":", __LINE__, ": ", obj.is_a, ": ", obj.heading_lev_markup); -              writeln(__FILE__, ":", __LINE__, ": ", obj.text); // check -            } -            break; -          default: -            if ((doc_matters.opt_action_bool["debug"])) { -              writeln(__FILE__, ":", __LINE__, ": ", obj.is_a, ": ", obj.heading_lev_markup); -            } -            break; -          } -        } else { -          switch (obj.use) { -          case "frontmatter": -            switch (obj.is_of) { -            case "para": -              switch (obj.is_a) { -              case "toc": -                doc_epub[segment_filename] ~= xhtml_format.toc(obj); -                break; -              default: -                if ((doc_matters.opt_action_bool["debug"])) { -                  writeln(__FILE__, ":", __LINE__, ": ", obj.is_a); -                } -                break; -              } -              break; -            default: -              if ((doc_matters.opt_action_bool["debug"])) { -                writeln(__FILE__, ":", __LINE__, ": ", obj.is_of); -              } -              break; -            } -            break; -          case "body": -            switch (obj.is_of) { -            case "para": -              switch (obj.is_a) { -              case "para": -                auto t = xhtml_format.para_seg(obj, suffix); -                doc_epub[segment_filename] ~= t[0]; -                doc_epub_endnotes[segment_filename] ~= t[1]; -                break; -              default: -                if ((doc_matters.opt_action_bool["debug"])) { -                  writeln(__FILE__, ":", __LINE__, ": ", obj.is_a); -                } -                break; -              } -              break; -            case "block": -              switch (obj.is_a) { -              case "quote": -                auto t = xhtml_format.quote_seg(obj, suffix); -                doc_epub[segment_filename] ~= to!string(t[0]); -                doc_epub_endnotes[segment_filename] ~= t[1]; -                break; -              case "group": -                auto t = xhtml_format.group_seg(obj, suffix); -                doc_epub[segment_filename] ~= to!string(t[0]); -                doc_epub_endnotes[segment_filename] ~= t[1]; -                break; -              case "block": -                auto t = xhtml_format.block_seg(obj, suffix); -                doc_epub[segment_filename] ~= to!string(t[0]); -                doc_epub_endnotes[segment_filename] ~= t[1]; -                break; -              case "poem": -                break; -              case "verse": -                auto t = xhtml_format.verse_seg(obj, suffix); -                doc_epub[segment_filename] ~= to!string(t[0]); -                doc_epub_endnotes[segment_filename] ~= t[1]; -                break; -              case "code": -                doc_epub[segment_filename] ~= xhtml_format.code(obj); -                break; -              case "table": -                auto t = xhtml_format.para_seg(obj, suffix); -                doc_epub[segment_filename] ~= t[0]; -                doc_epub_endnotes[segment_filename] ~= t[1]; -                break; -              default: -                if ((doc_matters.opt_action_bool["debug"])) { -                  writeln(__FILE__, ":", __LINE__, ": ", obj.is_a); -                } -                break; -              } -              break; -            default: -              if ((doc_matters.opt_action_bool["debug"])) { -                writeln(__FILE__, ":", __LINE__, ": ", obj.is_of); -              } -              break; -            } -            break; -          case "backmatter": -            switch (obj.is_of) { -            case "para": -              switch (obj.is_a) { -              case "endnote": -                auto t = xhtml_format.para_seg(obj, suffix); -                doc_epub[segment_filename] ~= t[0]; -                break; -              case "glossary": -                auto t = xhtml_format.para_seg(obj, suffix); -                doc_epub[segment_filename] ~= t[0]; -                doc_epub_endnotes[segment_filename] ~= t[1]; -                break; -              case "bibliography": -                auto t = xhtml_format.para_seg(obj, suffix); -                doc_epub[segment_filename] ~= t[0]; -                doc_epub_endnotes[segment_filename] ~= t[1]; -                break; -              case "bookindex": -                auto t = xhtml_format.para_seg(obj, suffix); -                doc_epub[segment_filename] ~= t[0]; -                doc_epub_endnotes[segment_filename] ~= t[1]; -                break; -              case "blurb": -                auto t = xhtml_format.para_seg(obj, suffix); -                doc_epub[segment_filename] ~= t[0]; -                doc_epub_endnotes[segment_filename] ~= t[1]; -                break; -              default: -                if ((doc_matters.opt_action_bool["debug"])) { -                  writeln(__FILE__, ":", __LINE__, ": ", obj.is_a); -                } -                break; -              } -              break; -            default: -              if ((doc_matters.opt_action_bool["debug"])) { -                writeln(__FILE__, ":", __LINE__, ": ", obj.is_of); -              } -              break; -            } -            break; -          case "comment": -            break; -          default: -            if ((doc_matters.opt_action_bool["debug"])) { -              writeln(__FILE__, ":", __LINE__, ": ", obj.use); -            } -            break; -          } -        } -      } -    } -    epub_write_output_files( -      doc_matters, -      doc_epub, -      doc_epub_endnotes, -      mimetypes, -      meta_inf_container_xml, -      oebps_toc_ncx, -      oebps_content_opf, -    ); -  } -  void epub_write_output_files(M,D,E,Mt,Mic,Ot,Oc)( -    M    doc_matters, -    D    doc_epub, -    E    doc_epub_endnotes, -    Mt   mimetypes, -    Mic  meta_inf_container_xml, -    Ot   oebps_toc_ncx, -    Oc   oebps_content_opf, -  ) { -    debug(asserts){ -      static assert(is(typeof(doc_epub)               == string[][string])); -      static assert(is(typeof(mimetypes)              == string)); -      static assert(is(typeof(meta_inf_container_xml) == string)); -      static assert(is(typeof(oebps_toc_ncx)          == string)); -      static assert(is(typeof(oebps_content_opf)      == string)); -    } -    mixin SiSUpaths; -    auto pth_epub = EpubPaths(); -    auto xhtml_format = outputXHTMLs(); -    try { -      if (!exists(pth_epub.doc_meta_inf(doc_matters.source_filename))) { -        pth_epub.doc_meta_inf(doc_matters.source_filename).mkdirRecurse; -      } -      if (!exists(pth_epub.doc_oebps_css(doc_matters.source_filename))) { -        pth_epub.doc_oebps_css(doc_matters.source_filename).mkdirRecurse; -      } -      if (!exists(pth_epub.doc_oebps_image(doc_matters.source_filename))) { -        pth_epub.doc_oebps_image(doc_matters.source_filename).mkdirRecurse; -      } -      /+ OEBPS/[segments].xhtml +/ -      foreach (seg_filename; doc_matters.segnames) { -        auto f = File(pth_epub.fn_oebps_content_xhtml(doc_matters.source_filename, seg_filename), "w"); -        /+ // f.writeln(seg_head); // not needed built and inserted earlier +/ -        foreach (docseg; doc_epub[seg_filename]) { -          f.writeln(docseg); -        } -        foreach (docseg; doc_epub_endnotes[seg_filename]) { -          f.writeln(docseg); -        } -        f.writeln(xhtml_format.tail); // needed for each lev4 -      } -      /+ mimetypes +/ -      auto f = File(pth_epub.fn_mimetypes(doc_matters.source_filename), "w"); -      f.writeln(mimetypes); -      /+  META-INF/container.xml +/ -      f = File(pth_epub.fn_dmi_container_xml(doc_matters.source_filename), "w"); -      f.writeln(meta_inf_container_xml); -      /+ OEBPS/toc.ncx +/ -      f = File(pth_epub.fn_oebps_toc_ncx(doc_matters.source_filename), "w"); -      f.writeln(oebps_toc_ncx); -      /+ OEBPS/content.opf +/ -      f = File(pth_epub.fn_oebps_content_opf(doc_matters.source_filename), "w"); -      f.writeln(oebps_content_opf); -      foreach (image; doc_matters.image_list) { -        if (exists("_sisu/image/"~ image)) { -          ("_sisu/image/"~ image) -          .copy((pth_epub.doc_oebps_image(doc_matters.source_filename)) ~ "/" ~ image); -        } -      } -    } -    catch (ErrnoException ex) { -      // Handle error -    } -  } -   -} diff --git a/src/sdp/output_epub3.d b/src/sdp/output_epub3.d new file mode 100644 index 0000000..f0ac2c3 --- /dev/null +++ b/src/sdp/output_epub3.d @@ -0,0 +1,717 @@ +template outputEPub3() { +  private import +    std.algorithm, +    std.array, +    std.container, +    std.digest.sha, +    std.exception, +    std.file, +    std.getopt, +    std.json, +    std.outbuffer, +    std.path, +    std.process, +    std.range, +    std.regex, +    std.stdio, +    std.string, +    std.traits, +    std.typecons, +    std.uni, +    std.utf, +    std.zip, +    std.conv : to; +  import +    create_zip_file, +    defaults, +    output_rgx, +    output_xhtmls; +  mixin InternalMarkup; +  mixin outputXHTMLs; +  string epub3_mimetypes() { +    string o; +    o = format(q"¶application/epub+zip¶") ~ "\n"; +    return o; +  } +  string epub3_container_xml() { +    string o; +    o = format(q"¶<?xml version='1.0' encoding='utf-8'?>¶") ~ "\n"; +    o ~= format(q"¶<container version="1.0" +  xmlns="urn:oasis:names:tc:opendocument:xmlns:container"> +  <rootfiles> +    <rootfile full-path="OEBPS/content.opf" +      media-type="application/oebps-package+xml" /> +  </rootfiles>¶") ~ "\n</container>\n"; +    return o; +  } +  string epub3_oebps_content(D,I,P)(D doc_abstraction, I doc_matters, P parts) { +    string uuid = "18275d951861c77f78acd05672c9906924c59f18a2e0ba06dad95959693e9bd8"; // TODO sort uuid in doc_matters! +    string content = format(q"¶  <?xml version='1.0' encoding='utf-8'?> +  <package xmlns="http://www.idpf.org/2007/opf" version="2.0" unique-identifier="EPB-UUID"> +    <metadata +      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" +      xmlns:dcterms="http://purl.org/dc/terms/" +      xmlns:dc="http://purl.org/dc/elements/1.1/" +      unique-identifier="urn:uuid:%s" version="2.0"> +      <!-- <dc:title id="title">%s</dc:title> --> +      <dc:title id="title">%s</dc:title> +      <meta refines="#title" property="title-type">main</meta> +      <dc:title id="subtitle">%s</dc:title> +      <meta refines="#subtitle" property="title-type">subtitle</meta> +      <dc:creator file-as="%s" id="aut">%s</dc:creator> +      <dc:language>%s</dc:language> +      <dc:date id="published">%s</dc:date> +      <dc:rights>Copyright: %s</dc:rights> +      <dc:identifier scheme="URI">%s</dc:identifier> +      <dc:identifier id="bookid">urn:uuid:%s</dc:identifier> +      <!-- <dc:identifier id="EPB-UUID">urn:uuid:%s</dc:identifier> --> +    </metadata> +    <manifest> +      <!-- NCX epub2 navigation --> +        <item id="ncx" href="toc.ncx" media-type="application/x-dtbncx+xml" /> +      <!-- CSS Style Sheets --> +        <item id="main-css" href="css/xhtml.css" media-type="text/css" /> +      <!-- nav epub3 navigation --> +        <item id="nav" href="toc_nav.xhtml" media-type="application/xhtml+xml" properties="nav" /> +  ¶", +      uuid, +      doc_matters.dochead_meta["title"]["full"], +      doc_matters.dochead_meta["title"]["main"], +      (doc_matters.dochead_meta["title"]["sub"].empty) +        ? "" : doc_matters.dochead_meta["title"]["sub"], +      (doc_matters.dochead_meta["creator"]["author"].empty) +        ? "" : doc_matters.dochead_meta["creator"]["author"], +      (doc_matters.dochead_meta["creator"]["author"].empty) +        ? "" : doc_matters.dochead_meta["creator"]["author"], +      doc_matters.language, +      (doc_matters.dochead_meta["date"]["published"].empty) +        ? "" : doc_matters.dochead_meta["date"]["published"], +      (doc_matters.dochead_meta["rights"]["copyright"].empty) +        ? "" : doc_matters.dochead_meta["rights"]["copyright"], +      uuid, +      uuid, +      uuid, +    ); +    content ~= "    " ~ "<!-- Content Documents -->" ~ "\n  "; +    content ~= parts["manifest_documents"]; +    // TODO sort jpg & png +    content ~= "    " ~ "<!-- Images -->" ~ "\n  "; +    foreach (image; doc_matters.image_list) { +      content ~= format(q"¶      <item id="%s" href="image/%s" media-type="image/png" /> +  ¶", +        image,                        // strip image type, remove .png .jpg suffix, use in media-type="image/" +        image, +      ); +    } +    content ~= "  " ~ "</manifest>"         ~ "\n  "; +    content ~= "  " ~ "<spine toc=\"ncx\">" ~ "\n  "; +    content ~= parts["spine"]; +    content ~= "  " ~ "</spine>"            ~ "\n  "; +    content ~= "  " ~ "<guide>"             ~ "\n  "; +    content ~= parts["guide"]; +    content ~= "  " ~ "</guide>"            ~ "\n  "; +    content ~= ""   ~ "</package>"; +    return content; +  } +  string epub3_oebps_toc_nav_xhtml(D,I)(D doc_abstraction, I doc_matters) { +    enum DomTags { none, open, close, close_and_open, open_still, } +    auto markup = InlineMarkup(); +    string toc ="<nav epub:type=\"toc\" id=\"toc\">\n"; +    foreach (sect; doc_matters.keys_seq_seg) { +      foreach (obj; doc_abstraction[sect]) { +        if (obj.is_a == "heading") { +          foreach_reverse (n; 0 .. 7) { +            string k = n.to!string; +            switch (obj.dom_collapsed[n]) { +            case DomTags.close : +              toc ~= markup.indent_by_spaces_provided((n + 1), "  ") ~ "</li>" ~ "\n"; +              toc ~= markup.indent_by_spaces_provided(n, "  ") ~ "</ol>" ~ "\n"; +              break; +            case DomTags.close_and_open : +              toc ~= markup.indent_by_spaces_provided((n + 1), "  ") ~ "</li>" ~ "\n"; +              if  (obj.dom_markedup[n] < 4) { +                toc ~= markup.indent_by_spaces_provided((n + 1), "  ") ~ "<li>" ~ "\n" +                ~ markup.indent_by_spaces_provided((n + 2), "  ") +                ~ "<span class=\"navhd\">" ~ obj.text ~ "</span>" ~ "\n"; +              } else { +                string hashtag =(obj.heading_lev_markup == 4) +                ? "" +                : ("#" ~ obj.ocn.to!string); +                toc ~= markup.indent_by_spaces_provided((n + 1), "  ") ~ "<li>" ~ "\n" +                ~ markup.indent_by_spaces_provided((n + 2), "  ") +                ~ "<a href=\"" ~ obj.segment_anchor_tag ~ ".xhtml" ~ hashtag ~ "\">" +                ~ obj.text +                ~ "</a>" ~ "\n"; +              } +              break; +            case DomTags.open : +              toc ~= markup.indent_by_spaces_provided(n, "  ") ~ "<ol>" ~ "\n"; +              if  (obj.dom_markedup[n] < 4) { +                toc ~= markup.indent_by_spaces_provided(n, "  ") +                ~ "<li><span class=\"navhd\">" ~ obj.text ~ "</span>" ~ "\n"; +              } else { +                string hashtag =(obj.heading_lev_markup == 4) +                ? "" +                : ("#" ~ obj.ocn.to!string); +                toc ~= markup.indent_by_spaces_provided((n + 1), "  ") ~ "<li>" ~ "\n" +                ~ markup.indent_by_spaces_provided((n + 2), "  ") +                ~ "<a href=\"" ~ obj.segment_anchor_tag ~ ".xhtml" ~ hashtag ~ "\">" +                ~ obj.text +                ~ "</a>" ~ "\n"; +              } +              break; +            default : +              break; +            } +          } +        } +      } +    } +    toc ~="</nav>\n"; +    return toc; +  } +  string epub2_oebps_toc_ncx(D,I)(D doc_abstraction, I doc_matters) { +    int counter = 0; +    string uuid = "18275d951861c77f78acd05672c9906924c59f18a2e0ba06dad95959693e9bd8"; // TODO shared elsewhere +    auto markup = InlineMarkup(); +    enum DomTags { none, open, close, close_and_open, open_still, } +    string toc = format(q"¶<?xml version='1.0' encoding='utf-8'?> +  <ncx xmlns="http://www.daisy.org/z3986/2005/ncx/" version="2005-1"> +    <head> +      <!-- four required metadata items (for all NCX documents, +        (including the relaxed constraints of OPS 2.0) --> +      <title>%s%s</title> +      <link href="css/xhtml.css" rel="stylesheet" type="text/css" id="main-css" /> +      <meta name="dtb:uid" content="urn:uuid:%s" /> +      <!-- <meta name="epub-creator" content="SiSU http://www.jus.uio.no/sisu (this copy)" /> --> +      <meta name="dtb:depth" content="%s" /> +      <meta name="dtb:totalPageCount" content="0" /> +      <meta name="dtb:maxPageNumber" content="0" /> +    </head> +    <docTitle> +      <text>%s</text> +    </docTitle> +    <docAuthor> +      <text>%s</text> +    </docAuthor> +    <navMap>¶", +      doc_matters.dochead_meta["title"]["full"],                                                               // title +      (doc_matters.dochead_meta["creator"]["author"].empty) ? "" : " by " ~ doc_matters.dochead_meta["creator"]["author"], // author +      uuid,                                                                                        // uuid +      "3",                                                                                         // content depth +      doc_matters.dochead_meta["title"]["full"],                                                               // title +      (doc_matters.dochead_meta["creator"]["author"].empty) ? "" : doc_matters.dochead_meta["creator"]["author"],          // author +    ); +    foreach (sect; doc_matters.keys_seq_seg) { +      foreach (obj; doc_abstraction[sect]) { +        if (obj.is_a == "heading") { +          foreach_reverse (k; 0 .. 7) { +            switch (obj.dom_markedup[k]) { +            case DomTags.close : +  toc ~= "</navPoint>"; +              break; +            case DomTags.close_and_open : +              ++counter; +  toc ~= "</navPoint>"; +  toc ~= format(q"¶<navPoint class="chapter" id="navpoint" playOrder="%s"> +  <navLabel> +    <text>%s</text> +  </navLabel> +  <content src="%s" />¶", +  counter, +  obj.text, +  obj.segment_anchor_tag,   // lev < 4 [no link]; lev == 4 [filename] markup.xhtml; lev > 4 [filename#ocn] (links done in segment_anchor_tag) +  ); +              break; +            case DomTags.open : +              ++counter; +  toc ~= format(q"¶<navPoint class="chapter" id="navpoint" playOrder="%s"> +  <navLabel> +    <text>%s</text> +  </navLabel> +  <content src="%s" />¶", +  counter, +  obj.text, +  obj.segment_anchor_tag,   // lev < 4 [no link]; lev == 4 [filename] markup.xhtml; lev > 4 [filename#ocn] (fix links in segment_anchor_tag) +  ); +              break; +            default : +              break; +            } +          } +        } +      } +    } +    toc ~= format(q"¶  </navMap> +  </ncx>¶"); +    return toc; +  } +   +  void outputEPub3(D,I)( +    auto return ref const D    doc_abstraction, +    auto return ref I          doc_matters, +  ) { +    mixin SiSUoutputRgxInit; +    auto xhtml_format = outputXHTMLs(); +    auto rgx = Rgx(); +    string[][string] doc_epub3; +    string[][string] doc_epub3_endnotes; +    string[] doc; +    string segment_filename; +    string[] top_level_headings = ["","","",""]; +    string[string] oepbs_content_parts; +    string suffix = ".xhtml"; +    foreach (part; doc_matters.keys_seq_seg) { +      foreach (obj; doc_abstraction[part]) { +        if (obj.is_a == "heading") { +          switch (obj.heading_lev_markup) { +          case 0: .. case 3: +            /+ fill buffer, and replace with new levels from 1 to 3 +/ +            switch (obj.heading_lev_markup) { +            case 0: +              top_level_headings[0] = ""; +              top_level_headings[1] = ""; +              top_level_headings[2] = ""; +              top_level_headings[3] = ""; +              goto default; +            case 1: +              top_level_headings[1] = ""; +              top_level_headings[2] = ""; +              top_level_headings[3] = ""; +              goto default; +            case 2: +              top_level_headings[2] = ""; +              top_level_headings[3] = ""; +              goto default; +            case 3: +              top_level_headings[3] = ""; +              goto default; +            default: +              auto t = xhtml_format.heading_seg(obj, suffix); +              top_level_headings[obj.heading_lev_markup] = t[0]; +              break; +            } +            break; +          case 4: +            segment_filename = obj.segment_anchor_tag; +            doc_epub3[segment_filename] ~= xhtml_format.seg_head(doc_matters.dochead_meta); +            foreach (top_level_heading; top_level_headings) { +              doc_epub3[segment_filename] ~= top_level_heading; +            } +            auto t = xhtml_format.heading_seg(obj, suffix); +            doc_epub3[segment_filename] ~= t[0]; +            doc_epub3_endnotes[segment_filename] ~= t[1]; +            break; +          case 5: .. case 7: +            auto t = xhtml_format.heading_seg(obj, suffix); +            doc_epub3[segment_filename] ~= t[0]; +            doc_epub3_endnotes[segment_filename] ~= t[1]; +            break; +          case 8: .. case 9: // unused numbers, if remain check +            if ((doc_matters.opt_action_bool["debug"])) { +              writeln(__FILE__, ":", __LINE__, ": ", obj.is_a, ": ", obj.heading_lev_markup); +              writeln(__FILE__, ":", __LINE__, ": ", obj.text); // check +            } +            break; +          default: +            if ((doc_matters.opt_action_bool["debug"])) { +              writeln(__FILE__, ":", __LINE__, ": ", obj.is_a, ": ", obj.heading_lev_markup); +            } +            break; +          } +        } else { +          switch (obj.use) { +          case "frontmatter": +            switch (obj.is_of) { +            case "para": +              switch (obj.is_a) { +              case "toc": +                doc_epub3[segment_filename] ~= xhtml_format.toc(obj); +                break; +              default: +                if ((doc_matters.opt_action_bool["debug"])) { +                  writeln(__FILE__, ":", __LINE__, ": ", obj.is_a); +                } +                break; +              } +              break; +            default: +              if ((doc_matters.opt_action_bool["debug"])) { +                writeln(__FILE__, ":", __LINE__, ": ", obj.is_of); +              } +              break; +            } +            break; +          case "body": +            switch (obj.is_of) { +            case "para": +              switch (obj.is_a) { +              case "para": +                auto t = xhtml_format.para_seg(obj, suffix); +                doc_epub3[segment_filename] ~= t[0]; +                doc_epub3_endnotes[segment_filename] ~= t[1]; +                break; +              default: +                if ((doc_matters.opt_action_bool["debug"])) { +                  writeln(__FILE__, ":", __LINE__, ": ", obj.is_a); +                } +                break; +              } +              break; +            case "block": +              switch (obj.is_a) { +              case "quote": +                auto t = xhtml_format.quote_seg(obj, suffix); +                doc_epub3[segment_filename] ~= to!string(t[0]); +                doc_epub3_endnotes[segment_filename] ~= t[1]; +                break; +              case "group": +                auto t = xhtml_format.group_seg(obj, suffix); +                doc_epub3[segment_filename] ~= to!string(t[0]); +                doc_epub3_endnotes[segment_filename] ~= t[1]; +                break; +              case "block": +                auto t = xhtml_format.block_seg(obj, suffix); +                doc_epub3[segment_filename] ~= to!string(t[0]); +                doc_epub3_endnotes[segment_filename] ~= t[1]; +                break; +              case "poem": +                break; +              case "verse": +                auto t = xhtml_format.verse_seg(obj, suffix); +                doc_epub3[segment_filename] ~= to!string(t[0]); +                doc_epub3_endnotes[segment_filename] ~= t[1]; +                break; +              case "code": +                doc_epub3[segment_filename] ~= xhtml_format.code(obj); +                break; +              case "table": +                auto t = xhtml_format.para_seg(obj, suffix); +                doc_epub3[segment_filename] ~= t[0]; +                doc_epub3_endnotes[segment_filename] ~= t[1]; +                break; +              default: +                if ((doc_matters.opt_action_bool["debug"])) { +                  writeln(__FILE__, ":", __LINE__, ": ", obj.is_a); +                } +                break; +              } +              break; +            default: +              if ((doc_matters.opt_action_bool["debug"])) { +                writeln(__FILE__, ":", __LINE__, ": ", obj.is_of); +              } +              break; +            } +            break; +          case "backmatter": +            switch (obj.is_of) { +            case "para": +              switch (obj.is_a) { +              case "endnote": +                auto t = xhtml_format.para_seg(obj, suffix); +                doc_epub3[segment_filename] ~= t[0]; +                break; +              case "glossary": +                auto t = xhtml_format.para_seg(obj, suffix); +                doc_epub3[segment_filename] ~= t[0]; +                doc_epub3_endnotes[segment_filename] ~= t[1]; +                break; +              case "bibliography": +                auto t = xhtml_format.para_seg(obj, suffix); +                doc_epub3[segment_filename] ~= t[0]; +                doc_epub3_endnotes[segment_filename] ~= t[1]; +                break; +              case "bookindex": +                auto t = xhtml_format.para_seg(obj, suffix); +                doc_epub3[segment_filename] ~= t[0]; +                doc_epub3_endnotes[segment_filename] ~= t[1]; +                break; +              case "blurb": +                auto t = xhtml_format.para_seg(obj, suffix); +                doc_epub3[segment_filename] ~= t[0]; +                doc_epub3_endnotes[segment_filename] ~= t[1]; +                break; +              default: +                if ((doc_matters.opt_action_bool["debug"])) { +                  writeln(__FILE__, ":", __LINE__, ": ", obj.is_a); +                } +                break; +              } +              break; +            default: +              if ((doc_matters.opt_action_bool["debug"])) { +                writeln(__FILE__, ":", __LINE__, ": ", obj.is_of); +              } +              break; +            } +            break; +          case "comment": +            break; +          default: +            if ((doc_matters.opt_action_bool["debug"])) { +              writeln(__FILE__, ":", __LINE__, ": ", obj.use); +            } +            break; +          } +        } +        if (obj.is_a == "heading") { +          if (obj.heading_lev_markup == 4) { +            oepbs_content_parts["manifest_documents"] ~= format(q"¶      <item id="%s.xhtml" href="%s.xhtml" media-type="application/xhtml+xml" /> +  ¶", +              obj.segment_anchor_tag, +              obj.segment_anchor_tag, +            ); +            oepbs_content_parts["spine"] ~= format(q"¶    <itemref idref="%s.xhtml" linear="yes" /> +  ¶", +              obj.segment_anchor_tag, +            ); +            oepbs_content_parts["guide"] ~= format(q"¶      <reference type="%s" href="%s" /> +  ¶", +              obj.segment_anchor_tag, +              obj.segment_anchor_tag, +            ); +          } else if (obj.heading_lev_markup > 4) { +            oepbs_content_parts["manifest_documents"] ~= format(q"¶      <item id="%s.xhtml#%s" href="%s.xhtml#%s" media-type="application/xhtml+xml" /> +  ¶", +              obj.segment_anchor_tag, +              obj.obj_cite_number, +              obj.segment_anchor_tag, +              obj.obj_cite_number, +            ); +            oepbs_content_parts["spine"] ~= format(q"¶    <itemref idref="%s.xhtml#%s" linear="yes" /> +  ¶", +              obj.segment_anchor_tag, +              obj.obj_cite_number, +            ); +            oepbs_content_parts["guide"] ~= format(q"¶      <reference type="%s#%s" href="%s#%s" /> +  ¶", +              obj.segment_anchor_tag, +              obj.obj_cite_number, +              obj.segment_anchor_tag, +              obj.obj_cite_number, +            ); +          } +        } +      } +    } +    /+ epub specific documents +/ +    auto mimetypes = epub3_mimetypes; +    auto meta_inf_container_xml = epub3_container_xml; +    auto oebps_toc_ncx = epub2_oebps_toc_ncx(doc_abstraction, doc_matters); +    auto oebps_toc_nav_xhtml = epub3_oebps_toc_nav_xhtml(doc_abstraction, doc_matters); +    auto oebps_content_opf = epub3_oebps_content(doc_abstraction, doc_matters, oepbs_content_parts); +    epub3_write_output_files( +      doc_matters, +      doc_epub3, +      doc_epub3_endnotes, +      mimetypes, +      meta_inf_container_xml, +      oebps_toc_nav_xhtml, +      oebps_toc_ncx, +      oebps_content_opf, +    ); +  } +  void epub3_write_output_files(M,D,E,Mt,Mic,Otnx,Otn,Oc)( +    M    doc_matters, +    D    doc_epub3, +    E    doc_epub3_endnotes, +    Mt   mimetypes, +    Mic  meta_inf_container_xml, +    Otnx oebps_toc_nav_xhtml, +    Otn  oebps_toc_ncx, +    Oc   oebps_content_opf, +  ) { +    debug(asserts) { +      static assert(is(typeof(doc_epub3)              == string[][string])); +      static assert(is(typeof(mimetypes)              == string)); +      static assert(is(typeof(meta_inf_container_xml) == string)); +      static assert(is(typeof(oebps_toc_nav_xhtml)    == string)); +      static assert(is(typeof(oebps_toc_ncx)          == string)); +      static assert(is(typeof(oebps_content_opf)      == string)); +    } +    mixin SiSUpaths; +    auto pth_epub3 = Epub3paths(); +    auto xhtml_format = outputXHTMLs(); +    /+ zip file +/ +    auto fn_epub = pth_epub3.epub_file(doc_matters.source_filename); +    auto zip = new ZipArchive(); // ZipArchive zip = new ZipArchive(); +    /+ zip archive member files +/ +    try { +      if (!exists(pth_epub3.doc_meta_inf(doc_matters.source_filename))) { +        pth_epub3.doc_meta_inf(doc_matters.source_filename).mkdirRecurse; +      } +      if (!exists(pth_epub3.doc_oebps_css(doc_matters.source_filename))) { +        pth_epub3.doc_oebps_css(doc_matters.source_filename).mkdirRecurse; +      } +      if (!exists(pth_epub3.doc_oebps_image(doc_matters.source_filename))) { +        pth_epub3.doc_oebps_image(doc_matters.source_filename).mkdirRecurse; +      } +      { /+ OEBPS/[segments].xhtml (the document contents) +/ +        foreach (seg_filename; doc_matters.segnames) { +          string fn = pth_epub3.fn_oebps_content_xhtml(doc_matters.source_filename, seg_filename); +          /+ add zip archive file members (with their content) +/ +          auto zip_arc_member_file = new ArchiveMember(); +          // add seg fn to zip archive +          zip_arc_member_file.name = fn; +          auto zip_data = new OutBuffer(); +          debug(epub_output) { +            string fn_dbg = pth_epub3.dbg_fn_oebps_content_xhtml(doc_matters.source_filename, seg_filename); +            auto f = File(fn_dbg, "w"); +          } +          /+ // f.writeln(seg_head); // not needed built and inserted earlier +/ +          foreach (docseg; doc_epub3[seg_filename]) { +            debug(epub_output) { f.writeln(docseg); } +            zip_data.write(docseg.dup); // cast as: char[] +          } +          foreach (docseg; doc_epub3_endnotes[seg_filename]) { +            debug(epub_output) { f.writeln(docseg); } +            zip_data.write(docseg.dup); // cast as: char[] +          } +          debug(epub_output) { f.writeln(xhtml_format.tail); } // needed for each lev4 +          zip_data.write(xhtml_format.tail.dup); // cast as: char[] +          zip_arc_member_file.expandedData = zip_data.toBytes(); +          zip.addMember(zip_arc_member_file); +          /+ create the zip file +/ +          createZipFile!()(fn_epub, zip.build()); +        } +      } +      string fn; +      debug(epub_output) { string fn_dbg; } +      File f; +      { /+ mimetypes (identify zip file type) +/ +        debug(epub_output) { +          fn_dbg = pth_epub3.dbg_fn_mimetypes(doc_matters.source_filename); +          File(fn_dbg, "w").writeln(mimetypes); +        } +        fn = pth_epub3.fn_mimetypes(doc_matters.source_filename); +        /+ add zip archive file members (with their content) +/ +        auto zip_arc_member_file = new ArchiveMember(); +        // add mimetypes to zip archive +        zip_arc_member_file.name = fn; +        auto zip_data = new OutBuffer(); +        zip_data.write(mimetypes.dup); // cast as: char[] +        zip_arc_member_file.expandedData = zip_data.toBytes(); +        zip.addMember(zip_arc_member_file); +        /+ create the zip file +/ +        createZipFile!()(fn_epub, zip.build()); +      } +      { /+  META-INF/container.xml (identify doc root) +/ +        debug(epub_output) { +          fn_dbg = pth_epub3.dbg_fn_dmi_container_xml(doc_matters.source_filename); +          File(fn_dbg, "w").writeln(meta_inf_container_xml); +        } +        fn = pth_epub3.fn_dmi_container_xml(doc_matters.source_filename); +        /+ add zip archive file members (with their content) +/ +        auto zip_arc_member_file = new ArchiveMember(); +        // add META-INF/container.xml to zip archive +        zip_arc_member_file.name = fn; +        auto zip_data = new OutBuffer(); +        zip_data.write(meta_inf_container_xml.dup); // cast as: char[] +        zip_arc_member_file.expandedData = zip_data.toBytes(); +        zip.addMember(zip_arc_member_file); +        /+ create the zip file +/ +        createZipFile!()(fn_epub, zip.build()); +      } +      { /+ OEBPS/toc_nav.xhtml (navigation toc epub3) +/ +        debug(epub_output) { +          fn_dbg = pth_epub3.dbg_fn_oebps_toc_nav_xhtml(doc_matters.source_filename); +          File(fn_dbg, "w").writeln(oebps_toc_nav_xhtml); +        } +        fn = pth_epub3.fn_oebps_toc_nav_xhtml(doc_matters.source_filename); +        /+ add zip archive file members (with their content) +/ +        auto zip_arc_member_file = new ArchiveMember(); +        // add OEBPS/toc_nav.xhtml to zip archive +        zip_arc_member_file.name = fn; +        auto zip_data = new OutBuffer(); +        zip_data.write(oebps_toc_nav_xhtml.dup); // cast as: char[] +        zip_arc_member_file.expandedData = zip_data.toBytes(); +        zip.addMember(zip_arc_member_file); +        /+ create the zip file +/ +        createZipFile!()(fn_epub, zip.build()); +      } +      { /+ TODO OEBPS/toc.ncx (navigation toc epub2) +/ +        debug(epub_output) { +          fn_dbg = pth_epub3.dbg_fn_oebps_toc_ncx(doc_matters.source_filename); +          File(fn_dbg, "w").writeln(oebps_toc_ncx); +        } +        fn = pth_epub3.fn_oebps_toc_ncx(doc_matters.source_filename); +        /+ add zip archive file members (with their content) +/ +        auto zip_arc_member_file = new ArchiveMember(); +        // add OEBPS/toc.ncx to zip archive +        zip_arc_member_file.name = fn; +        auto zip_data = new OutBuffer(); +        zip_data.write(oebps_toc_ncx.dup); // cast as: char[] +        zip_arc_member_file.expandedData = zip_data.toBytes(); +        zip.addMember(zip_arc_member_file); +        /+ create the zip file +/ +        createZipFile!()(fn_epub, zip.build()); +      } +      { /+ TODO OEBPS/content.opf (doc manifest) +/ +        debug(epub_output) { +          fn_dbg = pth_epub3.dbg_fn_oebps_content_opf(doc_matters.source_filename); +          File(fn_dbg, "w").writeln(oebps_content_opf); +        } +        fn = pth_epub3.fn_oebps_content_opf(doc_matters.source_filename); +        /+ add zip archive file members (with their content) +/ +        auto zip_arc_member_file = new ArchiveMember(); +        // add OEBPS/content.opf to zip archive +        zip_arc_member_file.name = fn; +        auto zip_data = new OutBuffer(); +        zip_data.write(oebps_content_opf.dup); // cast as: char[] +        zip_arc_member_file.expandedData = zip_data.toBytes(); +        zip.addMember(zip_arc_member_file); +        /+ create the zip file +/ +        createZipFile!()(fn_epub, zip.build()); +      } +      { /+ OEBPS/_sisu/image (images) +/ +        foreach (image; doc_matters.image_list) { +          if (exists("_sisu/image/"~ image)) { +            ("_sisu/image/"~ image) +            .copy((pth_epub3.doc_oebps_image(doc_matters.source_filename)) ~ "/" ~ image); +          } +        } +        foreach (image; doc_matters.image_list) { +          debug(epub_images) { +            writeln( +              "_sisu/image/", image, " -> ", +              pth_epub3.doc_oebps_image(doc_matters.source_filename), "/", image +            ); +          } +          auto fn_src = "_sisu/image/"~ image; +          auto fn_out =  pth_epub3.doc_oebps_image(doc_matters.source_filename).to!string ~ "/" ~ image; +          if (exists(fn_src)) { +            { +              auto zip_arc_member_file = new ArchiveMember(); +              zip_arc_member_file.name = fn_out; +              auto zip_data = new OutBuffer(); +              zip_data.write(cast(char[]) ((fn_src).read)); +              zip_arc_member_file.expandedData = zip_data.toBytes(); +              zip.addMember(zip_arc_member_file); +              createZipFile!()(fn_epub, zip.build()); +            } +          } +        } +      } +    } +    catch (ErrnoException ex) { +      // Handle error +    } +    debug(epub_archive) { +      if (exists(fn_epub)) { +        try { +          auto zipped = new ZipArchive((fn_epub).read); +          foreach (filename, member; zipped.directory) { +            auto data = zipped.expand(member); +            writeln(filename, " length ", data.length); // member.name +            // Use data +          } +        } +        catch (ZipException ex) { +          // Handle errors +        } +      } +    } +  } +   +} diff --git a/src/sdp/output_html.d b/src/sdp/output_html.d index ba6adc8..71faa67 100644 --- a/src/sdp/output_html.d +++ b/src/sdp/output_html.d @@ -3,22 +3,26 @@ template outputHTML() {      std.algorithm,      std.array,      std.container, +    std.digest.sha,      std.exception,      std.file,      std.getopt,      std.json, -    std.process, -    std.stdio, +    std.outbuffer,      std.path, +    std.process,      std.range,      std.regex, +    std.stdio,      std.string,      std.traits,      std.typecons,      std.uni,      std.utf, +    std.zip,      std.conv : to;    import +    create_zip_file,      defaults,      output_rgx,      output_xhtmls; @@ -169,7 +173,7 @@ template outputHTML() {      Fn fn_src,      C doc,    ) { -    debug(asserts){ +    debug(asserts) {        static assert(is(typeof(fn_src) == string));        static assert(is(typeof(doc)    == string[]));      } @@ -404,7 +408,7 @@ template outputHTML() {      D doc_html,      E doc_html_endnotes,    ) { -    debug(asserts){ +    debug(asserts) {        static assert(is(typeof(doc_html)      == string[][string]));      }      mixin SiSUoutputRgxInit; diff --git a/src/sdp/output_hub.d b/src/sdp/output_hub.d index 67275e0..65c8990 100644 --- a/src/sdp/output_hub.d +++ b/src/sdp/output_hub.d @@ -1,5 +1,5 @@  /++ -  output hub<BR> +  output hub<br>    check & generate output types requested  +/  template outputHub() { @@ -20,13 +20,14 @@ template outputHub() {      std.traits,      std.typecons,      std.uni, -    std.utf, +    std.utf; +  import      defaults, -    output_epub, +    output_epub3,      output_html,      output_xhtmls, -    source_sisupod; -  import +    source_sisupod, +    create_zip_file,      output_rgx,      output_xhtmls;    void outputHub(D,I)(D doc_abstraction, I doc_matters) { @@ -65,10 +66,10 @@ template outputHub() {        if ((doc_matters.opt_action_bool["verbose"])) {writeln("html scroll done");}      }      if (doc_matters.opt_action_bool["epub"]) { -      if ((doc_matters.opt_action_bool["verbose"])) {write("epub processing... ");} -      outputEPub!()(doc_abstraction, doc_matters); +      if ((doc_matters.opt_action_bool["verbose"])) {write("epub3 processing... ");} +      outputEPub3!()(doc_abstraction, doc_matters);        // epub.css_write; -      if ((doc_matters.opt_action_bool["verbose"])) {writeln("epub done");} +      if ((doc_matters.opt_action_bool["verbose"])) {writeln("epub3 done");}      }      if (doc_matters.opt_action_bool["pdf"]) {        /+ mixin outputPDF; +/ diff --git a/src/sdp/output_xhtmls.d b/src/sdp/output_xhtmls.d index 2a86d4c..804b82f 100644 --- a/src/sdp/output_xhtmls.d +++ b/src/sdp/output_xhtmls.d @@ -3,22 +3,26 @@ template outputXHTMLs() {      std.algorithm,      std.array,      std.container, +    std.digest.sha,      std.exception,      std.file,      std.getopt,      std.json, -    std.process, -    std.stdio, +    std.outbuffer,      std.path, +    std.process,      std.range,      std.regex, +    std.stdio,      std.string,      std.traits,      std.typecons,      std.uni,      std.utf, +    std.zip,      std.conv : to;    import +    create_zip_file,      defaults,      output_rgx,      output_xhtmls; @@ -30,7 +34,7 @@ template outputXHTMLs() {          .replaceAll(rgx.xhtml_ampersand,    "&")          .replaceAll(rgx.xhtml_less_than,    "<")          .replaceAll(rgx.xhtml_greater_than, ">") -        .replaceAll(rgx.xhtml_line_break,   "<br>"); +        .replaceAll(rgx.xhtml_line_break,   "<br />");        return _txt;      }      string font_face(string _txt){ @@ -61,7 +65,7 @@ template outputXHTMLs() {      auto scroll_head(Me)(        Me dochead_meta,      ) { -      debug(asserts){ +      debug(asserts) {          static assert(is(typeof(dochead_meta) == string[string][string]));        }        string o; @@ -69,26 +73,27 @@ template outputXHTMLs() {      <html>      <head>        <meta charset="utf-8"> -      <title> -        %s%s -      </title> -    <meta http-equiv="Content-Type" content="text/html;charset=utf-8" /> -      <meta name="dc.title" content="Title" /> -      <meta name="dc.author" content="Author" /> -      <meta name="dc.publisher" content="SiSU http://www.jus.uio.no/sisu (this copy)" /> -      <meta name="dc.date" content="year" /> -      <meta name="dc.date.created" content="year" /> -      <meta name="dc.date.issued" content="year" /> -      <meta name="dc.date.available" content="year" /> -      <meta name="dc.date.valid" content="year" /> -      <meta name="dc.date.modified" content="year" /> -      <meta name="dc.language" content="US" /> -      <meta name="dc.rights" content="Copyright: Copyright (C) year holder /> -      <meta name="generator" content="sdp [SiSU 7.1.8 of 2016w08/5 (2016-02-26)] (n*x and D)" /> -        <link rel="generator" href="http://www.sisudoc.org/" /> +        <title> +          %s%s +        </title> +        <meta http-equiv="Content-Type" content="text/html;charset=utf-8" /> +        <meta name="dc.title" content="Title" /> +        <meta name="dc.author" content="Author" /> +        <meta name="dc.publisher" content="SiSU http://www.jus.uio.no/sisu (this copy)" /> +        <meta name="dc.date" content="year" /> +        <meta name="dc.date.created" content="year" /> +        <meta name="dc.date.issued" content="year" /> +        <meta name="dc.date.available" content="year" /> +        <meta name="dc.date.valid" content="year" /> +        <meta name="dc.date.modified" content="year" /> +        <meta name="dc.language" content="US" /> +        <meta name="dc.rights" content="Copyright: Copyright (C) year holder /> +        <meta name="generator" content="sdp [SiSU 7.1.8 of 2016w08/5 (2016-02-26)] (n*x and D)" /> +      </meta> +      <link rel="generator" href="http://www.sisudoc.org/" />        <link rel="shortcut icon" href="../_sisu/image/rb7.ico" /> -      <link href="../../_sisu/css/html.css" rel="stylesheet"> -      <link href="../../../_sisu/css/html.css" rel="stylesheet"> +      <link href="../../_sisu/css/html.css" rel="stylesheet" /> +      <link href="../../../_sisu/css/html.css" rel="stylesheet" />      </head>      <body lang="en">      <a name="top" id="top"></a>¶", @@ -100,7 +105,7 @@ template outputXHTMLs() {      auto seg_head(Me)(        Me dochead_meta,      ) { -      debug(asserts){ +      debug(asserts) {          static assert(is(typeof(dochead_meta) == string[string][string]));        }        string o; @@ -108,26 +113,27 @@ template outputXHTMLs() {      <html>      <head>        <meta charset="utf-8"> -      <title> -        %s%s -      </title> -    <meta http-equiv="Content-Type" content="text/html;charset=utf-8" /> -      <meta name="dc.title" content="Title" /> -      <meta name="dc.author" content="Author" /> -      <meta name="dc.publisher" content="SiSU http://www.jus.uio.no/sisu (this copy)" /> -      <meta name="dc.date" content="year" /> -      <meta name="dc.date.created" content="year" /> -      <meta name="dc.date.issued" content="year" /> -      <meta name="dc.date.available" content="year" /> -      <meta name="dc.date.valid" content="year" /> -      <meta name="dc.date.modified" content="year" /> -      <meta name="dc.language" content="US" /> -      <meta name="dc.rights" content="Copyright: Copyright (C) year holder /> -      <meta name="generator" content="sdp [SiSU 7.1.8 of 2016w08/5 (2016-02-26)] (n*x and D)" /> -        <link rel="generator" href="http://www.sisudoc.org/" /> +        <title> +          %s%s +        </title> +        <meta http-equiv="Content-Type" content="text/html;charset=utf-8" /> +        <meta name="dc.title" content="Title" /> +        <meta name="dc.author" content="Author" /> +        <meta name="dc.publisher" content="SiSU http://www.jus.uio.no/sisu (this copy)" /> +        <meta name="dc.date" content="year" /> +        <meta name="dc.date.created" content="year" /> +        <meta name="dc.date.issued" content="year" /> +        <meta name="dc.date.available" content="year" /> +        <meta name="dc.date.valid" content="year" /> +        <meta name="dc.date.modified" content="year" /> +        <meta name="dc.language" content="US" /> +        <meta name="dc.rights" content="Copyright: Copyright (C) year holder" /> +        <meta name="generator" content="sdp [SiSU 7.1.8 of 2016w08/5 (2016-02-26)] (n*x and D)" /> +      </meta> +      <link rel="generator" href="http://www.sisudoc.org/" />        <link rel="shortcut icon" href="../_sisu/image/rb7.ico" /> -      <link href="../../_sisu/css/html.css" rel="stylesheet"> -      <link href="../../../_sisu/css/html.css" rel="stylesheet"> +      <link href="../../_sisu/css/html.css" rel="stylesheet" /> +      <link href="../../../_sisu/css/html.css" rel="stylesheet" />      </head>      <body lang="en">      <a name="top" id="top"></a>¶", @@ -192,13 +198,13 @@ template outputXHTMLs() {        return _txt;      }      auto inline_notes_scroll(O)( -      auto return ref const O         obj, -      string                  _txt, +      auto return ref const O   obj, +      string                    _txt,      ) {        if (obj.inline_notes_reg) {          _txt = (_txt).replaceAll(            rgx.inline_notes_delimiter_al_regular_number_note, -          ("<a href=\"#note_$1\"><note id=\"noteref_$1\"> <sup>$1</sup> </note></a>") +          ("<a href=\"#note_$1\"><note id=\"noteref_$1\"> <sup>$1</sup> </note></a>")          );        }        debug(markup_endnotes) { @@ -236,7 +242,7 @@ template outputXHTMLs() {              "\">",              "<note id=\"note_",              m.captures[1], -            "\"> <sup>", +            "\"> <sup>",              m.captures[1],              ".</sup></note></a>",              m.captures[2], @@ -245,7 +251,7 @@ template outputXHTMLs() {          }          _txt = (_txt).replaceAll(            rgx.inline_notes_delimiter_al_regular_number_note, -          ("<a href=\"#note_$1\"><note id=\"noteref_$1\"> <sup>$1</sup> </note></a>") +          ("<a href=\"#note_$1\"><note id=\"noteref_$1\"> <sup>$1</sup> </note></a>")          );        } else if (_txt.match(rgx.inline_notes_delimiter_al_regular_number_note)) {          debug(markup) { @@ -301,7 +307,7 @@ template outputXHTMLs() {        auto tags = _xhtml_anchor_tags(obj.anchor_tags);        string o;        if (obj.obj_cite_number.empty) { -        o = format(q"¶<br><hr /><br> +        o = format(q"¶<br /><hr /><br />        <div class="substance">          <h%s class="%s">%s            %s @@ -314,7 +320,7 @@ template outputXHTMLs() {            obj.heading_lev_markup,          );        } else { -        o = format(q"¶<br><hr /><br> +        o = format(q"¶<br /><hr /><br />        <div class="substance">          <label class="ocn"><a href="#%s" class="lnkocn">%s</a></label>          <h%s class="%s" id="%s"><a name="%s"></a>%s @@ -364,7 +370,7 @@ template outputXHTMLs() {        auto tags = _xhtml_anchor_tags(obj.anchor_tags);        _txt = font_face(_txt);        string o; -      _txt = (obj.bullet) ? ("●  " ~ _txt) : _txt; +      _txt = (obj.bullet) ? ("●  " ~ _txt) : _txt;        if (obj.obj_cite_number.empty) {          o = format(q"¶  <div class="substance">        <p class="%s" indent="h%si%s">%s @@ -541,7 +547,6 @@ template outputXHTMLs() {      </div>¶",            obj.is_a,            _txt -          // obj.text          );        } else {          o = format(q"¶  <div class="substance"> @@ -555,7 +560,6 @@ template outputXHTMLs() {            obj.is_a,            obj.obj_cite_number,            _txt -          // obj.text          );        }        return o; @@ -589,9 +593,9 @@ template outputXHTMLs() {      ) {        _txt = font_face(_txt);        _txt = (_txt) -        .replaceAll(rgx.newline, "<br>\n") -        .replaceAll(rgx.two_spaces, " " ~ " " ~ " " ~ " ") -        .replaceAll(rgx.nbsp_and_space, " " ~ " ") +        .replaceAll(rgx.newline, "<br />\n") +        .replaceAll(rgx.two_spaces, " " ~ " " ~ " " ~ " ") +        .replaceAll(rgx.nbsp_and_space, " " ~ " ")          .replaceAll(rgx.strip_br, "");        string o;        if (obj.obj_cite_number.empty) { @@ -723,8 +727,8 @@ template outputXHTMLs() {      ) {        string _txt = obj.text;        _txt = (_txt) -        .replaceAll(rgx.newline, "<br>\n") -        .replaceAll(rgx.nbsp_char, " "); +        .replaceAll(rgx.newline, "<br />\n") +        .replaceAll(rgx.nbsp_char, " ");        string o;        if (obj.obj_cite_number.empty) {            o = format(q"¶  <div class="substance"> diff --git a/src/sdp/source_sisupod.d b/src/sdp/source_sisupod.d index e6702bf..cf15348 100644 --- a/src/sdp/source_sisupod.d +++ b/src/sdp/source_sisupod.d @@ -3,103 +3,206 @@ template SiSUpod() {      std.algorithm,      std.array,      std.container, +    std.digest.sha,      std.exception,      std.file,      std.getopt,      std.json, -    std.process, -    std.stdio, +    std.outbuffer,      std.path, +    std.process,      std.range,      std.regex, +    std.stdio,      std.string,      std.traits,      std.typecons,      std.uni,      std.utf, +    std.zip,      std.conv : to;    import +    create_zip_file,      defaults,      output_rgx,      output_xhtmls;    void SiSUpod(T)(T doc_matters) { -    debug(asserts){ +    debug(asserts) {        // static assert(is(typeof(doc_matters) == tuple));      }      mixin SiSUoutputRgxInit;      mixin SiSUpaths; -    auto pth_sisupod = SiSUpodPaths(); +    auto pth_sisupod = SiSUpodPathsZipped(); +    auto pth_sisupod_filesystem = SiSUpodPathsFilesystemArchive();      mixin SiSUlanguageCodes;      auto lang = Lang();      auto rgx = Rgx();      assert (doc_matters.source_filename.match(rgx.src_fn));      try {        /+ create directory structure +/ -      if (!exists(pth_sisupod.doc(doc_matters.source_filename))) { -        pth_sisupod.doc(doc_matters.source_filename).mkdirRecurse; +      if (!exists(pth_sisupod_filesystem.doc(doc_matters.source_filename))) { +        pth_sisupod_filesystem.doc(doc_matters.source_filename).mkdirRecurse;        } -      if (!exists(pth_sisupod.conf(doc_matters.source_filename))) { -        pth_sisupod.conf(doc_matters.source_filename).mkdirRecurse; +      if (!exists(pth_sisupod_filesystem.conf(doc_matters.source_filename))) { +        pth_sisupod_filesystem.conf(doc_matters.source_filename).mkdirRecurse;        } -      if (!exists(pth_sisupod.css(doc_matters.source_filename))) { -        pth_sisupod.css(doc_matters.source_filename).mkdirRecurse; +      if (!exists(pth_sisupod_filesystem.css(doc_matters.source_filename))) { +        pth_sisupod_filesystem.css(doc_matters.source_filename).mkdirRecurse;        } -      if (!exists(pth_sisupod.image(doc_matters.source_filename))) { -        pth_sisupod.image(doc_matters.source_filename).mkdirRecurse; +      if (!exists(pth_sisupod_filesystem.image(doc_matters.source_filename))) { +        pth_sisupod_filesystem.image(doc_matters.source_filename).mkdirRecurse;        } -      if (!exists(pth_sisupod.doc_lng(doc_matters.source_filename, doc_matters.language))) { -        pth_sisupod.doc_lng(doc_matters.source_filename, doc_matters.language).mkdirRecurse; +      if (!exists(pth_sisupod_filesystem.doc_lng(doc_matters.source_filename, doc_matters.language))) { +        pth_sisupod_filesystem.doc_lng(doc_matters.source_filename, doc_matters.language).mkdirRecurse;        }        debug(sisupod) {          writeln(__LINE__, ": ", -          // doc_matters.environment["pwd"], "/", -            doc_matters.source_filename, " -> ", -          // doc_matters.environment["pwd"], "/", -            pth_sisupod.fn_doc( -              doc_matters.source_filename, -              doc_matters.language -        )); -      } -      if (exists(doc_matters.source_filename)) { -        copy( +          doc_matters.source_filename, " -> ", +          pth_sisupod_filesystem.fn_doc(            doc_matters.source_filename, -          pth_sisupod.fn_doc( -            doc_matters.source_filename, -            doc_matters.language +          doc_matters.language          ));        } -      if (doc_matters.file_insert_list.length > 0) { -        foreach (insert_file; doc_matters.file_insert_list) { -          debug(sisupod) { +      auto zip = new ZipArchive(); +      auto fn_sisupod = pth_sisupod.sisupod_filename(doc_matters.source_filename); +      { /+ bundle images +/ +        foreach (image; doc_matters.image_list) { +          debug(sisupodimages) {              writeln( +              "_sisu/image/", image, " -> ", +              pth_sisupod.image(doc_matters.source_filename), "/", image +            ); +          } +          auto fn_src = "_sisu/image/"~ image; +          auto fn_out =  pth_sisupod.image(doc_matters.source_filename).to!string ~ "/" ~ image; +          auto fn_out_filesystem =  pth_sisupod_filesystem.image(doc_matters.source_filename).to!string ~ "/" ~ image; +          if (exists(fn_src)) { +            fn_src.copy(fn_out_filesystem); +            { +              auto zip_arc_member_file = new ArchiveMember(); +              zip_arc_member_file.name = fn_out; +              auto zip_data = new OutBuffer(); +              zip_data.write(cast(char[]) ((fn_src).read)); +              zip_arc_member_file.expandedData = zip_data.toBytes(); +              zip.addMember(zip_arc_member_file); +              createZipFile!()(pth_sisupod.sisupod_filename(fn_src), zip.build()); +            } +          } +        } +      } +      { /+ bundle sisu_document_make +/ +        auto fn_src = "_sisu/sisu_document_make"; // check (_sisu/sisu_document_make) +        auto fn_out = pth_sisupod.conf(doc_matters.source_filename).to!string ~ "/" ~ "sisu_document_make"; +        auto fn_out_filesystem = pth_sisupod_filesystem.conf(doc_matters.source_filename).to!string ~ "/" ~ "sisu_document_make"; +        if (exists(fn_src)) { +          fn_src.copy(fn_out_filesystem); +          { +            auto zip_arc_member_file = new ArchiveMember(); +            zip_arc_member_file.name = fn_out; +            auto zip_data = new OutBuffer(); +            zip_data.write((fn_src).readText); +            zip_arc_member_file.expandedData = zip_data.toBytes(); +            zip.addMember(zip_arc_member_file); +            createZipFile!()(pth_sisupod.sisupod_filename(fn_src), zip.build()); +          } +        } +      } +      { /+ bundle primary file +/ +        auto fn_src = doc_matters.source_filename; +        auto fn_out = pth_sisupod.fn_doc(doc_matters.source_filename, doc_matters.language).to!string; +        auto fn_out_filesystem = pth_sisupod_filesystem.fn_doc(doc_matters.source_filename, doc_matters.language).to!string; +        if (exists(fn_src)) { +          fn_src.copy(fn_out_filesystem); +          { +            auto zip_arc_member_file = new ArchiveMember(); +            zip_arc_member_file.name = fn_out; +            auto zip_data = new OutBuffer(); +            zip_data.write((fn_src).readText); +            zip_arc_member_file.expandedData = zip_data.toBytes(); +            zip.addMember(zip_arc_member_file); +            createZipFile!()(pth_sisupod.sisupod_filename(fn_src), zip.build()); +          } +        } +      } +      { /+ bundle insert files +/ +        if (doc_matters.file_insert_list.length > 0) { +          foreach (insert_file; doc_matters.file_insert_list) { +            debug(sisupod) { +              writeln(                  insert_file, " -> ",                  pth_sisupod.fn_doc_insert(                    doc_matters.source_filename,                    insert_file,                    doc_matters.language -            )); -          } -          if (exists(insert_file)) { -            insert_file.copy( -              pth_sisupod.fn_doc_insert( -                doc_matters.source_filename, -                insert_file, -                doc_matters.language -            )); +              )); +            } +            auto fn_src = insert_file; +            auto fn_out = pth_sisupod.fn_doc_insert( +              doc_matters.source_filename, +              insert_file, +              doc_matters.language +            ).to!string; +            auto fn_out_filesystem = pth_sisupod_filesystem.fn_doc_insert( +              doc_matters.source_filename, +              insert_file, +              doc_matters.language +            ).to!string; +            if (exists(fn_src)) { +              fn_src.copy(fn_out_filesystem); +              { +                auto zip_arc_member_file = new ArchiveMember(); +                zip_arc_member_file.name = insert_file; +                auto zip_data = new OutBuffer(); +                zip_data.write((fn_src).readText); +                zip_arc_member_file.expandedData = zip_data.toBytes(); +                zip.addMember(zip_arc_member_file); +                createZipFile!()(pth_sisupod.sisupod_filename(fn_src), zip.build()); +              } +            }            }          }        } -      foreach (image; doc_matters.image_list) { -        debug(sisupod) { -          writeln( -              "_sisu/image/", image, " -> ", -              pth_sisupod.image(doc_matters.source_filename), "/", image -          ); +      if (exists(fn_sisupod)) { +        try { +          auto data = (cast(byte[]) (fn_sisupod).read); +          writefln("%-(%02x%) %s", data.sha256Of, fn_sisupod); +          debug(sisupod) { +            try { +              auto zipped = new ZipArchive((fn_sisupod).read); +              foreach (filename, member; zipped.directory) { +                auto data = zipped.expand(member); +                writeln("> ", filename, " length ", data.length); // filename == member.name +                // Use data +              } +            } +            catch (ZipException ex) { +              // Handle errors +            } +            if (doc_matters.source_filename == "en/the_wealth_of_networks.yochai_benkler.sst") { +              assert( +                ((data).sha256Of).toHexString +                == "DDE0013C13C6A4F06D4BE72087E2CDEF47697CA38A6A2D65BA7207DB6B144271", +                "\nsisupod: sha256 value for " +                ~ doc_matters.source_filename +                ~ " has changed, is now: " +                ~ ((data).sha256Of).toHexString +              ); +            } +            if (doc_matters.source_filename == "en/sisu_markup_stress_test.sst") { +              assert( +                ((data).sha256Of).toHexString +                == "112C0AEDD2518A1803D91A7CF5785274A3116C0779A631782D0C0813B212C68A", +                "\nsisupod: sha256 value for " +                ~ doc_matters.source_filename +                ~ " has changed, is now: " +                ~ ((data).sha256Of).toHexString +              ); +            } +          }          } -        if (exists("_sisu/image/"~ image)) { -          ("_sisu/image/"~ image).copy( -            (pth_sisupod.image(doc_matters.source_filename) ~ "/" ~ image) -          ); +          catch (ErrnoException ex) +        { +          // Handle errors          }        } diff --git a/views/version.txt b/views/version.txt index 7ae0f62..fe2ce85 100644 --- a/views/version.txt +++ b/views/version.txt @@ -4,4 +4,4 @@ struct Version {    int minor;    int patch;  } -enum ver = Version(0, 13, 8); +enum ver = Version(0, 13, 9); | 
