aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorRalph Amissah <ralph.amissah@gmail.com>2026-07-30 23:24:06 -0400
committerRalph Amissah <ralph.amissah@gmail.com>2026-07-31 14:48:09 -0400
commit569a22bdb0841f360af97683ded5006329a14b28 (patch)
tree5d8969d9c269792468219af492d068dfcb7ea720 /src
parentdigest (sha256) for document root heading (title) (diff)
digests (sha256) a revisitHEADmain
Diffstat (limited to 'src')
-rw-r--r--src/sisudoc/ocda/abstraction/ssp.d8
-rw-r--r--src/sisudoc/ocda/meta/metadoc_from_src.d12
-rw-r--r--src/sisudoc/ocda/meta/metadoc_from_src_functions.d44
-rw-r--r--src/sisudoc/ocda/meta/metadoc_object_setter.d9
-rw-r--r--src/sisudoc/outputs/io_out/source_pod.d42
5 files changed, 87 insertions, 28 deletions
diff --git a/src/sisudoc/ocda/abstraction/ssp.d b/src/sisudoc/ocda/abstraction/ssp.d
index cb3747b..a2135df 100644
--- a/src/sisudoc/ocda/abstraction/ssp.d
+++ b/src/sisudoc/ocda/abstraction/ssp.d
@@ -291,14 +291,16 @@ template spineAbstractionTxt() {
/+ ↓ sha256 digest +/
{
bool has_sha = false;
- foreach (b; obj.metainfo.sha256) {
+ foreach (b; obj.metainfo.sha256.text) {
if (b != 0) { has_sha = true; break; }
}
if (has_sha) {
- output ~= ".sha256: " ~ obj.metainfo.sha256.toHexString.to!string;
+ if (doc_matters.opt.action.vox_gt_2) {
+ writeln(obj.metainfo.sha256.summary); // USE check
+ }
+ output ~= ".sha256: " ~ obj.metainfo.sha256.text.toHexString.to!string;
}
}
-
/+ ↓ text attributes +/
if (obj.attrib.indent_base != 0 || obj.attrib.indent_hang != 0)
output ~= ".indent: " ~ obj.attrib.indent_base.to!string
diff --git a/src/sisudoc/ocda/meta/metadoc_from_src.d b/src/sisudoc/ocda/meta/metadoc_from_src.d
index 2955ee3..d41701c 100644
--- a/src/sisudoc/ocda/meta/metadoc_from_src.d
+++ b/src/sisudoc/ocda/meta/metadoc_from_src.d
@@ -1031,7 +1031,7 @@ template docAbstraction() {
_images ~= extract_images(obj.text);
obj = _image_dimensions(obj, manifested);
}
- obj.metainfo.sha256 = obj.obj_digest;
+ obj.metainfo.sha256 = obj.obj_digest(manifested);
obj = _links(obj);
}
}
@@ -1103,7 +1103,7 @@ template docAbstraction() {
obj.metainfo.ocn = obj_cite_digits.object_number;
obj.metainfo.identifier = obj_cite_digits.identifier;
}
- obj.metainfo.sha256 = obj.obj_digest;
+ obj.metainfo.sha256 = obj.obj_digest(manifested);
obj = _links(obj);
}
}
@@ -1139,7 +1139,7 @@ template docAbstraction() {
obj.metainfo.ocn = obj_cite_digits.object_number;
obj.metainfo.identifier = obj_cite_digits.identifier;
}
- obj.metainfo.sha256 = obj.obj_digest;
+ obj.metainfo.sha256 = obj.obj_digest(manifested);
obj = _links(obj);
}
}
@@ -1184,7 +1184,7 @@ template docAbstraction() {
obj.metainfo.o_n_book_index = obj_cite_digits.bkidx;
obj.metainfo.object_number_type = OCNtype.bkidx;
}
- obj.metainfo.sha256 = obj.obj_digest;
+ obj.metainfo.sha256 = obj.obj_digest(manifested);
obj = _links(obj);
}
// TODO assert failure, reinstate
@@ -1222,7 +1222,7 @@ template docAbstraction() {
obj.metainfo.object_number_off = obj_cite_digits.off;
obj.metainfo.object_number_type = OCNtype.non;
}
- obj.metainfo.sha256 = obj.obj_digest;
+ obj.metainfo.sha256 = obj.obj_digest(manifested);
obj = _links(obj);
}
}
@@ -1247,7 +1247,7 @@ template docAbstraction() {
foreach (ref obj; the_document_head_section) {
if (obj.metainfo.is_a == "heading") {
if (obj.metainfo.heading_lev_markup == 0) { // sha for document root heading, caught here, should have been done earlier
- obj.metainfo.sha256 = obj.obj_digest;
+ obj.metainfo.sha256 = obj.obj_digest(manifested);
}
foreach (pair; pairs) {
if (obj.metainfo.ocn == pair[0]) {
diff --git a/src/sisudoc/ocda/meta/metadoc_from_src_functions.d b/src/sisudoc/ocda/meta/metadoc_from_src_functions.d
index f5c9bec..3bd9292 100644
--- a/src/sisudoc/ocda/meta/metadoc_from_src_functions.d
+++ b/src/sisudoc/ocda/meta/metadoc_from_src_functions.d
@@ -3184,10 +3184,50 @@ template docAbstractionFunctions() {
}
// ↑ - object tags
// ↓ - object digest
- pure ubyte[32] obj_digest()(
+ // pure
+ SHA_256_Hashes_ obj_digest(M)(
ObjGenericComposite obj,
+ M manifested,
) {
- obj.metainfo.sha256 = obj.text.sha256Of;
+ ubyte[32] safeComputeHash(H)(H file_with_path) @trusted {
+ auto file_read = File(file_with_path, "r");
+ ubyte[32] file_sha256 = digest!SHA256(file_read.byChunk(4096 * 1024));
+ return file_sha256;
+ }
+ obj.metainfo.sha256.text = obj.text.sha256Of;
+ string image_with_path;
+ string image_path = manifested.src.image_dir_path ~ "/";
+ char[64] image_hash;
+ int n = 0;
+ if (obj.metainfo.is_a == "heading") {
+ obj.metainfo.sha256.summary ~=
+ obj.metainfo.sha256.text.toHexString ~ " "
+ ~ obj.metainfo.ocn.to!string ~ " "
+ ~ obj.metainfo.is_a ~ " "
+ ~ obj.metainfo.marked_up_level ~ "~ "
+ ~ obj.text;
+ // ~ image_summary; // heading assumed not to have image CONSIDER
+ } else {
+ if ((obj.text).match(rgx.inline_image)) {
+ foreach (m; (obj.text).matchAll(rgx.inline_image)) {
+ image_with_path = image_path ~ m["img"];
+ ubyte[32] image_sha256 = safeComputeHash(image_with_path);
+ obj.metainfo.sha256.images = [ m["img"] : image_sha256 ];
+ }
+ }
+ char[] image_summary;
+ if (obj.metainfo.sha256.images.length > 0) {
+ foreach (i,h; obj.metainfo.sha256.images) {
+ // writeln(h.toHexString.to!string, " - ", i);
+ image_summary ~= "\n" ~ h.toHexString.to!string ~ " - " ~ i;
+ }
+ }
+ obj.metainfo.sha256.summary ~=
+ obj.metainfo.sha256.text.toHexString
+ ~ " " ~ obj.metainfo.ocn.to!string ~ " "
+ ~ obj.metainfo.is_a
+ ~ image_summary;
+ }
return obj.metainfo.sha256;
}
// ↑ - object digest
diff --git a/src/sisudoc/ocda/meta/metadoc_object_setter.d b/src/sisudoc/ocda/meta/metadoc_object_setter.d
index c5c8b1b..718ce55 100644
--- a/src/sisudoc/ocda/meta/metadoc_object_setter.d
+++ b/src/sisudoc/ocda/meta/metadoc_object_setter.d
@@ -101,6 +101,11 @@ template ObjectSetter() {
string[] lev4_subtoc = [];
string[] anchor_tags = [];
}
+ struct SHA_256_Hashes_ {
+ char[] summary;
+ ubyte[32] text; // both text and inline footnotes; consider additionally separating text and footnotes
+ ubyte[32][string] images;
+ }
struct DocObj_MetaInfo_ {
string is_of_part = ""; // frontmatter, body, backmatter
string is_of_section = ""; // toc, body, glossary, biography, book index, blurb
@@ -119,7 +124,7 @@ template ObjectSetter() {
int o_n_bibliography = 0;
int o_n_book_index = 0;
int o_n_blurb = 0;
- string object_number_substantive() const @property {
+ string object_number_substantive() const @property {
return (o_n_substantive == 0) ? "" : o_n_substantive.to!string;
}
string object_number_non_substantive() const @property {
@@ -174,7 +179,7 @@ template ObjectSetter() {
int parent_ocn = 0;
int last_descendant_ocn = 0;
int[] children_headings;
- ubyte[32] sha256;
+ SHA_256_Hashes_ sha256;
}
struct ObjGenericComposite {
string text = "";
diff --git a/src/sisudoc/outputs/io_out/source_pod.d b/src/sisudoc/outputs/io_out/source_pod.d
index f6c73d6..b32abcd 100644
--- a/src/sisudoc/outputs/io_out/source_pod.d
+++ b/src/sisudoc/outputs/io_out/source_pod.d
@@ -51,6 +51,7 @@ module sisudoc.outputs.io_out.source_pod;
@system: // is not @safe: use: @system: or @trusted:
template spinePod() {
import std.digest.sha;
+ // import std.digest : toHexString;
import std.file;
import std.outbuffer;
import std.zip;
@@ -148,6 +149,21 @@ template spinePod() {
));
}
}
+ // ↓ - object digest & length
+ struct ST_file_stat {
+ ubyte[32] sha256hash;
+ ulong fileSize;
+ }
+ ST_file_stat getFileStat(F)(F filepath) @trusted {
+ auto file = File(filepath, "r");
+ ubyte[32] file_sha256 = digest!SHA256(file.byChunk(4096 * 1024));
+ ulong fileSize = file.size;
+ ST_file_stat _file;
+ _file.sha256hash = file_sha256;
+ _file.fileSize = fileSize;
+ return _file;
+ }
+ // ↑ - object digest & length
auto pod_zipMakeReady(M,P,S)(M doc_matters, P pths_pod, S _st) {
auto pth_dr_doc_src = doc_matters.src_path_info;
if (doc_matters.opt.action.vox_gt_3) { // correct
@@ -177,9 +193,8 @@ template spinePod() {
if (exists(fn_src_in)) {
debug(io) { writeln("(io debug) src out found: ", fn_src_in); }
{ // take DIGEST write to pod file digests.txt
- auto data = (cast(byte[]) (fn_src_in).read);
- _digests["shared"]["images"] ~= data.sha256Of.toHexString ~ "::" ~ data.length.to!string ~ " - " ~ image ~ "\n";
- // writeln(data.sha256Of.toHexString, "::", data.length, " - ", image);
+ ST_file_stat file_ = getFileStat(fn_src_in);
+ _digests["shared"]["images"] ~= file_.sha256hash.toHexString ~ "::" ~ file_.fileSize.to!string ~ " - " ~ image ~ "\n";
}
if (doc_matters.opt.action.source_or_pod) {
fn_src_in.copy(fn_src_out_filesystem);
@@ -216,9 +231,9 @@ template spinePod() {
if (exists(fn_src_in)) {
debug(io) { writeln("(io debug) src out found: ", fn_src_in); }
{ // take DIGEST write to pod file digests.txt
- auto data = (cast(byte[]) (fn_src_in).read);
- _digests[_lang]["ssp"] ~= data.sha256Of.toHexString
- ~ "::" ~ data.length.to!string ~ " - " ~ ssp_filename ~ "\n";
+ ST_file_stat file_ = getFileStat(fn_src_in);
+ _digests[_lang]["ssp"] ~= file_.sha256hash.toHexString
+ ~ "::" ~ file_.fileSize.to!string ~ " - " ~ ssp_filename ~ "\n";
}
fn_src_in.copy(fn_src_out_filesystem);
zip = podArchive("file_path_text", fn_src_in, fn_src_out_pod_zip_base, zip);
@@ -317,9 +332,8 @@ template spinePod() {
if (exists(_pth_file_sstm)) { // what of language?
debug(io) { writeln("(io debug) src in found: ", _pth_file_sstm); }
{ // take DIGEST write to pod file digests.txt
- auto data = (cast(byte[]) (_pth_file_sstm).read);
- _digests[_lang]["sstm"] ~= data.sha256Of.toHexString ~ "::" ~ data.length.to!string ~ " - " ~ doc_matters.src.filename ~ " - [" ~ _lang ~ "]";
- // writeln(data.sha256Of.toHexString, "::", data.length, " - ", doc_matters.src.filename);
+ ST_file_stat file_ = getFileStat(_pth_file_sstm);
+ _digests[_lang]["sstm"] ~= file_.sha256hash.toHexString ~ "::" ~ file_.fileSize.to!string ~ " - " ~ doc_matters.src.filename ~ " - [" ~ _lang ~ "]";
}
filelist_src_out_pod_arr ~= fn_src_out_pod_zip_base;
filelist_src_zpod_arr ~= fn_src_out_inside_pod;
@@ -378,9 +392,8 @@ template spinePod() {
foreach (_lang; doc_matters.pod.manifest_list_of_languages) {
string _pth_mkup_src_in = _path_to_pod ~ _podname ~ "/" ~ _root_to_lang ~ _lang ~ "/" ~ _filename;
{ // take DIGEST write to pod file digests.txt
- auto data = (cast(byte[]) (_pth_mkup_src_in).read);
- _digests[_language]["ssi"] ~= data.sha256Of.toHexString ~ "::" ~ data.length.to!string ~ " - " ~ _filename ~ " - [" ~ _lang ~ "]" ~ "\n";
- // writeln(data.sha256Of.toHexString, "::", data.length, " - ", _filename, " - [", _lang, "]");
+ ST_file_stat file_ = getFileStat(_pth_mkup_src_in);
+ _digests[_language]["ssi"] ~= file_.sha256hash.toHexString ~ "::" ~ file_.fileSize.to!string ~ " - " ~ _filename ~ " - [" ~ _lang ~ "]" ~ "\n";
}
string _pth_mkup_src_out = "pod/" ~ _root_to_lang ~ _lang ~ "/" ~ _filename;
if (exists(_pth_mkup_src_in)) {
@@ -406,9 +419,8 @@ template spinePod() {
} else {
auto fn_src_in = insert_file;
{ // take DIGEST write to pod file digests.txt // FIX likely bug insert_file includes path, not what you wish to write
- auto data = (cast(byte[]) (fn_src_in).read);
- _digests["en"]["ssi"] ~= data.sha256Of.toHexString ~ "::" ~ data.length.to!string ~ " - " ~ insert_file ~ "\n";
- // writeln(data.sha256Of.toHexString, "::", data.length, " - ", insert_file);
+ ST_file_stat file_ = getFileStat(fn_src_in);
+ _digests["en"]["ssi"] ~= file_.sha256hash.toHexString ~ "::" ~ file_.fileSize.to!string ~ " - " ~ insert_file ~ "\n";
}
auto fn_src_out_pod_zip_base
= pths_pod.fn_doc_insert(