Made stories interative by default

This commit is contained in:
p11 2025-04-08 01:17:30 +02:00
parent 9e180c2258
commit b7db49d88c

View File

@ -519,11 +519,11 @@ fn handle_relative_connection(
.rsplit_once('/') .rsplit_once('/')
.map_or(relative_path, |(_, title)| title); .map_or(relative_path, |(_, title)| title);
fn entry_handler( fn entry_handler<W: Write>(
path: &Path, path: &Path,
relative_path: &str, relative_path: &str,
censored: bool, censored: bool,
) -> impl Fn(&str, &mut TcpStream, usize) { ) -> impl Fn(&str, &mut W, usize) {
move |mut entry, output, level| { move |mut entry, output, level| {
let level = level + 1; let level = level + 1;
let mut pki_path = path.to_path_buf(); let mut pki_path = path.to_path_buf();
@ -573,14 +573,105 @@ fn handle_relative_connection(
if !title.is_empty() { if !title.is_empty() {
let _ = writeln!(stream, "<h1>{title}</h1>"); let _ = writeln!(stream, "<h1>{title}</h1>");
} }
convert_extended(
lines.map(Result::unwrap_or_default), let check_path: &Path = relative_path.as_ref();
&mut stream, let interactive = check_path.parent().is_some_and(|parent| {
Settings::default() std::fs::metadata(parent.with_extension("vng")).is_ok_and(|file| file.is_file())
.with_handler(entry_handler(path, relative_path, censored)) });
.with_start_level(start_level)
.with_use_textboxes(true), if interactive {
); let mut sections = Vec::new();
let mut current_section = Vec::new();
let mut add_section = |current_section: Vec<String>| {
if current_section.is_empty() {
return;
}
let mut section_html = Vec::new();
convert_extended(
current_section,
&mut section_html,
Settings::default()
.with_handler(entry_handler(path, relative_path, censored))
.with_start_level(start_level)
.with_use_textboxes(true),
);
sections.push(String::from_utf8_lossy(&section_html).into_owned());
};
for line in lines {
let line = line.unwrap_or_default();
if !line.is_empty() {
current_section.push(line);
continue;
}
add_section(std::mem::take(&mut current_section));
}
add_section(current_section);
let html = html! {
div id="story-container" {
div {
span id="section-counter" { "1/" (sections.len()) }
}
div {
button onclick="prev()" { "Prev" }
button onclick="next()" { "Next" }
}
@for (index, section) in sections.iter().enumerate() {
div class="story-section" data-section-index=(index)
style=(format!("display: {};", if index == 0 { "block" } else { "none" })) {
(maud::PreEscaped(section))
}
}
script {
(maud::PreEscaped(r"
let currentSection = 0;
const totalSections = ".to_owned() + &sections.len().to_string() + r";
function updateSection() {
document.querySelectorAll('.story-section').forEach((el, index) => {
el.style.display = index === currentSection ? 'block' : 'none';
});
document.getElementById('section-counter').textContent =
`${currentSection + 1}/${totalSections}`;
}
function prev() {
if (currentSection > 0) {
--currentSection;
updateSection();
}
}
function next() {
if (currentSection < totalSections - 1) {
++currentSection;
updateSection();
}
}
"))
}
}
};
let _ = write!(stream, "{}", html.into_string());
} else {
convert_extended(
lines.map(Result::unwrap_or_default),
&mut stream,
Settings::default()
.with_handler(entry_handler(path, relative_path, censored))
.with_start_level(start_level)
.with_use_textboxes(true),
);
}
section(&mut stream); section(&mut stream);