mirror of
https://github.com/yhirose/cpp-httplib.git
synced 2026-04-12 03:38:30 +00:00
Update pages-data.json with new content and structure for cpp-httplib documentation
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
use crate::config::{NavLink, SiteConfig};
|
||||
use crate::defaults;
|
||||
use crate::markdown::{Frontmatter, MarkdownRenderer};
|
||||
use crate::utils::copy_dir_recursive;
|
||||
use anyhow::{Context, Result};
|
||||
use serde::Serialize;
|
||||
use std::fs;
|
||||
@@ -55,7 +56,10 @@ struct Page {
|
||||
|
||||
pub fn build(src: &Path, out: &Path) -> Result<()> {
|
||||
let config = SiteConfig::load(src)?;
|
||||
let renderer = MarkdownRenderer::new(config.highlight_theme());
|
||||
let renderer = MarkdownRenderer::new(
|
||||
config.highlight_dark_theme(),
|
||||
config.highlight_light_theme(),
|
||||
);
|
||||
|
||||
// Build Tera: start with embedded defaults, then override with user templates
|
||||
let tera = build_tera(src)?;
|
||||
@@ -89,7 +93,7 @@ pub fn build(src: &Path, out: &Path) -> Result<()> {
|
||||
|
||||
for page in &pages {
|
||||
// Collect search data for pages-data.json
|
||||
let plain_body = strip_html_tags(&page.html_content);
|
||||
let plain_body = strip_html_tags(&remove_light_theme_blocks(&page.html_content));
|
||||
let truncated_body: String = plain_body.chars().take(500).collect();
|
||||
page_data_entries.push(PageDataEntry {
|
||||
title: page.frontmatter.title.clone(),
|
||||
@@ -405,24 +409,6 @@ fn copy_default_static(out: &Path) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn copy_dir_recursive(src: &Path, dst: &Path) -> Result<()> {
|
||||
for entry in WalkDir::new(src).into_iter().filter_map(|e| e.ok()) {
|
||||
let path = entry.path();
|
||||
let rel = path.strip_prefix(src)?;
|
||||
let target = dst.join(rel);
|
||||
|
||||
if path.is_dir() {
|
||||
fs::create_dir_all(&target)?;
|
||||
} else {
|
||||
if let Some(parent) = target.parent() {
|
||||
fs::create_dir_all(parent)?;
|
||||
}
|
||||
fs::copy(path, &target)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Strip HTML tags from a string and collapse whitespace into a single space,
|
||||
/// producing a plain-text representation suitable for search indexing.
|
||||
fn strip_html_tags(html: &str) -> String {
|
||||
@@ -446,3 +432,37 @@ fn strip_html_tags(html: &str) -> String {
|
||||
let collapsed: String = result.split_whitespace().collect::<Vec<_>>().join(" ");
|
||||
collapsed
|
||||
}
|
||||
|
||||
/// Remove `<div data-code-theme="light">...</div>` blocks so that
|
||||
/// dual-theme code snippets are only indexed once.
|
||||
fn remove_light_theme_blocks(html: &str) -> String {
|
||||
const MARKER: &str = "<div data-code-theme=\"light\"";
|
||||
let mut result = String::with_capacity(html.len());
|
||||
let mut remaining = html;
|
||||
|
||||
while let Some(start) = remaining.find(MARKER) {
|
||||
result.push_str(&remaining[..start]);
|
||||
remaining = &remaining[start..];
|
||||
|
||||
let mut depth: usize = 0;
|
||||
let mut i = 0;
|
||||
while i < remaining.len() {
|
||||
if remaining[i..].starts_with("<div") {
|
||||
depth += 1;
|
||||
i += 4;
|
||||
} else if remaining[i..].starts_with("</div>") {
|
||||
depth -= 1;
|
||||
i += 6;
|
||||
if depth == 0 {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
i += remaining[i..].chars().next().map_or(1, |c| c.len_utf8());
|
||||
}
|
||||
}
|
||||
remaining = &remaining[i..];
|
||||
}
|
||||
|
||||
result.push_str(remaining);
|
||||
result
|
||||
}
|
||||
|
||||
@@ -59,7 +59,8 @@ impl I18n {
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct Highlight {
|
||||
pub theme: Option<String>,
|
||||
pub dark_theme: Option<String>,
|
||||
pub light_theme: Option<String>,
|
||||
}
|
||||
|
||||
impl SiteConfig {
|
||||
@@ -81,10 +82,16 @@ impl SiteConfig {
|
||||
Ok(config)
|
||||
}
|
||||
|
||||
pub fn highlight_theme(&self) -> &str {
|
||||
pub fn highlight_dark_theme(&self) -> &str {
|
||||
self.highlight
|
||||
.as_ref()
|
||||
.and_then(|h| h.theme.as_deref())
|
||||
.and_then(|h| h.dark_theme.as_deref())
|
||||
.unwrap_or("base16-ocean.dark")
|
||||
}
|
||||
|
||||
pub fn highlight_light_theme(&self) -> Option<&str> {
|
||||
self.highlight
|
||||
.as_ref()
|
||||
.and_then(|h| h.light_theme.as_deref())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ mod config;
|
||||
mod defaults;
|
||||
mod markdown;
|
||||
mod serve;
|
||||
mod utils;
|
||||
|
||||
use anyhow::Result;
|
||||
use clap::{Parser, Subcommand, CommandFactory};
|
||||
|
||||
@@ -16,15 +16,17 @@ pub struct Frontmatter {
|
||||
pub struct MarkdownRenderer {
|
||||
syntax_set: SyntaxSet,
|
||||
theme_set: ThemeSet,
|
||||
theme_name: String,
|
||||
dark_theme: String,
|
||||
light_theme: Option<String>,
|
||||
}
|
||||
|
||||
impl MarkdownRenderer {
|
||||
pub fn new(theme_name: &str) -> Self {
|
||||
pub fn new(dark_theme: &str, light_theme: Option<&str>) -> Self {
|
||||
Self {
|
||||
syntax_set: SyntaxSet::load_defaults_newlines(),
|
||||
theme_set: ThemeSet::load_defaults(),
|
||||
theme_name: theme_name.to_string(),
|
||||
dark_theme: dark_theme.to_string(),
|
||||
light_theme: light_theme.map(|s| s.to_string()),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,16 +86,31 @@ impl MarkdownRenderer {
|
||||
}
|
||||
|
||||
fn highlight_code(&self, code: &str, lang: &str) -> String {
|
||||
if lang.is_empty() {
|
||||
return format!("<pre><code>{}</code></pre>", escape_html(code));
|
||||
let syntax = if lang.is_empty() {
|
||||
self.syntax_set.find_syntax_plain_text()
|
||||
} else {
|
||||
self.syntax_set
|
||||
.find_syntax_by_token(lang)
|
||||
.unwrap_or_else(|| self.syntax_set.find_syntax_plain_text())
|
||||
};
|
||||
|
||||
let dark_html = self.highlight_with_theme(code, syntax, &self.dark_theme);
|
||||
|
||||
match &self.light_theme {
|
||||
Some(light) => {
|
||||
let light_html = self.highlight_with_theme(code, syntax, light);
|
||||
format!(
|
||||
concat!(
|
||||
"<div class=\"code-block-wrapper\">",
|
||||
"<div data-code-theme=\"dark\">{}</div>",
|
||||
"<div data-code-theme=\"light\">{}</div>",
|
||||
"</div>",
|
||||
),
|
||||
dark_html, light_html
|
||||
)
|
||||
}
|
||||
None => dark_html,
|
||||
}
|
||||
|
||||
let syntax = self
|
||||
.syntax_set
|
||||
.find_syntax_by_token(lang)
|
||||
.unwrap_or_else(|| self.syntax_set.find_syntax_plain_text());
|
||||
|
||||
self.highlight_with_theme(code, syntax, &self.theme_name)
|
||||
}
|
||||
|
||||
fn highlight_with_theme(
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use crate::builder;
|
||||
use crate::config::SiteConfig;
|
||||
use crate::utils::copy_dir_recursive;
|
||||
use anyhow::{Context, Result};
|
||||
use notify::{Event, RecursiveMode, Watcher};
|
||||
use socket2::{Domain, Protocol, Socket, Type};
|
||||
@@ -280,24 +281,6 @@ fn send_ws_text_frame(mut stream: &TcpStream, msg: &str) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn copy_dir_recursive(src: &Path, dst: &Path) -> Result<()> {
|
||||
for entry in WalkDir::new(src).into_iter().filter_map(|e| e.ok()) {
|
||||
let path = entry.path();
|
||||
let rel = path.strip_prefix(src)?;
|
||||
let target = dst.join(rel);
|
||||
|
||||
if path.is_dir() {
|
||||
fs::create_dir_all(&target)?;
|
||||
} else {
|
||||
if let Some(parent) = target.parent() {
|
||||
fs::create_dir_all(parent)?;
|
||||
}
|
||||
fs::copy(path, &target)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn guess_mime(path: &Path) -> String {
|
||||
match path.extension().and_then(|e| e.to_str()) {
|
||||
Some("html") => "text/html; charset=utf-8".to_string(),
|
||||
|
||||
22
docs-gen/src/utils.rs
Normal file
22
docs-gen/src/utils.rs
Normal file
@@ -0,0 +1,22 @@
|
||||
use anyhow::Result;
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
use walkdir::WalkDir;
|
||||
|
||||
pub fn copy_dir_recursive(src: &Path, dst: &Path) -> Result<()> {
|
||||
for entry in WalkDir::new(src).into_iter().filter_map(|e| e.ok()) {
|
||||
let path = entry.path();
|
||||
let rel = path.strip_prefix(src)?;
|
||||
let target = dst.join(rel);
|
||||
|
||||
if path.is_dir() {
|
||||
fs::create_dir_all(&target)?;
|
||||
} else {
|
||||
if let Some(parent) = target.parent() {
|
||||
fs::create_dir_all(parent)?;
|
||||
}
|
||||
fs::copy(path, &target)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
Reference in New Issue
Block a user