Gonna finally make a good website

This commit is contained in:
Андреев Григорий 2025-04-01 20:10:28 +03:00
parent 2b02ffb79f
commit aac5804d95
10 changed files with 1607 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
target
.idea

1377
Cargo.lock generated Normal file

File diff suppressed because it is too large Load Diff

9
Cargo.toml Normal file
View File

@ -0,0 +1,9 @@
[package]
name = "yyyi_ru"
version = "0.1.0"
edition = "2024"
[dependencies]
axum = "0.8.3"
tokio = { version = "1.44.1", features = ["rt-multi-thread"] }
tera="1.20.0"

View File

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="/assets/css/common.css">
<title>Блог Гриши</title>
</head>
<body>
</body>
</html>

View File

@ -0,0 +1,21 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="/assets/css/common.css">
<title>Гришина заглавная страничка</title>
</head>
<body>
<div class="main-container">
<div>
<h2 class=""> Обо мне </h2>
<p class="description-text">
Я Андреев Григорий, от 21.06.2005.
Живу в Москве, учусь прогать, люблю курить dwm и иногда пишу разного рода дичь.
Самым интересным в своей жизни делюсь <a href="/blog">вот здесь</a>.
</p>
</div>
</div>
</body>
</html>

42
assets/css/common.css Normal file
View File

@ -0,0 +1,42 @@
body, html {
background-color: #151715;
color: white;
margin: 0;
padding: 0;
}
.main-container {
margin: 0 10px;
}
.flex-justify-content-center {
display: flex;
justify-content: center;
}
h2 {
font-weight: bold;
font-size: 1.5em;
padding-left: 40px;
}
.description-text {
padding-left: 20px;
}
a {
text-decoration: none;
color: aqua;
}
a:hover {
color: deepskyblue;
}
a:visited {
color: #4c259a;
}
a:visited:hover {
color: #613d9c;
}

2
src/lib.rs Normal file
View File

@ -0,0 +1,2 @@
pub mod yyyi_ru;
pub mod mtgott;

6
src/main.rs Normal file
View File

@ -0,0 +1,6 @@
use yyyi_ru::yyyi_ru::MAIN;
#[tokio::main]
async fn main() {
MAIN().await
}

4
src/mtgott/mod.rs Normal file
View File

@ -0,0 +1,4 @@
pub fn proclaim_glad_tidings() {
println!("This project uses My Train Goes Off The Track!\n\
But I ain't writing this shit second time")
}

132
src/yyyi_ru/mod.rs Normal file
View File

@ -0,0 +1,132 @@
use axum;
use std::io;
use std::fs;
use std::collections::HashMap;
use axum::http::HeaderValue;
use std::path::{Path, PathBuf};
use std::sync::Arc;
use axum::http::header::CONTENT_TYPE;
use tera;
use crate::mtgott::{proclaim_glad_tidings};
#[derive(Clone)]
struct StaticAsset {
content_type: HeaderValue,
content: Vec<u8>
}
#[derive(Clone)]
struct AssetsCache {
page_index: StaticAsset,
page_blog: StaticAsset,
static_assets: HashMap<String, StaticAsset>
}
struct ExtensionContentTypeCorr{
extension: &'static str,
content_type: HeaderValue,
}
fn read_static_html_page(p: &Path) -> io::Result<StaticAsset> {
Ok(StaticAsset {
content_type: HeaderValue::from_str("text/html").unwrap(),
content: fs::read(p)?
})
}
impl AssetsCache {
fn load(p: &Path, need: &[ExtensionContentTypeCorr]) -> Result<AssetsCache, io::Error> {
if !p.is_dir() {
return Err(io::Error::from(io::ErrorKind::NotADirectory))
}
let mut st: HashMap<String, StaticAsset> = HashMap::new();
let mut td: Vec<String> = vec![String::new()];
while td.len() > 0 {
let dshp_dir: String = td.pop().unwrap();
let p_dir = p.join(dshp_dir.clone());
for entry in fs::read_dir(p_dir)? {
let entry = entry?;
let dshp_child = if dshp_dir.len() > 0 {
format!("{dshp_dir}/{}", entry.file_name().to_str().unwrap())
} else {
String::from(entry.file_name().to_str().unwrap())
};
let p_child = p.join(dshp_child.clone());
if p_child.is_dir() {
td.push(dshp_child);
} else {
if let Some(ext) = need.iter().find(|ext| {dshp_child.ends_with(ext.extension)}) {
st.insert(dshp_child.clone(), StaticAsset {
content_type: ext.content_type.clone(),
content: fs::read(p.join(dshp_child))?
});
}
}
}
}
Ok(AssetsCache{
page_index: read_static_html_page(&p.join("HypertextPages/index.html"))?,
page_blog: read_static_html_page(&p.join("HypertextPages/blog.html"))?,
static_assets: st
})
}
}
async fn page_index(
axum::extract::State(assets): axum::extract::State<Arc<AssetsCache>>
) -> impl axum::response::IntoResponse {
(
[(CONTENT_TYPE, assets.page_index.content_type.clone())],
assets.page_index.content.clone()
)
}
async fn static_assets(
axum::extract::Path(path): axum::extract::Path<String>,
axum::extract::State(assets): axum::extract::State<Arc<AssetsCache>>,
) -> Result<([(axum::http::HeaderName, axum::http::HeaderValue); 1], Vec<u8>), axum::http::StatusCode> {
if let Some(file) = assets.static_assets.get(&path) {
return Ok((
[(CONTENT_TYPE, file.content_type.clone())],
file.content.clone()
))
}
Err(axum::http::StatusCode::NOT_FOUND)
}
async fn page_blog(
axum::extract::State(assets): axum::extract::State<Arc<AssetsCache>>
) -> impl axum::response::IntoResponse {
axum::response::Html(String::from_utf8(assets.page_blog.content.clone()).unwrap())
}
async fn fallback_page() -> axum::http::StatusCode {
axum::http::StatusCode::NOT_FOUND
}
pub async fn MAIN() {
let manifest_dir = env!("CARGO_MANIFEST_DIR");
println!("Cargo manifest dir: {manifest_dir}");
let static_assets_types: &[ExtensionContentTypeCorr] = &[
ExtensionContentTypeCorr{extension: "css", content_type: HeaderValue::from_str("text/css").unwrap()}
];
let assets = Arc::new(
AssetsCache::load(
&Path::new(manifest_dir).join("assets"),
static_assets_types).unwrap());
// build our application with a single route
let app = axum::Router::new()
.without_v07_checks()
.route("/", axum::routing::MethodRouter::new().get(page_index))
.route("/assets/{*path}", axum::routing::get(static_assets))
.route("/blog", axum::routing::get(page_blog))
.fallback(fallback_page).with_state(assets);
// run our app with hyper, listening globally on port 3000
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
axum::serve(listener, app).await.unwrap();
}