aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rwxr-xr-x,version5
-rwxr-xr-x[-rw-r--r--].envrc3
-rwxr-xr-x[-rw-r--r--].envrc-git-init1
-rwxr-xr-x[-rw-r--r--].envrc-local_7
-rwxr-xr-x[-rw-r--r--].envrc-nix9
-rw-r--r--.gitignore1
-rw-r--r--README4
-rw-r--r--README.md4
-rw-r--r--data/pod/sisu-spine-markup/media/text/en/sisu-spine-markup.sst2
-rw-r--r--doc/man/man1/spine.111
-rw-r--r--flake.lock6
-rw-r--r--flake.nix48
-rw-r--r--org/config_env.org33
-rw-r--r--org/config_git.org1
-rw-r--r--org/config_nix.org36
-rw-r--r--org/default_paths.org64
-rw-r--r--org/default_regex.org19
-rw-r--r--org/ocda.org12
-rw-r--r--org/ocda_functions.org37
-rw-r--r--org/out_latex.org31
-rw-r--r--org/out_metadata.org5
-rw-r--r--org/out_skel.org324
-rw-r--r--org/out_text.org565
-rw-r--r--org/output_hub.org28
-rw-r--r--org/spine.org34
-rw-r--r--org/spine_info.org4
-rw-r--r--org/spine_markup_sample.org2
-rw-r--r--src/sisudoc/io_out/hub.d14
-rw-r--r--src/sisudoc/io_out/latex.d24
-rw-r--r--src/sisudoc/io_out/metadata.d5
-rw-r--r--src/sisudoc/io_out/paths_output.d51
-rw-r--r--src/sisudoc/io_out/rgx.d8
-rw-r--r--src/sisudoc/io_out/skel.d268
-rw-r--r--src/sisudoc/io_out/text.d470
-rw-r--r--src/sisudoc/meta/metadoc_from_src.d12
-rw-r--r--src/sisudoc/meta/metadoc_from_src_functions.d37
-rw-r--r--src/sisudoc/meta/rgx.d18
-rwxr-xr-xsrc/sisudoc/spine.d34
38 files changed, 2139 insertions, 98 deletions
diff --git a/,version b/,version
new file mode 100755
index 0000000..34c0d8c
--- /dev/null
+++ b/,version
@@ -0,0 +1,5 @@
+#!/usr/bin/env sh
+SpineProjVer=`rg "Version\((\d+), (\d+), (\d+)\)" views/version.txt | sed -E 's/.*([0-9]+), ([0-9]+), ([0-9]+).*/spine-v\1.\2.\3/'` && \
+ SpineGitVer=`git describe | sed "s/^[a-z_-]\+\([0-9.]\+\)/\1/" | sed "s/\([^-]*-g\)/r\1/" | sed "s/-/./g"` && \
+ SpineGitBranch=`git branch --show-current` && \
+ echo "❯❯ $SpineProjVer - ($SpineGitBranch: $SpineGitVer)"
diff --git a/.envrc b/.envrc
index 669d42f..6145dfe 100644..100755
--- a/.envrc
+++ b/.envrc
@@ -1,8 +1,11 @@
+# -*- mode: sh -*-
if [ -f .envrc-git-init ]; then
source_env_if_exists .envrc-git-init || source .envrc-git-init
fi
if [ -f .envrc-local ]; then
source_env_if_exists .envrc-local || source .envrc-local
+elif [ -f .envrc-local_ ]; then
+ source_env_if_exists .envrc-local_ || source .envrc-local_
fi
if [ -f .envrc-nix ]; then
source_env_if_exists .envrc-nix || source .envrc-nix
diff --git a/.envrc-git-init b/.envrc-git-init
index ca74ec3..d78e46b 100644..100755
--- a/.envrc-git-init
+++ b/.envrc-git-init
@@ -1,3 +1,4 @@
+# -*- mode: sh -*-
if [[ ! -d ./.git ]]; then
git init
git add .
diff --git a/.envrc-local_ b/.envrc-local_
index fdb7953..85c5b09 100644..100755
--- a/.envrc-local_
+++ b/.envrc-local_
@@ -1,3 +1,4 @@
+# -*- mode: sh -*-
export SpineVER=$(git describe --long --tags | sed 's/^[ a-z_-]\+\([0-9.]\+\)/\1/;s/\([^-]*-g\)/r\1/;s/-/./g')
export SpineBIN=./result/bin/spine
# ❯❯ nix builds spine binary:
@@ -8,13 +9,17 @@ export SpineBIN=./result/bin/spine
#export SpineBIN=./bin/spine-dmd
# ❯❯ location of source files:
export SpineDOC=../sisudoc-spine-samples
+#export SpineDOC=./sisudoc-spine-samples
# ❯❯ location of source files pod:
-export SpinePOD=${SpineDOC}/markup/pod
+export SpinePOD=${SpineDOC}/markup/pod-samples/pod
# ❯❯ sisudoc-spine output processing path:
export SpineOUT=./OUTPUT_TEST_sisudocSpine
# ❯❯ sisudoc-spine output processing path (web server e.g.):
#export SpineOUT=/srv/www/spine
#export SpineOUTversioned=${SpineOUT}/${SpineVER}
+# ❯❯ www url doc root
+export SpineURLdocRoot='http://localhost'
+# export SpineURLdocRoot='https://sisudoc.org'
# ❯❯ path configured for cgi search form:
export SpineSearchActionLocal='http://localhost/spine_search'
export SpineSearchActionRemote='https://sisudoc.org/spine_search'
diff --git a/.envrc-nix b/.envrc-nix
index 2a3a0f0..443b5ad 100644..100755
--- a/.envrc-nix
+++ b/.envrc-nix
@@ -1,3 +1,4 @@
+# -*- mode: nix -*-
NIX_ENFORCE_PURITY=1
# - https://github.com/nix-community/nix-direnv
NixDirEnvVersion="3.0.7"
@@ -26,7 +27,7 @@ echo '
• nix develop using nixpkgs
❯❯ nix develop ".#dsh-nixpkgs-dmd" --print-build-logs -c zsh
❯❯ nix develop ".#dsh-nixpkgs-ldc" --print-build-logs -c zsh
- • nix develop using package overlays: (dmd-2.111.0, ldc-1.41.0, dub-1.39.0, dtools-2.110.0)
+ • nix develop using package overlays: (dmd-2.111.0, ldc-1.41.0, dub-1.40.0, dtools-2.110.0)
❯❯ nix develop ".#dsh-overlay-dmd" --print-build-logs -c zsh
❯❯ nix develop ".#dsh-overlay-ldc" --print-build-logs -c zsh
❯❯ nix flake show
@@ -40,7 +41,7 @@ echo '
• nix build using nixpkgs
❯❯ nix build ".#spine-nixpkgs-dmd" --print-build-logs
❯❯ nix build ".#spine-nixpkgs-ldc" --print-build-logs
- • nix build using package overlays: (dmd-2.111.0, ldc-1.41.0, dub-1.39.0, dtools-2.110.0)
+ • nix build using package overlays: (dmd-2.111.0, ldc-1.41.0, dub-1.40.0, dtools-2.110.0)
❯❯ nix build ".#spine-overlay-dmd" --print-build-logs
❯❯ nix build ".#spine-overlay-ldc" --print-build-logs
@@ -65,7 +66,9 @@ echo '
❯❯ ${SpineBIN} -v --source --pod --latex --latex-init --epub --html --html-link-pdf --html-link-curate --html-link-markup --curate --output=${SpineOUT} ${SpinePOD}/*
❯❯ ${SpineBIN} -v --sqlite-db-create --sqlite-db-filename=${SpineSQLdb} --sqlite-db-path=./_tmp-db
- ❯❯ ${SpineBIN} -v --sqlite-update --sqlite-db-filename=${SpineSQLdb} --sqlite-db-path=./_tmp-db ./markup/pod/*
+ ❯❯ ${SpineBIN} -v --sqlite-update --sqlite-db-filename=${SpineSQLdb} --sqlite-db-path=./_tmp-db ${SpinePOD}/*
+
+ ❯❯ ${SpineBIN} --source --pod --curate --text --latex --epub --html --manifest --html-link-search --html-link-pdf --html-link-text --html-link-curate --html-link-markup --html-link-source --html-link-pod --html-link-metadata --cgi-sqlite-search-filename="${SpineCGIform}" --cgi-url-action="${SpineSearchActionRemote}" --sqlite-db-path="${SpineDBpath}" --sqlite-db-filename="${SpineSQLdb}" --www-url-doc-root=${SpineURLdocRoot} --set-papersize="a4,letter" --output=${SpineOUT} ${SpinePOD}/*
'
echo "•
❯❯ ${SpineBIN} -v --source --pod --epub --html --html-link-curate --html-link-markup --curate --output=${SpineOUT} ${SpinePOD}/*
diff --git a/.gitignore b/.gitignore
index f9e14ab..857c640 100644
--- a/.gitignore
+++ b/.gitignore
@@ -21,6 +21,7 @@
!CHANGELOG
!makefile
!version.txt
+!,version
!configuration.txt
!*.json
!*.sdl
diff --git a/README b/README
index 9d739c6..a912344 100644
--- a/README
+++ b/README
@@ -260,6 +260,8 @@ for a document collection you can point to the document collection:
*** generate a cgi search form
+The CGI search form is built separately in the sisudoc-spine-search-cgi/ directory.
+
Steps:
1. Clone the sisudoc-spine-search-cgi repository
2. Configure views/configuration.txt with your web server settings
@@ -304,7 +306,7 @@ spine -v \
--output=/var/www/html \
~spineMarkupSamples/pod/*
-Note: The CGI search form is built separately in sisudoc-spine-search-cgi/
+Note: The CGI search form is built separately in the sisudoc-spine-search-cgi/ directory.
*** html with links to search form
diff --git a/README.md b/README.md
index 1615569..e95eef7 100644
--- a/README.md
+++ b/README.md
@@ -243,6 +243,8 @@ for a document collection you can point to the document collection:
### generate a cgi search form in d
+The CGI search form is built separately in the sisudoc-spine-search-cgi/ directory.
+
Steps:
1. Clone the sisudoc-spine-search-cgi repository
2. Configure views/configuration.txt with your web server settings
@@ -287,7 +289,7 @@ spine -v \
--output=/var/www/html \
~spineMarkupSamples/pod/*
-Note: The CGI search form is built separately in sisudoc-spine-search-cgi/
+Note: The CGI search form is built separately in the sisudoc-spine-search-cgi/ directory.
### html with links to search form
diff --git a/data/pod/sisu-spine-markup/media/text/en/sisu-spine-markup.sst b/data/pod/sisu-spine-markup/media/text/en/sisu-spine-markup.sst
index 6ae09d1..a2339b9 100644
--- a/data/pod/sisu-spine-markup/media/text/en/sisu-spine-markup.sst
+++ b/data/pod/sisu-spine-markup/media/text/en/sisu-spine-markup.sst
@@ -1153,7 +1153,7 @@ code(number){
3~ Tables
={ SiSU markup:tables;tables }
-Tables may be prepared in two either of two forms
+Tables may be prepared in either of two forms
!_ resulting output:
diff --git a/doc/man/man1/spine.1 b/doc/man/man1/spine.1
index 93443ae..7281f30 100644
--- a/doc/man/man1/spine.1
+++ b/doc/man/man1/spine.1
@@ -122,11 +122,6 @@ ascribed to --act0 to --act9
.B --asciidoc [path + filename]
asciidoc, smart text (not available)
.TP
-.B --cgi-search-form-codegen
- generate d code search form to search db specfied needs --output=[path] and
---sqlite-db-filename=[cgi search form name] or path to configuration file
---config=[full path to config file]
-.TP
.B --cgi-sqlite-search-filename=[filename]
name to give cgi-search form, (it generates a [filename].d file that requires
subsequent compilation) also required is the name of the sqlite db to be
@@ -568,11 +563,9 @@ spine -v --show-config --config= ~spineMarkupSamples/pod/.dr/config_local_site_t
.TP
spine -v --show-config --config=~spineMarkupSamples/pod/.dr
.TP
-spine -v --cgi-search-form-codegen --config=~spineMarkupSamples/pod/.dr/config_local
-.TP
-cd ~webDocRoot/cgi
+Note: The CGI search form is now built separately in the sisudoc-spine-search-cgi/ directory.
.TP
-dub --force --compiler=ldc2 && sudo cp -v cgi-bin/spine-search /usr/lib/cgi-bin/.
+See sisudoc-spine-search-cgi/README.md for build instructions.
.TP
.BR
diff --git a/flake.lock b/flake.lock
index 2fae547..9ea4a94 100644
--- a/flake.lock
+++ b/flake.lock
@@ -2,11 +2,11 @@
"nodes": {
"nixpkgs": {
"locked": {
- "lastModified": 1757746433,
- "narHash": "sha256-fEvTiU4s9lWgW7mYEU/1QUPirgkn+odUBTaindgiziY=",
+ "lastModified": 1761880412,
+ "narHash": "sha256-QoJjGd4NstnyOG4mm4KXF+weBzA2AH/7gn1Pmpfcb0A=",
"owner": "NixOS",
"repo": "nixpkgs",
- "rev": "6d7ec06d6868ac6d94c371458fc2391ded9ff13d",
+ "rev": "a7fc11be66bdfb5cdde611ee5ce381c183da8386",
"type": "github"
},
"original": {
diff --git a/flake.nix b/flake.nix
index 4209504..d4e823d 100644
--- a/flake.nix
+++ b/flake.nix
@@ -23,7 +23,7 @@
localOverlay = (final: prev: {
ldc = prev.callPackage ./nix-overlays/ldc { }; # -> ok 1.41.0
dmd = prev.callPackage ./nix-overlays/dmd { }; # -> ok 2.111.0
- dub = prev.callPackage ./nix-overlays/dub { }; # -> ? 1.39.0
+ dub = prev.callPackage ./nix-overlays/dub { }; # -> ? 1.40.0
dtools = prev.callPackage ./nix-overlays/dtools { }; # -> ok 2.110.0
#gdc = prev.callPackage ./nix-overlays/gdc { };
});
@@ -34,7 +34,8 @@
inherit system;
};
preBuild = ''
- export HOME=$(pwd)
+ export HOME=$TMPDIR
+ #export HOME=$(pwd)
'';
installPhase = ''
runHook preInstall
@@ -43,7 +44,9 @@
runHook postInstall
'';
postInstall = ''
+ echo "❯❯ ./result/bin/spine -v --source --pod --text --epub --html --html-link-pdf --html-link-curate --html-link-markup --curate --output=./OUTPUT_TEST_sisudocSpine ../sisu-spine-samples/markup/pod/*";
echo `ls -la $out/bin/spine`
+ echo "❯❯ spine-v${version} (rev: ${self.shortRev or "unknown"})"
$out/bin/spine -v
'';
in {
@@ -131,7 +134,7 @@
spine-overlay-dmd = stdenv.mkDerivation {
inherit pname;
inherit version;
- #name = "spine-0.18.0 dmd-2.111.0 dub-1.39.0";
+ #name = "spine-0.18.0 dmd-2.111.0 dub-1.40.0";
meta.mainProgram = "spine-dmd";
executable = true;
src = self;
@@ -155,7 +158,7 @@
spine-overlay-ldc = stdenv.mkDerivation {
inherit pname;
inherit version;
- #name = "spine-0.18.0 ldc-1.41.0 dub-1.39.0";
+ #name = "spine-0.18.0 ldc-1.41.0 dub-1.40.0";
meta.mainProgram = "spine-ldc";
executable = true;
src = self;
@@ -208,14 +211,23 @@
pkgs-ovl = pkgsForSystem system;
pkgs-nix = nixpkgsFor.${system};
shellHook = ''
- export Date=`date "+%Y%m%d"`
+ #export Date=`date "+%Y%m%d"`
## set local values in .envrc-local (or here if you must)
- echo " ❯❯ ./result/bin/spine -v --source --pod --epub --html --html-link-pdf --html-link-curate --html-link-markup --curate --output=./OUTPUT_TEST_sisudocSpine ../sisu-spine-samples/markup/pod/*";
+ echo '❯❯ nix build';
+ ## ImPure Nix environment
+ SpineGitVer=`git describe | sed "s/^[a-z_-]\+\([0-9.]\+\)/\1/" | sed "s/\([^-]*-g\)/r\1/" | sed "s/-/./g"` && \
+ SpineGitBranch=`git branch --show-current` && \
+ echo "❯❯ spine-v${version} - ($SpineGitBranch: $SpineGitVer)"
+ ## Pure Nix environment - version info from flake inputs
+ #echo "❯❯ spine-v${version} (rev: ${self.shortRev or "unknown"})"
+ echo '❯❯ $SpineBIN -v --source --pod --text --epub --html --html-link-pdf --html-link-curate --html-link-markup --curate --output=$SpineOUT $SpinePOD/*';
+ echo "❯❯ $SpineBIN -v --source --pod --text --epub --html --html-link-pdf --html-link-curate --html-link-markup --curate --output=$SpineOUT $SpinePOD/*";
+ echo '❯❯ nix flake update && nix flake check && nix flake show';
'';
in
with pkgs-nix; {
dsh-overlay = mkShell {
- name = "spine-0.18.0 base dev shell, ldc-1.41.0, dub-1.39.0 - dtools-2.110.0";
+ name = "spine-0.18.0 base dev shell, ldc-1.41.0, dub-1.40.0 - dtools-2.110.0";
inherit shell;
inherit devEnv;
packages = with pkgs-ovl; [
@@ -225,6 +237,8 @@
dtools
gnumake
sqlite
+ gnugrep gnused
+ ripgrep
];
inherit shellHook;
};
@@ -238,6 +252,8 @@
dtools
gnumake
sqlite
+ gnugrep gnused
+ ripgrep
];
inherit shellHook;
};
@@ -251,11 +267,13 @@
dtools
gnumake
sqlite
+ gnugrep gnused
+ ripgrep
];
inherit shellHook;
};
dsh-overlay-dmd = mkShell {
- name = "spine-0.18.0 base dev shell, dmd-2.111.0, dub-1.39.0 - dtools-2.110.0";
+ name = "spine-0.18.0 base dev shell, dmd-2.111.0, dub-1.40.0 - dtools-2.110.0";
inherit shell;
inherit devEnv;
packages = with pkgs-ovl; [
@@ -264,11 +282,13 @@
dtools
gnumake
sqlite
+ gnugrep gnused
+ ripgrep
];
inherit shellHook;
};
dsh-overlay-ldc = mkShell {
- name = "spine-0.18.0 base dev shell, ldc-1.41.0, dub-1.39.0 - dtools-2.110.0";
+ name = "spine-0.18.0 base dev shell, ldc-1.41.0, dub-1.40.0 - dtools-2.110.0";
inherit shell;
inherit devEnv;
packages = with pkgs-ovl; [
@@ -306,6 +326,8 @@
calibre #(suite includes: ebook-viewer)
koreader
foliate
+ gnugrep gnused
+ ripgrep
];
inherit shellHook;
};
@@ -327,6 +349,8 @@
w3m
# ❯❯ light graphical
#dillo
+ gnugrep gnused
+ ripgrep
];
inherit shellHook;
};
@@ -344,6 +368,8 @@
source-serif-pro
source-code-pro
texlive.combined.scheme-full
+ gnugrep gnused
+ ripgrep
];
inherit shellHook;
};
@@ -358,6 +384,8 @@
dtools
gnumake
sqlite
+ gnugrep gnused
+ ripgrep
];
inherit shellHook;
};
@@ -373,6 +401,8 @@
gnumake
sqlite
perl538Packages.Po4a
+ gnugrep gnused
+ ripgrep
];
inherit shellHook;
};
diff --git a/org/config_env.org b/org/config_env.org
index 2a2dac1..2fa1f25 100644
--- a/org/config_env.org
+++ b/org/config_env.org
@@ -33,12 +33,15 @@ fi
#+NAME: envrc
#+HEADER: :tangle ../.envrc
+#+HEADER: :shebang "# -*- mode: sh -*-"
#+BEGIN_SRC shell
if [ -f .envrc-git-init ]; then
source_env_if_exists .envrc-git-init || source .envrc-git-init
fi
if [ -f .envrc-local ]; then
source_env_if_exists .envrc-local || source .envrc-local
+elif [ -f .envrc-local_ ]; then
+ source_env_if_exists .envrc-local_ || source .envrc-local_
fi
if [ -f .envrc-nix ]; then
source_env_if_exists .envrc-nix || source .envrc-nix
@@ -53,6 +56,7 @@ fi
- ${NixDirEnvVersion}
#+HEADER: :tangle ../.envrc-nix
+#+HEADER: :shebang "# -*- mode: nix -*-"
#+BEGIN_SRC shell
NIX_ENFORCE_PURITY=1
# - https://github.com/nix-community/nix-direnv
@@ -121,7 +125,9 @@ echo '
❯❯ ${SpineBIN} -v --source --pod --latex --latex-init --epub --html --html-link-pdf --html-link-curate --html-link-markup --curate --output=${SpineOUT} ${SpinePOD}/*
❯❯ ${SpineBIN} -v --sqlite-db-create --sqlite-db-filename=${SpineSQLdb} --sqlite-db-path=./_tmp-db
- ❯❯ ${SpineBIN} -v --sqlite-update --sqlite-db-filename=${SpineSQLdb} --sqlite-db-path=./_tmp-db ./markup/pod/*
+ ❯❯ ${SpineBIN} -v --sqlite-update --sqlite-db-filename=${SpineSQLdb} --sqlite-db-path=./_tmp-db ${SpinePOD}/*
+
+ ❯❯ ${SpineBIN} --source --pod --curate --text --latex --epub --html --manifest --html-link-search --html-link-pdf --html-link-text --html-link-curate --html-link-markup --html-link-source --html-link-pod --html-link-metadata --cgi-sqlite-search-filename="${SpineCGIform}" --cgi-url-action="${SpineSearchActionRemote}" --sqlite-db-path="${SpineDBpath}" --sqlite-db-filename="${SpineSQLdb}" --www-url-doc-root=${SpineURLdocRoot} --set-papersize="a4,letter" --output=${SpineOUT} ${SpinePOD}/*
'
echo "•
❯❯ ${SpineBIN} -v --source --pod --epub --html --html-link-curate --html-link-markup --curate --output=${SpineOUT} ${SpinePOD}/*
@@ -132,6 +138,7 @@ echo "•
** .envrc-git-init
#+HEADER: :tangle ../.envrc-git-init
+#+HEADER: :shebang "# -*- mode: sh -*-"
#+HEADER: :noweb yes
#+BEGIN_SRC shell
if [[ ! -d ./.git ]]; then
@@ -140,11 +147,25 @@ if [[ ! -d ./.git ]]; then
fi
#+END_SRC
+** ,version (project & git version info)
+
+#+HEADER: :tangle ../,version
+#+HEADER: :noweb yes
+#+HEADER: :tangle-mode (identity #o755)
+#+HEADER: :shebang #!/usr/bin/env sh
+#+BEGIN_SRC shell
+SpineProjVer=`rg "Version\((\d+), (\d+), (\d+)\)" views/version.txt | sed -E 's/.*([0-9]+), ([0-9]+), ([0-9]+).*/spine-v\1.\2.\3/'` && \
+ SpineGitVer=`git describe | sed "s/^[a-z_-]\+\([0-9.]\+\)/\1/" | sed "s/\([^-]*-g\)/r\1/" | sed "s/-/./g"` && \
+ SpineGitBranch=`git branch --show-current` && \
+ echo "❯❯ $SpineProjVer - ($SpineGitBranch: $SpineGitVer)"
+#+END_SRC
+
** .envrc-local CHECK MODIFY
- bespoke modify appropriately and generate if needed
#+HEADER: :tangle ../.envrc-local_
+#+HEADER: :shebang "# -*- mode: sh -*-"
#+HEADER: :noweb yes
#+BEGIN_SRC shell
export SpineVER=$(git describe --long --tags | sed 's/^[ a-z_-]\+\([0-9.]\+\)/\1/;s/\([^-]*-g\)/r\1/;s/-/./g')
@@ -157,13 +178,17 @@ export SpineBIN=./result/bin/spine
#export SpineBIN=./bin/spine-dmd
# ❯❯ location of source files:
export SpineDOC=../sisudoc-spine-samples
+#export SpineDOC=./sisudoc-spine-samples
# ❯❯ location of source files pod:
-export SpinePOD=${SpineDOC}/markup/pod
+export SpinePOD=${SpineDOC}/markup/pod-samples/pod
# ❯❯ sisudoc-spine output processing path:
export SpineOUT=./OUTPUT_TEST_sisudocSpine
# ❯❯ sisudoc-spine output processing path (web server e.g.):
#export SpineOUT=/srv/www/spine
#export SpineOUTversioned=${SpineOUT}/${SpineVER}
+# ❯❯ www url doc root
+export SpineURLdocRoot='http://localhost'
+# export SpineURLdocRoot='https://sisudoc.org'
# ❯❯ path configured for cgi search form:
export SpineSearchActionLocal='http://localhost/spine_search'
export SpineSearchActionRemote='https://sisudoc.org/spine_search'
@@ -178,7 +203,7 @@ export SpineDBpath=/var/www/sqlite
#export SpineDBpath=/srv/www/spine/sqlite
#+END_SRC
-* versions GET
+* org includes - versions GET
** direnv
#+NAME: direnv_version
@@ -234,8 +259,6 @@ export SpineDBpath=/var/www/sqlite
<<./sisudoc_spine_version_info_and_doc_header_including_copyright_and_license.org:spine_project_version()>>
#+END_SRC
-** year
-
#+NAME: year
#+HEADER: :noweb yes
#+BEGIN_SRC emacs-lisp
diff --git a/org/config_git.org b/org/config_git.org
index fd0f037..771f7bc 100644
--- a/org/config_git.org
+++ b/org/config_git.org
@@ -45,6 +45,7 @@
!CHANGELOG
!makefile
!version.txt
+!,version
!configuration.txt
!*.json
!*.sdl
diff --git a/org/config_nix.org b/org/config_nix.org
index 9454cb3..167a406 100644
--- a/org/config_nix.org
+++ b/org/config_nix.org
@@ -57,7 +57,8 @@
inherit system;
};
preBuild = ''
- export HOME=$(pwd)
+ export HOME=$TMPDIR
+ #export HOME=$(pwd)
'';
installPhase = ''
runHook preInstall
@@ -66,7 +67,9 @@
runHook postInstall
'';
postInstall = ''
+ echo "❯❯ ./result/bin/spine -v --source --pod --text --epub --html --html-link-pdf --html-link-curate --html-link-markup --curate --output=./OUTPUT_TEST_sisudocSpine ../sisu-spine-samples/markup/pod/*";
echo `ls -la $out/bin/spine`
+ echo "❯❯ spine-v${version} (rev: ${self.shortRev or "unknown"})"
$out/bin/spine -v
'';
in {
@@ -231,9 +234,18 @@
pkgs-ovl = pkgsForSystem system;
pkgs-nix = nixpkgsFor.${system};
shellHook = ''
- export Date=`date "+%Y%m%d"`
+ #export Date=`date "+%Y%m%d"`
## set local values in .envrc-local (or here if you must)
- echo " ❯❯ ./result/bin/spine -v --source --pod --epub --html --html-link-pdf --html-link-curate --html-link-markup --curate --output=./OUTPUT_TEST_sisudocSpine ../sisu-spine-samples/markup/pod/*";
+ echo '❯❯ nix build';
+ ## ImPure Nix environment
+ SpineGitVer=`git describe | sed "s/^[a-z_-]\+\([0-9.]\+\)/\1/" | sed "s/\([^-]*-g\)/r\1/" | sed "s/-/./g"` && \
+ SpineGitBranch=`git branch --show-current` && \
+ echo "❯❯ spine-v${version} - ($SpineGitBranch: $SpineGitVer)"
+ ## Pure Nix environment - version info from flake inputs
+ #echo "❯❯ spine-v${version} (rev: ${self.shortRev or "unknown"})"
+ echo '❯❯ $SpineBIN -v --source --pod --text --epub --html --html-link-pdf --html-link-curate --html-link-markup --curate --output=$SpineOUT $SpinePOD/*';
+ echo "❯❯ $SpineBIN -v --source --pod --text --epub --html --html-link-pdf --html-link-curate --html-link-markup --curate --output=$SpineOUT $SpinePOD/*";
+ echo '❯❯ nix flake update && nix flake check && nix flake show';
'';
in
with pkgs-nix; {
@@ -248,6 +260,8 @@
dtools
gnumake
sqlite
+ gnugrep gnused
+ ripgrep
];
inherit shellHook;
};
@@ -261,6 +275,8 @@
dtools
gnumake
sqlite
+ gnugrep gnused
+ ripgrep
];
inherit shellHook;
};
@@ -274,6 +290,8 @@
dtools
gnumake
sqlite
+ gnugrep gnused
+ ripgrep
];
inherit shellHook;
};
@@ -287,6 +305,8 @@
dtools
gnumake
sqlite
+ gnugrep gnused
+ ripgrep
];
inherit shellHook;
};
@@ -329,6 +349,8 @@
calibre #(suite includes: ebook-viewer)
koreader
foliate
+ gnugrep gnused
+ ripgrep
];
inherit shellHook;
};
@@ -350,6 +372,8 @@
w3m
# ❯❯ light graphical
#dillo
+ gnugrep gnused
+ ripgrep
];
inherit shellHook;
};
@@ -367,6 +391,8 @@
source-serif-pro
source-code-pro
texlive.combined.scheme-full
+ gnugrep gnused
+ ripgrep
];
inherit shellHook;
};
@@ -381,6 +407,8 @@
dtools
gnumake
sqlite
+ gnugrep gnused
+ ripgrep
];
inherit shellHook;
};
@@ -396,6 +424,8 @@
gnumake
sqlite
perl538Packages.Po4a
+ gnugrep gnused
+ ripgrep
];
inherit shellHook;
};
diff --git a/org/default_paths.org b/org/default_paths.org
index 2aaab14..f73a9ef 100644
--- a/org/default_paths.org
+++ b/org/default_paths.org
@@ -993,6 +993,8 @@ import sisudoc.meta.rgx_files;
<<template_paths_sqlite_0>>
<<template_paths_sqlite_1>>
<<template_paths_sqlite_2>>
+<<template_paths_text>>
+<<template_paths_skel>>
#+END_SRC
** shared out path, base directory :out:
@@ -1457,7 +1459,7 @@ template spinePathsODT() {
auto spinePathsODT(M)(
M doc_matters,
) {
- auto out_pth = spineOutPaths!()( doc_matters.output_path, doc_matters.src.language);
+ auto out_pth = spineOutPaths!()(doc_matters.output_path, doc_matters.src.language);
string base_dir = "odf";
struct _PathsStruct {
string base_pth() { // dir will contain odt document file (also debug file tree)
@@ -1688,6 +1690,66 @@ template spinePathsSQLite() {
}
#+END_SRC
+** _text_ :text:
+
+#+NAME: template_paths_text
+#+BEGIN_SRC d
+template spinePathsText() {
+ import std.conv;
+ auto spinePathsText(M)(
+ M doc_matters,
+ ) {
+ auto out_pth = spineOutPaths!()(doc_matters.output_path, doc_matters.src.language);
+ string base_dir = "text";
+ struct _PathsStruct {
+ string base_pth() {
+ return (((out_pth.output_base).chainPath(base_dir)).asNormalizedPath).array;
+ }
+ string base_filename(string fn_src) {
+ return fn_src.baseName.stripExtension;
+ }
+ string text_file() {
+ return ((base_pth.chainPath(doc_matters.src.doc_uid_out ~ ".txt")).asNormalizedPath).array;
+ }
+ string dirtop() {
+ return "".chainPath("").array;
+ }
+ }
+ return _PathsStruct();
+ }
+}
+#+END_SRC
+
+** _skel_ :skel:
+
+#+NAME: template_paths_skel
+#+BEGIN_SRC d
+template spinePathsSkel() {
+ import std.conv;
+ auto spinePathsSkel(M)(
+ M doc_matters,
+ ) {
+ auto out_pth = spineOutPaths!()(doc_matters.output_path, doc_matters.src.language);
+ string base_dir = "skel";
+ struct _PathsStruct {
+ string base_pth() {
+ return (((out_pth.output_base).chainPath(base_dir)).asNormalizedPath).array;
+ }
+ string base_filename(string fn_src) {
+ return fn_src.baseName.stripExtension;
+ }
+ string skel_file() {
+ return ((base_pth.chainPath(doc_matters.src.doc_uid_out ~ ".skel")).asNormalizedPath).array;
+ }
+ string dirtop() {
+ return "".chainPath("").array;
+ }
+ }
+ return _PathsStruct();
+ }
+}
+#+END_SRC
+
* org includes
** project version
diff --git a/org/default_regex.org b/org/default_regex.org
index 9a0ded7..1c0ca2f 100644
--- a/org/default_regex.org
+++ b/org/default_regex.org
@@ -308,9 +308,9 @@ static table_col_separator_nl = ctRegex!(`[┊]$`, "mg");
#+BEGIN_SRC d
/+ inline markup footnotes endnotes +/
static inline_notes_curly_gen = ctRegex!(`~\{.+?\}~`, "m");
-static inline_notes_curly = ctRegex!(`~\{\s*(.+?)\}~`, "mg");
-static inline_notes_curly_sp_asterisk = ctRegex!(`~\{[*]+\s+(.+?)\}~`, "m");
-static inline_notes_curly_sp_plus = ctRegex!(`~\{[+]+\s+(.+?)\}~`, "m");
+static inline_notes_curly = ctRegex!(`~\{\s*(.+?)\s*\}~`, "mg");
+static inline_notes_curly_sp_asterisk = ctRegex!(`~\{[*]+\s+(.+?)\s*\}~`, "m");
+static inline_notes_curly_sp_plus = ctRegex!(`~\{[+]+\s+(.+?)\s*\}~`, "m");
static note_ref = ctRegex!(`^\S+?noteref_(?P<ref>[0-9]+)`, "mg"); // {^{73.}^}#noteref_73
#+END_SRC
@@ -331,8 +331,8 @@ static smid_inline_url_generic = ctRegex!(`(?:^|[}(\[ ])(
static smid_inline_url = ctRegex!(`((?:(?:https?|git):\/\/|¤?\.\.\/|¤?\.\/|¤|#)[a-zA-Z0-9_]\S*)`, "mg");
static smid_inline_link_naked_url = ctRegex!(`(?P<pre>^|[ (\[])(?P<link>(?:(?:https?|git):\/\/|¤?\.\.\/|¤?\.\/|¤)\S+?)(?=[.,;:?!'"]?([ )\]]|$))`, "mg");
static smid_inline_link_markup_regular = ctRegex!(`(?P<pre>^|[ (\[])\{\s*(?P<content>.+?)\s*\}(?P<link>(?:(?:https?|git):\/\/|¤?\.\.\/|¤?\.\/|¤|#)\S+?)(?=[;:!,?.]?([ )\]]|$))`, "mg");
-static smid_inline_link_endnote_url_helper_punctuated = ctRegex!(`\{~\^\s+(?P<content>.+?)\}(?P<link>(?:(?:https?|git):\/\/|¤?\.\.\/|¤?\.\/|¤|#)\S+?)(?=[.,;:?!]?([ ]|$))`, "mg");
-static smid_inline_link_endnote_url_helper = ctRegex!(`\{~\^\s+(?P<content>.+?)\}(?P<link>(?:(?:https?|git):\/\/|¤?\.\.\/|¤?\.\/|¤|#)\S+)`, "mg");
+static smid_inline_link_endnote_url_helper_punctuated = ctRegex!(`\{~\^\s+(?P<content>.+?)\s*\}(?P<link>(?:(?:https?|git):\/\/|¤?\.\.\/|¤?\.\/|¤|#)\S+?)(?=[.,;:?!]?([ ]|$))`, "mg");
+static smid_inline_link_endnote_url_helper = ctRegex!(`\{~\^\s+(?P<content>.+?)\s*\}(?P<link>(?:(?:https?|git):\/\/|¤?\.\.\/|¤?\.\/|¤|#)\S+)`, "mg");
#+END_SRC
#+BEGIN_SRC d
@@ -507,7 +507,6 @@ static make_breakcolumn = ctRegex!(`break=(?P<breakcolum
#+END_SRC
* 2. ctRegex defaults shared by meta & output (generic)
-
** meta
#+NAME: prgmkup_rgx_meta
@@ -545,9 +544,9 @@ static middle_dot = ctRegex!(`·`, "mg");
static br_empty_line = ctRegex!(`\n[ ]*\n`, "mg");
static br_linebreaks_newlines = ctRegex!(`[\n┘┙]`, "mg");
static br_linebreaks = ctRegex!(`[┘┙]`, "mg");
-static br_line = ctRegex!(`┘`, "mg");
-static br_line_inline = ctRegex!(`┙`, "mg");
-static br_line_spaced = ctRegex!(`┚`, "mg");
+static br_line = ctRegex!(`\s*┘\s*`, "mg");
+static br_line_inline = ctRegex!(`\s*┙\s*`, "mg");
+static br_line_spaced = ctRegex!(`\s*┚\s*`, "mg");
#+END_SRC
#+BEGIN_SRC d
@@ -609,6 +608,7 @@ static inline_al_delimiter_open_regular = ctRegex!(`【\s`, "m");
static inline_al_delimiter_open_symbol_star = ctRegex!(`【[*]\s`, "m");
static inline_al_delimiter_open_symbol_plus = ctRegex!(`【[+]\s`, "m");
static inline_text_and_note_al_ = ctRegex!(`(.+?(?:【[*+]*\s+.+?】|.+))`, "mg");
+static endnote_section_note = ctRegex!(`┥\s*⑆\^┨(?P<notenumber>\d+)\.┣\^┝┤(?P<link>¤?.+?)├.+`, "mg");
#+END_SRC
#+BEGIN_SRC d
@@ -634,6 +634,7 @@ static inline_link_hash = ctRegex!(`┥(?P<text>.+?)┝
static inline_link_seg_and_hash = ctRegex!(`┥(?P<text>.+?)┝┤(?P<link>(?P<seg>[^/#├]*)#(?P<hash>.+?))├`, "mg");
static inline_link_clean = ctRegex!(`┤(?:.+?)├|[┥┝]`, "mg");
static inline_link_toc_to_backmatter = ctRegex!(`┤#(?P<link>endnotes|bibliography|bookindex|glossary|blurb)├`, "mg");
+static find_bookindex_ocn_link_and_comma = ctRegex!(`[, ]*┥.+?┝┤#?\S+?├`, "mg");
static url = ctRegex!(`https?://`, "mg");
static uri = ctRegex!(`(?:https?|git)://`, "mg");
static uri_identify_components = ctRegex!(`(?P<type>(?:https?|git)://)(?P<path>\S+?/)(?P<file>[^/]+)$`, "mg");
diff --git a/org/ocda.org b/org/ocda.org
index d03d1cc..ee24570 100644
--- a/org/ocda.org
+++ b/org/ocda.org
@@ -796,7 +796,7 @@ _loopMarkupSrcByLineStruct loopMarkupSrcByLine(
comp_obj_.has.inline_links = substantive_obj_misc_struct.has_links;
comp_obj_.has.image_without_dimensions = substantive_obj_misc_struct.has_images_without_dimensions;
the_document_body_section ~= comp_obj_;
- tag_assoc = an_object.inline_para_link_anchor(tag_in_seg, tag_assoc);
+ tag_assoc = an_object.inline_para_link_anchor(tag_in_seg, tag_assoc);
{
ST_txt_by_line_common_reset _get = txt_by_line_common_reset_(line_occur, an_object, pith);
{
@@ -972,7 +972,7 @@ ST_endnotes en_st = note_section.backmatter_endnote_objects(obj_cite_digits, opt
}
{ // document segnames
ST_segnames get_segnames;
- get_segnames = the_document_body_section.after_doc_determine_segnames(the_document_endnotes_section, the_document_glossary_section, the_document_bibliography_section, the_document_bookindex_section, the_document_blurb_section, segnames, html_segnames_ptr_cntr, html_segnames_ptr); //
+ get_segnames = the_document_body_section.after_doc_determine_segnames(the_document_endnotes_section, the_document_glossary_section, the_document_bibliography_section, the_document_bookindex_section, the_document_blurb_section, segnames, html_segnames_ptr_cntr, html_segnames_ptr);
segnames = get_segnames.segnames;
html_segnames_ptr_cntr = get_segnames.html_segnames_ptr_cntr;
html_segnames_ptr = get_segnames.html_segnames_ptr;
@@ -1409,36 +1409,42 @@ string[][string] document_section_keys_sequenced = [
"scroll": ["head", "toc", "body",],
"seg": ["head", "toc", "body",],
"sql": ["head", "body",],
- "latex": ["head", "toc", "body",]
+ "latex": ["head", "toc", "body",],
+ "text": ["head", "toc", "body",],
];
if (document_the["endnotes"].length > 1) {
document_section_keys_sequenced["scroll"] ~= "endnotes";
document_section_keys_sequenced["seg"] ~= "endnotes";
document_section_keys_sequenced["latex"] ~= "endnotes";
+ document_section_keys_sequenced["text"] ~= "endnotes";
}
if (document_the["glossary"].length > 1) {
document_section_keys_sequenced["scroll"] ~= "glossary";
document_section_keys_sequenced["seg"] ~= "glossary";
document_section_keys_sequenced["sql"] ~= "glossary";
document_section_keys_sequenced["latex"] ~= "glossary";
+ document_section_keys_sequenced["text"] ~= "glossary";
}
if (document_the["bibliography"].length > 1) {
document_section_keys_sequenced["scroll"] ~= "bibliography";
document_section_keys_sequenced["seg"] ~= "bibliography";
document_section_keys_sequenced["sql"] ~= "bibliography";
document_section_keys_sequenced["latex"] ~= "bibliography";
+ document_section_keys_sequenced["text"] ~= "bibliography";
}
if (document_the["bookindex"].length > 1) {
document_section_keys_sequenced["scroll"] ~= "bookindex";
document_section_keys_sequenced["seg"] ~= "bookindex";
document_section_keys_sequenced["sql"] ~= "bookindex";
document_section_keys_sequenced["latex"] ~= "bookindex";
+ document_section_keys_sequenced["text"] ~= "bookindex";
}
if (document_the["blurb"].length > 1) {
document_section_keys_sequenced["scroll"] ~= "blurb";
document_section_keys_sequenced["seg"] ~= "blurb";
document_section_keys_sequenced["sql"] ~= "blurb";
document_section_keys_sequenced["latex"] ~= "blurb";
+ document_section_keys_sequenced["text"] ~= "blurb";
}
if ((opt_action.html)
|| (opt_action.html_scroll)
diff --git a/org/ocda_functions.org b/org/ocda_functions.org
index 90574f4..0b997b7 100644
--- a/org/ocda_functions.org
+++ b/org/ocda_functions.org
@@ -2747,10 +2747,8 @@ static struct ObjInlineMarkup {
CMM conf_make_meta,
Flag!"_new_doc" _new_doc
) {
- obj_txt["munge"] = obj_[obj_key_].dup;
- obj_txt["munge"] = (obj_["is"].match(ctRegex!(`verse|code`)))
- ? obj_txt["munge"]
- : obj_txt["munge"].strip;
+ obj_txt["munge"] = obj_[obj_key_].dup;
+ obj_txt["munge"] = (obj_["is"].match(ctRegex!(`verse|code`))) ? obj_txt["munge"] : obj_txt["munge"].strip;
if (_new_doc) {
anchor_tag = "";
}
@@ -2769,8 +2767,8 @@ static struct ObjInlineMarkup {
|| (obj_["is"] == "group")
|| (obj_["is"] == "block")
|| (obj_["is"] == "verse")) {
- obj_txt["munge"] = (obj_txt["munge"]).inline_markup_faces;
- obj_txt["munge"] = (obj_txt["munge"]).links_and_images;
+ obj_txt["munge"] = (obj_txt["munge"]).inline_markup_faces;
+ obj_txt["munge"] = (obj_txt["munge"]).links_and_images;
}
switch (obj_["is"]) {
case "heading":
@@ -3553,8 +3551,8 @@ ubyte[32] obj_digest()(
// ↓ - endnotes
struct NotesSection {
string[string] object_notes;
- int previous_count;
- int mkn;
+ int previous_count;
+ int mkn;
static auto rgx = RgxI();
private auto gather_notes_for_endnote_section(
ObjGenericComposite[] contents_am,
@@ -4455,11 +4453,31 @@ ST_the_section build_the_blurb_section(Opt) (
int html_segnames_ptr_cntr,
int html_segnames_ptr,
) {
+ string[string][string] notes_;
+ if (the_document_body_section.length > 1) {
+ string _notes;
+ foreach (ref obj; the_document_body_section) {
+ if (obj.has.inline_notes_reg) {
+ if ((obj.text).matchFirst(rgx.inline_notes_al_gen)) {
+ foreach (m; (obj.text).matchAll(rgx.inline_notes_al_regular_number_note)) {
+ _notes ~= "\n\n" ~ m["num"] ~ ". " ~ m["note"];
+ notes_[(m["num"])]["ocn"] = obj.metainfo.ocn.to!string;
+ }
+ }
+ }
+ }
+ }
if (the_document_endnotes_section.length > 1) {
segnames["html"] ~= "endnotes";
segnames["epub"] ~= "endnotes";
html_segnames_ptr = html_segnames_ptr_cntr;
foreach (ref obj; the_document_endnotes_section) {
+ auto matches = (obj.text).matchAll(rgx.endnote_section_note);
+ foreach (m; matches) {
+ obj.metainfo.parent_ocn = notes_[(m["notenumber"])]["ocn"].to!int;
+ }
+ }
+ foreach (ref obj; the_document_endnotes_section) {
if (obj.metainfo.is_a == "heading") {
obj.metainfo.parent_ocn = obj.metainfo.markedup_ancestors[obj.metainfo.parent_lev_markup];
}
@@ -5652,6 +5670,9 @@ auto docSectKeysSeq(string[][string] document_section_keys_sequenced) {
string[] latex() {
return document_section_keys_sequenced["latex"];
}
+ string[] text() {
+ return document_section_keys_sequenced["text"];
+ }
}
return doc_sect_keys_seq();
}
diff --git a/org/out_latex.org b/org/out_latex.org
index 84791d2..1d5336e 100644
--- a/org/out_latex.org
+++ b/org/out_latex.org
@@ -72,6 +72,7 @@ template outputLaTeX() {
<<Function_shared_para>>
<<Function_shared_bookindex>>
<<Function_shared_heading>>
+<<Function_shared_quote>>
<<Function_shared_group>>
<<Function_shared_block>>
<<Function_shared_verse>>
@@ -1562,6 +1563,30 @@ string bullets_and_indentation(O)(
#+END_SRC
*** grouped text
+**** quote
+
+#+NAME: Function_shared_quote
+#+BEGIN_SRC d
+ string quote(O,M)(
+ string _txt,
+ O obj,
+ M doc_matters,
+ ) {
+ if (obj.metainfo.is_a == "quote") {
+ string _tex_para;
+ _tex_para = q"┃\ocn{%s}\objBlockOpen
+"%s"
+\objBlockClose
+┃";
+ _txt = format(_tex_para,
+ obj.metainfo.object_number,
+ _txt.nbsp_char.footnotes.split(rgx.br_linebreaks_newlines).join("\\br\n").strip
+ ).strip;
+ }
+ return _txt;
+ }
+#+END_SRC
+
**** group
- (hardspace not honored) clear hardspace marker
@@ -1581,7 +1606,7 @@ string bullets_and_indentation(O)(
┃";
_txt = format(_tex_para,
obj.metainfo.object_number,
- _txt.footnotes.split(rgx.br_line_spaced).join("\\brl{1}").strip // provides more control (more noise, not as tidy)
+ _txt.footnotes.split(rgx.br_line_spaced).join(" \\brl{1} ").strip // provides more control (more noise, not as tidy)
// _txt.footnotes.split(rgx.br_line_spaced).join("") // this works using a line-space, looks tidy, keep ref.
).strip;
}
@@ -2228,7 +2253,9 @@ case "body": assert(part == "body" || "head"); // surprise
case "block":
switch (obj.metainfo.is_a) {
case "quote":
- goto default; // TODO
+ _txt = _txt.quote(obj, doc_matters)
+ .links_and_images(obj, doc_matters);
+ goto default;
case "group": /+ (hardspaces not honored) [remove any hardspace marker] +/
_txt = _txt.group(obj, doc_matters)
.links_and_images(obj, doc_matters);
diff --git a/org/out_metadata.org b/org/out_metadata.org
index 5a7e579..d92ff92 100644
--- a/org/out_metadata.org
+++ b/org/out_metadata.org
@@ -83,6 +83,7 @@ if (doc_matters.opt.action.debug_do) {
}
auto pth_html = spinePathsHTML!()(doc_matters.output_path, doc_matters.src.language);
auto pth_epub = spinePathsEPUB!()(doc_matters.output_path, doc_matters.src.language);
+auto pth_text = spinePathsText!()(doc_matters);
auto pth_pdf = spinePathsPDF!()(doc_matters);
auto pth_pod = spinePathsPods!()(doc_matters);
metadata_ ~= format(q"┃<body lang="en" xml:lang="en">
@@ -164,6 +165,10 @@ if ((doc_matters.opt.action.html_link_pdf) || (doc_matters.opt.action.html_link_
~ "." ~ doc_matters.src.language ~ ".letter.portrait.pdf\" class=\"lnkicon\">"
~ "&nbsp;□&nbsp;pdf&nbsp;(U.S.&nbsp;letter)&nbsp;</a>]&nbsp";
}
+if (doc_matters.opt.action.html_link_text) {
+ metadata_ ~= "&nbsp;&nbsp;[<a href=\"../" ~ "text/" ~ doc_matters.src.filename_base ~ "." ~ doc_matters.src.language ~ ".txt\" class=\"lnkicon\">"
+ ~ "&nbsp;□&nbsp;txt&nbsp;</a>]&nbsp";
+}
metadata_ ~= "</p>";
if (doc_matters.opt.action.html_link_markup_source) {
metadata_ ~= "<hr /><p class=\"lev1\">source: " ~ doc_matters.src.filename_base ~ "</p>";
diff --git a/org/out_skel.org b/org/out_skel.org
new file mode 100644
index 0000000..43be371
--- /dev/null
+++ b/org/out_skel.org
@@ -0,0 +1,324 @@
+-*- mode: org -*-
+#+TITLE: sisudoc spine (doc_reform) output xmls
+#+DESCRIPTION: documents - structuring, publishing in multiple formats & search
+#+FILETAGS: :spine:output:skel:
+#+AUTHOR: Ralph Amissah
+#+EMAIL: [[mailto:ralph.amissah@gmail.com][ralph.amissah@gmail.com]]
+#+COPYRIGHT: Copyright (C) 2015 - 2025 Ralph Amissah
+#+LANGUAGE: en
+#+STARTUP: content hideblocks hidestars noindent entitiespretty
+#+PROPERTY: header-args :exports code
+#+PROPERTY: header-args+ :noweb yes
+#+PROPERTY: header-args+ :results output none
+#+PROPERTY: header-args+ :cache no
+#+PROPERTY: header-args+ :padline no
+#+PROPERTY: header-args+ :mkdirp yes
+#+OPTIONS: H:3 num:nil toc:t \n:t ::t |:t ^:nil -:t f:t *:t
+
+- [[./doc-reform.org][doc-reform.org]] [[./][org/]]
+- [[./output_hub.org][output_hub]]
+
+* Skel
+** outputSkel template
+
+#+HEADER: :tangle "../src/sisudoc/io_out/skel.d"
+#+HEADER: :noweb yes
+#+BEGIN_SRC d
+<<doc_header_including_copyright_and_license>>
+module sisudoc.io_out.skel;
+@safe:
+template outputSkel() {
+ <<munge>>
+ <<the_document>>
+ void outputSkel(D,M) (
+ const D doc_abstraction,
+ M doc_matters,
+ ) {
+ import std.stdio;
+ import sisudoc.io_out;
+ <<skel_out>>
+ skel_out(doc_abstraction, doc_matters);
+ }
+}
+#+END_SRC
+
+** Output
+
+#+NAME: skel_out
+#+HEADER: :noweb yes
+#+BEGIN_SRC d
+void skel_out(D,M)(
+ const D doc_abstraction,
+ M doc_matters,
+) {
+ struct Skel {
+ string head;
+ string content;
+ string tail;
+ }
+ auto skel = Skel();
+ skel.head = theDocument!().skel_head(doc_matters);
+ skel.content = theDocument!().skel_body(doc_abstraction, doc_matters);
+ skel.tail = theDocument!().skel_tail(doc_matters);
+ auto pth_skel = spinePathsSkel(doc_matters);
+ try {
+ import std.file;
+ if (!exists(pth_skel.base_pth)) {
+ (pth_skel.base_pth).mkdirRecurse;
+ }
+ } catch (ErrnoException ex) {
+ }
+ if (doc_matters.opt.action.vox_gt_1) {
+ writeln(" ", pth_skel.skel_file);
+ }
+ // writeln(pth_skel.base_pth);
+ auto f = File(pth_skel.skel_file, "w");
+ f.writeln(skel.head);
+ f.writeln(skel.content);
+ f.writeln(skel.tail);
+}
+#+END_SRC
+
+* The Document
+** theDocument template
+
+#+NAME: the_document
+#+HEADER: :noweb yes
+#+BEGIN_SRC d
+template theDocument() {
+ import std.stdio;
+ import sisudoc.io_out;
+ <<skel_head>>
+ <<skel_body_assign_munge>>
+ <<skel_tail>>
+}
+#+END_SRC
+
+** the Document (assign munge)
+*** Head
+
+#+NAME: skel_head
+#+HEADER: :noweb yes
+#+BEGIN_SRC d
+// static auto rgx = RgxO();
+string skel_head(M)(
+ M doc_matters,
+) {
+ return "head";
+}
+#+END_SRC
+
+*** Body munge assign
+
+#+NAME: skel_body_assign_munge
+#+HEADER: :noweb yes
+#+BEGIN_SRC d
+string skel_body(D,M)(
+ const D doc_abstraction,
+ M doc_matters,
+) {
+ string doc_object = "";
+ foreach (section; doc_matters.has.keys_seq.scroll) {
+ foreach (obj; doc_abstraction[section]) {
+ if (obj.metainfo.is_a == "toc") { doc_object ~= munge!().toc(obj); }
+ if (obj.metainfo.is_a == "heading") { doc_object ~= munge!().heading(obj); }
+ if (obj.metainfo.is_a == "para") { doc_object ~= munge!().para(obj); }
+ if (obj.metainfo.is_a == "group") { doc_object ~= munge!().group(obj); }
+ if (obj.metainfo.is_a == "block") { doc_object ~= munge!().block(obj); }
+ if (obj.metainfo.is_a == "poem") { doc_object ~= munge!().poem(obj); }
+ if (obj.metainfo.is_a == "verse") { doc_object ~= munge!().verse(obj); }
+ if (obj.metainfo.is_a == "code") { doc_object ~= munge!().code(obj); }
+ if (obj.metainfo.is_a == "quote") { doc_object ~= munge!().quote(obj); }
+ if (obj.metainfo.is_a == "table") { doc_object ~= munge!().table(obj); }
+ if (obj.metainfo.is_a == "endnote") { doc_object ~= munge!().endnote(obj); }
+ if (obj.metainfo.is_a == "bookindex") { doc_object ~= munge!().bookindex(obj); }
+ if (obj.metainfo.is_a == "bibliography") { doc_object ~= munge!().bibliography(obj); }
+ if (obj.metainfo.is_a == "glossary") { doc_object ~= munge!().glossary(obj); }
+ if (obj.metainfo.is_a == "blurb") { doc_object ~= munge!().blurb(obj); }
+ if (obj.metainfo.is_a == "comment") { doc_object ~= munge!().comment(obj); }
+ }
+ }
+ return doc_object;
+}
+#+END_SRC
+
+*** Tail
+
+#+NAME: skel_tail
+#+HEADER: :noweb yes
+#+BEGIN_SRC d
+string skel_tail(M)(
+ M doc_matters,
+) {
+ return "tail";
+}
+#+END_SRC
+
+* Munge
+
+#+NAME: munge
+#+HEADER: :noweb yes
+#+BEGIN_SRC d
+template munge() {
+ import std.stdio;
+ import std.conv;
+ void puts(string _obj_is) {
+ writeln(__FILE__, ":", __LINE__, ": ", _obj_is);
+ }
+ string newline = "\n";
+ string newlines = "\n\n";
+ string toc(O)(O obj) {
+ // puts(obj.metainfo.is_a);
+ // return "toc\n";
+ return obj.text ~ newline;
+ }
+ string heading(O)(O obj) {
+ /+
+ +/
+ // puts(obj.metainfo.is_a);
+ // return obj.metainfo.is_a;
+ return obj.text ~ newline ~ "「" ~ obj.metainfo.ocn.to!string ~ "」" ~ newlines;
+ }
+ string para(O)(O obj) {
+ /+
+ +/
+ // puts(obj.metainfo.is_a);
+ // return obj.metainfo.is_a;
+ return obj.text ~ newline ~ "「" ~ obj.metainfo.ocn.to!string ~ "」" ~ newlines;
+ }
+ string group(O)(O obj) {
+ /+
+ The "group" is different from the "block" mark in that "group" does not
+ preserve whitespace, the "block" mark does. The text falling within the
+ block is a single object.
+ +/
+ // puts(obj.metainfo.is_a);
+ // return obj.metainfo.is_a;
+ return obj.text ~ newline ~ "「" ~ obj.metainfo.ocn.to!string ~ "」" ~ newlines;
+ }
+ string block(O)(O obj) {
+ /+
+ The "block" is different from the "group" mark in that the "block" mark
+ (like the "poem" mark) preserves whitespace, the "group" mark does not.
+ The text falling within the "block" is a single object, which is different
+ from the "poem" mark where each identified verse is an object.
+ +/
+ // puts(obj.metainfo.is_a);
+ // return obj.metainfo.is_a;
+ return obj.text ~ newline ~ "「" ~ obj.metainfo.ocn.to!string ~ "」" ~ newlines;
+ }
+ string poem(O)(O obj) {
+ /+
+ The "poem" mark like the "block" preserves whitespace. Text followed by
+ two newlines are identified as verse and each verse is an object i.e. a
+ poem may consist of multiple verse each of which is identified as an
+ object, unlike a text "block" which is identified as a single object.
+ +/
+ // puts(obj.metainfo.is_a);
+ // return obj.metainfo.is_a;
+ // return obj.text ~ newline ~ "「" ~ obj.metainfo.ocn.to!string ~ "」" ~ newlines;
+ return obj.text ~ newlines;
+ }
+ string verse(O)(O obj) {
+ /+
+ See description of poem, the poem is demarkated but the verse is the
+ object.
+ +/
+ // puts(obj.metainfo.is_a);
+ // return obj.metainfo.is_a;
+ return obj.text ~ newline ~ "「" ~ obj.metainfo.ocn.to!string ~ "」" ~ newlines;
+ }
+ string code(O)(O obj) {
+ /+
+ "Code" blocks are a single text object, in which the original text is
+ preserved.
+ +/
+ // puts(obj.metainfo.is_a);
+ // return obj.metainfo.is_a;
+ return obj.text ~ newline ~ "「" ~ obj.metainfo.ocn.to!string ~ "」" ~ newlines;
+ }
+ string quote(O)(O obj) {
+ /+
+ +/
+ // puts(obj.metainfo.is_a);
+ // return obj.metainfo.is_a;
+ return obj.text ~ newline ~ "「" ~ obj.metainfo.ocn.to!string ~ "」" ~ newlines;
+ }
+ string table(O)(O obj) {
+ /+
+ +/
+ // puts(obj.metainfo.is_a);
+ // return obj.metainfo.is_a;
+ return obj.text ~ newline ~ "「" ~ obj.metainfo.ocn.to!string ~ "」" ~ newlines;
+ }
+ string endnote(O)(O obj) {
+ /+
+ +/
+ // puts(obj.metainfo.is_a);
+ // return obj.metainfo.is_a;
+ return obj.text ~ newlines;
+ }
+ string bookindex(O)(O obj) {
+ /+
+ +/
+ // puts(obj.metainfo.is_a);
+ // return obj.metainfo.is_a;
+ return obj.text ~ newlines;
+ }
+ string bibliography(O)(O obj) {
+ /+
+ +/
+ // puts(obj.metainfo.is_a);
+ // return obj.metainfo.is_a;
+ return obj.text ~ newlines;
+ }
+ string glossary(O)(O obj) {
+ /+
+ +/
+ // puts(obj.metainfo.is_a);
+ // return obj.metainfo.is_a;
+ return obj.text ~ newlines;
+ }
+ string blurb(O)(O obj) {
+ /+
+ +/
+ // puts(obj.metainfo.is_a);
+ // return obj.metainfo.is_a;
+ return obj.text ~ newlines;
+ }
+ string comment(O)(O obj) {
+ /+
+ +/
+ // puts(obj.metainfo.is_a);
+ // return obj.metainfo.is_a;
+ return obj.text ~ newlines;
+ }
+}
+#+END_SRC
+
+* org includes
+** spine project VERSION
+
+#+NAME: spine_version
+#+HEADER: :noweb yes
+#+BEGIN_SRC emacs-lisp
+<<./sisudoc_spine_version_info_and_doc_header_including_copyright_and_license.org:spine_project_version()>>
+#+END_SRC
+
+** year
+
+#+NAME: year
+#+HEADER: :noweb yes
+#+BEGIN_SRC emacs-lisp
+<<./sisudoc_spine_version_info_and_doc_header_including_copyright_and_license.org:year()>>
+#+END_SRC
+
+** document header including copyright & license
+
+#+NAME: doc_header_including_copyright_and_license
+#+HEADER: :noweb yes
+#+BEGIN_SRC emacs-lisp
+<<./sisudoc_spine_version_info_and_doc_header_including_copyright_and_license.org:spine_doc_header_including_copyright_and_license()>>
+#+END_SRC
+
+* __END__
diff --git a/org/out_text.org b/org/out_text.org
new file mode 100644
index 0000000..02d6294
--- /dev/null
+++ b/org/out_text.org
@@ -0,0 +1,565 @@
+-*- mode: org -*-
+#+TITLE: sisudoc spine (doc_reform) output xmls
+#+DESCRIPTION: documents - structuring, publishing in multiple formats & search
+#+FILETAGS: :spine:output:text:
+#+AUTHOR: Ralph Amissah
+#+EMAIL: [[mailto:ralph.amissah@gmail.com][ralph.amissah@gmail.com]]
+#+COPYRIGHT: Copyright (C) 2015 - 2025 Ralph Amissah
+#+LANGUAGE: en
+#+STARTUP: content hideblocks hidestars noindent entitiespretty
+#+PROPERTY: header-args :exports code
+#+PROPERTY: header-args+ :noweb yes
+#+PROPERTY: header-args+ :results output none
+#+PROPERTY: header-args+ :cache no
+#+PROPERTY: header-args+ :padline no
+#+PROPERTY: header-args+ :mkdirp yes
+#+OPTIONS: H:3 num:nil toc:t \n:t ::t |:t ^:nil -:t f:t *:t
+
+- [[./doc-reform.org][doc-reform.org]] [[./][org/]]
+- [[./output_hub.org][output_hub]]
+
+* Text
+** outputText template
+
+#+HEADER: :tangle "../src/sisudoc/io_out/text.d"
+#+HEADER: :noweb yes
+#+BEGIN_SRC d
+<<doc_header_including_copyright_and_license>>
+module sisudoc.io_out.text;
+@safe:
+template outputText() {
+ <<munge>>
+ <<the_document>>
+ void outputText(D,M) (
+ const D doc_abstraction,
+ M doc_matters,
+ ) {
+ import std.stdio;
+ import sisudoc.io_out;
+ <<text_out>>
+ text_out(doc_abstraction, doc_matters);
+ }
+}
+#+END_SRC
+
+** Output
+
+#+NAME: text_out
+#+HEADER: :noweb yes
+#+BEGIN_SRC d
+void text_out(D,M)(
+ const D doc_abstraction,
+ M doc_matters,
+) {
+ struct Text {
+ string head;
+ string content;
+ string tail;
+ }
+ auto text = Text();
+ // text.head = theDocument!().text_head(doc_matters);
+ text.content = theDocument!().text_body(doc_abstraction, doc_matters);
+ text.tail = theDocument!().text_tail(doc_matters);
+ auto pth_text = spinePathsText(doc_matters);
+ try {
+ import std.file;
+ if (!exists(pth_text.base_pth)) {
+ (pth_text.base_pth).mkdirRecurse;
+ }
+ } catch (ErrnoException ex) {
+ }
+ if (doc_matters.opt.action.vox_gt_1) {
+ writeln(" ", pth_text.text_file);
+ }
+ // writeln(pth_text.base_pth);
+ auto f = File(pth_text.text_file, "w");
+ // f.writeln(text.head);
+ f.writeln(text.content);
+ f.writeln(text.tail);
+}
+#+END_SRC
+
+* The Document
+** theDocument template
+
+#+NAME: the_document
+#+HEADER: :noweb yes
+#+BEGIN_SRC d
+template theDocument() {
+ import std.stdio;
+ import sisudoc.io_out;
+ <<text_head>>
+ <<text_body_assign_munge>>
+ <<text_tail>>
+}
+#+END_SRC
+
+** the Document (assign munge)
+*** Head SKIP
+
+#+NAME: text_head
+#+HEADER: :noweb yes
+#+BEGIN_SRC d
+string text_head(M)(
+ M doc_matters,
+) {
+ return "head";
+}
+#+END_SRC
+
+*** Body munge assign
+
+#+NAME: text_body_assign_munge
+#+HEADER: :noweb yes
+#+BEGIN_SRC d
+string text_body(D,M)(
+ const D doc_abstraction,
+ M doc_matters,
+) {
+ string doc_object = "";
+ foreach (section; doc_matters.has.keys_seq.scroll) {
+ foreach (obj; doc_abstraction[section]) {
+ if (obj.metainfo.is_a == "toc") { doc_object ~= munge!().toc(obj, doc_matters); }
+ if (obj.metainfo.is_a == "heading") { doc_object ~= munge!().heading(obj, doc_matters); }
+ if (obj.metainfo.is_a == "para") { doc_object ~= munge!().para(obj, doc_matters); }
+ if (obj.metainfo.is_a == "group") { doc_object ~= munge!().group(obj, doc_matters); }
+ if (obj.metainfo.is_a == "block") { doc_object ~= munge!().block(obj, doc_matters); }
+ if (obj.metainfo.is_a == "poem") { doc_object ~= munge!().poem(obj, doc_matters); } // CHECK
+ if (obj.metainfo.is_a == "verse") { doc_object ~= munge!().verse(obj, doc_matters); } // CHECK
+ if (obj.metainfo.is_a == "code") { doc_object ~= munge!().code(obj, doc_matters); }
+ if (obj.metainfo.is_a == "quote") { doc_object ~= munge!().quote(obj, doc_matters); } // LATER
+ if (obj.metainfo.is_a == "table") { doc_object ~= munge!().table(obj, doc_matters); }
+ if (obj.metainfo.is_a == "endnote") { doc_object ~= munge!().endnote(obj, doc_matters); }
+ if (obj.metainfo.is_a == "bookindex") { doc_object ~= munge!().bookindex(obj, doc_matters); } // CHECK
+ if (obj.metainfo.is_a == "bibliography") { doc_object ~= munge!().bibliography(obj, doc_matters); } // CHECK
+ if (obj.metainfo.is_a == "glossary") { doc_object ~= munge!().glossary(obj, doc_matters); } // CHECK
+ if (obj.metainfo.is_a == "blurb") { doc_object ~= munge!().blurb(obj, doc_matters); } // CHECK
+ if (obj.metainfo.is_a == "comment") { doc_object ~= munge!().comment(obj, doc_matters); } // LATER
+ }
+ }
+ return doc_object;
+}
+#+END_SRC
+
+*** Tail
+
+#+NAME: text_tail
+#+HEADER: :noweb yes
+#+BEGIN_SRC d
+string text_tail(M)(
+ M doc_matters,
+) {
+ string metadata_;
+ if (doc_matters.opt.action.debug_do) {
+ writeln(doc_matters.src.filename_base);
+ writeln("Title: ", doc_matters.conf_make_meta.meta.title_full);
+ writeln(" Author: ", doc_matters.conf_make_meta.meta.creator_author);
+ writeln(" Published: ", doc_matters.conf_make_meta.meta.date_published);
+ writeln(" Copyright: ", doc_matters.conf_make_meta.meta.rights_copyright);
+ writeln(" License: ", doc_matters.conf_make_meta.meta.rights_license);
+ }
+ if (!(doc_matters.conf_make_meta.meta.title_full.empty)) {
+ metadata_ ~= "Title: " ~ doc_matters.conf_make_meta.meta.title_full ~ "\n\n";
+ } else if (doc_matters.opt.action.debug_do || doc_matters.opt.action.vox_gt_3) {
+ writeln("ERROR no Title information provided in document header ", doc_matters.src.filename_base);
+ }
+ if (!(doc_matters.conf_make_meta.meta.creator_author.empty)) {
+ if (doc_matters.opt.action.html_link_curate) {
+ metadata_ ~= "Author: " ~ doc_matters.conf_make_meta.meta.creator_author_surname.translate([' ' : "_"])
+ ~ doc_matters.conf_make_meta.meta.creator_author ~ "\n\n";
+ } else {
+ metadata_ ~= "Author: "
+ ~ doc_matters.conf_make_meta.meta.creator_author ~ "\n\n";
+ }
+ } else if (doc_matters.opt.action.debug_do || doc_matters.opt.action.vox_gt_3) {
+ writeln("ERROR no Author information provided in document header ", doc_matters.src.filename_base);
+ }
+ metadata_ ~= "Published: " ~ doc_matters.conf_make_meta.meta.date_published ~ "\n\n";
+ if (!(doc_matters.conf_make_meta.meta.rights_copyright.empty)) {
+ metadata_ ~= "Copyright: " ~ doc_matters.conf_make_meta.meta.rights_copyright ~ "\n\n";
+ } else if (doc_matters.opt.action.debug_do || doc_matters.opt.action.vox_gt_3) {
+ writeln("WARNING no Copyright information provided in document header ", doc_matters.src.filename_base);
+ }
+ if (!(doc_matters.conf_make_meta.meta.rights_license.empty)) {
+ metadata_ ~= "License: " ~ doc_matters.conf_make_meta.meta.rights_license ~ "\n\n";
+ } else if (doc_matters.opt.action.debug_do || doc_matters.opt.action.vox_gt_3) {
+ writeln("WARNING no License information provided in document header ", doc_matters.src.filename_base);
+ }
+ metadata_ ~= doc_matters.generator_program.project_name.strip ~ "\n";
+ metadata_ ~= doc_matters.generator_program.url_home.strip;
+ return metadata_;
+}
+#+END_SRC
+
+* Munge
+
+#+NAME: munge
+#+HEADER: :noweb yes
+#+BEGIN_SRC d
+template munge() {
+ import sisudoc.io_out;
+ import sisudoc.io_out.rgx;
+ import std.stdio;
+ import std.conv;
+ import std.conv : to;
+ import std.typecons : Nullable;
+ mixin spineRgxOut;
+ static auto rgx = RgxO();
+ void puts(string _obj_is) {
+ writeln(__FILE__, ":", __LINE__, ": ", _obj_is);
+ }
+ string newline = "\n";
+ string newlines = "\n\n";
+ template special_characters_and_font_face() {
+ string code(string _txt){
+ _txt = _txt.replaceAll(rgx.nbsp_char, " ");
+ return _txt;
+ }
+ string general(string _txt) {
+ _txt = _txt
+ .replaceAll(rgx.nbsp_char, " ")
+ .replaceAll(rgx.br_line, "\n")
+ .replaceAll(rgx.br_line_inline, "\n")
+ .replaceAll(rgx.br_line_spaced, "\n\n")
+ .replaceAll(rgx.inline_strike, "-{$1}-")
+ .replaceAll(rgx.inline_insert, "+{$1}+")
+ .replaceAll(rgx.inline_cite, "\"{$1}\"")
+ .replaceAll(rgx.inline_emphasis, "!{$1}!")
+ .replaceAll(rgx.inline_bold, "*{$1}*")
+ .replaceAll(rgx.inline_italics, "/{$1}/")
+ .replaceAll(rgx.inline_underscore, "_{$1}_")
+ .replaceAll(rgx.inline_superscript, "^{$1}^")
+ .replaceAll(rgx.inline_subscript, ",{$1},")
+ .replaceAll(rgx.inline_mono, "#{$1}#");
+ return _txt;
+ }
+ string links_and_images(string _txt){
+ if (_txt.match(rgx.inline_link)) {
+ foreach (m; _txt.matchAll(rgx.inline_link)) {
+ _txt = (m.captures[3] == "0")
+ ? _txt.replaceFirst(rgx.inline_link, (m.captures[1]))
+ : _txt.replaceFirst(rgx.inline_link, (m.captures[1] ~ " ≫" ~ m.captures[3]));
+ }
+ }
+ if (_txt.matchFirst(rgx.inline_image)) {
+ foreach (m; _txt.matchAll(rgx.inline_image)) {
+ _txt = _txt.replaceFirst(rgx.inline_image, (m.captures[3]));
+ }
+ }
+ return _txt;
+ }
+ }
+ string generalMunge(O,M)(O obj, M doc_matters) {
+ string _txt = obj.text;
+ string _notes;
+ string _ocn;
+ string general_munge;
+ _ocn = (obj.metainfo.ocn == 0 || doc_matters.opt.action.ocn_off)
+ ? "" : "「" ~ obj.metainfo.ocn.to!string ~ "」" ~ newline;
+ if (_txt.matchFirst(rgx.inline_notes_al_gen)) {
+ foreach (m; _txt.matchAll(rgx.inline_notes_al_regular_number_note)) {
+ _notes ~= newlines ~ m["num"] ~ ". "
+ ~ special_characters_and_font_face!().general(m["note"].replaceAll(rgx.inline_link, ("$1")));
+ }
+ }
+ _txt = _txt.replaceAll(rgx.inline_notes_al_regular_number_note, "[$1]");
+ _txt = (obj.metainfo.is_a == "code")
+ ? special_characters_and_font_face!().code(_txt)
+ : special_characters_and_font_face!().general(_txt);
+ _txt = special_characters_and_font_face!().links_and_images(_txt);
+ general_munge = (obj.metainfo.is_a == "heading")
+ ? newline ~ _txt ~ _notes ~ newline ~ _ocn ~ newline
+ : _txt ~ _notes ~ newline ~ _ocn ~ newline;
+ return general_munge;
+ }
+ string toc(O,M)(O obj, M doc_matters) {
+ // puts(obj.metainfo.is_a);
+ // return "toc\n";
+ // _txt = _special_characters_and_font_face(obj.text);
+ string _txt = special_characters_and_font_face!().general(obj.text);
+ string _spaces;
+ switch (obj.attrib.indent_hang) {
+ case 1: _spaces = "";
+ break;
+ case 2: _spaces = ":";
+ break;
+ case 3: _spaces = "∴";
+ break;
+ case 4: _spaces = " ";
+ break;
+ case 5: _spaces = " ";
+ break;
+ case 6: _spaces = " ";
+ break;
+ case 7: _spaces = " ";
+ break;
+ case 8: _spaces = " ";
+ break;
+ default:
+ break;
+ }
+ _txt = (doc_matters.opt.action.ocn_off)
+ ? _txt.replaceAll(rgx.inline_link, (_spaces ~ "$1"))
+ : _txt.replaceAll(rgx.inline_link, (_spaces ~ "$1 ≫ $3"));
+ return _txt ~ newline;
+ }
+ string heading(O,M)(O obj, M doc_matters) {
+ // puts(obj.metainfo.is_a);
+ // return obj.metainfo.is_a;
+ string _general_munge = generalMunge(obj,doc_matters);
+ return _general_munge;
+ }
+ string para(O,M)(O obj, M doc_matters) {
+ // puts(obj.metainfo.is_a);
+ // return obj.metainfo.is_a;
+ string _general_munge = generalMunge(obj,doc_matters);
+ return _general_munge;
+ }
+ string group(O,M)(O obj, M doc_matters) {
+ /+
+ The "group" is different from the "block" mark in that "group" does not
+ preserve whitespace, the "block" mark does. The text falling within the
+ block is a single object.
+ +/
+ // puts(obj.metainfo.is_a);
+ // return obj.metainfo.is_a;
+ string _general_munge = generalMunge(obj,doc_matters);
+ return _general_munge;
+ }
+ string block(O,M)(O obj, M doc_matters) {
+ /+
+ The "block" is different from the "group" mark in that the "block" mark
+ (like the "poem" mark) preserves whitespace, the "group" mark does not.
+ The text falling within the "block" is a single object, which is different
+ from the "poem" mark where each identified verse is an object.
+ +/
+ // puts(obj.metainfo.is_a);
+ // return obj.metainfo.is_a;
+ string _general_munge = generalMunge(obj,doc_matters);
+ return _general_munge;
+ }
+ string poem(O,M)(O obj, M doc_matters) { // LATER
+ /+
+ The "poem" mark like the "block" preserves whitespace. Text followed by
+ two newlines are identified as verse and each verse is an object i.e. a
+ poem may consist of multiple verse each of which is identified as an
+ object, unlike a text "block" which is identified as a single object.
+ +/
+ // puts(obj.metainfo.is_a);
+ // return obj.metainfo.is_a;
+ return obj.text ~ newlines;
+ }
+ string verse(O,M)(O obj, M doc_matters) {
+ /+
+ See description of poem, the poem is demarkated but the verse is the
+ object.
+ +/
+ // puts(obj.metainfo.is_a);
+ // return obj.metainfo.is_a;
+ string _general_munge = generalMunge(obj,doc_matters);
+ return _general_munge;
+ }
+ string code(O,M)(O obj, M doc_matters) {
+ /+
+ "Code" blocks are a single text object, in which the original text is
+ preserved.
+ +/
+ // puts(obj.metainfo.is_a);
+ // return obj.metainfo.is_a;
+ string _general_munge = generalMunge(obj,doc_matters);
+ return _general_munge;
+ }
+ string quote(O,M)(O obj, M doc_matters) { // LATER
+ // puts(obj.metainfo.is_a);
+ // return obj.metainfo.is_a;
+ return obj.text ~ newline ~ "「" ~ obj.metainfo.ocn.to!string ~ "」" ~ newlines;
+ }
+ string table(O,M)(O obj, M doc_matters) {
+ // puts(obj.metainfo.is_a);
+ // return obj.metainfo.is_a;
+ auto tablarize(O)(
+ string _txt,
+ const O obj,
+ ) {
+ string[] _table_rows = (_txt).split(rgx.table_delimiter_row);
+ string[] _table_cols;
+ string _table = "";
+ string _tablenote = "";
+ int[] _col_width;
+ _col_width.length = obj.table.number_of_columns.to!ulong;
+ foreach(row_idx, row; _table_rows) {
+ _table_cols = row.split(rgx.table_delimiter_col);
+ _table ~= "";
+ foreach(col_idx, cell; _table_cols) {
+ if (!((_table_cols.length == 1)
+ && (_table_rows.length <= row_idx+2))) {
+ if (_col_width[col_idx] < (cell.length.to!int)) {
+ _col_width[col_idx] = cell.length.to!int;
+ }
+ }
+ }
+ }
+ foreach(row_idx, row; _table_rows) {
+ _table_cols = row.split(rgx.table_delimiter_col);
+ foreach(col_idx, cell; _table_cols) {
+ if ((_table_cols.length == 1)
+ && (_table_rows.length <= row_idx+2)) { // check row_idx+2 (rather than == ++row_idx)
+ _tablenote ~= cell ~ newline;
+ } else {
+ if (obj.table.column_aligns[col_idx] == "l") {
+ _table ~= format(q"┃%-*s%s┃",
+ _col_width[col_idx],
+ cell,
+ (_table_cols.length > (col_idx + 1)) ? " ┊ " : ""
+ );
+ } else {
+ _table ~= format(q"┃%*s%s┃",
+ _col_width[col_idx],
+ cell,
+ (_table_cols.length > (col_idx + 1)) ? " ┊ " : ""
+ );
+ }
+ _table = _table
+ .replaceAll(regex("\\s*$"), "");
+ }
+ }
+ _table ~= newline;
+ }
+ Tuple!(string, string) t = tuple(
+ _table,
+ _tablenote,
+ );
+ return t;
+ }
+ // string _txt = obj.text;
+ // writeln(obj.table.column_widths);
+ auto _t = tablarize(obj.text, obj);
+ string _txt = _t[0];
+ string _tablenote = _t[1];
+ return _txt ~ _tablenote ~ "「" ~ obj.metainfo.ocn.to!string ~ "」" ~ newlines;
+ }
+ string endnote(O,M)(O obj, M doc_matters) {
+ // puts(obj.metainfo.is_a);
+ // return obj.metainfo.is_a;
+ string _ocn;
+ _ocn = "「" ~ obj.metainfo.ocn.to!string ~ "」";
+ string _txt = obj.text;
+ string _parent_ocn;
+ _txt = _txt
+ .replaceAll(rgx.inline_link, ("$1")) // consider
+ .replaceFirst(rgx.inline_superscript, ("$1"));
+ _parent_ocn = (obj.metainfo.parent_ocn == 0 || doc_matters.opt.action.ocn_off)
+ ? "" : " ≫" ~ obj.metainfo.parent_ocn.to!string;
+ _txt = special_characters_and_font_face!().general(_txt) ~ _parent_ocn;
+ return _txt ~ newlines;
+ }
+ string bookindex(O,M)(O obj, M doc_matters) {
+ // puts(obj.metainfo.is_a);
+ // return obj.metainfo.is_a;
+ string _txt = obj.text;
+ _txt = (doc_matters.opt.action.ocn_off)
+ ? _txt.replaceAll(rgx.find_bookindex_ocn_link_and_comma, "")
+ .replaceAll(regex("\\s*\\\\"), "")
+ : _txt.replaceAll(rgx.inline_link, ("≫$1"))
+ .replaceAll(regex("\\s*\\\\"), "");
+ _txt = special_characters_and_font_face!().general(_txt);
+ return _txt ~ newlines;
+ }
+ string bibliography(O,M)(O obj, M doc_matters) {
+ // puts(obj.metainfo.is_a);
+ // return obj.metainfo.is_a;
+ string _txt = obj.text;
+ _txt = special_characters_and_font_face!().general(_txt);
+ return _txt ~ newlines;
+ // ALT:
+ // string _general_munge = generalMunge(obj,doc_matters);
+ // return _general_munge;
+ }
+ string glossary(O,M)(O obj, M doc_matters) {
+ // puts(obj.metainfo.is_a);
+ // return obj.metainfo.is_a;
+ string _txt = obj.text;
+ _txt = special_characters_and_font_face!().general(_txt);
+ return _txt;
+ }
+ string blurb(O,M)(O obj, M doc_matters) {
+ // puts(obj.metainfo.is_a);
+ // return obj.metainfo.is_a;
+ string _general_munge = generalMunge(obj,doc_matters);
+ return _general_munge;
+ }
+ string comment(O,M)(O obj, M doc_matters) { // LATER
+ /+
+ +/
+ // puts(obj.metainfo.is_a);
+ // return obj.metainfo.is_a;
+ return obj.text ~ newlines;
+ }
+}
+#+END_SRC
+
+* org includes
+** spine project VERSION
+
+#+NAME: spine_version
+#+HEADER: :noweb yes
+#+BEGIN_SRC emacs-lisp
+<<./sisudoc_spine_version_info_and_doc_header_including_copyright_and_license.org:spine_project_version()>>
+#+END_SRC
+
+** year
+
+#+NAME: year
+#+HEADER: :noweb yes
+#+BEGIN_SRC emacs-lisp
+<<./sisudoc_spine_version_info_and_doc_header_including_copyright_and_license.org:year()>>
+#+END_SRC
+
+** document header including copyright & license
+
+#+NAME: doc_header_including_copyright_and_license
+#+HEADER: :noweb yes
+#+BEGIN_SRC emacs-lisp
+<<./sisudoc_spine_version_info_and_doc_header_including_copyright_and_license.org:spine_doc_header_including_copyright_and_license()>>
+#+END_SRC
+
+* __END__
+* TODO WORKON
+
+#+BEGIN_SRC org
+TODO
+ PRIORITY
+ LATER
+- object types
+ - comment
+ - quote
+- images ? remove?? (currently with inline links)
+- anchor tags (for internal links)?
+
+WISH
+- underline headings?
+- break para text at set width?
+- text wrap at text-line-width specified option
+
+DONE
+- line breaks
+- font face: bold, italics etc.
+- object types
+ - toc
+ - inline_link /[┥┝┤├]
+ - indents
+ obj.metainfo.heading_lev_markup < 4
+ - group
+ - block
+ - code
+ - verse
+ - table
+ - endnote section
+ - point back to object number of origin, use parent_ocn (used e.g. in text output: endnote info on calling object ≫\d+)
+ - bookindex
+ - bibliography
+ - glossary
+ - blurb
+- inline_link /[┥┝┤├]
+#+END_SRC
+
diff --git a/org/output_hub.org b/org/output_hub.org
index e7216f1..47123b2 100644
--- a/org/output_hub.org
+++ b/org/output_hub.org
@@ -35,7 +35,7 @@ template outputHub() {
@system void outputHub(D)(D doc) {
mixin Msg;
auto msg = Msg!()(doc.matters);
- enum outTask { source_or_pod, sqlite, sqlite_multi, latex, odt, epub, html_scroll, html_seg, html_stuff }
+ enum outTask { source_or_pod, sqlite, sqlite_multi, latex, odt, epub, html_scroll, html_seg, html_stuff, text, skel }
void Scheduled(D)(int sched, D doc) {
auto msg = Msg!()(doc.matters);
<<output_scheduled_task_source_or_pod>>
@@ -45,8 +45,10 @@ template outputHub() {
<<output_scheduled_task_html_seg>>
<<output_scheduled_task_html_out>>
<<output_scheduled_task_latex>>
+ <<output_scheduled_task_text>>
<<output_scheduled_task_odt>>
<<output_scheduled_task_sqlite>>
+ <<output_scheduled_task_skel>>
}
if (doc.matters.opt.action.vox_gt_1) { writeln(doc.matters.src.filename_base); }
if (!(doc.matters.opt.action.parallelise_subprocesses)) {
@@ -230,6 +232,18 @@ if (sched == outTask.latex) {
}
#+END_SRC
+**** text :text:txt:
+
+#+NAME: output_scheduled_task_text
+#+BEGIN_SRC d
+if (sched == outTask.text) {
+ msg.v("text processing... ");
+ import sisudoc.io_out.text;
+ outputText!()(doc.abstraction, doc.matters);
+ msg.vv("text done");
+}
+#+END_SRC
+
**** odf / odt :odf:odt:
#+NAME: output_scheduled_task_odt
@@ -242,6 +256,18 @@ if (sched == outTask.odt) {
}
#+END_SRC
+**** skel :skel:text:
+
+#+NAME: output_scheduled_task_skel
+#+BEGIN_SRC d
+if (sched == outTask.skel) {
+ msg.v("skel processing... ");
+ import sisudoc.io_out.skel;
+ outputSkel!()(doc.abstraction, doc.matters);
+ msg.vv("skel done");
+}
+#+END_SRC
+
**** sqlite discrete :sqlite:
#+NAME: output_scheduled_task_sqlite
diff --git a/org/spine.org b/org/spine.org
index 6acc62f..9971dc2 100644
--- a/org/spine.org
+++ b/org/spine.org
@@ -311,6 +311,7 @@ bool[string] opts = [
"html-link-pdf-a4" : false,
"html-link-pdf-letter" : false,
"html-link-search" : false,
+ "html-link-text" : false,
"html-seg" : false,
"html-scroll" : false,
"latex" : false,
@@ -320,6 +321,7 @@ bool[string] opts = [
"light" : false,
"manifest" : false,
"hide-ocn" : false,
+ "no-ocn" : false,
"ocn-off" : false,
"odf" : false,
"odt" : false,
@@ -343,6 +345,7 @@ bool[string] opts = [
"show-pod" : false,
"show-sqlite" : false,
"show-summary" : false,
+ "skel" : false,
"source" : false,
"sqlite-discrete" : false,
"sqlite-db-create" : false,
@@ -431,6 +434,7 @@ auto helpInfo = getopt(args,
"html-link-pdf", "provide html link to pdf a4 & letter output", &opts["html-link-pdf"],
"html-link-pdf-a4", "provide html link to pdf a4 output", &opts["html-link-pdf-a4"],
"html-link-pdf-letter", "provide html link to pdf letter size output", &opts["html-link-pdf-letter"],
+ "html-link-text", "provide html link to text output", &opts["html-link-text"],
"html-link-search", "html embedded search submission", &opts["html-link-search"],
"html-seg", "process html output", &opts["html-seg"],
"html-scroll", "process html output", &opts["html-scroll"],
@@ -441,6 +445,7 @@ auto helpInfo = getopt(args,
"latex-header-sty", "latex document header sty files", &opts["latex-header-sty"],
"light", "default light theme", &opts["light"],
"manifest", "process manifest output", &opts["manifest"],
+ "no-ocn", "object cite numbers", &opts["no-ocn"],
"ocn-off", "object cite numbers", &opts["ocn-off"],
"odf", "open document format text (--odt)", &opts["odf"],
"odt", "open document format text", &opts["odt"],
@@ -480,6 +485,7 @@ auto helpInfo = getopt(args,
"set-digest", "default hash digest type (e.g. sha256)", &settings["set-digest"],
"set-papersize", "default papersize (latex pdf eg. a4 or a5 or b4 or letter)", &settings["set-papersize"],
"set-textwrap", "default textwrap (e.g. 80 (characters)", &settings["set-textwrap"],
+ "skel", "skel (dummy outline)", &opts["skel"],
"sqlite-discrete", "process discrete sqlite output", &opts["sqlite-discrete"],
"sqlite-db-create", "create db, create tables", &opts["sqlite-db-create"],
"sqlite-db-drop", "drop tables & db", &opts["sqlite-db-drop"],
@@ -527,7 +533,7 @@ if (helpInfo.helpWanted) {
#+NAME: spine_args_get_options_aa2str
#+BEGIN_SRC d
-enum outTask { source_or_pod, sqlite, sqlite_multi, latex, odt, epub, html_scroll, html_seg, html_stuff }
+enum outTask { source_or_pod, sqlite, sqlite_multi, latex, odt, epub, html_scroll, html_seg, html_stuff, text, skel }
struct OptActions {
@trusted bool allow_downloads() {
return opts["allow-downloads"];
@@ -631,6 +637,12 @@ struct OptActions {
@trusted bool html_link_pdf_letter() {
return (opts["html-link-pdf-letter"]) ? true : false;
}
+ @trusted bool html_link_text() {
+ return (opts["html-link-text"]) ? true : false;
+ }
+ @trusted bool text_link_curate() {
+ return (opts["text-link-curate"]) ? true : false;
+ }
@trusted bool html_link_search() {
return (opts["html-link-search"]) ? true : false;
}
@@ -665,7 +677,7 @@ struct OptActions {
return opts["hide-ocn"];
}
@trusted bool ocn_off() {
- return opts["ocn-off"];
+ return ((opts["ocn-off"]) || (opts["no-ocn"])) ? true : false;
}
@trusted bool pod() {
return opts["pod"];
@@ -739,6 +751,12 @@ struct OptActions {
|| opts["sqlite-update"]
) ? true : false;
}
+ @trusted bool skel() {
+ return opts["skel"];
+ }
+ @trusted bool text() {
+ return opts["text"];
+ }
@trusted bool vox_0() { // --silent
return opts["vox_is0"];
}
@@ -775,9 +793,6 @@ struct OptActions {
@trusted bool vox_default() { return vox_gt_1; } // defalt, & above
@trusted bool vox_verbose() { return vox_gt_2; } // --verbose -v & above
@trusted bool vox_very_verbose() { return vox_gt_3; } // --very-verbose
- @trusted bool text() {
- return opts["text"];
- }
@trusted bool xhtml() {
return opts["xhtml"];
}
@@ -891,6 +906,8 @@ struct OptActions {
|| latex
|| manifest
|| sqlite_discrete
+ || text
+ || skel
) {
_is = true;
} else { _is = false; }
@@ -909,6 +926,8 @@ struct OptActions {
if (html_stuff) { schedule ~= outTask.html_stuff; }
if (odt) { schedule ~= outTask.odt; }
if (latex) { schedule ~= outTask.latex; }
+ if (text) { schedule ~= outTask.text; }
+ if (skel) { schedule ~= outTask.skel; }
return schedule.sort().uniq;
}
@trusted bool abstraction() {
@@ -925,6 +944,8 @@ struct OptActions {
|| sqlite_discrete
|| sqlite_delete
|| sqlite_update
+ || text
+ || skel
) ? true : false;
}
@trusted bool require_processing_files() {
@@ -946,6 +967,7 @@ struct OptActions {
|| sqlite_update
|| text
|| xhtml
+ || skel
) ? true : false;
}
@trusted bool meta_processing_general() {
@@ -958,6 +980,8 @@ struct OptActions {
|| latex
|| sqlite_discrete
|| sqlite_update
+ || text
+ || skel
) ? true :false;
}
@trusted bool meta_processing_xml_dom() {
diff --git a/org/spine_info.org b/org/spine_info.org
index 4a2b128..7459672 100644
--- a/org/spine_info.org
+++ b/org/spine_info.org
@@ -624,6 +624,8 @@ for a document collection you can point to the document collection:
#+NAME: sisudoc_spine_README_command_examples_search_db_cgi_text
#+BEGIN_SRC text
+The CGI search form is built separately in the sisudoc-spine-search-cgi/ directory.
+
Steps:
1. Clone the sisudoc-spine-search-cgi repository
2. Configure views/configuration.txt with your web server settings
@@ -670,7 +672,7 @@ spine -v \
--output=/var/www/html \
~spineMarkupSamples/pod/*
-Note: The CGI search form is built separately in sisudoc-spine-search-cgi/
+Note: The CGI search form is built separately in the sisudoc-spine-search-cgi/ directory.
#+END_SRC
#+NAME: sisudoc_spine_README_command_examples_html_with_links_to_search_form_text
diff --git a/org/spine_markup_sample.org b/org/spine_markup_sample.org
index 2965fe5..60c6272 100644
--- a/org/spine_markup_sample.org
+++ b/org/spine_markup_sample.org
@@ -1300,7 +1300,7 @@ code(number){
3~ Tables
={ SiSU markup:tables;tables }
-Tables may be prepared in two either of two forms
+Tables may be prepared in either of two forms
!_ resulting output:
diff --git a/src/sisudoc/io_out/hub.d b/src/sisudoc/io_out/hub.d
index 0e25811..f98be01 100644
--- a/src/sisudoc/io_out/hub.d
+++ b/src/sisudoc/io_out/hub.d
@@ -62,7 +62,7 @@ template outputHub() {
@system void outputHub(D)(D doc) {
mixin Msg;
auto msg = Msg!()(doc.matters);
- enum outTask { source_or_pod, sqlite, sqlite_multi, latex, odt, epub, html_scroll, html_seg, html_stuff }
+ enum outTask { source_or_pod, sqlite, sqlite_multi, latex, odt, epub, html_scroll, html_seg, html_stuff, text, skel }
void Scheduled(D)(int sched, D doc) {
auto msg = Msg!()(doc.matters);
if (sched == outTask.source_or_pod) {
@@ -118,6 +118,12 @@ template outputHub() {
outputLaTeX!()(doc.abstraction, doc.matters);
msg.vv("latex done");
}
+ if (sched == outTask.text) {
+ msg.v("text processing... ");
+ import sisudoc.io_out.text;
+ outputText!()(doc.abstraction, doc.matters);
+ msg.vv("text done");
+ }
if (sched == outTask.odt) {
msg.v("odf:odt processing... ");
import sisudoc.io_out.odt;
@@ -130,6 +136,12 @@ template outputHub() {
doc.SQLiteHubDiscreteBuildTablesAndPopulate!();
msg.vv("sqlite done");
}
+ if (sched == outTask.skel) {
+ msg.v("skel processing... ");
+ import sisudoc.io_out.skel;
+ outputSkel!()(doc.abstraction, doc.matters);
+ msg.vv("skel done");
+ }
}
if (doc.matters.opt.action.vox_gt_1) { writeln(doc.matters.src.filename_base); }
if (!(doc.matters.opt.action.parallelise_subprocesses)) {
diff --git a/src/sisudoc/io_out/latex.d b/src/sisudoc/io_out/latex.d
index 02e434e..96511c4 100644
--- a/src/sisudoc/io_out/latex.d
+++ b/src/sisudoc/io_out/latex.d
@@ -777,6 +777,24 @@ template outputLaTeX() {
}
return _txt.strip;
}
+ string quote(O,M)(
+ string _txt,
+ O obj,
+ M doc_matters,
+ ) {
+ if (obj.metainfo.is_a == "quote") {
+ string _tex_para;
+ _tex_para = q"┃\ocn{%s}\objBlockOpen
+"%s"
+\objBlockClose
+┃";
+ _txt = format(_tex_para,
+ obj.metainfo.object_number,
+ _txt.nbsp_char.footnotes.split(rgx.br_linebreaks_newlines).join("\\br\n").strip
+ ).strip;
+ }
+ return _txt;
+ }
string group(O,M)(
string _txt,
O obj,
@@ -790,7 +808,7 @@ template outputLaTeX() {
┃";
_txt = format(_tex_para,
obj.metainfo.object_number,
- _txt.footnotes.split(rgx.br_line_spaced).join("\\brl{1}").strip // provides more control (more noise, not as tidy)
+ _txt.footnotes.split(rgx.br_line_spaced).join(" \\brl{1} ").strip // provides more control (more noise, not as tidy)
// _txt.footnotes.split(rgx.br_line_spaced).join("") // this works using a line-space, looks tidy, keep ref.
).strip;
}
@@ -1207,7 +1225,9 @@ template outputLaTeX() {
case "block":
switch (obj.metainfo.is_a) {
case "quote":
- goto default; // TODO
+ _txt = _txt.quote(obj, doc_matters)
+ .links_and_images(obj, doc_matters);
+ goto default;
case "group": /+ (hardspaces not honored) [remove any hardspace marker] +/
_txt = _txt.group(obj, doc_matters)
.links_and_images(obj, doc_matters);
diff --git a/src/sisudoc/io_out/metadata.d b/src/sisudoc/io_out/metadata.d
index 6e6183b..a89b31a 100644
--- a/src/sisudoc/io_out/metadata.d
+++ b/src/sisudoc/io_out/metadata.d
@@ -417,6 +417,7 @@ string theme_light_1 = format(q"┃
}
auto pth_html = spinePathsHTML!()(doc_matters.output_path, doc_matters.src.language);
auto pth_epub = spinePathsEPUB!()(doc_matters.output_path, doc_matters.src.language);
+ auto pth_text = spinePathsText!()(doc_matters);
auto pth_pdf = spinePathsPDF!()(doc_matters);
auto pth_pod = spinePathsPods!()(doc_matters);
metadata_ ~= format(q"┃<body lang="en" xml:lang="en">
@@ -498,6 +499,10 @@ string theme_light_1 = format(q"┃
~ "." ~ doc_matters.src.language ~ ".letter.portrait.pdf\" class=\"lnkicon\">"
~ "&nbsp;□&nbsp;pdf&nbsp;(U.S.&nbsp;letter)&nbsp;</a>]&nbsp";
}
+ if (doc_matters.opt.action.html_link_text) {
+ metadata_ ~= "&nbsp;&nbsp;[<a href=\"../" ~ "text/" ~ doc_matters.src.filename_base ~ "." ~ doc_matters.src.language ~ ".txt\" class=\"lnkicon\">"
+ ~ "&nbsp;□&nbsp;txt&nbsp;</a>]&nbsp";
+ }
metadata_ ~= "</p>";
if (doc_matters.opt.action.html_link_markup_source) {
metadata_ ~= "<hr /><p class=\"lev1\">source: " ~ doc_matters.src.filename_base ~ "</p>";
diff --git a/src/sisudoc/io_out/paths_output.d b/src/sisudoc/io_out/paths_output.d
index a5b73a0..c3e677d 100644
--- a/src/sisudoc/io_out/paths_output.d
+++ b/src/sisudoc/io_out/paths_output.d
@@ -471,7 +471,7 @@ template spinePathsODT() {
auto spinePathsODT(M)(
M doc_matters,
) {
- auto out_pth = spineOutPaths!()( doc_matters.output_path, doc_matters.src.language);
+ auto out_pth = spineOutPaths!()(doc_matters.output_path, doc_matters.src.language);
string base_dir = "odf";
struct _PathsStruct {
string base_pth() { // dir will contain odt document file (also debug file tree)
@@ -668,3 +668,52 @@ template spinePathsSQLite() {
return _PathsStruct();
}
}
+
+template spinePathsText() {
+ import std.conv;
+ auto spinePathsText(M)(
+ M doc_matters,
+ ) {
+ auto out_pth = spineOutPaths!()(doc_matters.output_path, doc_matters.src.language);
+ string base_dir = "text";
+ struct _PathsStruct {
+ string base_pth() {
+ return (((out_pth.output_base).chainPath(base_dir)).asNormalizedPath).array;
+ }
+ string base_filename(string fn_src) {
+ return fn_src.baseName.stripExtension;
+ }
+ string text_file() {
+ return ((base_pth.chainPath(doc_matters.src.doc_uid_out ~ ".txt")).asNormalizedPath).array;
+ }
+ string dirtop() {
+ return "".chainPath("").array;
+ }
+ }
+ return _PathsStruct();
+ }
+}
+template spinePathsSkel() {
+ import std.conv;
+ auto spinePathsSkel(M)(
+ M doc_matters,
+ ) {
+ auto out_pth = spineOutPaths!()(doc_matters.output_path, doc_matters.src.language);
+ string base_dir = "skel";
+ struct _PathsStruct {
+ string base_pth() {
+ return (((out_pth.output_base).chainPath(base_dir)).asNormalizedPath).array;
+ }
+ string base_filename(string fn_src) {
+ return fn_src.baseName.stripExtension;
+ }
+ string skel_file() {
+ return ((base_pth.chainPath(doc_matters.src.doc_uid_out ~ ".skel")).asNormalizedPath).array;
+ }
+ string dirtop() {
+ return "".chainPath("").array;
+ }
+ }
+ return _PathsStruct();
+ }
+}
diff --git a/src/sisudoc/io_out/rgx.d b/src/sisudoc/io_out/rgx.d
index 9c70c1e..f54deda 100644
--- a/src/sisudoc/io_out/rgx.d
+++ b/src/sisudoc/io_out/rgx.d
@@ -78,9 +78,9 @@ static template spineRgxOut() {
static br_empty_line = ctRegex!(`\n[ ]*\n`, "mg");
static br_linebreaks_newlines = ctRegex!(`[\n┘┙]`, "mg");
static br_linebreaks = ctRegex!(`[┘┙]`, "mg");
- static br_line = ctRegex!(`┘`, "mg");
- static br_line_inline = ctRegex!(`┙`, "mg");
- static br_line_spaced = ctRegex!(`┚`, "mg");
+ static br_line = ctRegex!(`\s*┘\s*`, "mg");
+ static br_line_inline = ctRegex!(`\s*┙\s*`, "mg");
+ static br_line_spaced = ctRegex!(`\s*┚\s*`, "mg");
/+ quotation marks +/
static quotes_open_and_close = ctRegex!(`[“”]`, "mg");
/+ inline markup footnotes endnotes +/
@@ -95,6 +95,7 @@ static template spineRgxOut() {
static inline_al_delimiter_open_symbol_star = ctRegex!(`【[*]\s`, "m");
static inline_al_delimiter_open_symbol_plus = ctRegex!(`【[+]\s`, "m");
static inline_text_and_note_al_ = ctRegex!(`(.+?(?:【[*+]*\s+.+?】|.+))`, "mg");
+ static endnote_section_note = ctRegex!(`┥\s*⑆\^┨(?P<notenumber>\d+)\.┣\^┝┤(?P<link>¤?.+?)├.+`, "mg");
/+ inline markup links +/
static inline_image = ctRegex!(`(?P<pre>┥)☼(?P<imginf>(?P<img>[a-zA-Z0-9._-]+?\.(?:jpg|gif|png)),w(?P<width>\d+)h(?P<height>\d+))\s*(?P<post>.*?┝┤.*?├)`, "mg");
static inline_image_without_dimensions = ctRegex!(`(?P<pre>┥)☼(?P<imginf>(?P<img>[a-zA-Z0-9._-]+?\.(?:jpg|gif|png)),w(?P<width>0)h(?P<height>0))\s*(?P<post>.*?┝┤.*?├)`, "mg");
@@ -109,6 +110,7 @@ static template spineRgxOut() {
static inline_link_seg_and_hash = ctRegex!(`┥(?P<text>.+?)┝┤(?P<link>(?P<seg>[^/#├]*)#(?P<hash>.+?))├`, "mg");
static inline_link_clean = ctRegex!(`┤(?:.+?)├|[┥┝]`, "mg");
static inline_link_toc_to_backmatter = ctRegex!(`┤#(?P<link>endnotes|bibliography|bookindex|glossary|blurb)├`, "mg");
+ static find_bookindex_ocn_link_and_comma = ctRegex!(`[, ]*┥.+?┝┤#?\S+?├`, "mg");
static url = ctRegex!(`https?://`, "mg");
static uri = ctRegex!(`(?:https?|git)://`, "mg");
static uri_identify_components = ctRegex!(`(?P<type>(?:https?|git)://)(?P<path>\S+?/)(?P<file>[^/]+)$`, "mg");
diff --git a/src/sisudoc/io_out/skel.d b/src/sisudoc/io_out/skel.d
new file mode 100644
index 0000000..b616695
--- /dev/null
+++ b/src/sisudoc/io_out/skel.d
@@ -0,0 +1,268 @@
+/+
+- Name: SisuDoc Spine, Doc Reform [a part of]
+ - Description: documents, structuring, processing, publishing, search
+ - static content generator
+
+ - Author: Ralph Amissah
+ [ralph.amissah@gmail.com]
+
+ - Copyright: (C) 2015 - 2025 Ralph Amissah, All Rights Reserved.
+
+ - License: AGPL 3 or later:
+
+ Spine (SiSU), a framework for document structuring, publishing and
+ search
+
+ Copyright (C) Ralph Amissah
+
+ This program is free software: you can redistribute it and/or modify it
+ under the terms of the GNU AFERO General Public License as published by the
+ Free Software Foundation, either version 3 of the License, or (at your
+ option) any later version.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program. If not, see [https://www.gnu.org/licenses/].
+
+ If you have Internet connection, the latest version of the AGPL should be
+ available at these locations:
+ [https://www.fsf.org/licensing/licenses/agpl.html]
+ [https://www.gnu.org/licenses/agpl.html]
+
+ - Spine (by Doc Reform, related to SiSU) uses standard:
+ - docReform markup syntax
+ - standard SiSU markup syntax with modified headers and minor modifications
+ - docReform object numbering
+ - standard SiSU object citation numbering & system
+
+ - Homepages:
+ [https://www.sisudoc.org]
+ [https://www.doc-reform.org]
+
+ - Git
+ [https://git.sisudoc.org/]
+
++/
+module sisudoc.io_out.skel;
+@safe:
+template outputSkel() {
+ template munge() {
+ import std.stdio;
+ import std.conv;
+ void puts(string _obj_is) {
+ writeln(__FILE__, ":", __LINE__, ": ", _obj_is);
+ }
+ string newline = "\n";
+ string newlines = "\n\n";
+ string toc(O)(O obj) {
+ // puts(obj.metainfo.is_a);
+ // return "toc\n";
+ return obj.text ~ newline;
+ }
+ string heading(O)(O obj) {
+ /+
+ +/
+ // puts(obj.metainfo.is_a);
+ // return obj.metainfo.is_a;
+ return obj.text ~ newline ~ "「" ~ obj.metainfo.ocn.to!string ~ "」" ~ newlines;
+ }
+ string para(O)(O obj) {
+ /+
+ +/
+ // puts(obj.metainfo.is_a);
+ // return obj.metainfo.is_a;
+ return obj.text ~ newline ~ "「" ~ obj.metainfo.ocn.to!string ~ "」" ~ newlines;
+ }
+ string group(O)(O obj) {
+ /+
+ The "group" is different from the "block" mark in that "group" does not
+ preserve whitespace, the "block" mark does. The text falling within the
+ block is a single object.
+ +/
+ // puts(obj.metainfo.is_a);
+ // return obj.metainfo.is_a;
+ return obj.text ~ newline ~ "「" ~ obj.metainfo.ocn.to!string ~ "」" ~ newlines;
+ }
+ string block(O)(O obj) {
+ /+
+ The "block" is different from the "group" mark in that the "block" mark
+ (like the "poem" mark) preserves whitespace, the "group" mark does not.
+ The text falling within the "block" is a single object, which is different
+ from the "poem" mark where each identified verse is an object.
+ +/
+ // puts(obj.metainfo.is_a);
+ // return obj.metainfo.is_a;
+ return obj.text ~ newline ~ "「" ~ obj.metainfo.ocn.to!string ~ "」" ~ newlines;
+ }
+ string poem(O)(O obj) {
+ /+
+ The "poem" mark like the "block" preserves whitespace. Text followed by
+ two newlines are identified as verse and each verse is an object i.e. a
+ poem may consist of multiple verse each of which is identified as an
+ object, unlike a text "block" which is identified as a single object.
+ +/
+ // puts(obj.metainfo.is_a);
+ // return obj.metainfo.is_a;
+ // return obj.text ~ newline ~ "「" ~ obj.metainfo.ocn.to!string ~ "」" ~ newlines;
+ return obj.text ~ newlines;
+ }
+ string verse(O)(O obj) {
+ /+
+ See description of poem, the poem is demarkated but the verse is the
+ object.
+ +/
+ // puts(obj.metainfo.is_a);
+ // return obj.metainfo.is_a;
+ return obj.text ~ newline ~ "「" ~ obj.metainfo.ocn.to!string ~ "」" ~ newlines;
+ }
+ string code(O)(O obj) {
+ /+
+ "Code" blocks are a single text object, in which the original text is
+ preserved.
+ +/
+ // puts(obj.metainfo.is_a);
+ // return obj.metainfo.is_a;
+ return obj.text ~ newline ~ "「" ~ obj.metainfo.ocn.to!string ~ "」" ~ newlines;
+ }
+ string quote(O)(O obj) {
+ /+
+ +/
+ // puts(obj.metainfo.is_a);
+ // return obj.metainfo.is_a;
+ return obj.text ~ newline ~ "「" ~ obj.metainfo.ocn.to!string ~ "」" ~ newlines;
+ }
+ string table(O)(O obj) {
+ /+
+ +/
+ // puts(obj.metainfo.is_a);
+ // return obj.metainfo.is_a;
+ return obj.text ~ newline ~ "「" ~ obj.metainfo.ocn.to!string ~ "」" ~ newlines;
+ }
+ string endnote(O)(O obj) {
+ /+
+ +/
+ // puts(obj.metainfo.is_a);
+ // return obj.metainfo.is_a;
+ return obj.text ~ newlines;
+ }
+ string bookindex(O)(O obj) {
+ /+
+ +/
+ // puts(obj.metainfo.is_a);
+ // return obj.metainfo.is_a;
+ return obj.text ~ newlines;
+ }
+ string bibliography(O)(O obj) {
+ /+
+ +/
+ // puts(obj.metainfo.is_a);
+ // return obj.metainfo.is_a;
+ return obj.text ~ newlines;
+ }
+ string glossary(O)(O obj) {
+ /+
+ +/
+ // puts(obj.metainfo.is_a);
+ // return obj.metainfo.is_a;
+ return obj.text ~ newlines;
+ }
+ string blurb(O)(O obj) {
+ /+
+ +/
+ // puts(obj.metainfo.is_a);
+ // return obj.metainfo.is_a;
+ return obj.text ~ newlines;
+ }
+ string comment(O)(O obj) {
+ /+
+ +/
+ // puts(obj.metainfo.is_a);
+ // return obj.metainfo.is_a;
+ return obj.text ~ newlines;
+ }
+ }
+ template theDocument() {
+ import std.stdio;
+ import sisudoc.io_out;
+ // static auto rgx = RgxO();
+ string skel_head(M)(
+ M doc_matters,
+ ) {
+ return "head";
+ }
+ string skel_body(D,M)(
+ const D doc_abstraction,
+ M doc_matters,
+ ) {
+ string doc_object = "";
+ foreach (section; doc_matters.has.keys_seq.scroll) {
+ foreach (obj; doc_abstraction[section]) {
+ if (obj.metainfo.is_a == "toc") { doc_object ~= munge!().toc(obj); }
+ if (obj.metainfo.is_a == "heading") { doc_object ~= munge!().heading(obj); }
+ if (obj.metainfo.is_a == "para") { doc_object ~= munge!().para(obj); }
+ if (obj.metainfo.is_a == "group") { doc_object ~= munge!().group(obj); }
+ if (obj.metainfo.is_a == "block") { doc_object ~= munge!().block(obj); }
+ if (obj.metainfo.is_a == "poem") { doc_object ~= munge!().poem(obj); }
+ if (obj.metainfo.is_a == "verse") { doc_object ~= munge!().verse(obj); }
+ if (obj.metainfo.is_a == "code") { doc_object ~= munge!().code(obj); }
+ if (obj.metainfo.is_a == "quote") { doc_object ~= munge!().quote(obj); }
+ if (obj.metainfo.is_a == "table") { doc_object ~= munge!().table(obj); }
+ if (obj.metainfo.is_a == "endnote") { doc_object ~= munge!().endnote(obj); }
+ if (obj.metainfo.is_a == "bookindex") { doc_object ~= munge!().bookindex(obj); }
+ if (obj.metainfo.is_a == "bibliography") { doc_object ~= munge!().bibliography(obj); }
+ if (obj.metainfo.is_a == "glossary") { doc_object ~= munge!().glossary(obj); }
+ if (obj.metainfo.is_a == "blurb") { doc_object ~= munge!().blurb(obj); }
+ if (obj.metainfo.is_a == "comment") { doc_object ~= munge!().comment(obj); }
+ }
+ }
+ return doc_object;
+ }
+ string skel_tail(M)(
+ M doc_matters,
+ ) {
+ return "tail";
+ }
+ }
+ void outputSkel(D,M) (
+ const D doc_abstraction,
+ M doc_matters,
+ ) {
+ import std.stdio;
+ import sisudoc.io_out;
+ void skel_out(D,M)(
+ const D doc_abstraction,
+ M doc_matters,
+ ) {
+ struct Skel {
+ string head;
+ string content;
+ string tail;
+ }
+ auto skel = Skel();
+ skel.head = theDocument!().skel_head(doc_matters);
+ skel.content = theDocument!().skel_body(doc_abstraction, doc_matters);
+ skel.tail = theDocument!().skel_tail(doc_matters);
+ auto pth_skel = spinePathsSkel(doc_matters);
+ try {
+ import std.file;
+ if (!exists(pth_skel.base_pth)) {
+ (pth_skel.base_pth).mkdirRecurse;
+ }
+ } catch (ErrnoException ex) {
+ }
+ if (doc_matters.opt.action.vox_gt_1) {
+ writeln(" ", pth_skel.skel_file);
+ }
+ // writeln(pth_skel.base_pth);
+ auto f = File(pth_skel.skel_file, "w");
+ f.writeln(skel.head);
+ f.writeln(skel.content);
+ f.writeln(skel.tail);
+ }
+ skel_out(doc_abstraction, doc_matters);
+ }
+}
diff --git a/src/sisudoc/io_out/text.d b/src/sisudoc/io_out/text.d
new file mode 100644
index 0000000..9401bae
--- /dev/null
+++ b/src/sisudoc/io_out/text.d
@@ -0,0 +1,470 @@
+/+
+- Name: SisuDoc Spine, Doc Reform [a part of]
+ - Description: documents, structuring, processing, publishing, search
+ - static content generator
+
+ - Author: Ralph Amissah
+ [ralph.amissah@gmail.com]
+
+ - Copyright: (C) 2015 - 2025 Ralph Amissah, All Rights Reserved.
+
+ - License: AGPL 3 or later:
+
+ Spine (SiSU), a framework for document structuring, publishing and
+ search
+
+ Copyright (C) Ralph Amissah
+
+ This program is free software: you can redistribute it and/or modify it
+ under the terms of the GNU AFERO General Public License as published by the
+ Free Software Foundation, either version 3 of the License, or (at your
+ option) any later version.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program. If not, see [https://www.gnu.org/licenses/].
+
+ If you have Internet connection, the latest version of the AGPL should be
+ available at these locations:
+ [https://www.fsf.org/licensing/licenses/agpl.html]
+ [https://www.gnu.org/licenses/agpl.html]
+
+ - Spine (by Doc Reform, related to SiSU) uses standard:
+ - docReform markup syntax
+ - standard SiSU markup syntax with modified headers and minor modifications
+ - docReform object numbering
+ - standard SiSU object citation numbering & system
+
+ - Homepages:
+ [https://www.sisudoc.org]
+ [https://www.doc-reform.org]
+
+ - Git
+ [https://git.sisudoc.org/]
+
++/
+module sisudoc.io_out.text;
+@safe:
+template outputText() {
+ template munge() {
+ import sisudoc.io_out;
+ import sisudoc.io_out.rgx;
+ import std.stdio;
+ import std.conv;
+ import std.conv : to;
+ import std.typecons : Nullable;
+ mixin spineRgxOut;
+ static auto rgx = RgxO();
+ void puts(string _obj_is) {
+ writeln(__FILE__, ":", __LINE__, ": ", _obj_is);
+ }
+ string newline = "\n";
+ string newlines = "\n\n";
+ template special_characters_and_font_face() {
+ string code(string _txt){
+ _txt = _txt.replaceAll(rgx.nbsp_char, " ");
+ return _txt;
+ }
+ string general(string _txt) {
+ _txt = _txt
+ .replaceAll(rgx.nbsp_char, " ")
+ .replaceAll(rgx.br_line, "\n")
+ .replaceAll(rgx.br_line_inline, "\n")
+ .replaceAll(rgx.br_line_spaced, "\n\n")
+ .replaceAll(rgx.inline_strike, "-{$1}-")
+ .replaceAll(rgx.inline_insert, "+{$1}+")
+ .replaceAll(rgx.inline_cite, "\"{$1}\"")
+ .replaceAll(rgx.inline_emphasis, "!{$1}!")
+ .replaceAll(rgx.inline_bold, "*{$1}*")
+ .replaceAll(rgx.inline_italics, "/{$1}/")
+ .replaceAll(rgx.inline_underscore, "_{$1}_")
+ .replaceAll(rgx.inline_superscript, "^{$1}^")
+ .replaceAll(rgx.inline_subscript, ",{$1},")
+ .replaceAll(rgx.inline_mono, "#{$1}#");
+ return _txt;
+ }
+ string links_and_images(string _txt){
+ if (_txt.match(rgx.inline_link)) {
+ foreach (m; _txt.matchAll(rgx.inline_link)) {
+ _txt = (m.captures[3] == "0")
+ ? _txt.replaceFirst(rgx.inline_link, (m.captures[1]))
+ : _txt.replaceFirst(rgx.inline_link, (m.captures[1] ~ " ≫" ~ m.captures[3]));
+ }
+ }
+ if (_txt.matchFirst(rgx.inline_image)) {
+ foreach (m; _txt.matchAll(rgx.inline_image)) {
+ _txt = _txt.replaceFirst(rgx.inline_image, (m.captures[3]));
+ }
+ }
+ return _txt;
+ }
+ }
+ string generalMunge(O,M)(O obj, M doc_matters) {
+ string _txt = obj.text;
+ string _notes;
+ string _ocn;
+ string general_munge;
+ _ocn = (obj.metainfo.ocn == 0 || doc_matters.opt.action.ocn_off)
+ ? "" : "「" ~ obj.metainfo.ocn.to!string ~ "」" ~ newline;
+ if (_txt.matchFirst(rgx.inline_notes_al_gen)) {
+ foreach (m; _txt.matchAll(rgx.inline_notes_al_regular_number_note)) {
+ _notes ~= newlines ~ m["num"] ~ ". "
+ ~ special_characters_and_font_face!().general(m["note"].replaceAll(rgx.inline_link, ("$1")));
+ }
+ }
+ _txt = _txt.replaceAll(rgx.inline_notes_al_regular_number_note, "[$1]");
+ _txt = (obj.metainfo.is_a == "code")
+ ? special_characters_and_font_face!().code(_txt)
+ : special_characters_and_font_face!().general(_txt);
+ _txt = special_characters_and_font_face!().links_and_images(_txt);
+ general_munge = (obj.metainfo.is_a == "heading")
+ ? newline ~ _txt ~ _notes ~ newline ~ _ocn ~ newline
+ : _txt ~ _notes ~ newline ~ _ocn ~ newline;
+ return general_munge;
+ }
+ string toc(O,M)(O obj, M doc_matters) {
+ // puts(obj.metainfo.is_a);
+ // return "toc\n";
+ // _txt = _special_characters_and_font_face(obj.text);
+ string _txt = special_characters_and_font_face!().general(obj.text);
+ string _spaces;
+ switch (obj.attrib.indent_hang) {
+ case 1: _spaces = "";
+ break;
+ case 2: _spaces = ":";
+ break;
+ case 3: _spaces = "∴";
+ break;
+ case 4: _spaces = " ";
+ break;
+ case 5: _spaces = " ";
+ break;
+ case 6: _spaces = " ";
+ break;
+ case 7: _spaces = " ";
+ break;
+ case 8: _spaces = " ";
+ break;
+ default:
+ break;
+ }
+ _txt = (doc_matters.opt.action.ocn_off)
+ ? _txt.replaceAll(rgx.inline_link, (_spaces ~ "$1"))
+ : _txt.replaceAll(rgx.inline_link, (_spaces ~ "$1 ≫ $3"));
+ return _txt ~ newline;
+ }
+ string heading(O,M)(O obj, M doc_matters) {
+ // puts(obj.metainfo.is_a);
+ // return obj.metainfo.is_a;
+ string _general_munge = generalMunge(obj,doc_matters);
+ return _general_munge;
+ }
+ string para(O,M)(O obj, M doc_matters) {
+ // puts(obj.metainfo.is_a);
+ // return obj.metainfo.is_a;
+ string _general_munge = generalMunge(obj,doc_matters);
+ return _general_munge;
+ }
+ string group(O,M)(O obj, M doc_matters) {
+ /+
+ The "group" is different from the "block" mark in that "group" does not
+ preserve whitespace, the "block" mark does. The text falling within the
+ block is a single object.
+ +/
+ // puts(obj.metainfo.is_a);
+ // return obj.metainfo.is_a;
+ string _general_munge = generalMunge(obj,doc_matters);
+ return _general_munge;
+ }
+ string block(O,M)(O obj, M doc_matters) {
+ /+
+ The "block" is different from the "group" mark in that the "block" mark
+ (like the "poem" mark) preserves whitespace, the "group" mark does not.
+ The text falling within the "block" is a single object, which is different
+ from the "poem" mark where each identified verse is an object.
+ +/
+ // puts(obj.metainfo.is_a);
+ // return obj.metainfo.is_a;
+ string _general_munge = generalMunge(obj,doc_matters);
+ return _general_munge;
+ }
+ string poem(O,M)(O obj, M doc_matters) { // LATER
+ /+
+ The "poem" mark like the "block" preserves whitespace. Text followed by
+ two newlines are identified as verse and each verse is an object i.e. a
+ poem may consist of multiple verse each of which is identified as an
+ object, unlike a text "block" which is identified as a single object.
+ +/
+ // puts(obj.metainfo.is_a);
+ // return obj.metainfo.is_a;
+ return obj.text ~ newlines;
+ }
+ string verse(O,M)(O obj, M doc_matters) {
+ /+
+ See description of poem, the poem is demarkated but the verse is the
+ object.
+ +/
+ // puts(obj.metainfo.is_a);
+ // return obj.metainfo.is_a;
+ string _general_munge = generalMunge(obj,doc_matters);
+ return _general_munge;
+ }
+ string code(O,M)(O obj, M doc_matters) {
+ /+
+ "Code" blocks are a single text object, in which the original text is
+ preserved.
+ +/
+ // puts(obj.metainfo.is_a);
+ // return obj.metainfo.is_a;
+ string _general_munge = generalMunge(obj,doc_matters);
+ return _general_munge;
+ }
+ string quote(O,M)(O obj, M doc_matters) { // LATER
+ // puts(obj.metainfo.is_a);
+ // return obj.metainfo.is_a;
+ return obj.text ~ newline ~ "「" ~ obj.metainfo.ocn.to!string ~ "」" ~ newlines;
+ }
+ string table(O,M)(O obj, M doc_matters) {
+ // puts(obj.metainfo.is_a);
+ // return obj.metainfo.is_a;
+ auto tablarize(O)(
+ string _txt,
+ const O obj,
+ ) {
+ string[] _table_rows = (_txt).split(rgx.table_delimiter_row);
+ string[] _table_cols;
+ string _table = "";
+ string _tablenote = "";
+ int[] _col_width;
+ _col_width.length = obj.table.number_of_columns.to!ulong;
+ foreach(row_idx, row; _table_rows) {
+ _table_cols = row.split(rgx.table_delimiter_col);
+ _table ~= "";
+ foreach(col_idx, cell; _table_cols) {
+ if (!((_table_cols.length == 1)
+ && (_table_rows.length <= row_idx+2))) {
+ if (_col_width[col_idx] < (cell.length.to!int)) {
+ _col_width[col_idx] = cell.length.to!int;
+ }
+ }
+ }
+ }
+ foreach(row_idx, row; _table_rows) {
+ _table_cols = row.split(rgx.table_delimiter_col);
+ foreach(col_idx, cell; _table_cols) {
+ if ((_table_cols.length == 1)
+ && (_table_rows.length <= row_idx+2)) { // check row_idx+2 (rather than == ++row_idx)
+ _tablenote ~= cell ~ newline;
+ } else {
+ if (obj.table.column_aligns[col_idx] == "l") {
+ _table ~= format(q"┃%-*s%s┃",
+ _col_width[col_idx],
+ cell,
+ (_table_cols.length > (col_idx + 1)) ? " ┊ " : ""
+ );
+ } else {
+ _table ~= format(q"┃%*s%s┃",
+ _col_width[col_idx],
+ cell,
+ (_table_cols.length > (col_idx + 1)) ? " ┊ " : ""
+ );
+ }
+ _table = _table
+ .replaceAll(regex("\\s*$"), "");
+ }
+ }
+ _table ~= newline;
+ }
+ Tuple!(string, string) t = tuple(
+ _table,
+ _tablenote,
+ );
+ return t;
+ }
+ // string _txt = obj.text;
+ // writeln(obj.table.column_widths);
+ auto _t = tablarize(obj.text, obj);
+ string _txt = _t[0];
+ string _tablenote = _t[1];
+ return _txt ~ _tablenote ~ "「" ~ obj.metainfo.ocn.to!string ~ "」" ~ newlines;
+ }
+ string endnote(O,M)(O obj, M doc_matters) {
+ // puts(obj.metainfo.is_a);
+ // return obj.metainfo.is_a;
+ string _ocn;
+ _ocn = "「" ~ obj.metainfo.ocn.to!string ~ "」";
+ string _txt = obj.text;
+ string _parent_ocn;
+ _txt = _txt
+ .replaceAll(rgx.inline_link, ("$1")) // consider
+ .replaceFirst(rgx.inline_superscript, ("$1"));
+ _parent_ocn = (obj.metainfo.parent_ocn == 0 || doc_matters.opt.action.ocn_off)
+ ? "" : " ≫" ~ obj.metainfo.parent_ocn.to!string;
+ _txt = special_characters_and_font_face!().general(_txt) ~ _parent_ocn;
+ return _txt ~ newlines;
+ }
+ string bookindex(O,M)(O obj, M doc_matters) {
+ // puts(obj.metainfo.is_a);
+ // return obj.metainfo.is_a;
+ string _txt = obj.text;
+ _txt = (doc_matters.opt.action.ocn_off)
+ ? _txt.replaceAll(rgx.find_bookindex_ocn_link_and_comma, "")
+ .replaceAll(regex("\\s*\\\\"), "")
+ : _txt.replaceAll(rgx.inline_link, ("≫$1"))
+ .replaceAll(regex("\\s*\\\\"), "");
+ _txt = special_characters_and_font_face!().general(_txt);
+ return _txt ~ newlines;
+ }
+ string bibliography(O,M)(O obj, M doc_matters) {
+ // puts(obj.metainfo.is_a);
+ // return obj.metainfo.is_a;
+ string _txt = obj.text;
+ _txt = special_characters_and_font_face!().general(_txt);
+ return _txt ~ newlines;
+ // ALT:
+ // string _general_munge = generalMunge(obj,doc_matters);
+ // return _general_munge;
+ }
+ string glossary(O,M)(O obj, M doc_matters) {
+ // puts(obj.metainfo.is_a);
+ // return obj.metainfo.is_a;
+ string _txt = obj.text;
+ _txt = special_characters_and_font_face!().general(_txt);
+ return _txt;
+ }
+ string blurb(O,M)(O obj, M doc_matters) {
+ // puts(obj.metainfo.is_a);
+ // return obj.metainfo.is_a;
+ string _general_munge = generalMunge(obj,doc_matters);
+ return _general_munge;
+ }
+ string comment(O,M)(O obj, M doc_matters) { // LATER
+ /+
+ +/
+ // puts(obj.metainfo.is_a);
+ // return obj.metainfo.is_a;
+ return obj.text ~ newlines;
+ }
+ }
+ template theDocument() {
+ import std.stdio;
+ import sisudoc.io_out;
+ string text_head(M)(
+ M doc_matters,
+ ) {
+ return "head";
+ }
+ string text_body(D,M)(
+ const D doc_abstraction,
+ M doc_matters,
+ ) {
+ string doc_object = "";
+ foreach (section; doc_matters.has.keys_seq.scroll) {
+ foreach (obj; doc_abstraction[section]) {
+ if (obj.metainfo.is_a == "toc") { doc_object ~= munge!().toc(obj, doc_matters); }
+ if (obj.metainfo.is_a == "heading") { doc_object ~= munge!().heading(obj, doc_matters); }
+ if (obj.metainfo.is_a == "para") { doc_object ~= munge!().para(obj, doc_matters); }
+ if (obj.metainfo.is_a == "group") { doc_object ~= munge!().group(obj, doc_matters); }
+ if (obj.metainfo.is_a == "block") { doc_object ~= munge!().block(obj, doc_matters); }
+ if (obj.metainfo.is_a == "poem") { doc_object ~= munge!().poem(obj, doc_matters); } // CHECK
+ if (obj.metainfo.is_a == "verse") { doc_object ~= munge!().verse(obj, doc_matters); } // CHECK
+ if (obj.metainfo.is_a == "code") { doc_object ~= munge!().code(obj, doc_matters); }
+ if (obj.metainfo.is_a == "quote") { doc_object ~= munge!().quote(obj, doc_matters); } // LATER
+ if (obj.metainfo.is_a == "table") { doc_object ~= munge!().table(obj, doc_matters); }
+ if (obj.metainfo.is_a == "endnote") { doc_object ~= munge!().endnote(obj, doc_matters); }
+ if (obj.metainfo.is_a == "bookindex") { doc_object ~= munge!().bookindex(obj, doc_matters); } // CHECK
+ if (obj.metainfo.is_a == "bibliography") { doc_object ~= munge!().bibliography(obj, doc_matters); } // CHECK
+ if (obj.metainfo.is_a == "glossary") { doc_object ~= munge!().glossary(obj, doc_matters); } // CHECK
+ if (obj.metainfo.is_a == "blurb") { doc_object ~= munge!().blurb(obj, doc_matters); } // CHECK
+ if (obj.metainfo.is_a == "comment") { doc_object ~= munge!().comment(obj, doc_matters); } // LATER
+ }
+ }
+ return doc_object;
+ }
+ string text_tail(M)(
+ M doc_matters,
+ ) {
+ string metadata_;
+ if (doc_matters.opt.action.debug_do) {
+ writeln(doc_matters.src.filename_base);
+ writeln("Title: ", doc_matters.conf_make_meta.meta.title_full);
+ writeln(" Author: ", doc_matters.conf_make_meta.meta.creator_author);
+ writeln(" Published: ", doc_matters.conf_make_meta.meta.date_published);
+ writeln(" Copyright: ", doc_matters.conf_make_meta.meta.rights_copyright);
+ writeln(" License: ", doc_matters.conf_make_meta.meta.rights_license);
+ }
+ if (!(doc_matters.conf_make_meta.meta.title_full.empty)) {
+ metadata_ ~= "Title: " ~ doc_matters.conf_make_meta.meta.title_full ~ "\n\n";
+ } else if (doc_matters.opt.action.debug_do || doc_matters.opt.action.vox_gt_3) {
+ writeln("ERROR no Title information provided in document header ", doc_matters.src.filename_base);
+ }
+ if (!(doc_matters.conf_make_meta.meta.creator_author.empty)) {
+ if (doc_matters.opt.action.html_link_curate) {
+ metadata_ ~= "Author: " ~ doc_matters.conf_make_meta.meta.creator_author_surname.translate([' ' : "_"])
+ ~ doc_matters.conf_make_meta.meta.creator_author ~ "\n\n";
+ } else {
+ metadata_ ~= "Author: "
+ ~ doc_matters.conf_make_meta.meta.creator_author ~ "\n\n";
+ }
+ } else if (doc_matters.opt.action.debug_do || doc_matters.opt.action.vox_gt_3) {
+ writeln("ERROR no Author information provided in document header ", doc_matters.src.filename_base);
+ }
+ metadata_ ~= "Published: " ~ doc_matters.conf_make_meta.meta.date_published ~ "\n\n";
+ if (!(doc_matters.conf_make_meta.meta.rights_copyright.empty)) {
+ metadata_ ~= "Copyright: " ~ doc_matters.conf_make_meta.meta.rights_copyright ~ "\n\n";
+ } else if (doc_matters.opt.action.debug_do || doc_matters.opt.action.vox_gt_3) {
+ writeln("WARNING no Copyright information provided in document header ", doc_matters.src.filename_base);
+ }
+ if (!(doc_matters.conf_make_meta.meta.rights_license.empty)) {
+ metadata_ ~= "License: " ~ doc_matters.conf_make_meta.meta.rights_license ~ "\n\n";
+ } else if (doc_matters.opt.action.debug_do || doc_matters.opt.action.vox_gt_3) {
+ writeln("WARNING no License information provided in document header ", doc_matters.src.filename_base);
+ }
+ metadata_ ~= doc_matters.generator_program.project_name.strip ~ "\n";
+ metadata_ ~= doc_matters.generator_program.url_home.strip;
+ return metadata_;
+ }
+ }
+ void outputText(D,M) (
+ const D doc_abstraction,
+ M doc_matters,
+ ) {
+ import std.stdio;
+ import sisudoc.io_out;
+ void text_out(D,M)(
+ const D doc_abstraction,
+ M doc_matters,
+ ) {
+ struct Text {
+ string head;
+ string content;
+ string tail;
+ }
+ auto text = Text();
+ // text.head = theDocument!().text_head(doc_matters);
+ text.content = theDocument!().text_body(doc_abstraction, doc_matters);
+ text.tail = theDocument!().text_tail(doc_matters);
+ auto pth_text = spinePathsText(doc_matters);
+ try {
+ import std.file;
+ if (!exists(pth_text.base_pth)) {
+ (pth_text.base_pth).mkdirRecurse;
+ }
+ } catch (ErrnoException ex) {
+ }
+ if (doc_matters.opt.action.vox_gt_1) {
+ writeln(" ", pth_text.text_file);
+ }
+ // writeln(pth_text.base_pth);
+ auto f = File(pth_text.text_file, "w");
+ // f.writeln(text.head);
+ f.writeln(text.content);
+ f.writeln(text.tail);
+ }
+ text_out(doc_abstraction, doc_matters);
+ }
+}
diff --git a/src/sisudoc/meta/metadoc_from_src.d b/src/sisudoc/meta/metadoc_from_src.d
index 24ae935..4240a3f 100644
--- a/src/sisudoc/meta/metadoc_from_src.d
+++ b/src/sisudoc/meta/metadoc_from_src.d
@@ -770,7 +770,7 @@ template docAbstraction() {
comp_obj_.has.inline_links = substantive_obj_misc_struct.has_links;
comp_obj_.has.image_without_dimensions = substantive_obj_misc_struct.has_images_without_dimensions;
the_document_body_section ~= comp_obj_;
- tag_assoc = an_object.inline_para_link_anchor(tag_in_seg, tag_assoc);
+ tag_assoc = an_object.inline_para_link_anchor(tag_in_seg, tag_assoc);
{
ST_txt_by_line_common_reset _get = txt_by_line_common_reset_(line_occur, an_object, pith);
{
@@ -939,7 +939,7 @@ template docAbstraction() {
}
{ // document segnames
ST_segnames get_segnames;
- get_segnames = the_document_body_section.after_doc_determine_segnames(the_document_endnotes_section, the_document_glossary_section, the_document_bibliography_section, the_document_bookindex_section, the_document_blurb_section, segnames, html_segnames_ptr_cntr, html_segnames_ptr); //
+ get_segnames = the_document_body_section.after_doc_determine_segnames(the_document_endnotes_section, the_document_glossary_section, the_document_bibliography_section, the_document_bookindex_section, the_document_blurb_section, segnames, html_segnames_ptr_cntr, html_segnames_ptr);
segnames = get_segnames.segnames;
html_segnames_ptr_cntr = get_segnames.html_segnames_ptr_cntr;
html_segnames_ptr = get_segnames.html_segnames_ptr;
@@ -1376,36 +1376,42 @@ template docAbstraction() {
"scroll": ["head", "toc", "body",],
"seg": ["head", "toc", "body",],
"sql": ["head", "body",],
- "latex": ["head", "toc", "body",]
+ "latex": ["head", "toc", "body",],
+ "text": ["head", "toc", "body",],
];
if (document_the["endnotes"].length > 1) {
document_section_keys_sequenced["scroll"] ~= "endnotes";
document_section_keys_sequenced["seg"] ~= "endnotes";
document_section_keys_sequenced["latex"] ~= "endnotes";
+ document_section_keys_sequenced["text"] ~= "endnotes";
}
if (document_the["glossary"].length > 1) {
document_section_keys_sequenced["scroll"] ~= "glossary";
document_section_keys_sequenced["seg"] ~= "glossary";
document_section_keys_sequenced["sql"] ~= "glossary";
document_section_keys_sequenced["latex"] ~= "glossary";
+ document_section_keys_sequenced["text"] ~= "glossary";
}
if (document_the["bibliography"].length > 1) {
document_section_keys_sequenced["scroll"] ~= "bibliography";
document_section_keys_sequenced["seg"] ~= "bibliography";
document_section_keys_sequenced["sql"] ~= "bibliography";
document_section_keys_sequenced["latex"] ~= "bibliography";
+ document_section_keys_sequenced["text"] ~= "bibliography";
}
if (document_the["bookindex"].length > 1) {
document_section_keys_sequenced["scroll"] ~= "bookindex";
document_section_keys_sequenced["seg"] ~= "bookindex";
document_section_keys_sequenced["sql"] ~= "bookindex";
document_section_keys_sequenced["latex"] ~= "bookindex";
+ document_section_keys_sequenced["text"] ~= "bookindex";
}
if (document_the["blurb"].length > 1) {
document_section_keys_sequenced["scroll"] ~= "blurb";
document_section_keys_sequenced["seg"] ~= "blurb";
document_section_keys_sequenced["sql"] ~= "blurb";
document_section_keys_sequenced["latex"] ~= "blurb";
+ document_section_keys_sequenced["text"] ~= "blurb";
}
if ((opt_action.html)
|| (opt_action.html_scroll)
diff --git a/src/sisudoc/meta/metadoc_from_src_functions.d b/src/sisudoc/meta/metadoc_from_src_functions.d
index 3ae10d1..63143e9 100644
--- a/src/sisudoc/meta/metadoc_from_src_functions.d
+++ b/src/sisudoc/meta/metadoc_from_src_functions.d
@@ -2557,10 +2557,8 @@ template docAbstractionFunctions() {
CMM conf_make_meta,
Flag!"_new_doc" _new_doc
) {
- obj_txt["munge"] = obj_[obj_key_].dup;
- obj_txt["munge"] = (obj_["is"].match(ctRegex!(`verse|code`)))
- ? obj_txt["munge"]
- : obj_txt["munge"].strip;
+ obj_txt["munge"] = obj_[obj_key_].dup;
+ obj_txt["munge"] = (obj_["is"].match(ctRegex!(`verse|code`))) ? obj_txt["munge"] : obj_txt["munge"].strip;
if (_new_doc) {
anchor_tag = "";
}
@@ -2579,8 +2577,8 @@ template docAbstractionFunctions() {
|| (obj_["is"] == "group")
|| (obj_["is"] == "block")
|| (obj_["is"] == "verse")) {
- obj_txt["munge"] = (obj_txt["munge"]).inline_markup_faces;
- obj_txt["munge"] = (obj_txt["munge"]).links_and_images;
+ obj_txt["munge"] = (obj_txt["munge"]).inline_markup_faces;
+ obj_txt["munge"] = (obj_txt["munge"]).links_and_images;
}
switch (obj_["is"]) {
case "heading":
@@ -3299,8 +3297,8 @@ template docAbstractionFunctions() {
// ↓ - endnotes
struct NotesSection {
string[string] object_notes;
- int previous_count;
- int mkn;
+ int previous_count;
+ int mkn;
static auto rgx = RgxI();
private auto gather_notes_for_endnote_section(
ObjGenericComposite[] contents_am,
@@ -4235,11 +4233,31 @@ template docAbstractionFunctions() {
int html_segnames_ptr_cntr,
int html_segnames_ptr,
) {
+ string[string][string] notes_;
+ if (the_document_body_section.length > 1) {
+ string _notes;
+ foreach (ref obj; the_document_body_section) {
+ if (obj.has.inline_notes_reg) {
+ if ((obj.text).matchFirst(rgx.inline_notes_al_gen)) {
+ foreach (m; (obj.text).matchAll(rgx.inline_notes_al_regular_number_note)) {
+ _notes ~= "\n\n" ~ m["num"] ~ ". " ~ m["note"];
+ notes_[(m["num"])]["ocn"] = obj.metainfo.ocn.to!string;
+ }
+ }
+ }
+ }
+ }
if (the_document_endnotes_section.length > 1) {
segnames["html"] ~= "endnotes";
segnames["epub"] ~= "endnotes";
html_segnames_ptr = html_segnames_ptr_cntr;
foreach (ref obj; the_document_endnotes_section) {
+ auto matches = (obj.text).matchAll(rgx.endnote_section_note);
+ foreach (m; matches) {
+ obj.metainfo.parent_ocn = notes_[(m["notenumber"])]["ocn"].to!int;
+ }
+ }
+ foreach (ref obj; the_document_endnotes_section) {
if (obj.metainfo.is_a == "heading") {
obj.metainfo.parent_ocn = obj.metainfo.markedup_ancestors[obj.metainfo.parent_lev_markup];
}
@@ -5406,6 +5424,9 @@ template docSectKeysSeq() {
string[] latex() {
return document_section_keys_sequenced["latex"];
}
+ string[] text() {
+ return document_section_keys_sequenced["text"];
+ }
}
return doc_sect_keys_seq();
}
diff --git a/src/sisudoc/meta/rgx.d b/src/sisudoc/meta/rgx.d
index 259ab82..86ca40c 100644
--- a/src/sisudoc/meta/rgx.d
+++ b/src/sisudoc/meta/rgx.d
@@ -148,16 +148,16 @@ static template spineRgxIn() {
static table_col_separator_nl = ctRegex!(`[┊]$`, "mg");
/+ inline markup footnotes endnotes +/
static inline_notes_curly_gen = ctRegex!(`~\{.+?\}~`, "m");
- static inline_notes_curly = ctRegex!(`~\{\s*(.+?)\}~`, "mg");
- static inline_notes_curly_sp_asterisk = ctRegex!(`~\{[*]+\s+(.+?)\}~`, "m");
- static inline_notes_curly_sp_plus = ctRegex!(`~\{[+]+\s+(.+?)\}~`, "m");
+ static inline_notes_curly = ctRegex!(`~\{\s*(.+?)\s*\}~`, "mg");
+ static inline_notes_curly_sp_asterisk = ctRegex!(`~\{[*]+\s+(.+?)\s*\}~`, "m");
+ static inline_notes_curly_sp_plus = ctRegex!(`~\{[+]+\s+(.+?)\s*\}~`, "m");
static note_ref = ctRegex!(`^\S+?noteref_(?P<ref>[0-9]+)`, "mg"); // {^{73.}^}#noteref_73
static smid_inline_url_generic = ctRegex!(`(?:^|[}(\[ ])(?:(?:https?|git):\/\/|¤?\.\.\/|¤?\.\/|¤|#)[a-zA-Z0-9_#]`, "mg");
static smid_inline_url = ctRegex!(`((?:(?:https?|git):\/\/|¤?\.\.\/|¤?\.\/|¤|#)[a-zA-Z0-9_]\S*)`, "mg");
static smid_inline_link_naked_url = ctRegex!(`(?P<pre>^|[ (\[])(?P<link>(?:(?:https?|git):\/\/|¤?\.\.\/|¤?\.\/|¤)\S+?)(?=[.,;:?!'"]?([ )\]]|$))`, "mg");
static smid_inline_link_markup_regular = ctRegex!(`(?P<pre>^|[ (\[])\{\s*(?P<content>.+?)\s*\}(?P<link>(?:(?:https?|git):\/\/|¤?\.\.\/|¤?\.\/|¤|#)\S+?)(?=[;:!,?.]?([ )\]]|$))`, "mg");
- static smid_inline_link_endnote_url_helper_punctuated = ctRegex!(`\{~\^\s+(?P<content>.+?)\}(?P<link>(?:(?:https?|git):\/\/|¤?\.\.\/|¤?\.\/|¤|#)\S+?)(?=[.,;:?!]?([ ]|$))`, "mg");
- static smid_inline_link_endnote_url_helper = ctRegex!(`\{~\^\s+(?P<content>.+?)\}(?P<link>(?:(?:https?|git):\/\/|¤?\.\.\/|¤?\.\/|¤|#)\S+)`, "mg");
+ static smid_inline_link_endnote_url_helper_punctuated = ctRegex!(`\{~\^\s+(?P<content>.+?)\s*\}(?P<link>(?:(?:https?|git):\/\/|¤?\.\.\/|¤?\.\/|¤|#)\S+?)(?=[.,;:?!]?([ ]|$))`, "mg");
+ static smid_inline_link_endnote_url_helper = ctRegex!(`\{~\^\s+(?P<content>.+?)\s*\}(?P<link>(?:(?:https?|git):\/\/|¤?\.\.\/|¤?\.\/|¤|#)\S+)`, "mg");
static image = ctRegex!(`([a-zA-Z0-9._-]+?\.(?:png|gif|jpg))`, "mg");
static smid_image = ctRegex!(`(?P<pre>(?:^|[ ])[{┥](?:~\^\s+|\s*))(?P<image>[a-zA-Z0-9._-]+?\.(?:png|gif|jpg))(?P<post>(?:.*?)\s*[}┝](?:image|┤.*?├|(?:(?:https?|git):\/\/|¤?\.\.\/|¤?\.\/|¤|#)\S+?)(?=[;:!,?.]?([ )\]]|$)))`, "mg");
static smid_image_generic = ctRegex!(`(?:^|[ ])[{┥](?:~\^\s+|\s*)\S+\.(?:png|gif|jpg).*?[}┝](?:image|┤.*?├|(?:(?:https?|git):\/\/|¤?\.\.\/|¤?\.\/|¤|#)\S+?)(?=[;:!,?.]?([ )\]]|$))`, "mg");
@@ -221,9 +221,9 @@ static template spineRgxIn() {
static br_empty_line = ctRegex!(`\n[ ]*\n`, "mg");
static br_linebreaks_newlines = ctRegex!(`[\n┘┙]`, "mg");
static br_linebreaks = ctRegex!(`[┘┙]`, "mg");
- static br_line = ctRegex!(`┘`, "mg");
- static br_line_inline = ctRegex!(`┙`, "mg");
- static br_line_spaced = ctRegex!(`┚`, "mg");
+ static br_line = ctRegex!(`\s*┘\s*`, "mg");
+ static br_line_inline = ctRegex!(`\s*┙\s*`, "mg");
+ static br_line_spaced = ctRegex!(`\s*┚\s*`, "mg");
/+ inline markup footnotes endnotes +/
static inline_notes_al = ctRegex!(`【(?:[*+]\s+|\s*)(.+?)】`, "mg");
static inline_notes_al_special = ctRegex!(`【(?:[*+]\s+)(.+?)】`, "mg"); // TODO remove match when special footnotes are implemented
@@ -236,6 +236,7 @@ static template spineRgxIn() {
static inline_al_delimiter_open_symbol_star = ctRegex!(`【[*]\s`, "m");
static inline_al_delimiter_open_symbol_plus = ctRegex!(`【[+]\s`, "m");
static inline_text_and_note_al_ = ctRegex!(`(.+?(?:【[*+]*\s+.+?】|.+))`, "mg");
+ static endnote_section_note = ctRegex!(`┥\s*⑆\^┨(?P<notenumber>\d+)\.┣\^┝┤(?P<link>¤?.+?)├.+`, "mg");
/+ inline markup links +/
static inline_image = ctRegex!(`(?P<pre>┥)☼(?P<imginf>(?P<img>[a-zA-Z0-9._-]+?\.(?:jpg|gif|png)),w(?P<width>\d+)h(?P<height>\d+))\s*(?P<post>.*?┝┤.*?├)`, "mg");
static inline_image_without_dimensions = ctRegex!(`(?P<pre>┥)☼(?P<imginf>(?P<img>[a-zA-Z0-9._-]+?\.(?:jpg|gif|png)),w(?P<width>0)h(?P<height>0))\s*(?P<post>.*?┝┤.*?├)`, "mg");
@@ -250,6 +251,7 @@ static template spineRgxIn() {
static inline_link_seg_and_hash = ctRegex!(`┥(?P<text>.+?)┝┤(?P<link>(?P<seg>[^/#├]*)#(?P<hash>.+?))├`, "mg");
static inline_link_clean = ctRegex!(`┤(?:.+?)├|[┥┝]`, "mg");
static inline_link_toc_to_backmatter = ctRegex!(`┤#(?P<link>endnotes|bibliography|bookindex|glossary|blurb)├`, "mg");
+ static find_bookindex_ocn_link_and_comma = ctRegex!(`[, ]*┥.+?┝┤#?\S+?├`, "mg");
static url = ctRegex!(`https?://`, "mg");
static uri = ctRegex!(`(?:https?|git)://`, "mg");
static uri_identify_components = ctRegex!(`(?P<type>(?:https?|git)://)(?P<path>\S+?/)(?P<file>[^/]+)$`, "mg");
diff --git a/src/sisudoc/spine.d b/src/sisudoc/spine.d
index eceaf51..f53fc09 100755
--- a/src/sisudoc/spine.d
+++ b/src/sisudoc/spine.d
@@ -144,6 +144,7 @@ string program_name = "spine";
"html-link-pdf-a4" : false,
"html-link-pdf-letter" : false,
"html-link-search" : false,
+ "html-link-text" : false,
"html-seg" : false,
"html-scroll" : false,
"latex" : false,
@@ -153,6 +154,7 @@ string program_name = "spine";
"light" : false,
"manifest" : false,
"hide-ocn" : false,
+ "no-ocn" : false,
"ocn-off" : false,
"odf" : false,
"odt" : false,
@@ -176,6 +178,7 @@ string program_name = "spine";
"show-pod" : false,
"show-sqlite" : false,
"show-summary" : false,
+ "skel" : false,
"source" : false,
"sqlite-discrete" : false,
"sqlite-db-create" : false,
@@ -250,6 +253,7 @@ string program_name = "spine";
"html-link-pdf", "provide html link to pdf a4 & letter output", &opts["html-link-pdf"],
"html-link-pdf-a4", "provide html link to pdf a4 output", &opts["html-link-pdf-a4"],
"html-link-pdf-letter", "provide html link to pdf letter size output", &opts["html-link-pdf-letter"],
+ "html-link-text", "provide html link to text output", &opts["html-link-text"],
"html-link-search", "html embedded search submission", &opts["html-link-search"],
"html-seg", "process html output", &opts["html-seg"],
"html-scroll", "process html output", &opts["html-scroll"],
@@ -260,6 +264,7 @@ string program_name = "spine";
"latex-header-sty", "latex document header sty files", &opts["latex-header-sty"],
"light", "default light theme", &opts["light"],
"manifest", "process manifest output", &opts["manifest"],
+ "no-ocn", "object cite numbers", &opts["no-ocn"],
"ocn-off", "object cite numbers", &opts["ocn-off"],
"odf", "open document format text (--odt)", &opts["odf"],
"odt", "open document format text", &opts["odt"],
@@ -299,6 +304,7 @@ string program_name = "spine";
"set-digest", "default hash digest type (e.g. sha256)", &settings["set-digest"],
"set-papersize", "default papersize (latex pdf eg. a4 or a5 or b4 or letter)", &settings["set-papersize"],
"set-textwrap", "default textwrap (e.g. 80 (characters)", &settings["set-textwrap"],
+ "skel", "skel (dummy outline)", &opts["skel"],
"sqlite-discrete", "process discrete sqlite output", &opts["sqlite-discrete"],
"sqlite-db-create", "create db, create tables", &opts["sqlite-db-create"],
"sqlite-db-drop", "drop tables & db", &opts["sqlite-db-drop"],
@@ -339,7 +345,7 @@ string program_name = "spine";
if (helpInfo.helpWanted) {
defaultGetoptPrinter("Some information about the program.", helpInfo.options);
}
- enum outTask { source_or_pod, sqlite, sqlite_multi, latex, odt, epub, html_scroll, html_seg, html_stuff }
+ enum outTask { source_or_pod, sqlite, sqlite_multi, latex, odt, epub, html_scroll, html_seg, html_stuff, text, skel }
struct OptActions {
@trusted bool allow_downloads() {
return opts["allow-downloads"];
@@ -443,6 +449,12 @@ string program_name = "spine";
@trusted bool html_link_pdf_letter() {
return (opts["html-link-pdf-letter"]) ? true : false;
}
+ @trusted bool html_link_text() {
+ return (opts["html-link-text"]) ? true : false;
+ }
+ @trusted bool text_link_curate() {
+ return (opts["text-link-curate"]) ? true : false;
+ }
@trusted bool html_link_search() {
return (opts["html-link-search"]) ? true : false;
}
@@ -477,7 +489,7 @@ string program_name = "spine";
return opts["hide-ocn"];
}
@trusted bool ocn_off() {
- return opts["ocn-off"];
+ return ((opts["ocn-off"]) || (opts["no-ocn"])) ? true : false;
}
@trusted bool pod() {
return opts["pod"];
@@ -551,6 +563,12 @@ string program_name = "spine";
|| opts["sqlite-update"]
) ? true : false;
}
+ @trusted bool skel() {
+ return opts["skel"];
+ }
+ @trusted bool text() {
+ return opts["text"];
+ }
@trusted bool vox_0() { // --silent
return opts["vox_is0"];
}
@@ -587,9 +605,6 @@ string program_name = "spine";
@trusted bool vox_default() { return vox_gt_1; } // defalt, & above
@trusted bool vox_verbose() { return vox_gt_2; } // --verbose -v & above
@trusted bool vox_very_verbose() { return vox_gt_3; } // --very-verbose
- @trusted bool text() {
- return opts["text"];
- }
@trusted bool xhtml() {
return opts["xhtml"];
}
@@ -703,6 +718,8 @@ string program_name = "spine";
|| latex
|| manifest
|| sqlite_discrete
+ || text
+ || skel
) {
_is = true;
} else { _is = false; }
@@ -721,6 +738,8 @@ string program_name = "spine";
if (html_stuff) { schedule ~= outTask.html_stuff; }
if (odt) { schedule ~= outTask.odt; }
if (latex) { schedule ~= outTask.latex; }
+ if (text) { schedule ~= outTask.text; }
+ if (skel) { schedule ~= outTask.skel; }
return schedule.sort().uniq;
}
@trusted bool abstraction() {
@@ -737,6 +756,8 @@ string program_name = "spine";
|| sqlite_discrete
|| sqlite_delete
|| sqlite_update
+ || text
+ || skel
) ? true : false;
}
@trusted bool require_processing_files() {
@@ -758,6 +779,7 @@ string program_name = "spine";
|| sqlite_update
|| text
|| xhtml
+ || skel
) ? true : false;
}
@trusted bool meta_processing_general() {
@@ -770,6 +792,8 @@ string program_name = "spine";
|| latex
|| sqlite_discrete
|| sqlite_update
+ || text
+ || skel
) ? true :false;
}
@trusted bool meta_processing_xml_dom() {