aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/sisudoc
diff options
context:
space:
mode:
Diffstat (limited to 'src/sisudoc')
-rw-r--r--src/sisudoc/ocda/abstraction/db_in.d1
-rw-r--r--src/sisudoc/ocda/abstraction/doc_has.d40
-rw-r--r--src/sisudoc/ocda/abstraction/ssp.d12
-rw-r--r--src/sisudoc/ocda/abstraction/ssp_in.d1
-rw-r--r--src/sisudoc/ocda/meta/metadoc_from_src.d31
-rw-r--r--src/sisudoc/ocda/meta/metadoc_object_setter.d10
-rw-r--r--src/sisudoc/outputs/io_out/create_ocda_db.d6
7 files changed, 76 insertions, 25 deletions
diff --git a/src/sisudoc/ocda/abstraction/db_in.d b/src/sisudoc/ocda/abstraction/db_in.d
index 0d78f12..6e9b0e2 100644
--- a/src/sisudoc/ocda/abstraction/db_in.d
+++ b/src/sisudoc/ocda/abstraction/db_in.d
@@ -277,6 +277,7 @@ template spineAbstractionDbRead() {
obj.tags.segment_anchor_tag_epub = row[_col["segment_epub"]].as!string;
obj.tags.html_segment_anchor_tag_is = row[_col["segment_html_is"]].as!string;
obj.tags.epub_segment_anchor_tag_is = row[_col["segment_epub_is"]].as!string;
+ obj.tags.segment_lv4_is = row[_col["segment_lv4_is"]].as!string;
obj.tags.anchor_tag_html = row[_col["anchor"]].as!string;
obj.tags.heading_lev_anchor_tag = row[_col["heading_lev_anchor"]].as!string;
{
diff --git a/src/sisudoc/ocda/abstraction/doc_has.d b/src/sisudoc/ocda/abstraction/doc_has.d
index 75a4640..051da33 100644
--- a/src/sisudoc/ocda/abstraction/doc_has.d
+++ b/src/sisudoc/ocda/abstraction/doc_has.d
@@ -163,20 +163,6 @@ template spineDocHasFromAbstraction() {
_out.quotes = _count(_doc_has_block, "quotes");
string[] _images;
string[string][string] _tag_assoc;
- /+ ↓ keys waiting for the level 4 segment that will hold them.
-
- a heading above level 4 opens no html segment, so a cross reference
- to it has to land on the next level 4 heading, which has not been
- seen yet when the heading is read. The parser does this the same
- way, back-filling a pending tag when the level 4 heading arrives
- (metadoc_from_src.d, "tag_assoc[lv0_to_lv3_html_tag]"), and the
- order of the objects is what both are reading it from.
- +/
- string[] _awaiting_lv4;
- void _backfill(string _seg) {
- foreach (_k; _awaiting_lv4) { _tag_assoc[_k]["seg_lv4"] = _seg; }
- _awaiting_lv4 = [];
- }
/+ ↓ segnames["html"] is seeded with the toc, which is a segment of its
own before any level 4 heading opens one +/
_out.segnames_lv4 ~= "toc";
@@ -226,6 +212,7 @@ template spineDocHasFromAbstraction() {
+/
if (obj.tags.heading_lev_anchor_tag.length > 0
&& obj.tags.in_segment_html.length > 0
+ && obj.metainfo.heading_lev_markup >= 4
) {
_tag_assoc[obj.tags.heading_lev_anchor_tag]["seg_lv4"]
= obj.tags.in_segment_html;
@@ -245,14 +232,23 @@ template spineDocHasFromAbstraction() {
if (obj.metainfo.heading_lev_markup <= 4) {
_out.segnames_lv_0_to_4 ~= obj.tags.segment_anchor_tag_epub;
}
- if (obj.metainfo.heading_lev_markup == 4) {
- if (_section == "body") { _out.segnames_lv4 ~= obj.tags.anchor_tag_html; }
- /+ ↓ this is the segment the headings above it were waiting for +/
- _backfill(obj.tags.in_segment_html);
- } else if (obj.metainfo.heading_lev_markup < 4) {
- foreach (_k; [obj.metainfo.identifier, obj.tags.heading_lev_anchor_tag,
- obj.tags.anchor_tag_html]) {
- if (_k.length > 0) { _awaiting_lv4 ~= _k; }
+ if (_section == "body" && obj.metainfo.heading_lev_markup == 4) {
+ _out.segnames_lv4 ~= obj.tags.anchor_tag_html;
+ }
+ /+ ↓ a heading above level 4 opens no html segment of its own, so
+ a cross reference to it lands on the level 4 segment that
+ follows. That is .segment_lv4_is, resolved in ocda where the
+ finished sections are to hand and carried by the artefact, so
+ there is nothing to work out here
+ +/
+ if (obj.tags.segment_lv4_is.length > 0) {
+ /+ ↓ seg_lv4 only, and not through heading_lev_anchor_tag: that
+ names the level 4 heading itself, whose own entry says it
+ opens that segment rather than merely sits in it. epub
+ segments go down to level 1, so seg_lv1to4 is untouched
+ +/
+ foreach (_k; [obj.metainfo.identifier, obj.tags.anchor_tag_html]) {
+ if (_k.length > 0) { _tag_assoc[_k]["seg_lv4"] = obj.tags.segment_lv4_is; }
}
}
}
diff --git a/src/sisudoc/ocda/abstraction/ssp.d b/src/sisudoc/ocda/abstraction/ssp.d
index 6b487d7..487a33b 100644
--- a/src/sisudoc/ocda/abstraction/ssp.d
+++ b/src/sisudoc/ocda/abstraction/ssp.d
@@ -61,7 +61,9 @@ module sisudoc.ocda.abstraction.ssp;
1.1 2026-09-10 @source block; the document metadata the output writers
read carried in full (14 meta and 3 make properties
- added); was 0.1
+ added); .segment_lv4_is, the segment a cross
+ reference to a heading above level 4 lands on;
+ was 0.1
+/
enum ssp_format_version = "1.1";
enum ssp_format_version_major = "1";
@@ -380,6 +382,14 @@ template sspObjectRecord() {
if (obj.tags.epub_segment_anchor_tag_is.length > 0) {
output ~= ".segment_epub_is: " ~ obj.tags.epub_segment_anchor_tag_is;
}
+ /+ ↓ the level 4 segment a cross reference to this heading lands on,
+ emitted only where it is not the segment the heading sits in, which
+ is every heading at level 4 or below +/
+ if (obj.tags.segment_lv4_is.length > 0
+ && obj.tags.segment_lv4_is != obj.tags.html_segment_anchor_tag_is
+ ) {
+ output ~= ".segment_lv4_is: " ~ obj.tags.segment_lv4_is;
+ }
/+ ↓ heading ancestors text +/
{
bool has_hat = false;
diff --git a/src/sisudoc/ocda/abstraction/ssp_in.d b/src/sisudoc/ocda/abstraction/ssp_in.d
index 873cb7e..59a5b80 100644
--- a/src/sisudoc/ocda/abstraction/ssp_in.d
+++ b/src/sisudoc/ocda/abstraction/ssp_in.d
@@ -311,6 +311,7 @@ template spineAbstractionRead() {
case "segment_epub": obj.tags.segment_anchor_tag_epub = _val; break;
case "segment_html_is": obj.tags.html_segment_anchor_tag_is = _val; break;
case "segment_epub_is": obj.tags.epub_segment_anchor_tag_is = _val; break;
+ case "segment_lv4_is": obj.tags.segment_lv4_is = _val; break;
case "heading_ancestors_text":
{
string[8] _h;
diff --git a/src/sisudoc/ocda/meta/metadoc_from_src.d b/src/sisudoc/ocda/meta/metadoc_from_src.d
index c5e2ce8..fb30a94 100644
--- a/src/sisudoc/ocda/meta/metadoc_from_src.d
+++ b/src/sisudoc/ocda/meta/metadoc_from_src.d
@@ -1246,6 +1246,37 @@ template docAbstraction() {
the_document_bookindex_section = get_ancestors.the_document_bookindex_section;
the_document_blurb_section = get_ancestors.the_document_blurb_section;
}
+ /+ ↓ the html segment a cross reference to a heading lands on.
+ a heading above level 4 opens no html segment, so a link to it goes
+ to the level 4 heading that follows it. The build loop cannot know
+ that yet and back-fills tag_assoc when the level 4 heading arrives
+ (see lv0to3_tags); this is the same answer, kept on the object, so
+ that it travels with the abstraction instead of living only in a map
+ the parser holds. Walking backwards, the last level 4 seen is the
+ next one for everything above it.
+ +/
+ {
+ string _next_lv4;
+ foreach_reverse (ref obj; the_document_body_section) {
+ if (obj.metainfo.is_a != "heading") { continue; }
+ if (obj.metainfo.heading_lev_markup == 4) {
+ _next_lv4 = obj.tags.anchor_tag_html;
+ } else if (obj.metainfo.heading_lev_markup < 4) {
+ obj.tags.segment_lv4_is = _next_lv4;
+ }
+ }
+ /+ ↓ the head section's title sits above the body and resolves to the
+ body's first level 4 heading, which is what _next_lv4 now holds
+ +/
+ foreach_reverse (ref obj; the_document_head_section) {
+ if (obj.metainfo.is_a != "heading") { continue; }
+ if (obj.metainfo.heading_lev_markup == 4) {
+ _next_lv4 = obj.tags.anchor_tag_html;
+ } else if (obj.metainfo.heading_lev_markup < 4) {
+ obj.tags.segment_lv4_is = _next_lv4;
+ }
+ }
+ }
// get descendants
if (the_document_body_section.length > 1) {
auto pairs = after_doc_get_descendants(
diff --git a/src/sisudoc/ocda/meta/metadoc_object_setter.d b/src/sisudoc/ocda/meta/metadoc_object_setter.d
index 2eab062..6c090db 100644
--- a/src/sisudoc/ocda/meta/metadoc_object_setter.d
+++ b/src/sisudoc/ocda/meta/metadoc_object_setter.d
@@ -130,6 +130,16 @@ template ObjectSetter() {
string segment_anchor_tag_epub = "";
string html_segment_anchor_tag_is = "";
string epub_segment_anchor_tag_is = "";
+ /+ the html segment a cross reference to this heading lands on.
+ a heading above level 4 opens no html segment of its own, so a link to
+ it has to go to the level 4 heading that follows, which is not known
+ when the heading is read ("for html segname need following lv4 not yet
+ known", metadoc_from_src.d). It is resolved in a pass over the
+ finished sections and kept here, so that it is a property of the
+ object like any other and travels with the abstraction rather than
+ living only in the tag_associations map the parser builds.
+ +/
+ string segment_lv4_is = "";
string heading_lev_anchor_tag = "";
string segname_prev = "";
string segname_next = "";
diff --git a/src/sisudoc/outputs/io_out/create_ocda_db.d b/src/sisudoc/outputs/io_out/create_ocda_db.d
index f184854..b2cfd62 100644
--- a/src/sisudoc/outputs/io_out/create_ocda_db.d
+++ b/src/sisudoc/outputs/io_out/create_ocda_db.d
@@ -172,6 +172,7 @@ template spineAbstractionDb() {
segment_epub TEXT,
segment_html_is TEXT,
segment_epub_is TEXT,
+ segment_lv4_is TEXT,
anchor TEXT,
heading_lev_anchor TEXT,
heading_ancestors_text TEXT
@@ -324,7 +325,7 @@ template spineAbstractionDb() {
~ "indent_base, indent_hang, bullet, lang,"
~ "has_links, has_notes_reg, has_notes_star, has_images, has_images_no_dim,"
~ "segment, segment_prev, segment_next, segment_epub,"
- ~ "segment_html_is, segment_epub_is,"
+ ~ "segment_html_is, segment_epub_is, segment_lv4_is,"
~ "anchor, heading_lev_anchor, heading_ancestors_text,"
~ "table_cols, table_widths, table_aligns, table_header,"
~ "code_linenumbers, text"
@@ -339,7 +340,7 @@ template spineAbstractionDb() {
~ ":indent_base, :indent_hang, :bullet, :lang,"
~ ":has_links, :has_notes_reg, :has_notes_star, :has_images, :has_images_no_dim,"
~ ":segment, :segment_prev, :segment_next, :segment_epub,"
- ~ ":segment_html_is, :segment_epub_is,"
+ ~ ":segment_html_is, :segment_epub_is, :segment_lv4_is,"
~ ":anchor, :heading_lev_anchor, :heading_ancestors_text,"
~ ":table_cols, :table_widths, :table_aligns, :table_header,"
~ ":code_linenumbers, :text"
@@ -483,6 +484,7 @@ template spineAbstractionDb() {
bindStr(":segment_epub", obj.tags.segment_anchor_tag_epub);
bindStr(":segment_html_is", obj.tags.html_segment_anchor_tag_is);
bindStr(":segment_epub_is", obj.tags.epub_segment_anchor_tag_is);
+ bindStr(":segment_lv4_is", obj.tags.segment_lv4_is);
bindStr(":anchor", obj.tags.anchor_tag_html);
bindStr(":heading_lev_anchor", obj.tags.heading_lev_anchor_tag);
bindJsonStrs(":heading_ancestors_text", obj.tags.heading_ancestors_text);