Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

favicon as default twitter preview card #1425

Merged
merged 11 commits into from
Jan 31, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 44 additions & 21 deletions src/subcommand/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ impl Server {
.route("/content/:inscription_id", get(Self::content))
.route("/faq", get(Self::faq))
.route("/favicon.ico", get(Self::favicon))
.route("/favicon.png", get(Self::favicon_png))
.route("/feed.xml", get(Self::feed))
.route("/input/:block/:transaction/:input", get(Self::input))
.route("/inscription/:inscription_id", get(Self::inscription))
Expand All @@ -161,6 +162,7 @@ impl Server {
.route("/tx/:txid", get(Self::transaction))
.layer(Extension(index))
.layer(Extension(options.chain()))
.layer(Extension(self.acme_domains()?.first().cloned()))
.layer(SetResponseHeaderLayer::if_not_present(
header::CONTENT_SECURITY_POLICY,
HeaderValue::from_static("default-src 'self'"),
Expand Down Expand Up @@ -362,6 +364,7 @@ impl Server {

async fn sat(
Extension(chain): Extension<Chain>,
Extension(domain): Extension<Option<String>>,
Extension(index): Extension<Arc<Index>>,
Path(DeserializeFromStr(sat)): Path<DeserializeFromStr<Sat>>,
) -> ServerResult<PageHtml<SatHtml>> {
Expand All @@ -374,7 +377,7 @@ impl Server {
blocktime: index.blocktime(sat.height())?,
inscription: index.get_inscription_id_by_sat(sat)?,
}
.page(chain, index.has_sat_index()?),
.page(chain, domain, index.has_sat_index()?),
)
}

Expand All @@ -384,6 +387,7 @@ impl Server {

async fn output(
Extension(chain): Extension<Chain>,
Extension(domain): Extension<Option<String>>,
Extension(index): Extension<Arc<Index>>,
Path(outpoint): Path<OutPoint>,
) -> ServerResult<PageHtml<OutputHtml>> {
Expand Down Expand Up @@ -426,12 +430,13 @@ impl Server {
chain,
output,
}
.page(chain, index.has_sat_index()?),
.page(chain, domain, index.has_sat_index()?),
)
}

async fn range(
Extension(chain): Extension<Chain>,
Extension(domain): Extension<Option<String>>,
Extension(index): Extension<Arc<Index>>,
Path((DeserializeFromStr(start), DeserializeFromStr(end))): Path<(
DeserializeFromStr<Sat>,
Expand All @@ -443,7 +448,7 @@ impl Server {
Ordering::Greater => Err(ServerError::BadRequest(
"range start greater than range end".to_string(),
)),
Ordering::Less => Ok(RangeHtml { start, end }.page(chain, index.has_sat_index()?)),
Ordering::Less => Ok(RangeHtml { start, end }.page(chain, domain, index.has_sat_index()?)),
}
}

Expand All @@ -457,11 +462,15 @@ impl Server {

async fn home(
Extension(chain): Extension<Chain>,
Extension(domain): Extension<Option<String>>,
Extension(index): Extension<Arc<Index>>,
) -> ServerResult<PageHtml<HomeHtml>> {
Ok(
HomeHtml::new(index.blocks(100)?, index.get_homepage_inscriptions()?)
.page(chain, index.has_sat_index()?),
HomeHtml::new(index.blocks(100)?, index.get_homepage_inscriptions()?).page(
chain,
domain,
index.has_sat_index()?,
),
)
}

Expand All @@ -471,6 +480,7 @@ impl Server {

async fn block(
Extension(chain): Extension<Chain>,
Extension(domain): Extension<Option<String>>,
Extension(index): Extension<Arc<Index>>,
Path(DeserializeFromStr(query)): Path<DeserializeFromStr<BlockQuery>>,
) -> ServerResult<PageHtml<BlockHtml>> {
Expand All @@ -496,13 +506,17 @@ impl Server {
};

Ok(
BlockHtml::new(block, Height(height), Self::index_height(&index)?)
.page(chain, index.has_sat_index()?),
BlockHtml::new(block, Height(height), Self::index_height(&index)?).page(
chain,
domain,
index.has_sat_index()?,
),
)
}

async fn transaction(
Extension(index): Extension<Arc<Index>>,
Extension(domain): Extension<Option<String>>,
Extension(chain): Extension<Chain>,
Path(txid): Path<Txid>,
) -> ServerResult<PageHtml<TransactionHtml>> {
Expand All @@ -519,7 +533,7 @@ impl Server {
inscription.map(|_| txid.into()),
chain,
)
.page(chain, index.has_sat_index()?),
.page(chain, domain, index.has_sat_index()?),
)
}

Expand Down Expand Up @@ -588,11 +602,7 @@ impl Server {
})
.unwrap_or_default()
{
Ok(
Self::static_asset(Path("/favicon.png".to_string()))
.await
.into_response(),
)
Self::favicon_png().await
} else {
Ok(
(
Expand All @@ -607,14 +617,22 @@ impl Server {
}
}

async fn favicon_png() -> ServerResult<Response> {
Ok(
Self::static_asset(Path("/favicon.png".to_string()))
.await
.into_response(),
)
}

async fn feed(
Extension(chain): Extension<Chain>,
Extension(index): Extension<Arc<Index>>,
) -> ServerResult<Response> {
let mut builder = rss::ChannelBuilder::default();

match chain {
Chain::Mainnet => builder.title("Inscriptions"),
Chain::Mainnet => builder.title("Inscriptions".to_string()),
_ => builder.title(format!("Inscriptions – {chain:?}")),
};

Expand All @@ -623,8 +641,8 @@ impl Server {
for (number, id) in index.get_feed_inscriptions(100)? {
builder.item(
rss::ItemBuilder::default()
.title(format!("Inscription {number}"))
.link(format!("/inscription/{id}"))
.title(Some(format!("Inscription {number}")))
.link(Some(format!("/inscription/{id}")))
.guid(Some(rss::Guid {
value: format!("/inscription/{id}"),
permalink: true,
Expand Down Expand Up @@ -671,6 +689,7 @@ impl Server {

async fn input(
Extension(chain): Extension<Chain>,
Extension(domain): Extension<Option<String>>,
Extension(index): Extension<Arc<Index>>,
Path(path): Path<(u64, usize, usize)>,
) -> Result<PageHtml<InputHtml>, ServerError> {
Expand All @@ -692,7 +711,7 @@ impl Server {
.nth(path.2)
.ok_or_not_found(not_found)?;

Ok(InputHtml { path, input }.page(chain, index.has_sat_index()?))
Ok(InputHtml { path, input }.page(chain, domain, index.has_sat_index()?))
}

async fn faq() -> Redirect {
Expand Down Expand Up @@ -795,6 +814,7 @@ impl Server {

async fn inscription(
Extension(chain): Extension<Chain>,
Extension(domain): Extension<Option<String>>,
Extension(index): Extension<Arc<Index>>,
Path(inscription_id): Path<InscriptionId>,
) -> ServerResult<PageHtml<InscriptionHtml>> {
Expand Down Expand Up @@ -845,27 +865,30 @@ impl Server {
satpoint,
timestamp: timestamp(entry.timestamp),
}
.page(chain, index.has_sat_index()?),
.page(chain, domain, index.has_sat_index()?),
)
}

async fn inscriptions(
Extension(chain): Extension<Chain>,
Extension(domain): Extension<Option<String>>,
Extension(index): Extension<Arc<Index>>,
) -> ServerResult<PageHtml<InscriptionsHtml>> {
Self::inscriptions_inner(chain, index, None).await
Self::inscriptions_inner(chain, domain, index, None).await
}

async fn inscriptions_from(
Extension(chain): Extension<Chain>,
Extension(domain): Extension<Option<String>>,
Extension(index): Extension<Arc<Index>>,
Path(from): Path<u64>,
) -> ServerResult<PageHtml<InscriptionsHtml>> {
Self::inscriptions_inner(chain, index, Some(from)).await
Self::inscriptions_inner(chain, domain, index, Some(from)).await
}

async fn inscriptions_inner(
chain: Chain,
domain: Option<String>,
index: Arc<Index>,
from: Option<u64>,
) -> ServerResult<PageHtml<InscriptionsHtml>> {
Expand All @@ -876,7 +899,7 @@ impl Server {
next,
prev,
}
.page(chain, index.has_sat_index()?),
.page(chain, domain, index.has_sat_index()?),
)
}

Expand Down
21 changes: 13 additions & 8 deletions src/templates.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,30 +37,32 @@ mod transaction;
pub(crate) struct PageHtml<T: PageContent> {
chain: Chain,
content: T,
domain: Option<String>,
has_sat_index: bool,
}

impl<T> PageHtml<T>
where
T: PageContent,
{
pub(crate) fn new(content: T, chain: Chain, has_sat_index: bool) -> Self {
pub(crate) fn new(content: T, chain: Chain, domain: Option<String>, has_sat_index: bool) -> Self {
Self {
content,
has_sat_index,
chain,
domain,
has_sat_index,
}
}
}

pub(crate) trait PageContent: Display + 'static {
fn title(&self) -> String;

fn page(self, chain: Chain, has_sat_index: bool) -> PageHtml<Self>
fn page(self, chain: Chain, domain: Option<String>, has_sat_index: bool) -> PageHtml<Self>
where
Self: Sized,
{
PageHtml::new(self, chain, has_sat_index)
PageHtml::new(self, chain, domain, has_sat_index)
}

fn preview_image_url(&self) -> Option<Trusted<String>> {
Expand Down Expand Up @@ -89,13 +91,16 @@ mod tests {
#[test]
fn page() {
assert_regex_match!(
Foo.page(Chain::Mainnet, true),
Foo.page(Chain::Mainnet, Some("signet.ordinals.com".into()), true),
r"<!doctype html>
<html lang=en>
<head>
<meta charset=utf-8>
<meta name=format-detection content='telephone=no'>
<meta name=viewport content='width=device-width,initial-scale=1.0'>
<meta property=og:title content='Foo'>
<meta property=og:image content='https://signet.ordinals.com/favicon.png'>
<meta property=twitter:card content='summary'>
<title>Foo</title>
<link rel=alternate href=/feed.xml type=application/rss\+xml title='Inscription RSS Feed'>
<link rel=stylesheet href=/static/index.css>
Expand Down Expand Up @@ -127,23 +132,23 @@ mod tests {
#[test]
fn page_mainnet() {
assert_regex_match!(
Foo.page(Chain::Mainnet, true),
Foo.page(Chain::Mainnet, None, true),
r".*<nav>\s*<a href=/>Ordinals<sup>alpha</sup></a>.*"
);
}

#[test]
fn page_no_sat_index() {
assert_regex_match!(
Foo.page(Chain::Mainnet, false),
Foo.page(Chain::Mainnet, None, false),
r".*<nav>\s*<a href=/>Ordinals<sup>alpha</sup></a>.*<a href=/clock>Clock</a>\s*<form action=/search.*",
);
}

#[test]
fn page_signet() {
assert_regex_match!(
Foo.page(Chain::Signet, true),
Foo.page(Chain::Signet, None, true),
r".*<nav>\s*<a href=/>Ordinals<sup>signet</sup></a>.*"
);
}
Expand Down
8 changes: 4 additions & 4 deletions templates/page.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
<meta charset=utf-8>
<meta name=format-detection content='telephone=no'>
<meta name=viewport content='width=device-width,initial-scale=1.0'>
%% if let Some(url) = self.content.preview_image_url() {
<meta property=og:image content='{{ url }}'>
%% }
<meta property=og:title content='{{ self.content.title() }}'>
<meta property=og:image content='https://{% if let Some(domain) = &self.domain { %}{{ domain }}{% } else { %}ordinals.com{% } %}/favicon.png'>
raphjaph marked this conversation as resolved.
Show resolved Hide resolved
<meta property=twitter:card content='summary'>
raphjaph marked this conversation as resolved.
Show resolved Hide resolved
<title>{{ self.content.title() }}</title>
<link rel=alternate href=/feed.xml type=application/rss+xml title='Inscription RSS Feed'>
<link rel=stylesheet href=/static/index.css>
Expand All @@ -16,7 +16,7 @@
<body>
<header>
<nav>
<a href=/>Ordinals<sup>{% if self.chain == Chain::Mainnet { %}alpha{% } else { %}{{self.chain}}{% } %}</sup></a>
<a href=/>Ordinals<sup>{% if self.chain == Chain::Mainnet { %}alpha{% } else { %}{{ self.chain }}{% } %}</sup></a>
raphjaph marked this conversation as resolved.
Show resolved Hide resolved
<a href=https://docs.ordinals.com/>Handbook</a>
<a href=https://github.com/casey/ord>Wallet</a>
<a href=/clock>Clock</a>
Expand Down
4 changes: 3 additions & 1 deletion tests/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,9 @@ fn inscription_page() {
TestServer::spawn_with_args(&rpc_server, &[]).assert_response_regex(
format!("/inscription/{inscription}"),
format!(
".*<meta property=og:image content='/content/{inscription}'>.*
".*<meta property=og:title content='Inscription 0'>.*
.*<meta property=og:image content='https://.*/favicon.png'>.*
.*<meta property=twitter:card content='summary'>.*
<h1>Inscription 0</h1>
.*<iframe .* src=/preview/{inscription}></iframe>.*
<dl>
Expand Down