aboutsummaryrefslogtreecommitdiffhomepage
path: root/org
diff options
context:
space:
mode:
Diffstat (limited to 'org')
-rw-r--r--org/in_source_files.org2
-rw-r--r--org/ocda.org31
-rw-r--r--org/ocda_get.org40
-rw-r--r--org/ocda_obj_setter.org10
-rw-r--r--org/out_src_abstraction_ocda_peg_ssp.org12
-rw-r--r--org/out_src_abstraction_sqlite_db.org6
6 files changed, 76 insertions, 25 deletions
diff --git a/org/in_source_files.org b/org/in_source_files.org
index e78970a..4ba1b10 100644
--- a/org/in_source_files.org
+++ b/org/in_source_files.org
@@ -1048,6 +1048,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;
@@ -1390,6 +1391,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/org/ocda.org b/org/ocda.org
index f58e955..db24139 100644
--- a/org/ocda.org
+++ b/org/ocda.org
@@ -1356,6 +1356,37 @@ if (the_document_blurb_section.length > 1) { // writeln("blurb");
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/org/ocda_get.org b/org/ocda_get.org
index 7ea9260..64fff57 100644
--- a/org/ocda_get.org
+++ b/org/ocda_get.org
@@ -143,20 +143,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";
@@ -206,6 +192,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;
@@ -225,14 +212,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/org/ocda_obj_setter.org b/org/ocda_obj_setter.org
index a6c25f2..e0e7363 100644
--- a/org/ocda_obj_setter.org
+++ b/org/ocda_obj_setter.org
@@ -216,6 +216,16 @@ struct DocObj_Tags_ {
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/org/out_src_abstraction_ocda_peg_ssp.org b/org/out_src_abstraction_ocda_peg_ssp.org
index 5e26a4f..511c589 100644
--- a/org/out_src_abstraction_ocda_peg_ssp.org
+++ b/org/out_src_abstraction_ocda_peg_ssp.org
@@ -43,7 +43,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";
@@ -362,6 +364,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/org/out_src_abstraction_sqlite_db.org b/org/out_src_abstraction_sqlite_db.org
index dab8291..70c118a 100644
--- a/org/out_src_abstraction_sqlite_db.org
+++ b/org/out_src_abstraction_sqlite_db.org
@@ -154,6 +154,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
@@ -306,7 +307,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"
@@ -321,7 +322,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"
@@ -465,6 +466,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);