diff options
| author | Ralph Amissah <ralph.amissah@gmail.com> | 2026-07-30 23:24:06 -0400 |
|---|---|---|
| committer | Ralph Amissah <ralph.amissah@gmail.com> | 2026-07-31 14:48:09 -0400 |
| commit | 569a22bdb0841f360af97683ded5006329a14b28 (patch) | |
| tree | 5d8969d9c269792468219af492d068dfcb7ea720 /src | |
| parent | digest (sha256) for document root heading (title) (diff) | |
Diffstat (limited to 'src')
| -rw-r--r-- | src/sisudoc/ocda/abstraction/ssp.d | 8 | ||||
| -rw-r--r-- | src/sisudoc/ocda/meta/metadoc_from_src.d | 12 | ||||
| -rw-r--r-- | src/sisudoc/ocda/meta/metadoc_from_src_functions.d | 44 | ||||
| -rw-r--r-- | src/sisudoc/ocda/meta/metadoc_object_setter.d | 9 | ||||
| -rw-r--r-- | src/sisudoc/outputs/io_out/source_pod.d | 42 |
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( |
