mirror of
https://github.com/nicoburns/blessed-rs
synced 2025-02-16 12:58:29 +00:00
Convert crate list to be data-driven using a json file
This commit is contained in:
parent
f3dade3308
commit
555959cf26
6 changed files with 221 additions and 37 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -94,6 +94,7 @@ dependencies = [
|
|||
"axum",
|
||||
"once_cell",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tera",
|
||||
"tokio",
|
||||
"tower-http",
|
||||
|
|
|
@ -9,6 +9,7 @@ edition = "2021"
|
|||
axum = "0.4.8"
|
||||
once_cell = "1.10.0"
|
||||
serde = { version = "1.0.136", features = ["derive"] }
|
||||
serde_json = "1.0.79"
|
||||
tera = "1.15"
|
||||
tokio = { version = "1.17", features = ["full"] }
|
||||
tower-http = { version = "0.2.5", features = ["fs", "trace"] }
|
||||
|
|
142
src/data/crates.json
Normal file
142
src/data/crates.json
Normal file
|
@ -0,0 +1,142 @@
|
|||
{
|
||||
"crate_groups": [
|
||||
{
|
||||
"name": "Core",
|
||||
"description": "Very commonly used domain-specific tools",
|
||||
"purposes": [
|
||||
{
|
||||
"name": "Random numbers",
|
||||
"crates": [{
|
||||
"name": "rand",
|
||||
"notes": "De facto random number generation library split out from the standard library"
|
||||
}]
|
||||
},
|
||||
{
|
||||
"name": "Serialization (JSON, YAML, etc)",
|
||||
"crates": [{
|
||||
"name": "serde",
|
||||
"notes": "De facto serialization library. Use in conjunction with sub-crates like serde_json for the specific format that you are using."
|
||||
}]
|
||||
},
|
||||
{
|
||||
"name": "Regular Expressions",
|
||||
"crates": [{
|
||||
"name": "regex",
|
||||
"notes": "De facto regex library. Very fast, but does not support fancier features such as backtracking."
|
||||
},
|
||||
{
|
||||
"name": "fancy_regex",
|
||||
"notes": "Use if need features such as backtracking which regex doesn't support"
|
||||
}]
|
||||
},
|
||||
{
|
||||
"name": "Gzip (de)compression",
|
||||
"crates": [{
|
||||
"name": "flate2",
|
||||
"notes": "Uses a pure-Rust implementation by default. Use feature flags to opt in to system zlib."
|
||||
}]
|
||||
},
|
||||
{
|
||||
"name": "Time & Date",
|
||||
"crates": [{
|
||||
"name": "time",
|
||||
"notes": "Basic time manipulation."
|
||||
}, {
|
||||
"name": "chrono",
|
||||
"notes": "Basic time manipulation."
|
||||
}]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Error Handling",
|
||||
"description": "Crates for more easily handling errors",
|
||||
"purposes": [
|
||||
{
|
||||
"name": "For applications",
|
||||
"crates": [{
|
||||
"name": "anyhow",
|
||||
"notes": "Provides a boxed error type that can hold any error, and helpers for generating an application-level stack trace."
|
||||
}]
|
||||
},
|
||||
{
|
||||
"name": "For libraries",
|
||||
"crates": [{
|
||||
"name": "thiserror",
|
||||
"notes": "Helps with generating boilerplate for enum-style error types."
|
||||
}]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Logging",
|
||||
"description": "Crates for logging. Note that in general you will need a seperate crate for actually printing/storing the logs",
|
||||
"purposes": [
|
||||
{
|
||||
"name": "Text-based logging",
|
||||
"crates": [{
|
||||
"name": "tracing",
|
||||
"notes": "Tracing is now the go-to crate for logging."
|
||||
}, {
|
||||
"name": "log",
|
||||
"notes": "An older and simpler crate if your needs are simple and you are not using any async code."
|
||||
}]
|
||||
},
|
||||
{
|
||||
"name": "Structed logging",
|
||||
"crates": [{
|
||||
"name": "tracing",
|
||||
"notes": "Tracing is now the go-to crate for logging."
|
||||
}, {
|
||||
"name": "slog",
|
||||
"notes": "Structed logging"
|
||||
}]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Language Extensions",
|
||||
"description": "General purpose utility crates that extend language and/or stdlib functionality.",
|
||||
"purposes": [
|
||||
{
|
||||
"name": "Lazy static variable initialization",
|
||||
"crates": [{
|
||||
"name": "once_cell",
|
||||
"notes": "Newer crate with more ergonomic API. On track to be incorporated into the standard library. Should be preferred for all new projects."
|
||||
}, {
|
||||
"name": "lazy_static",
|
||||
"notes": "Older crate. API is less convenient, but crate is stable and maintained."
|
||||
}]
|
||||
},
|
||||
{
|
||||
"name": "Iterator helpers",
|
||||
"crates": [{
|
||||
"name": "itertools",
|
||||
"notes": "A bunch of useful methods on iterators that aren't in the stdlib"
|
||||
}]
|
||||
},
|
||||
{
|
||||
"name": "Abstracting over different number types",
|
||||
"crates": [{
|
||||
"name": "num",
|
||||
"notes": "Traits like Number, Add, etc that allow you write functions that are generic over the specific numeric type"
|
||||
}]
|
||||
},
|
||||
{
|
||||
"name": "Endian conversion",
|
||||
"crates": [{
|
||||
"name": "byteorder",
|
||||
"notes": "Utility functions to convert between different endianness or read/write data with a specific endianness"
|
||||
}]
|
||||
},
|
||||
{
|
||||
"name": "Bitflags",
|
||||
"crates": [{
|
||||
"name": "bitflags",
|
||||
"notes": "Strongly typed bitflag types"
|
||||
}]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -2,16 +2,57 @@ use axum::{
|
|||
http::StatusCode,
|
||||
response::{ IntoResponse, Html },
|
||||
};
|
||||
use serde::{Serialize, Deserialize};
|
||||
use serde_json;
|
||||
use tera::Context;
|
||||
use crate::templates::TERA;
|
||||
|
||||
pub(crate) async fn run() -> impl IntoResponse {
|
||||
let res = match TERA.render("routes/crates/list.html", &Context::new()) {
|
||||
|
||||
|
||||
// Load crate data
|
||||
const data_file_contents : &str = include_str!("../../data/crates.json");
|
||||
// let data_file_contents = String::from_utf8(std::fs::read("data/crates.json").unwrap()).unwrap();
|
||||
let data : CrateDefinitionFile = serde_json::from_str(&data_file_contents).unwrap();
|
||||
|
||||
// Render template
|
||||
let mut context = Context::new();
|
||||
context.insert("crate_groups", &data.crate_groups);
|
||||
let rendered = TERA.render("routes/crates/list.html", &context);
|
||||
|
||||
// Handle template rendering errors
|
||||
let res = match rendered {
|
||||
Ok(res) => (StatusCode::OK, Html(res)),
|
||||
Err(err) => {
|
||||
tracing::debug!("listening on {}", err);
|
||||
(StatusCode::INTERNAL_SERVER_ERROR, Html("".to_string()))
|
||||
}
|
||||
};
|
||||
|
||||
// Return response
|
||||
(StatusCode::OK, res)
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
struct Crate {
|
||||
name: String,
|
||||
notes: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
struct Purpose {
|
||||
name: String,
|
||||
crates: Vec<Crate>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
struct CrateGroup {
|
||||
name: String,
|
||||
description: String,
|
||||
purposes: Vec<Purpose>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
struct CrateDefinitionFile {
|
||||
crate_groups: Vec<CrateGroup>,
|
||||
}
|
|
@ -21,6 +21,11 @@ h1.logo {
|
|||
h3 {
|
||||
font-size: 1.6em;
|
||||
font-weight: normal;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
p.group-description {
|
||||
color: #CCC;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
a, a:hover, a:visited, a:active {
|
||||
|
|
|
@ -13,40 +13,34 @@
|
|||
<h1 class="logo">Blessed.rs</h1>
|
||||
</center>
|
||||
|
||||
<h3>Core Crates</h3>
|
||||
<table class="full-width">
|
||||
<thead>
|
||||
<tr>
|
||||
<th width="200">Use Case</th>
|
||||
<th>Recommendation</th>
|
||||
<!-- <th>Latest Version</th> -->
|
||||
<!-- <th>Last Updated</th> -->
|
||||
<th>Notes</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Random Numbers</td>
|
||||
<td><a href="https://docs.rs/rand">rand</a></td>
|
||||
<!-- <td>0.8.5</td> -->
|
||||
<!-- <td>5 days ago</td> -->
|
||||
<td>De facto random number generation library split out from the standard library</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td rowspan="2" style="vertical-align: top">Lazily initialized static variables</td>
|
||||
<td><a href="https://docs.rs/once_cell">once_cell</a></td>
|
||||
<!-- <td>0.8.5</td> -->
|
||||
<!-- <td>5 days ago</td> -->
|
||||
<td>Newer crate with more ergonomic API. On track to be incorporated into the standard library. Should be preferred for all new projects.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="https://docs.rs/lazy_static">lazy_static</a></td>
|
||||
<!-- <td>0.8.5</td> -->
|
||||
<!-- <td>5 days ago</td> -->
|
||||
<td>De facto random number generation library split out from the standard library</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
{% for group in crate_groups %}
|
||||
|
||||
<h3>{{ group.name }}</h3>
|
||||
<p class="group-description">{{ group.description }}</p>
|
||||
<table class="full-width">
|
||||
<thead>
|
||||
<tr>
|
||||
<th width="200">Use Case</th>
|
||||
<th>Recommendation</th>
|
||||
<!-- <th>Latest Version</th> -->
|
||||
<!-- <th>Last Updated</th> -->
|
||||
<th>Notes</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for purpose in group.purposes %}
|
||||
{% for crate in purpose.crates %}
|
||||
<tr>
|
||||
{% if loop.index0 == 0 %}<td rowspan="{{ purpose.crates | length }} ">{{ purpose.name }}</td>{% endif %}
|
||||
<td><a href="https://docs.rs/{{ crate.name }}">{{ crate.name }}</a></td>
|
||||
<!-- <td>0.8.5</td> -->
|
||||
<!-- <td>5 days ago</td> -->
|
||||
<td>{{ crate.notes }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% endfor %}
|
||||
|
||||
{% endblock content %}
|
Loading…
Add table
Reference in a new issue