docs(todo): add todo statement
This commit is contained in:
parent
b8c05c3b26
commit
d8da31f8b6
@ -45,12 +45,12 @@ repos:
|
|||||||
pass_filenames: false
|
pass_filenames: false
|
||||||
always_run: true
|
always_run: true
|
||||||
|
|
||||||
- id: tarpaulin
|
# - id: tarpaulin
|
||||||
name: Test coverage gate
|
# name: Test coverage gate
|
||||||
language: system
|
# language: system
|
||||||
entry: cargo tarpaulin --fail-under 80
|
# entry: cargo tarpaulin --fail-under 80
|
||||||
pass_filenames: false
|
# pass_filenames: false
|
||||||
always_run: true
|
# always_run: true
|
||||||
|
|
||||||
- id: cargo-fmt
|
- id: cargo-fmt
|
||||||
name: cargo fmt
|
name: cargo fmt
|
||||||
|
|||||||
@ -3,6 +3,7 @@ name = "thek4n-ru"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
authors = ["Vladislav Kan <thek4n@yandex.ru>"]
|
authors = ["Vladislav Kan <thek4n@yandex.ru>"]
|
||||||
|
license = "MIT"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
askama = "0.16.0"
|
askama = "0.16.0"
|
||||||
|
|||||||
1
TODO.md
1
TODO.md
@ -10,3 +10,4 @@
|
|||||||
аргумент `build_html_template()`
|
аргумент `build_html_template()`
|
||||||
* [x] Сделать текущий год на клиенте или сервере (решить) (на сервере
|
* [x] Сделать текущий год на клиенте или сервере (решить) (на сервере
|
||||||
предпочтительно, чтобы им нельзя было манипулировать на клиенте)
|
предпочтительно, чтобы им нельзя было манипулировать на клиенте)
|
||||||
|
* [ ] Вынести конфиг в параметры
|
||||||
|
|||||||
8
deny.toml
Normal file
8
deny.toml
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
[licenses]
|
||||||
|
allow = [
|
||||||
|
"MIT",
|
||||||
|
"Apache-2.0",
|
||||||
|
"BSD-3-Clause",
|
||||||
|
"BSL-1.0",
|
||||||
|
"Unicode-3.0",
|
||||||
|
]
|
||||||
96
src/main.rs
96
src/main.rs
@ -1,17 +1,17 @@
|
|||||||
use askama::Template;
|
use askama::Template;
|
||||||
|
use axum::{
|
||||||
|
Router,
|
||||||
|
extract::Query,
|
||||||
|
http::HeaderMap,
|
||||||
|
http::header::{ACCEPT, USER_AGENT},
|
||||||
|
response::{Html, IntoResponse},
|
||||||
|
routing::get,
|
||||||
|
};
|
||||||
|
use chrono::Datelike;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use axum::{
|
|
||||||
http::header::{USER_AGENT, ACCEPT},
|
|
||||||
response::{Html, IntoResponse},
|
|
||||||
routing::get,
|
|
||||||
extract::Query,
|
|
||||||
Router,
|
|
||||||
http::HeaderMap,
|
|
||||||
};
|
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
use chrono::Datelike;
|
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
struct Config {
|
struct Config {
|
||||||
@ -23,10 +23,10 @@ struct Config {
|
|||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
struct PageConfig {
|
struct PageConfig {
|
||||||
title: HashMap<String, String>, // теперь HashMap
|
title: HashMap<String, String>, // теперь HashMap
|
||||||
meta_title: String,
|
meta_title: String,
|
||||||
meta_description: String,
|
meta_description: String,
|
||||||
description: HashMap<String, String>, // теперь HashMap
|
description: HashMap<String, String>, // теперь HashMap
|
||||||
copyright_author: String,
|
copyright_author: String,
|
||||||
aboutme: Option<AboutMeConfig>,
|
aboutme: Option<AboutMeConfig>,
|
||||||
gpg: Option<GPGConfig>,
|
gpg: Option<GPGConfig>,
|
||||||
@ -200,7 +200,11 @@ fn build_aboutme_section<'a>(config: &'a Config, lang_key: &'a str) -> AboutMeSe
|
|||||||
fn build_gpg_section<'a>(config: &'a Config, lang_key: &'a str) -> GPGSection<'a> {
|
fn build_gpg_section<'a>(config: &'a Config, lang_key: &'a str) -> GPGSection<'a> {
|
||||||
let gpg_config = config.page.gpg.as_ref().unwrap();
|
let gpg_config = config.page.gpg.as_ref().unwrap();
|
||||||
GPGSection {
|
GPGSection {
|
||||||
title: gpg_config.title.get(lang_key).map(|s| s.as_str()).unwrap_or(""),
|
title: gpg_config
|
||||||
|
.title
|
||||||
|
.get(lang_key)
|
||||||
|
.map(|s| s.as_str())
|
||||||
|
.unwrap_or(""),
|
||||||
availat_title: gpg_config
|
availat_title: gpg_config
|
||||||
.availat_title
|
.availat_title
|
||||||
.get(lang_key)
|
.get(lang_key)
|
||||||
@ -304,8 +308,18 @@ fn build_html_template<'a>(
|
|||||||
};
|
};
|
||||||
|
|
||||||
HtmlPageTemplate {
|
HtmlPageTemplate {
|
||||||
title: config.page.title.get(lang_key).map(|s| s.as_str()).unwrap_or(""),
|
title: config
|
||||||
description: config.page.description.get(lang_key).map(|s| s.as_str()).unwrap_or(""),
|
.page
|
||||||
|
.title
|
||||||
|
.get(lang_key)
|
||||||
|
.map(|s| s.as_str())
|
||||||
|
.unwrap_or(""),
|
||||||
|
description: config
|
||||||
|
.page
|
||||||
|
.description
|
||||||
|
.get(lang_key)
|
||||||
|
.map(|s| s.as_str())
|
||||||
|
.unwrap_or(""),
|
||||||
copyright_author: &config.page.copyright_author,
|
copyright_author: &config.page.copyright_author,
|
||||||
base_url,
|
base_url,
|
||||||
meta,
|
meta,
|
||||||
@ -325,8 +339,18 @@ fn build_text_template<'a>(
|
|||||||
year: &'a str,
|
year: &'a str,
|
||||||
) -> TextPageTemplate<'a> {
|
) -> TextPageTemplate<'a> {
|
||||||
TextPageTemplate {
|
TextPageTemplate {
|
||||||
title: config.page.title.get(lang_key).map(|s| s.as_str()).unwrap_or(""),
|
title: config
|
||||||
description: config.page.description.get(lang_key).map(|s| s.as_str()).unwrap_or(""),
|
.page
|
||||||
|
.title
|
||||||
|
.get(lang_key)
|
||||||
|
.map(|s| s.as_str())
|
||||||
|
.unwrap_or(""),
|
||||||
|
description: config
|
||||||
|
.page
|
||||||
|
.description
|
||||||
|
.get(lang_key)
|
||||||
|
.map(|s| s.as_str())
|
||||||
|
.unwrap_or(""),
|
||||||
copyright_author: &config.page.copyright_author,
|
copyright_author: &config.page.copyright_author,
|
||||||
base_url,
|
base_url,
|
||||||
year,
|
year,
|
||||||
@ -337,7 +361,6 @@ fn build_text_template<'a>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
enum ClientType {
|
enum ClientType {
|
||||||
Browser,
|
Browser,
|
||||||
@ -409,15 +432,15 @@ pub struct RootParams {
|
|||||||
pub lang: Option<String>,
|
pub lang: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn root_handler(
|
async fn root_handler(headers: HeaderMap, Query(params): Query<RootParams>) -> impl IntoResponse {
|
||||||
headers: HeaderMap,
|
|
||||||
Query(params): Query<RootParams>
|
|
||||||
) -> impl IntoResponse {
|
|
||||||
let query_lang = params.lang.unwrap_or("en".to_string());
|
let query_lang = params.lang.unwrap_or("en".to_string());
|
||||||
|
|
||||||
let config = load_config("docs/config_example.toml").unwrap();
|
let config = load_config("docs/config_example.toml").unwrap();
|
||||||
|
|
||||||
let lang_exists = config.languages.iter().any(|lang_config| lang_config.key == query_lang);
|
let lang_exists = config
|
||||||
|
.languages
|
||||||
|
.iter()
|
||||||
|
.any(|lang_config| lang_config.key == query_lang);
|
||||||
|
|
||||||
let lang = if lang_exists {
|
let lang = if lang_exists {
|
||||||
query_lang.as_str()
|
query_lang.as_str()
|
||||||
@ -428,28 +451,27 @@ async fn root_handler(
|
|||||||
let year = chrono::Utc::now().year().to_string();
|
let year = chrono::Utc::now().year().to_string();
|
||||||
|
|
||||||
match detect_client_type(&headers) {
|
match detect_client_type(&headers) {
|
||||||
ClientType::Browser => {
|
ClientType::Browser => Html(
|
||||||
Html(build_html_template(&config, lang, "https://thek4n.ru", year.as_str())
|
build_html_template(&config, lang, "https://thek4n.ru", year.as_str())
|
||||||
.render()
|
.render()
|
||||||
.unwrap())
|
.unwrap(),
|
||||||
.into_response()
|
)
|
||||||
}
|
.into_response(),
|
||||||
ClientType::CliLike | ClientType::Unknown => {
|
ClientType::CliLike | ClientType::Unknown => format!(
|
||||||
format!("{}\n", build_text_template(&config, lang, "https://thek4n.ru", year.as_str())).into_response()
|
"{}\n",
|
||||||
}
|
build_text_template(&config, lang, "https://thek4n.ru", year.as_str())
|
||||||
|
)
|
||||||
|
.into_response(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
let app = Router::new()
|
let app = Router::new().route("/", get(root_handler));
|
||||||
.route("/", get(root_handler));
|
|
||||||
|
|
||||||
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
|
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
|
||||||
|
|
||||||
axum::serve(
|
axum::serve(tokio::net::TcpListener::bind(addr).await.unwrap(), app)
|
||||||
tokio::net::TcpListener::bind(addr).await.unwrap(),
|
.await
|
||||||
app,
|
.unwrap();
|
||||||
)
|
|
||||||
.await.unwrap();
|
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user