fixed responsiveness, and added cli options to disable navigation or toggle localhost
This commit is contained in:
47
src/main.rs
47
src/main.rs
@@ -63,14 +63,24 @@ enum Commands {
|
|||||||
Serve {
|
Serve {
|
||||||
/// Path to the directory containing SUMMARY.md
|
/// Path to the directory containing SUMMARY.md
|
||||||
path: PathBuf,
|
path: PathBuf,
|
||||||
|
|
||||||
|
/// Whether the home page and navbar should be removed
|
||||||
|
#[arg(short, long)]
|
||||||
|
no_navigation: bool,
|
||||||
|
|
||||||
/// Port to listen on
|
/// Port to listen on
|
||||||
#[arg(short, long, default_value = "3456")]
|
#[arg(short, long, default_value = "3456")]
|
||||||
port: u16,
|
port: u16,
|
||||||
|
|
||||||
|
/// Whether to serve on 0.0.0.0 (local network)
|
||||||
|
#[arg(short = 'H', long)]
|
||||||
|
host: bool,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
struct AppState {
|
struct AppState {
|
||||||
docs_dir: PathBuf,
|
docs_dir: PathBuf,
|
||||||
|
no_navigation: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
@@ -84,10 +94,18 @@ async fn main() -> anyhow::Result<()> {
|
|||||||
let cli = Cli::parse();
|
let cli = Cli::parse();
|
||||||
|
|
||||||
match cli.command {
|
match cli.command {
|
||||||
Commands::Serve { path, port } => {
|
Commands::Serve {
|
||||||
|
path,
|
||||||
|
port,
|
||||||
|
host,
|
||||||
|
no_navigation,
|
||||||
|
} => {
|
||||||
let abs_path = std::fs::canonicalize(&path)?;
|
let abs_path = std::fs::canonicalize(&path)?;
|
||||||
|
|
||||||
let shared_state = Arc::new(AppState { docs_dir: abs_path });
|
let shared_state = Arc::new(AppState {
|
||||||
|
docs_dir: abs_path,
|
||||||
|
no_navigation,
|
||||||
|
});
|
||||||
|
|
||||||
let app = Router::new()
|
let app = Router::new()
|
||||||
.route("/", get(render_summary))
|
.route("/", get(render_summary))
|
||||||
@@ -95,8 +113,14 @@ async fn main() -> anyhow::Result<()> {
|
|||||||
.route("/style.css", get(serve_css))
|
.route("/style.css", get(serve_css))
|
||||||
.with_state(shared_state);
|
.with_state(shared_state);
|
||||||
|
|
||||||
let listener = tokio::net::TcpListener::bind(format!("0.0.0.0:{}", port)).await?;
|
let addr = if host {
|
||||||
tracing::info!("Listening on http://localhost:{}", port);
|
format!("0.0.0.0:{}", port)
|
||||||
|
} else {
|
||||||
|
format!("127.0.0.1:{}", port)
|
||||||
|
};
|
||||||
|
|
||||||
|
let listener = tokio::net::TcpListener::bind(&addr).await?;
|
||||||
|
tracing::info!("Listening on {}", addr);
|
||||||
axum::serve(listener, app).await?;
|
axum::serve(listener, app).await?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -105,6 +129,10 @@ async fn main() -> anyhow::Result<()> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn render_summary(State(state): State<Arc<AppState>>) -> impl IntoResponse {
|
async fn render_summary(State(state): State<Arc<AppState>>) -> impl IntoResponse {
|
||||||
|
if state.no_navigation {
|
||||||
|
return (StatusCode::NOT_FOUND, "Navigation is disabled").into_response();
|
||||||
|
}
|
||||||
|
|
||||||
let mut context = Context::new();
|
let mut context = Context::new();
|
||||||
context.insert("title", "Pages");
|
context.insert("title", "Pages");
|
||||||
|
|
||||||
@@ -150,8 +178,8 @@ async fn render_summary(State(state): State<Arc<AppState>>) -> impl IntoResponse
|
|||||||
context.insert("files", &pages);
|
context.insert("files", &pages);
|
||||||
|
|
||||||
match TEMPLATES.render("home.html", &context) {
|
match TEMPLATES.render("home.html", &context) {
|
||||||
Ok(rendered) => Html(rendered),
|
Ok(rendered) => Html(rendered).into_response(),
|
||||||
Err(e) => Html(format!("<h1>Template Error</h1><pre>{}</pre>", e)),
|
Err(e) => Html(format!("<h1>Template Error</h1><pre>{}</pre>", e)).into_response(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -198,13 +226,18 @@ async fn render_md_file(content: &String, filename: &str, state: Arc<AppState>)
|
|||||||
let mut html_output = String::new();
|
let mut html_output = String::new();
|
||||||
html::push_html(&mut html_output, renderer);
|
html::push_html(&mut html_output, renderer);
|
||||||
|
|
||||||
let (prev_page, next_page) = get_nav_links(&state.docs_dir, filename);
|
let (prev_page, next_page) = if state.no_navigation {
|
||||||
|
(None, None)
|
||||||
|
} else {
|
||||||
|
get_nav_links(&state.docs_dir, filename)
|
||||||
|
};
|
||||||
|
|
||||||
let mut context = Context::new();
|
let mut context = Context::new();
|
||||||
context.insert("title", filename);
|
context.insert("title", filename);
|
||||||
context.insert("content", &html_output);
|
context.insert("content", &html_output);
|
||||||
context.insert("prev_page", &prev_page);
|
context.insert("prev_page", &prev_page);
|
||||||
context.insert("next_page", &next_page);
|
context.insert("next_page", &next_page);
|
||||||
|
context.insert("no_navigation", &state.no_navigation);
|
||||||
|
|
||||||
match TEMPLATES.render("page.html", &context) {
|
match TEMPLATES.render("page.html", &context) {
|
||||||
Ok(rendered) => Html(rendered),
|
Ok(rendered) => Html(rendered),
|
||||||
|
|||||||
@@ -3,16 +3,19 @@
|
|||||||
<head>
|
<head>
|
||||||
{% block head %}
|
{% block head %}
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>{{ title }}</title>
|
<title>{{ title }}</title>
|
||||||
<link rel="stylesheet" href="/style.css">
|
<link rel="stylesheet" href="/style.css">
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
|
||||||
{% endblock head %}
|
{% endblock head %}
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body {% if no_navigation %}style="padding-top: 40px;"{% endif %}>
|
||||||
|
{% if not no_navigation %}
|
||||||
<nav>
|
<nav>
|
||||||
<a href="/">Home</a>
|
<a href="/">Home</a>
|
||||||
</nav>
|
</nav>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
<div id="content">{% block content %}{% endblock content %}</div>
|
<div id="content">{% block content %}{% endblock content %}</div>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ body {
|
|||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
article {
|
article {
|
||||||
@@ -212,7 +213,7 @@ input[type="checkbox"]:checked::before {
|
|||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
padding-top: 100px;
|
padding-top: 75px;
|
||||||
}
|
}
|
||||||
|
|
||||||
nav {
|
nav {
|
||||||
@@ -234,6 +235,7 @@ nav {
|
|||||||
nav a {
|
nav a {
|
||||||
color: var(--text-main);
|
color: var(--text-main);
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
|
font-size: 1.2rem;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
margin-left: 20px;
|
margin-left: 20px;
|
||||||
transition: color 0.2s ease;
|
transition: color 0.2s ease;
|
||||||
|
|||||||
Reference in New Issue
Block a user