Skip to content

Commit

Permalink
Convert / to boilerplate template (#317)
Browse files Browse the repository at this point in the history
  • Loading branch information
casey authored Aug 17, 2022
1 parent b747581 commit d1d2fc2
Show file tree
Hide file tree
Showing 8 changed files with 196 additions and 81 deletions.
23 changes: 7 additions & 16 deletions src/subcommand/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ use super::*;

use {
self::{
deserialize_ordinal_from_str::DeserializeOrdinalFromStr, templates::OrdinalHtml,
deserialize_ordinal_from_str::DeserializeOrdinalFromStr,
templates::{ordinal::OrdinalHtml, root::RootHtml, Content},
tls_acceptor::TlsAcceptor,
},
clap::ArgGroup,
Expand Down Expand Up @@ -150,7 +151,7 @@ impl Server {
extract::Path(DeserializeOrdinalFromStr(ordinal)): extract::Path<DeserializeOrdinalFromStr>,
) -> impl IntoResponse {
match index.blocktime(ordinal.height()) {
Ok(blocktime) => OrdinalHtml { ordinal, blocktime }.into_response(),
Ok(blocktime) => OrdinalHtml { ordinal, blocktime }.page().into_response(),
Err(err) => {
eprintln!("Failed to retrieve height from index: {err}");
(
Expand Down Expand Up @@ -227,20 +228,9 @@ impl Server {

async fn root(index: extract::Extension<Arc<Index>>) -> impl IntoResponse {
match index.all() {
Ok(blocks) => (
StatusCode::OK,
Html(format!(
"<ul>\n{}</ul>",
blocks
.iter()
.map(|(height, hash)| format!(
" <li>{height} - <a href='/block/{hash}'>{hash}</a></li>\n"
))
.collect::<String>(),
)),
),
Err(error) => {
eprintln!("Error serving request for root: {error}");
Ok(blocks) => RootHtml { blocks }.page().into_response(),
Err(err) => {
eprintln!("Error getting blocks: {err}");
(
StatusCode::INTERNAL_SERVER_ERROR,
Html(
Expand All @@ -250,6 +240,7 @@ impl Server {
.to_string(),
),
)
.into_response()
}
}
}
Expand Down
78 changes: 45 additions & 33 deletions src/subcommand/server/templates.rs
Original file line number Diff line number Diff line change
@@ -1,46 +1,58 @@
use {super::*, boilerplate::Display};

pub(crate) mod ordinal;
pub(crate) mod root;

#[derive(Display)]
pub(crate) struct OrdinalHtml {
pub(crate) ordinal: Ordinal,
pub(crate) blocktime: Blocktime,
pub(crate) struct PageHtml {
content: Box<dyn Content>,
}

pub(crate) trait Content: Display {
fn title(&self) -> String;

fn page(self) -> PageHtml;
}

#[cfg(test)]
mod tests {
use {super::*, pretty_assertions::assert_eq, unindent::Unindent};
use super::*;

#[test]
fn ordinal_html() {
assert_eq!(
OrdinalHtml {
ordinal: Ordinal(0),
blocktime: Blocktime::Confirmed(0),
fn page() {
struct Foo;

impl Display for Foo {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "<h1>Foo</h1>")
}
.to_string(),
"
<!doctype html>
<html>
<head>
<meta charset=utf-8>
<title>0°0′0″0‴</title>
</head>
<body>
<dl><dt>number</dt><dd>0</dd></dl>
<dl><dt>decimal</dt><dd>0.0</dd></dl>
<dl><dt>degree</dt><dd>0°0′0″0‴</dd></dl>
<dl><dt>name</dt><dd>nvtdijuwxlp</dd></dl>
<dl><dt>height</dt><dd>0</dd></dl>
<dl><dt>cycle</dt><dd>0</dd></dl>
<dl><dt>epoch</dt><dd>0</dd></dl>
<dl><dt>period</dt><dd>0</dd></dl>
<dl><dt>offset</dt><dd>0</dd></dl>
<dl><dt>rarity</dt><dd>mythic</dd></dl>
<dl><dt>block time</dt><dd>1970-01-01 00:00:00</dd></dl>
</body>
</html>
"
.unindent()
}

impl Content for Foo {
fn title(&self) -> String {
"Foo".to_string()
}

fn page(self) -> PageHtml {
PageHtml {
content: Box::new(self),
}
}
}

assert_eq!(
Foo.page().to_string(),
"<!doctype html>
<html lang=en>
<head>
<meta charset=utf-8>
<title>Foo</title>
</head>
<body>
<h1>Foo</h1>
</body>
</html>
"
);
}
}
51 changes: 51 additions & 0 deletions src/subcommand/server/templates/ordinal.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
use super::*;

#[derive(Display)]
pub(crate) struct OrdinalHtml {
pub(crate) ordinal: Ordinal,
pub(crate) blocktime: Blocktime,
}

impl Content for OrdinalHtml {
fn title(&self) -> String {
self.ordinal.degree().to_string()
}

fn page(self) -> PageHtml {
PageHtml {
content: Box::new(self),
}
}
}

#[cfg(test)]
mod tests {
use {super::*, pretty_assertions::assert_eq, unindent::Unindent};

#[test]
fn ordinal_html() {
assert_eq!(
OrdinalHtml {
ordinal: Ordinal(0),
blocktime: Blocktime::Confirmed(0),
}
.to_string(),
"
<h1>Ordinal 0</h1>
<dl>
<dt>decimal</dt><dd>0.0</dd>
<dt>degree</dt><dd>0°0′0″0‴</dd>
<dt>name</dt><dd>nvtdijuwxlp</dd>
<dt>height</dt><dd>0</dd>
<dt>cycle</dt><dd>0</dd>
<dt>epoch</dt><dd>0</dd>
<dt>period</dt><dd>0</dd>
<dt>offset</dt><dd>0</dd>
<dt>rarity</dt><dd>mythic</dd>
<dt>block time</dt><dd>1970-01-01 00:00:00</dd>
</dl>
"
.unindent()
);
}
}
50 changes: 50 additions & 0 deletions src/subcommand/server/templates/root.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
use super::*;

#[derive(Display)]
pub(crate) struct RootHtml {
pub(crate) blocks: Vec<(u64, BlockHash)>,
}

impl Content for RootHtml {
fn title(&self) -> String {
"Ordinal Block Explorer".to_string()
}

fn page(self) -> PageHtml {
PageHtml {
content: Box::new(self),
}
}
}

#[cfg(test)]
mod tests {
use {super::*, pretty_assertions::assert_eq, unindent::Unindent};

#[test]
fn root_html() {
assert_eq!(
RootHtml {
blocks: vec![
(
1,
"1111111111111111111111111111111111111111111111111111111111111111".parse().unwrap()
),
(
0,
"0000000000000000000000000000000000000000000000000000000000000000".parse().unwrap()
)
],
}
.to_string(),
"
<h1>Recent Blocks</h1>
<ul>
<li>1 - <a href=/block/1111111111111111111111111111111111111111111111111111111111111111>1111111111111111111111111111111111111111111111111111111111111111</a></li>
<li>0 - <a href=/block/0000000000000000000000000000000000000000000000000000000000000000>0000000000000000000000000000000000000000000000000000000000000000</a></li>
</ul>
"
.unindent()
);
}
}
33 changes: 13 additions & 20 deletions templates/ordinal.html
Original file line number Diff line number Diff line change
@@ -1,20 +1,13 @@
<!doctype html>
<html>
<head>
<meta charset=utf-8>
<title>{{ self.ordinal.degree() }}</title>
</head>
<body>
<dl><dt>number</dt><dd>{{ self.ordinal.n() }}</dd></dl>
<dl><dt>decimal</dt><dd>{{ self.ordinal.decimal() }}</dd></dl>
<dl><dt>degree</dt><dd>{{ self.ordinal.degree() }}</dd></dl>
<dl><dt>name</dt><dd>{{ self.ordinal.name() }}</dd></dl>
<dl><dt>height</dt><dd>{{ self.ordinal.height() }}</dd></dl>
<dl><dt>cycle</dt><dd>{{ self.ordinal.cycle() }}</dd></dl>
<dl><dt>epoch</dt><dd>{{ self.ordinal.epoch() }}</dd></dl>
<dl><dt>period</dt><dd>{{ self.ordinal.period() }}</dd></dl>
<dl><dt>offset</dt><dd>{{ self.ordinal.third() }}</dd></dl>
<dl><dt>rarity</dt><dd>{{ self.ordinal.rarity() }}</dd></dl>
<dl><dt>block time</dt><dd>{{ self.blocktime }}</dd></dl>
</body>
</html>
<h1>Ordinal {{ self.ordinal.n() }}</h1>
<dl>
<dt>decimal</dt><dd>{{ self.ordinal.decimal() }}</dd>
<dt>degree</dt><dd>{{ self.ordinal.degree() }}</dd>
<dt>name</dt><dd>{{ self.ordinal.name() }}</dd>
<dt>height</dt><dd>{{ self.ordinal.height() }}</dd>
<dt>cycle</dt><dd>{{ self.ordinal.cycle() }}</dd>
<dt>epoch</dt><dd>{{ self.ordinal.epoch() }}</dd>
<dt>period</dt><dd>{{ self.ordinal.period() }}</dd>
<dt>offset</dt><dd>{{ self.ordinal.third() }}</dd>
<dt>rarity</dt><dd>{{ self.ordinal.rarity() }}</dd>
<dt>block time</dt><dd>{{ self.blocktime }}</dd>
</dl>
10 changes: 10 additions & 0 deletions templates/page.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<!doctype html>
<html lang=en>
<head>
<meta charset=utf-8>
<title>{{ self.content.title() }}</title>
</head>
<body>
$$ self.content
</body>
</html>
6 changes: 6 additions & 0 deletions templates/root.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<h1>Recent Blocks</h1>
<ul>
%% for block in &self.blocks {
<li>{{block.0}} - <a href=/block/{{block.1}}>{{block.1}}</a></li>
%% }
</ul>
26 changes: 14 additions & 12 deletions tests/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,21 +68,22 @@ fn range_links_to_first() {

#[test]
fn ordinal_number() {
State::new().request_regex("ordinal/0", 200, ".*<dl><dt>number</dt><dd>0</dd></dl>.*");
State::new().request_regex("ordinal/0", 200, ".*<h1>Ordinal 0</h1>.*");
}

#[test]
fn ordinal_decimal() {
State::new().request_regex("ordinal/0.0", 200, ".*<dl><dt>number</dt><dd>0</dd></dl>.*");
State::new().request_regex("ordinal/0.0", 200, ".*<h1>Ordinal 0</h1>.*");
}

#[test]
fn ordinal_degree() {
State::new().request_regex(
"ordinal/0°0′0″0‴",
200,
".*<dl><dt>number</dt><dd>0</dd></dl>.*",
);
State::new().request_regex("ordinal/0°0′0″0‴", 200, ".*<h1>Ordinal 0</h1>.*");
}

#[test]
fn ordinal_name() {
State::new().request_regex("ordinal/nvtdijuwxlp", 200, ".*<h1>Ordinal 0</h1>.*");
}

#[test]
Expand Down Expand Up @@ -140,9 +141,10 @@ fn root() {
state.request_regex(
"/",
200,
".*<ul>
<li>1 - <a href='/block/[[:xdigit:]]{64}'>[[:xdigit:]]{64}</a></li>
<li>0 - <a href='/block/0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206'>0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206</a></li>
".*<h1>Recent Blocks</h1>
<ul>
<li>1 - <a href=/block/[[:xdigit:]]{64}>[[:xdigit:]]{64}</a></li>
<li>0 - <a href=/block/0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206>0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206</a></li>
</ul>.*",
);
}
Expand Down Expand Up @@ -211,7 +213,7 @@ fn unmined_ordinal() {
state.request_regex(
"ordinal/0",
200,
".*<dl><dt>block time</dt><dd>2011-02-02 23:16:42</dd></dl>.*",
".*<dt>block time</dt><dd>2011-02-02 23:16:42</dd>.*",
);
}

Expand All @@ -221,6 +223,6 @@ fn mined_ordinal() {
state.request_regex(
"ordinal/5000000000",
200,
".*<dl><dt>block time</dt><dd>.* \\(expected\\)</dd></dl>.*",
".*<dt>block time</dt><dd>.* \\(expected\\)</dd>.*",
);
}

0 comments on commit d1d2fc2

Please sign in to comment.