diff options
| author | Ralph Amissah <ralph.amissah@gmail.com> | 2026-08-26 18:25:08 -0400 |
|---|---|---|
| committer | Ralph Amissah <ralph.amissah@gmail.com> | 2026-08-28 09:01:12 -0400 |
| commit | 0456cf8f767124e0a0033fac09d7ae3b666e389d (patch) | |
| tree | 6e08c0fa00d44f7d7dda610618f743341040c279 | |
| parent | sha summary, mostly cosmetic, some work on images (diff) | |
.ssp: image as repeatable self-describing property
a repeatable record, one line per image, filename first:
.image: won_benkler_2_1.png sha256:5BA492C2...D128 bytes:93861
an object embedding more than one image emits more than one .image
line.
(assisted by Claude-Code)
| -rw-r--r-- | org/out_src_abstraction_ocda_ssp.org | 38 | ||||
| -rw-r--r-- | src/sisudoc/ocda/abstraction/ssp.d | 40 |
2 files changed, 27 insertions, 51 deletions
diff --git a/org/out_src_abstraction_ocda_ssp.org b/org/out_src_abstraction_ocda_ssp.org index 32ffdab..2d8b128 100644 --- a/org/out_src_abstraction_ocda_ssp.org +++ b/org/out_src_abstraction_ocda_ssp.org @@ -31,7 +31,6 @@ rename source_abstraction_peg_txt.d <<doc_header_including_copyright_and_license>> module sisudoc.ocda.abstraction.ssp; @safe: - /+ ↓ write document abstraction as human-readable .ssp text file +/ template spineAbstractionTxt() { import std.conv : to; @@ -41,17 +40,14 @@ template spineAbstractionTxt() { import std.stdio; import std.string; import std.array; - void spineAbstractionTxt(D)(D doc) { auto doc_abstraction = doc.abstraction; auto doc_matters = doc.matters; string[] output; - /+ ↓ header comment +/ output ~= "% SiSU Document Abstraction v0.1"; output ~= "% Source: " ~ doc_matters.src.filename; output ~= ""; - /+ ↓ @meta block +/ output ~= "@meta {"; auto meta = doc_matters.conf_make_meta.meta; @@ -115,7 +111,6 @@ template spineAbstractionTxt() { output ~= " notes.summary: " ~ meta.notes_summary; output ~= "}"; output ~= ""; - /+ ↓ @make block +/ output ~= "@make {"; auto make = doc_matters.conf_make_meta.make; @@ -127,7 +122,6 @@ template spineAbstractionTxt() { output ~= " auto_num_depth: " ~ make.auto_num_depth.to!string; output ~= "}"; output ~= ""; - /+ ↓ @doc_has block +/ output ~= "@doc_has {"; output ~= " inline_links: " ~ doc_matters.has.inline_links.to!string; @@ -142,23 +136,18 @@ template spineAbstractionTxt() { output ~= " quotes: " ~ doc_matters.has.quotes.to!string; output ~= "}"; output ~= ""; - /+ ↓ document sections +/ string[] section_order = ["head", "toc", "body", "endnotes", "glossary", "bibliography", "bookindex", "blurb"]; - foreach (section; section_order) { if (section !in doc_abstraction) continue; auto section_objs = doc_abstraction[section]; if (section_objs.length == 0) continue; - output ~= "@" ~ section ~ " {"; output ~= ""; - foreach (obj; section_objs) { /+ ↓ object declaration line +/ string obj_decl = "[" ~ obj.metainfo.ocn.to!string ~ "] "; - if (obj.metainfo.is_a == "heading") { string lev = obj.metainfo.marked_up_level; obj_decl ~= "heading :" ~ lev; @@ -170,7 +159,6 @@ template spineAbstractionTxt() { obj_decl ~= obj.metainfo.is_a; } output ~= obj_decl; - /+ ↓ properties (only non-default values) +/ if (obj.metainfo.is_of_part.length > 0) output ~= ".part: " ~ obj.metainfo.is_of_part; @@ -181,7 +169,6 @@ template spineAbstractionTxt() { output ~= ".parent: " ~ obj.metainfo.parent_ocn.to!string; if (obj.metainfo.last_descendant_ocn != 0) output ~= ".last_descendant: " ~ obj.metainfo.last_descendant_ocn.to!string; - /+ ↓ child headings (from pre-computed map) +/ if (obj.metainfo.children_headings.length > 0) { string[] ch; @@ -190,7 +177,6 @@ template spineAbstractionTxt() { } output ~= ".children: " ~ ch.join(" "); } - /+ ↓ ancestors (only if non-zero) +/ { bool has_anc = false; @@ -250,7 +236,6 @@ template spineAbstractionTxt() { output ~= ".dom_status_collapsed: " ~ ds; } } - if (obj.metainfo.heading_lev_collapsed < 9) output ~= ".heading_lev_collapsed: " ~ obj.metainfo.heading_lev_collapsed.to!string; if (obj.metainfo.parent_lev_markup != 0) @@ -269,7 +254,6 @@ template spineAbstractionTxt() { output ~= ".meta_lang: " ~ obj.metainfo.lang; if (obj.metainfo.syntax.length > 0) output ~= ".meta_syntax: " ~ obj.metainfo.syntax; - /+ ↓ sha256 digest +/ { bool has_sha = false; @@ -283,6 +267,19 @@ template spineAbstractionTxt() { output ~= ".sha256: " ~ obj.metainfo.sha256.text.toHexString.to!string; } } + /+ ↓ images, repeatable record, one per image in order of appearance: + .image: <filename> sha256:<HEX> bytes:<n> + filename first (the object's handle on the image), remaining fields + self-describing key:value tokens so that further fields (e.g. dim:) + can be added later without invalidating existing readers + +/ + if (obj.metainfo.sha256.images.length > 0) { + foreach (i; obj.metainfo.sha256.images) { + output ~= ".image: " ~ i.fileName + ~ " sha256:" ~ i.fileHash_sha256.toHexString.to!string + ~ " bytes:" ~ i.fileSize.to!string; + } + } /+ ↓ text attributes +/ if (obj.attrib.indent_base != 0 || obj.attrib.indent_hang != 0) output ~= ".indent: " ~ obj.attrib.indent_base.to!string @@ -291,7 +288,6 @@ template spineAbstractionTxt() { output ~= ".bullet: true"; if (obj.attrib.language.length > 0) output ~= ".lang: " ~ obj.attrib.language; - /+ ↓ has flags +/ { string[] has_flags; @@ -303,7 +299,6 @@ template spineAbstractionTxt() { if (has_flags.length > 0) output ~= ".has: " ~ has_flags.join(" "); } - /+ ↓ table properties +/ if (obj.metainfo.is_a == "table" && obj.table.number_of_columns > 0) { output ~= ".table_cols: " ~ obj.table.number_of_columns.to!string; @@ -320,7 +315,6 @@ template spineAbstractionTxt() { if (obj.table.walls) output ~= ".table_walls: true"; } - /+ ↓ code block properties +/ if (obj.metainfo.is_a == "code") { if (obj.code_block.syntax.length > 0) @@ -328,7 +322,6 @@ template spineAbstractionTxt() { if (obj.code_block.linenumbers) output ~= ".code_linenumbers: true"; } - /+ ↓ stow (extracted links) +/ if (obj.stow.link.length > 0) { foreach (lnk; obj.stow.link) { @@ -336,7 +329,6 @@ template spineAbstractionTxt() { output ~= ".stow_link: " ~ lnk; } } - /+ ↓ tag properties +/ if (obj.tags.in_segment_html.length > 0) output ~= ".segment: " ~ obj.tags.in_segment_html; @@ -375,21 +367,17 @@ template spineAbstractionTxt() { output ~= ".anchor_tag: " ~ at; } } - /+ ↓ text content +/ if (obj.text.length > 0) { foreach (line; obj.text.split("\n")) { output ~= "| " ~ line; } } - output ~= ""; } - output ~= "}"; output ~= ""; } - /+ ↓ write to file +/ /+ path: <output_path>/<language>/abstraction/<doc_uid_out>.ssp +/ string out_root = (doc_matters.output_path.length > 0) diff --git a/src/sisudoc/ocda/abstraction/ssp.d b/src/sisudoc/ocda/abstraction/ssp.d index 4f9dd45..95f7fda 100644 --- a/src/sisudoc/ocda/abstraction/ssp.d +++ b/src/sisudoc/ocda/abstraction/ssp.d @@ -49,7 +49,6 @@ +/ module sisudoc.ocda.abstraction.ssp; @safe: - /+ ↓ write document abstraction as human-readable .ssp text file +/ template spineAbstractionTxt() { import std.conv : to; @@ -59,17 +58,14 @@ template spineAbstractionTxt() { import std.stdio; import std.string; import std.array; - void spineAbstractionTxt(D)(D doc) { auto doc_abstraction = doc.abstraction; auto doc_matters = doc.matters; string[] output; - /+ ↓ header comment +/ output ~= "% SiSU Document Abstraction v0.1"; output ~= "% Source: " ~ doc_matters.src.filename; output ~= ""; - /+ ↓ @meta block +/ output ~= "@meta {"; auto meta = doc_matters.conf_make_meta.meta; @@ -133,7 +129,6 @@ template spineAbstractionTxt() { output ~= " notes.summary: " ~ meta.notes_summary; output ~= "}"; output ~= ""; - /+ ↓ @make block +/ output ~= "@make {"; auto make = doc_matters.conf_make_meta.make; @@ -145,7 +140,6 @@ template spineAbstractionTxt() { output ~= " auto_num_depth: " ~ make.auto_num_depth.to!string; output ~= "}"; output ~= ""; - /+ ↓ @doc_has block +/ output ~= "@doc_has {"; output ~= " inline_links: " ~ doc_matters.has.inline_links.to!string; @@ -160,23 +154,18 @@ template spineAbstractionTxt() { output ~= " quotes: " ~ doc_matters.has.quotes.to!string; output ~= "}"; output ~= ""; - /+ ↓ document sections +/ string[] section_order = ["head", "toc", "body", "endnotes", "glossary", "bibliography", "bookindex", "blurb"]; - foreach (section; section_order) { if (section !in doc_abstraction) continue; auto section_objs = doc_abstraction[section]; if (section_objs.length == 0) continue; - output ~= "@" ~ section ~ " {"; output ~= ""; - foreach (obj; section_objs) { /+ ↓ object declaration line +/ string obj_decl = "[" ~ obj.metainfo.ocn.to!string ~ "] "; - if (obj.metainfo.is_a == "heading") { string lev = obj.metainfo.marked_up_level; obj_decl ~= "heading :" ~ lev; @@ -188,7 +177,6 @@ template spineAbstractionTxt() { obj_decl ~= obj.metainfo.is_a; } output ~= obj_decl; - /+ ↓ properties (only non-default values) +/ if (obj.metainfo.is_of_part.length > 0) output ~= ".part: " ~ obj.metainfo.is_of_part; @@ -199,7 +187,6 @@ template spineAbstractionTxt() { output ~= ".parent: " ~ obj.metainfo.parent_ocn.to!string; if (obj.metainfo.last_descendant_ocn != 0) output ~= ".last_descendant: " ~ obj.metainfo.last_descendant_ocn.to!string; - /+ ↓ child headings (from pre-computed map) +/ if (obj.metainfo.children_headings.length > 0) { string[] ch; @@ -208,7 +195,6 @@ template spineAbstractionTxt() { } output ~= ".children: " ~ ch.join(" "); } - /+ ↓ ancestors (only if non-zero) +/ { bool has_anc = false; @@ -268,7 +254,6 @@ template spineAbstractionTxt() { output ~= ".dom_status_collapsed: " ~ ds; } } - if (obj.metainfo.heading_lev_collapsed < 9) output ~= ".heading_lev_collapsed: " ~ obj.metainfo.heading_lev_collapsed.to!string; if (obj.metainfo.parent_lev_markup != 0) @@ -287,7 +272,6 @@ template spineAbstractionTxt() { output ~= ".meta_lang: " ~ obj.metainfo.lang; if (obj.metainfo.syntax.length > 0) output ~= ".meta_syntax: " ~ obj.metainfo.syntax; - /+ ↓ sha256 digest +/ { bool has_sha = false; @@ -296,11 +280,24 @@ template spineAbstractionTxt() { } if (has_sha) { if (doc_matters.opt.action.vox_gt_3) { - writeln(obj.metainfo.sha256.summary); // USE check + writeln(obj.metainfo.sha256.summary); } output ~= ".sha256: " ~ obj.metainfo.sha256.text.toHexString.to!string; } } + /+ ↓ images, repeatable record, one per image in order of appearance: + .image: <filename> sha256:<HEX> bytes:<n> + filename first (the object's handle on the image), remaining fields + self-describing key:value tokens so that further fields (e.g. dim:) + can be added later without invalidating existing readers + +/ + if (obj.metainfo.sha256.images.length > 0) { + foreach (i; obj.metainfo.sha256.images) { + output ~= ".image: " ~ i.fileName + ~ " sha256:" ~ i.fileHash_sha256.toHexString.to!string + ~ " bytes:" ~ i.fileSize.to!string; + } + } /+ ↓ text attributes +/ if (obj.attrib.indent_base != 0 || obj.attrib.indent_hang != 0) output ~= ".indent: " ~ obj.attrib.indent_base.to!string @@ -309,7 +306,6 @@ template spineAbstractionTxt() { output ~= ".bullet: true"; if (obj.attrib.language.length > 0) output ~= ".lang: " ~ obj.attrib.language; - /+ ↓ has flags +/ { string[] has_flags; @@ -321,7 +317,6 @@ template spineAbstractionTxt() { if (has_flags.length > 0) output ~= ".has: " ~ has_flags.join(" "); } - /+ ↓ table properties +/ if (obj.metainfo.is_a == "table" && obj.table.number_of_columns > 0) { output ~= ".table_cols: " ~ obj.table.number_of_columns.to!string; @@ -338,7 +333,6 @@ template spineAbstractionTxt() { if (obj.table.walls) output ~= ".table_walls: true"; } - /+ ↓ code block properties +/ if (obj.metainfo.is_a == "code") { if (obj.code_block.syntax.length > 0) @@ -346,7 +340,6 @@ template spineAbstractionTxt() { if (obj.code_block.linenumbers) output ~= ".code_linenumbers: true"; } - /+ ↓ stow (extracted links) +/ if (obj.stow.link.length > 0) { foreach (lnk; obj.stow.link) { @@ -354,7 +347,6 @@ template spineAbstractionTxt() { output ~= ".stow_link: " ~ lnk; } } - /+ ↓ tag properties +/ if (obj.tags.in_segment_html.length > 0) output ~= ".segment: " ~ obj.tags.in_segment_html; @@ -393,21 +385,17 @@ template spineAbstractionTxt() { output ~= ".anchor_tag: " ~ at; } } - /+ ↓ text content +/ if (obj.text.length > 0) { foreach (line; obj.text.split("\n")) { output ~= "| " ~ line; } } - output ~= ""; } - output ~= "}"; output ~= ""; } - /+ ↓ write to file +/ /+ path: <output_path>/<language>/abstraction/<doc_uid_out>.ssp +/ string out_root = (doc_matters.output_path.length > 0) |
