Skip to content

Commit 071fbd4

Browse files
committed
feat: use bootstrap to beautify the page
1 parent 7d0979a commit 071fbd4

File tree

11 files changed

+429
-100
lines changed

11 files changed

+429
-100
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ cargo run --bin init
1111

1212
When you need to insert a blog: markd "title name" ./your_post.md
1313
```
14-
cargo run --bin markd "kip-data" ./post.md
14+
cargo run --bin markd "Welcome to KipData" ./post.md
1515
```
1616

1717
Server up!

assets/css/blog.css

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/* stylelint-disable stylistic/selector-list-comma-newline-after */
2+
3+
.blog-header-logo {
4+
font-family: "Playfair Display", Georgia, "Times New Roman", serif/*rtl:Amiri, Georgia, "Times New Roman", serif*/;
5+
font-size: 2.25rem;
6+
}
7+
8+
.blog-header-logo:hover {
9+
text-decoration: none;
10+
}
11+
12+
h1, h2, h3, h4, h5, h6 {
13+
font-family: "Playfair Display", Georgia, "Times New Roman", serif/*rtl:Amiri, Georgia, "Times New Roman", serif*/;
14+
}
15+
16+
.flex-auto {
17+
flex: 0 0 auto;
18+
}
19+
20+
.h-250 { height: 250px; }
21+
@media (min-width: 768px) {
22+
.h-md-250 { height: 250px; }
23+
}
24+
25+
/* Pagination */
26+
.blog-pagination {
27+
margin-bottom: 4rem;
28+
}
29+
30+
/*
31+
* Blog posts
32+
*/
33+
.blog-post {
34+
margin-bottom: 4rem;
35+
}
36+
.blog-post-meta {
37+
margin-bottom: 1.25rem;
38+
color: #727272;
39+
}

assets/css/blog.rtl.css

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/* stylelint-disable stylistic/selector-list-comma-newline-after */
2+
3+
.blog-header-logo {
4+
font-family: Amiri, Georgia, "Times New Roman", serif;
5+
font-size: 2.25rem;
6+
}
7+
8+
.blog-header-logo:hover {
9+
text-decoration: none;
10+
}
11+
12+
h1, h2, h3, h4, h5, h6 {
13+
font-family: Amiri, Georgia, "Times New Roman", serif;
14+
}
15+
16+
.flex-auto {
17+
flex: 0 0 auto;
18+
}
19+
20+
.h-250 { height: 250px; }
21+
@media (min-width: 768px) {
22+
.h-md-250 { height: 250px; }
23+
}
24+
25+
/* Pagination */
26+
.blog-pagination {
27+
margin-bottom: 4rem;
28+
}
29+
30+
/*
31+
* Blog posts
32+
*/
33+
.blog-post {
34+
margin-bottom: 4rem;
35+
}
36+
.blog-post-meta {
37+
margin-bottom: 1.25rem;
38+
color: #727272;
39+
}

assets/js/color-modes.js

+80
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
/*!
2+
* Color mode toggler for Bootstrap's docs (https://getbootstrap.com/)
3+
* Copyright 2011-2023 The Bootstrap Authors
4+
* Licensed under the Creative Commons Attribution 3.0 Unported License.
5+
*/
6+
7+
(() => {
8+
'use strict'
9+
10+
const getStoredTheme = () => localStorage.getItem('theme')
11+
const setStoredTheme = theme => localStorage.setItem('theme', theme)
12+
13+
const getPreferredTheme = () => {
14+
const storedTheme = getStoredTheme()
15+
if (storedTheme) {
16+
return storedTheme
17+
}
18+
19+
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'
20+
}
21+
22+
const setTheme = theme => {
23+
if (theme === 'auto' && window.matchMedia('(prefers-color-scheme: dark)').matches) {
24+
document.documentElement.setAttribute('data-bs-theme', 'dark')
25+
} else {
26+
document.documentElement.setAttribute('data-bs-theme', theme)
27+
}
28+
}
29+
30+
setTheme(getPreferredTheme())
31+
32+
const showActiveTheme = (theme, focus = false) => {
33+
const themeSwitcher = document.querySelector('#bd-theme')
34+
35+
if (!themeSwitcher) {
36+
return
37+
}
38+
39+
const themeSwitcherText = document.querySelector('#bd-theme-text')
40+
const activeThemeIcon = document.querySelector('.theme-icon-active use')
41+
const btnToActive = document.querySelector(`[data-bs-theme-value="${theme}"]`)
42+
const svgOfActiveBtn = btnToActive.querySelector('svg use').getAttribute('href')
43+
44+
document.querySelectorAll('[data-bs-theme-value]').forEach(element => {
45+
element.classList.remove('active')
46+
element.setAttribute('aria-pressed', 'false')
47+
})
48+
49+
btnToActive.classList.add('active')
50+
btnToActive.setAttribute('aria-pressed', 'true')
51+
activeThemeIcon.setAttribute('href', svgOfActiveBtn)
52+
const themeSwitcherLabel = `${themeSwitcherText.textContent} (${btnToActive.dataset.bsThemeValue})`
53+
themeSwitcher.setAttribute('aria-label', themeSwitcherLabel)
54+
55+
if (focus) {
56+
themeSwitcher.focus()
57+
}
58+
}
59+
60+
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => {
61+
const storedTheme = getStoredTheme()
62+
if (storedTheme !== 'light' && storedTheme !== 'dark') {
63+
setTheme(getPreferredTheme())
64+
}
65+
})
66+
67+
window.addEventListener('DOMContentLoaded', () => {
68+
showActiveTheme(getPreferredTheme())
69+
70+
document.querySelectorAll('[data-bs-theme-value]')
71+
.forEach(toggle => {
72+
toggle.addEventListener('click', () => {
73+
const theme = toggle.getAttribute('data-bs-theme-value')
74+
setStoredTheme(theme)
75+
setTheme(theme)
76+
showActiveTheme(theme, true)
77+
})
78+
})
79+
})
80+
})()
File renamed without changes.

post.md

+8-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1-
# Welcome to KipData
1+
### Nice to meet you!
22

3-
Github: https://github.com/KipData
3+
We have built SQL calculations and KV storage from scratch using Rust, covering most of the SQL syntax.
4+
We sincerely hope that you can participate and try to use our projects
5+
**Just for fun!**
6+
7+
8+
Thanks,
9+
Kould

src/assets/post.css

-6
This file was deleted.

src/main.rs

+20-50
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use axum::{
22
http::StatusCode, routing::{get, Router},
33
response::{Html, IntoResponse},
4-
extract::{State, Path},
4+
extract::State,
55
};
66

77
use tower_http::services::ServeDir;
@@ -31,10 +31,6 @@ pub(crate) const BANNER: &str = "
3131
█████ ░░██████
3232
░░░░░ ░░░░░░ ";
3333

34-
// post template
35-
// localhost:4000/post/:query_title
36-
#[derive(Template)]
37-
#[template(path = "posts.html")]
3834
struct PostTemplate<'a> {
3935
post_title: &'a str,
4036
post_date: String,
@@ -46,8 +42,7 @@ struct PostTemplate<'a> {
4642
#[derive(Template)]
4743
#[template(path = "index.html")]
4844
pub struct IndexTemplate<'a> {
49-
pub index_title: String,
50-
pub index_links: &'a Vec<String>,
45+
posts: Vec<PostTemplate<'a>>,
5146
}
5247

5348
// SQL query will return all posts
@@ -86,51 +81,27 @@ mod filters {
8681
}
8782
}
8883

89-
// post router uses two extractors
90-
// Path to extract the query: localhost:4000/post/thispart
91-
// State that holds a Vec<Post> used to render the post that the query matches
92-
async fn post(Path(query_title): Path<String>, State(state): State<Arc<Database<KipStorage>>>) -> impl IntoResponse {
93-
let mut template = PostTemplate{post_title: "none", post_date: "none".to_string(), post_body: "none"};
94-
let posts = get_posts(&state).await.unwrap();
95-
// if the user's query matches a post title then render a template
96-
for post in &posts {
97-
if query_title == post.post_title {
98-
let post_date = post
99-
.post_date
100-
.format("%Y-%m-%d %H:%M:%S")
101-
.to_string();
102-
103-
template = PostTemplate{
104-
post_title: &post.post_title,
105-
post_date,
106-
post_body: &post.post_body
107-
};
108-
break;
109-
} else {
110-
continue
111-
}
112-
}
113-
114-
// 404 if no title found matching the user's query
115-
if &template.post_title == &"none" {
116-
return (StatusCode::NOT_FOUND, "404 not found").into_response();
117-
}
118-
119-
match template.render() {
120-
Ok(html) => Html(html).into_response(),
121-
Err(_) => (StatusCode::INTERNAL_SERVER_ERROR, "try again later").into_response()
122-
}
123-
}
124-
12584
// index router (homepage) will return all blog titles in anchor links
12685
async fn index(State(state): State<Arc<Database<KipStorage>>>) -> impl IntoResponse {
127-
let mut plinks: Vec<String> = Vec::new();
128-
129-
for post in get_posts(&state).await.unwrap() {
130-
plinks.push(post.post_title);
131-
}
86+
let posts = get_posts(&state).await.unwrap();
13287

133-
let template = IndexTemplate{index_title: String::from("Kip-Blog"), index_links: &plinks};
88+
let template = IndexTemplate{
89+
posts: posts
90+
.iter()
91+
.map(|post| {
92+
let post_date = post
93+
.post_date
94+
.format("%Y-%m-%d %H:%M:%S")
95+
.to_string();
96+
97+
PostTemplate {
98+
post_title: &post.post_title,
99+
post_date,
100+
post_body: &post.post_body
101+
}
102+
})
103+
.collect_vec()
104+
};
134105

135106
match template.render() {
136107
Ok(html) => Html(html).into_response(),
@@ -147,7 +118,6 @@ async fn main() {
147118

148119
let app = Router::new()
149120
.route("/", get(index))
150-
.route("/post/:query_title", get(post))
151121
.with_state(Arc::new(kip_sql))
152122
.nest_service("/assets", ServeDir::new("assets"));
153123

templates/base.html

-14
This file was deleted.

0 commit comments

Comments
 (0)