diff options
Diffstat (limited to 'org/ocda_reserved.org')
| -rw-r--r-- | org/ocda_reserved.org | 212 |
1 files changed, 212 insertions, 0 deletions
diff --git a/org/ocda_reserved.org b/org/ocda_reserved.org new file mode 100644 index 0000000..eddf455 --- /dev/null +++ b/org/ocda_reserved.org @@ -0,0 +1,212 @@ +-*- mode: org -*- +#+TITLE: sisudoc spine (doc_reform) object-centric document abstraction +#+DESCRIPTION: documents - structuring, publishing in multiple formats & search +#+SUMMARY: process markup document, create document abstraction +#+FILETAGS: :spine:abstraction: +#+AUTHOR: Ralph Amissah +#+EMAIL: [[mailto:ralph.amissah@gmail.com][ralph.amissah@gmail.com]] +#+COPYRIGHT: Copyright (C) 2015 (continuously updated, current 2026) Ralph Amissah +#+LANGUAGE: en +#+STARTUP: content hideblocks hidestars noindent entitiespretty +#+PROPERTY: header-args+ :eval never-export :exports code +#+PROPERTY: header-args+ :noweb yes :padline no +#+PROPERTY: header-args+ :results silent :cache no +#+PROPERTY: header-args+ :mkdirp yes +#+OPTIONS: H:3 num:nil toc:t \n:t ::t |:t ^:nil -:t f:t *:t +- magic single double-quote → " ← FIX changes hilighting behavior (occuring + after it) in org document. INVESTIGATE (org-mode CONFIG?) FIND & FIX + +- [[./doc-reform.org][doc-reform.org]] [[./][org/]] + +* reserved file names + +#+HEADER: :tangle "../src/sisudoc/ocda/meta/reserved_names.d" +#+HEADER: :noweb yes +#+BEGIN_SRC d +<<doc_header_including_copyright_and_license>> +/++ + the segment names spine keeps for itself<br><br> + + the one list of them, and the check that says when a document's own + heading has claimed one<br><br> + + [sisudoc.ocda.meta.reserved_names] ++/ +module sisudoc.ocda.meta.reserved_names; +@safe: +/+ ↓ spine names the sections it generates, these names are reserved. + . + The table of contents, the gathered endnotes, the glossary, the + bibliography, the book index and the blurb are not in the markup: spine + makes them, and gives each a segment name of its own. A document whose + own heading asks for one of those names ("1~endnotes Endnote") is asking + for a name that is already taken, and before this was noticed both wrote + into the same file: the generated section and the author's heading, with + the navigation listing that file twice, the second time behind its own + earlier entry in reading order. + . + The parser therefore seeds the set of heading anchor names it has seen + with these before it reads a document, so that a heading claiming one is + disambiguated by ocn suffix the same way a repeated anchor tag is, and + the generated section keeps the name the table of contents links to. + . + Two things live here rather than in the parser: + . + the list so that the parser's seeding and the check below cannot + come to hold different ideas of what is reserved; + . + the check which runs over a finished abstraction, names the + headings that were renamed, and is what tells an author + that a heading of theirs is not called what they wrote. + A warning: the document is correct and complete, and the + name it ends up with works. --strict makes it a failure, + for the run that is meant to be publishable. + . + The renaming is not something the author has to accept. A heading given + any other anchor name ("1~my-notes Endnote") keeps it, and the warning + goes away. ++/ +/+ ↓ mixed in as a named mixin (mixin spineReservedNames _name;) and its + imports are inside its functions rather than at template scope: what a + mixin template declares at its own scope is visible in the scope it is + mixed into, and an import there can hijack a name the host was already + resolving by UFCS. ++/ +template spineReservedNames() { + /+ ↓ the names spine makes for itself, in one place. + _the_title is the head section's own; the rest are the generated + sections, and are the section keys of the abstraction. + +/ + string[] reservedHeadingAnchorNames() { + return [ + "toc", "endnotes", "glossary", "bibliography", "bookindex", "blurb", + "_the_title", + ]; + } + /+ ↓ the same, as the set the parser seeds itself with +/ + bool[string] reservedHeadingAnchorTags() { + bool[string] _reserved; + foreach (_name; reservedHeadingAnchorNames()) { _reserved[_name] = true; } + return _reserved; + } + /+ ↓ one heading that asked for a name spine had already taken +/ + struct ST_ReservedNameUse { + string section; // where in the abstraction it sits + string reserved; // the name it asked for + string anchor; // the name it was given instead + string level; // as marked up, :A :B 1 2 ... + int ocn; + } + /+ ↓ was this heading renamed out of the way of a reserved name? + . + Read off the anchor rather than reported by the parser: the parser + renames by appending the object's number, so "endnotes" becomes + "endnotes-135" on the object whose ocn is 135, and that pairing is what + identifies it. Requiring the number to be the object's own is what keeps + a heading an author really did call "endnotes-135" from being reported as + something it is not. + +/ + private string _reservedNameClaimedBy(O)(O obj) { + import std.conv : to; + string _anchor = obj.tags.anchor_tag_html; + if (_anchor.length == 0) { return ""; } + string _suffix = "-" ~ obj.metainfo.ocn.to!string; + if (_anchor.length <= _suffix.length) { return ""; } + if (_anchor[($ - _suffix.length) .. $] != _suffix) { return ""; } + string _stem = _anchor[0 .. ($ - _suffix.length)]; + foreach (_name; reservedHeadingAnchorNames()) { + if (_stem == _name) { return _name; } + } + return ""; + } + /+ ↓ every heading of a document that claimed a reserved name. + document order, the section order the .ssp is written in, so that two + runs over the same document report it the same way round. + +/ + ST_ReservedNameUse[] reservedNameHeadings(D)(D doc) { + import std.algorithm : canFind, sort; + import std.conv : to; + ST_ReservedNameUse[] _out; + string[] _sections = ["head", "toc", "body", "endnotes", + "glossary", "bibliography", "bookindex", "blurb", "tail"]; + string[] _extra; + foreach (_k; doc.abstraction.byKey) { + if (!_sections.canFind(_k)) { _extra ~= _k; } + } + foreach (_k; _extra.sort) { _sections ~= _k; } + foreach (section; _sections) { + if (section !in doc.abstraction) { continue; } + foreach (obj; doc.abstraction[section]) { + if (obj.metainfo.is_a != "heading") { continue; } + string _claimed = _reservedNameClaimedBy(obj); + if (_claimed.length == 0) { continue; } + /+ ↓ the generated sections carry the reserved names themselves and are + not what this is about: they are headings spine made, and they keep + the plain name. Only an object that was renamed reaches here, and a + generated one never is. + +/ + ST_ReservedNameUse _u; + _u.section = section; + _u.reserved = _claimed; + _u.anchor = obj.tags.anchor_tag_html; + _u.level = obj.metainfo.marked_up_level; + _u.ocn = obj.metainfo.ocn.to!int; + _out ~= _u; + } + } + return _out; + } + /+ ↓ the report, as the lines to print. + the document is named once and its headings indented under it, as the ocn + alignment check does, so that a run over a collection reads as a list of + documents. + +/ + string[] reservedNameReportLines( + string doc_key, + string lang, + ST_ReservedNameUse[] _uses, + ) { + import std.conv : to; + string[] _out; + if (_uses.length == 0) { return _out; } + _out ~= "WARNING reserved segment name: " ~ doc_key + ~ ((lang.length > 0) ? " [" ~ lang ~ "]" : ""); + foreach (_u; _uses) { + _out ~= " heading " ~ _u.level ~ " at ocn " ~ _u.ocn.to!string + ~ " asks for \"" ~ _u.reserved + ~ "\", which spine gives its own generated section"; + _out ~= " it is named \"" ~ _u.anchor + ~ "\" instead; give the heading another name to keep one of your own"; + } + return _out; + } +} +#+END_SRC + +* org includes +** project version + +#+NAME: spine_version +#+HEADER: :noweb yes +#+BEGIN_SRC emacs-lisp +<<./sisudoc_spine_version_info_and_doc_header_including_copyright_and_license.org:spine_project_version()>> +#+END_SRC + +** year + +#+NAME: year +#+HEADER: :noweb yes +#+BEGIN_SRC emacs-lisp +<<./sisudoc_spine_version_info_and_doc_header_including_copyright_and_license.org:year()>> +#+END_SRC + +** document header including copyright & license + +#+NAME: doc_header_including_copyright_and_license +#+HEADER: :noweb yes +#+BEGIN_SRC emacs-lisp +<<./sisudoc_spine_version_info_and_doc_header_including_copyright_and_license.org:spine_doc_header_including_copyright_and_license()>> +#+END_SRC + +* __END__ + |
