19std::string replace_all(std::string text, std::string_view token,
20 std::string_view replacement) {
22 while ((pos = text.find(token, pos)) != std::string::npos) {
23 text.replace(pos, token.size(), replacement);
24 pos += replacement.size();
29std::string slugify(std::string_view title) {
31 result.reserve(title.size());
32 bool last_was_separator =
true;
33 for (
const char raw : title) {
34 const auto c =
static_cast<unsigned char>(raw);
35 if (std::isalnum(c)) {
36 result.push_back(
static_cast<char>(std::tolower(c)));
37 last_was_separator =
false;
38 }
else if (!last_was_separator) {
39 result.push_back(
'_');
40 last_was_separator =
true;
43 while (!result.empty() && result.back() ==
'_') { result.pop_back(); }
47constexpr std::string_view kMonoMainTemplate =
48 R
"NOTEX(\documentclass[light]{@CLASS@}
50% PREAMBLE ────────────────────────────────────────────────────────────────
52% Additional packages here
54% Title, Author and Date
59% DOCUMENT ────────────────────────────────────────────────────────────────
75constexpr std::string_view kMultiMainTemplate =
76 R
"NOTEX(\documentclass[light]{@CLASS@}
78% PREAMBLE ────────────────────────────────────────────────────────────────
80% Additional packages here
81\usepackage{subfiles} % Modular document structure (best loaded last)
83% Title, Author and Date
88% DOCUMENT ────────────────────────────────────────────────────────────────
101constexpr std::string_view kSectionTemplate =
102 R
"NOTEX(\documentclass[../main.tex]{subfiles}
114constexpr std::string_view kBibliographyStarter =
141 return replace_all(std::string(kMonoMainTemplate),
"@CLASS@", class_path);
145 const std::vector<std::string>& section_stems) {
146 std::string sections_block;
147 for (std::size_t i = 0; i < section_stems.size(); ++i) {
148 if (i != 0) sections_block +=
"\\pagebreak\n";
149 sections_block +=
"\\subfile{sections/" + section_stems[i] +
"}\n";
153 replace_all(std::string(kMultiMainTemplate),
"@CLASS@", class_path);
154 return replace_all(std::move(result),
"@SECTIONS@", sections_block);
158 return std::to_string(number) +
"_" + slugify(title);
161std::string
section(
int number, std::string_view title) {
163 replace_all(std::string(kSectionTemplate),
"@TITLE@", title);
164 return replace_all(std::move(result),
"@NUMBER@", std::to_string(number));
168 return std::string(kBibliographyStarter);
std::string section(int number, std::string_view title)
Generates a numbered section subfile.
std::string mono_main(std::string_view class_path)
Generates the entry file for a single-file project.
std::string multi_main(std::string_view class_path, const std::vector< std::string > §ion_stems={"1_introduction"})
Generates the entry file for a multi-file project, referencing section_stems in order.
std::string bibliography_starter()
std::string section_stem(int number, std::string_view title)
Computes the filename stem (no directory, no extension) for a numbered section.
@ MULTI
main.tex plus a sections/ directory of subfiles.
@ MONO
A single main.tex file.
std::optional< ProjectType > project_type_from_string(std::string_view name)
Parses a project type name.
std::string_view to_string(ProjectType type)
templates: encoded skeletons used to scaffold new NoTeX projects.