#include #include "util.h" #include "file.h" #include "html_util.h" #include "heading.h" #include "log.h" #include "show.h" std::ostream& operator<<(std::ostream& os, const Heading h) { os << h.m_level << " " << h.m_filename << " " << h.m_section << " " << h.m_id << " " << h.m_number << " " << h.m_title; return os; } std::string levels_to_section(std::vector levels) { (void)K::log(3); std::string result {}; auto count = levels.size(); for (unsigned int i = 0; i < count; i++) { if (levels[i] == 0) break; result += std::to_string(levels[i]); if (i < count - 1) result += "."; } if (count > 1) result = result.substr(0, result.size()-1); return result; } int part_number = 1; int unnumbered_id = 0; /* std::tuple, std::vector, unsigned int> add_section_numbers(const std::string& s, const std::string& basename, std::vector levels, unsigned int initial_id, std::map& section_id_map) { (void)K::log(3); auto depth { levels.size() }; std::vector headings {}; std::string text { s }; std::regex section_rgx (R"((.*?)(.*?))"); std::regex part_rgx (R"((.*?)Part (\d+)\s*
\s*(.*?)\s*)"); std::regex id_rgx(R"((.*?)id=\"([-\w]+)\"(.*))"); unsigned int id_number { initial_id }; //std::string result {}; std::stringstream result {}; for (std::string line : regex_split(s, std::regex(R"(\n)"), false)) { std::smatch match {}; if (std::regex_match(line, match, part_rgx)) { std::string pre { match[1] }; std::string attr { match[2] }; std::string level { match[3] }; std::string title { match[4] }; std::string id_prefix { "_part_"}; std::string id {}; std::smatch id_match {}; if (std::regex_match(attr, id_match, id_rgx)) { id = id_match[2]; } else { id = id_prefix + std::to_string(part_number); } //title = "Part " + std::to_string(part_number) + " - " + title; //std::string section = "Part " + level; std::string section = "Part " + std::to_string(part_number); elements_t part_title { html::elt("kt-part", { html::elt("span", section).attr("class", "sectionnumber"), html::elt("span", trim(title)).attr("class", "sectiontitle") }) .attr("id", id) .attr("data-level", level) }; result << pre << part_title << "\n"; headings.push_back(Heading(0, basename, section, id, "0", title)); part_number += 1; } else if (std::regex_match(line, match, section_rgx)) { std::string pre { match[1] }; int level { std::stoi(match[2]) }; std::string attr { match[3] }; std::string title { match[4] }; bool numbered = attr.find("numbered") != std::string::npos; std::string section {}; if (numbered) { levels[level-1] = levels[level-1] + 1; for (unsigned int li = level; li < depth; li++) levels[li] = 0; section = levels_to_section(levels); } std::string id {}; std::smatch id_match {}; if (std::regex_match(attr, id_match, id_rgx)) { id = id_match[2]; } else { if (section.size() == 0) { id = "_su_" + std::to_string(unnumbered_id++); } else { id = "_s_" + string_replace(section, ".", "_"); } } std::string link_target = file_basename(basename) + link_delimiter + id; section_id_map[title] = link_target; //

// 1Image tests

elements_t title_parts {}; if (numbered) { title_parts.push_back(html::elt("span", trim(section)).attr("class", "sectionnumber")); } title_parts.push_back(html::elt("span", trim(title)).attr("class", "sectiontitle")); // msg() << "title_parts: " << title_parts << "\n"; elements_t section_title { html::elt("h"+std::to_string(level), title_parts) .attr("id", id) .attr("data-level", std::to_string(level))}; // msg() << pre << section_title << "\n"; result << pre << section_title << "\n"; headings.push_back(Heading(level, basename, section, id, "0", title)); } else { result << line << "\n"; } } //std::cout << "add_section_numbers: " << result.str() << " " //<< headings.size() << " " << levels.size() << " " << id_number << "\n"; return std::tuple(result.str(), headings, levels, id_number); } */ std::string make_html_table_of_contents(std::vector headings) { elements_t toc { html::elt("h1", "Contents") }; for (auto [level, filename, section, id, number, title] : headings) { toc.push_back( html::elt("div", html::elt("a", { html::elt("span", section).attr("class", "level_number"), title }) .attr("href", "^#" + id) .attr("class", "level")) .attr("class", "level" + std::to_string(level))); } //auto toc_elt = html::elt("div", toc).attr("id", "toc"); std::string result { "
\n" + to_string(toc) + "\n
\n" }; return result; } std::string toc_link_attrs( const std::string& section, const std::string& title, const std::string& filename, const std::string& target, int level) { std::string basename = file_basename(filename); std::stringstream ss {}; ss << "class=\"navlink\" data-page=\"" << basename << "\" data-target=\"" << target << "\">\n\n"; if (section.size() > 0) { ss << "" << section << "\n"; } ss << "" << title << "\n" << "\n"; return ss.str(); } std::pair make_navigation_table_of_contents(std::vector headings) { std::stringstream toc {}; long unsigned int i = 1; //int max_level = 0; //int last_level = 0; int max_level = 1; int last_level = 1; toc << "
    \n"; int min_level = 7; for (auto h : headings) { min_level = std::min(h.m_level, min_level); } bool unnumbered_start = headings.size() > 0 ? headings[0].m_section.empty() : false; if (unnumbered_start) { // Unnumbered first section (preface, for example) toc << "
      \n"; } for (auto [item_level, filename, section, id, number, title] : headings) { // msg() << " level: " << item_level << "; filename: " << filename << "; section: " << section // << "; id: " << id << "; number: " << number << "; title: " << title << "\n"; bool promote_unnumbered = unnumbered_start && min_level == 0 and section.empty(); if (promote_unnumbered) { item_level--; } std::string basename = file_basename(filename); max_level = std::max(max_level, item_level); //int next_level = i < headings.size() ? headings[i].m_level : 0; int next_level = i < headings.size() ? headings[i].m_level : 1; if (promote_unnumbered) { next_level = std::max(0, next_level - 1); } // std::cout << "|" << item_level << "|" << section << "|" << id << "|" // << title << "| " << "next: " << next_level << "\n"; std::string link = toc_link_attrs(section, title, basename, id, item_level); if (next_level == item_level) { toc << "
    • \n"; /* } else if (next_level > item_level) { toc << "
    • " << "\n" << "
        \n"; */ } else if (next_level > item_level) { toc << "
      • \n" << "\n" << "
          \n"; } else { //toc << "
        • \n
        \n
      • \n"; toc << "
      • \n"; /* if (unnumbered_start) { next_level += 1; } */ int offset = unnumbered_start ? 1 : 0; //int offset = unnumbered_start ? 3 : 2; offset = 0; for (int lev = item_level; lev > next_level + offset; lev--) { toc << "
      \n
    • \n"; } unnumbered_start = false; } i++; last_level = item_level; } toc << "
    \n"; for (int j = 0; j < last_level - 2; j++) { toc << "\n
\n"; } return {max_level, toc.str()}; } void show_table_of_contents( const std::string& kt_root_filename, const std::string& title, std::vector headings) { long unsigned int width = kt_root_filename.size(); for (Heading h : headings) { width = std::max(width, h.m_filename.size()); } width += 2; int tab = 2; std::string current_filename = ""; std::string bar = " | "; std::cout << "\n" << std::string(width - kt_root_filename.size(), ' ') << kt_root_filename << bar << title << "\n"; for (auto [level, filename, section, id, number, htitle] : headings) { std::string f = ""; if (filename != current_filename) { f = std::string(width - filename.size(), ' ') + filename + bar; current_filename = filename; } else { f = std::string(width, ' ') + bar; } std::cout << f << std::string((level-1) * tab, ' ') << section << " " << htitle << "\n"; } std::cout << "\n"; } std::string cache_table_of_contents( const std::string& kt_root_filename, const std::string& title, std::vector headings) { long unsigned int width = kt_root_filename.size(); for (Heading h : headings) { width = std::max(width, h.m_filename.size()); } width += 2; int tab = 2; std::string current_filename = ""; std::string bar = " | "; std::stringstream ss {}; ss << "\n" << std::string(width - kt_root_filename.size(), ' ') << kt_root_filename << bar << title << "\n"; for (auto [level, filename, section, id, number, htitle] : headings) { std::string f = ""; if (filename != current_filename) { f = std::string(width - filename.size(), ' ') + filename + bar; current_filename = filename; } else { f = std::string(width, ' ') + bar; } ss << f << std::string((level) * tab, ' '); if (section.size() > 0) { ss << section << " "; } ss << htitle << "\n"; } ss << "\n"; std::string cache_filename = cache_directory(kt_root_filename, "_html_pages") + "/toc.txt"; string_to_file(cache_filename, ss.str()); return cache_filename; }