// @link :section -- a link to a section by the TEXT of its heading. // // Decided by Andy, 2026-10-12. :section (argtype section_link) written // alone says the heading is in the CURRENT file; written with a value, the // value is the basename (no directory, no extension) of the file of the // same @document that has it. So a link names exactly one file, and a // title shared between files is never ambiguous. Titles match with // klammer markup removed and whitespace collapsed to one space, // case-sensitive. // // Resolution happens here, when @document assembles its files -- the only // place every heading is known -- from two markers the klammers emit: // Link __seclink____KTSL__<file>__ (in the href / \hyperlink; // <file> empty for the current one) // Section %__sectionlink__<id>__KTSL__<basename>__KTSL__<title>__ (tex only; // the html pass reads the heading elements themselves, which // carry their ids after insert_ids()) // KTSL separates the fields because a title or a basename may contain a // single underscore (md_to_sks_test). A file the document does not have, a // title the file does not have, and a title it has more than once are // errors, never fallbacks (the commands do not warn and continue). #ifndef SECTION_LINK_H #define SECTION_LINK_H #include <string> #include <vector> struct Section_target { std::string title {}; // normalized std::string basename {}; // the file's basename, "" for :text content std::string id {}; // the anchor: html id, or tex \hypertarget name }; // The comparison form of a heading's text: tags and TeX control sequences // removed, braces dropped, whitespace collapsed, trimmed. std::string normalize_section_title(const std::string& s); // The target a :section link names, or an Argument_error that says why // there is none. FILE is the :section value ("" for the current file), // WHERE the basename of the file holding the link ("" for the document's // :text) and FILES the document's basenames. At assembly the link's own // position is gone, so the file is the location an error can give // (Locator::none(), never the C++ site). Section_target resolve_section_target( const std::vector<Section_target>& table, const std::string& title, const std::string& file, const std::string& where, const std::vector<std::string>& files); #endif